2011-11-11 11 views
9

Algunos antecedentes (una especie de continuación de TLabel and TGroupbox Captions Flicker on Resize):Adición de ventana no VCL en la cola VCL align

  • lo tanto, tengo una aplicación que carga diferentes plugins y crea una nueva pestaña en un TPageControl para cada uno.
  • Cada DLL tiene un TForm asociado.
  • Los formularios se crean con su padre padre como el nuevo TTabSheet. Dado que las TTabSheets no son un elemento primario del formulario por lo que VCL es en cuestión (no deseó utilizar RTL dinámico, y complementos hechos en otros idiomas) Tengo que manejar los cambios de tamaño manualmente.

acabo parecen estar funcionando en una gran cantidad de nuevos temas (pero grandes experiencias de aprendizaje) para este tipo "plug-in" de la aplicación.

Por lo tanto, mi lucha actual es tratar de tener un complemento que no se inserte en una TTabSheet, pero se redimensionará y alineará directamente en el formulario.

ya que esto sería más fácil de explicar con una imagen: Visual representation of question Ahora podría hacerlo manualmente la alineación y el cambio de tamaño, pero yo preferiría tener los procedimientos de alineación VCL (alClient, alTop, etc) hacerlo por mí. De esa manera solo tendría que establecer la alineación de complementos en su forma sin pensar.

Después de mirar a través de la fuente de VCL comencé a recorrer el código de alineación y cómo se llama. Básicamente cuando un TControl consigue un WM_RESIZE lo hará:

  1. llamada Realinee() que llama AlignControl()
  2. AlignControl() obtendrá el rect cliente y llamar AlignControls()
  3. AlignControls() llamará DoAlign() para cada tipo TAlignment en este orden: alTop, alBottom, alLeft, bien, alClient, alCustom, alNone
  4. DoAlign() hará un bucle a través de FControls y FWinControls (que son TLists) y se alineará adecuadamente

Así que mi proceso de pensamiento es que si creo un nuevo TWinControl, configuro su manejador en el formulario de complementos (ventana), e insértelo en la lista FControls con la alineación adecuada, debería hacer mi trabajo por mí.

Por supuesto que estoy aquí, así que falló miserablemente. Incluso obtengo un AV al salir de la aplicación sobre un identificador de ventana no válido. Supongo que el TWinControl que he creado está tratando de liberar el formulario de control de los complementos (ventana) que ya no existe.

Lo que he intentado:

procedure AddHandleToControlList(AHandle: DWORD; Align: TAlign); 
var 
    NewWinControl : TWinControl; 
begin 
    NewWinControl := TWinControl.Create(frmMain); 
    NewWinControl.WindowHandle := AHandle; 
    NewWinControl.Align := Align; 
    NewWinControl.Width := frmMain.ClientWidth; 
    NewWinControl.Height := 30; 
    NewWinControl.Parent := frmMain; 
end; 

procedure AddHandleToControlList(AHandle: DWORD; Align: TAlign); 
var 
    NewWinControl : TWinControl; 
begin 
    NewWinControl := TWinControl.Create(frmMain); 
    NewWinControl.WindowHandle := AHandle; 
    NewWinControl.Align := Align; 
    NewWinControl.Width := frmMain.ClientWidth; 
    NewWinControl.Height := 30; 
    TWinControl(frmMain).Insert(NewWinControl); 
end; 

Soooo, pensamientos?

EDIT 1:

Ok, así que esto agrega correctamente el control de la lista y se ajusta el conjunto TAlign (por qué es que me paso 8 horas tratando de encontrar algo mejor, he puesto aquí, y a continuación, sólo aparece la respuesta ... oh bien alguien podría encontrar esta pregunta y mis divagaciones útil):

procedure AddHandleToControlList(AHandle: DWORD; AName: PChar; ATop, ALeft, AWidth, AHeight: Integer; AAlign: TAlign); 
var 
    NewWinControl : TWinControl; 
begin 
    NewWinControl := TWinControl.Create(frmMain); 
    With NewWinControl Do 
    begin 
    Name := AName; 
    Top := ATop; 
    Left := ALeft; 
    Width := AWidth; 
    Height := AHeight; 
    Align := AAlign; 
    WindowHandle := AHandle; 
    Visible := True; 
    end; 
    TWinControl(frmMain).InsertControl(NewWinControl); 
end; 

el problema ahora es que cuando se cierra la aplicación, me sale el error no válido AV ... seguiré !!

EDIT 2: Ok, por lo que es TWinControl.DestroyWindowHandle que plantea la AV porque el identificador de ventana no existe más. Estoy tratando de pensar en una solución limpia.

Respuesta

9

Derive una nueva clase de TWinControl y anule su método virtual DestroyWindowHandle() para no liberar el HWND que usted proporciona. La implementación predeterminada de TWinControl.DestroyWindowHandle() llama a la función Win32 API DestroyWnd().

+0

¡Esa es una solución mucho más elegante que lo que estaba haciendo! ¡Perfecto, gracias! – ThievingSix

+0

+1 dulce como puede ser –

+0

+1. De acuerdo con David, ¡bien! –

Cuestiones relacionadas