2011-11-11 18 views
9

Alcuni di fondo (una specie di continuazione di TLabel and TGroupbox Captions Flicker on Resize):Aggiunta finestra non VCL in coda VCL align

  • Così, Ho un'applicazione che carica diversi plugin e crea una nuova scheda su un TPageControl per ognuno.
  • Ad ogni DLL è associato un TForm.
  • I moduli vengono creati con il genitore hWnd come nuovo TTabSheet. Poiché il TTabSheets non è un genitore del modulo fino a VCL è interessato (non ha voluto utilizzare RTL dinamico e plugin creati in altre lingue) Devo gestire le ridimensionamenti manualmente.

ho solo sembrano essere in esecuzione in un sacco di nuove emissioni (ma grandi esperienze di apprendimento) per questo tipo "plug-in" di applicazione.

Quindi, il mio attuale problema è cercare di avere un plug-in che non viene inserito in un TTabSheet ma verrà ridimensionato e allineato direttamente sul modulo.

Dal momento che questo sarebbe stato più facile da spiegare con un'immagine: Visual representation of question Ora potrebbe fare manualmente l'allineamento e il ridimensionamento, ma mi piacerebbe molto meglio che le procedure di allineamento VCL (alClient, ALTOP, ecc) fallo per me. In questo modo dovrei semplicemente impostare l'allineamento dei plugin sulla sua forma senza pensare.

Dopo aver esaminato la sorgente VCL, ho iniziato a scorrere il codice di allineamento e come è chiamato. Fondamentalmente, quando un TControl ottiene un WM_RESIZE lo farà:

  1. chiamata Riallinea(), che chiama AlignControl()
  2. AlignControl() otterrà il rect cliente e chiamare AlignControls()
  3. AlignControls() chiamerà DoAlign() per ciascun tipo TAlignment in questo ordine: ALTOP, alBottom, alLeft, va bene, alClient, alCustom, alNone
  4. DoAlign() loop attraverso FControls e FWinControls (che sono TLists) e li allineare appropriatamente

Quindi il mio processo di pensiero è che se creo un nuovo TWinControl, impostiamo il suo handle sul modulo dei plugin (finestra) e lo inserisco nell'elenco di FControls con l'allineamento corretto che dovrebbe svolgere il mio lavoro per me.

Ovviamente sono qui, quindi ha fallito miseramente. Ottengo anche un AV quando si esce dall'applicazione su un handle di finestra non valido. La mia ipotesi è che il TWinControl che ho creato stia cercando di liberare l'handle del modulo plugin (finestra) che non esiste più.

Quello che ho provato:

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, pensieri?

EDIT 1:

Ok, quindi questo aggiunge correttamente il controllo alla lista e si conforma il set TAlign (perché è che trascorro 8 ore cercando di capire qualcosa, ho posto qui, e allora la risposta appare solo ... vabbè che qualcuno potrebbe trovare questa domanda e le mie divagazioni utile):

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; 

il problema ora è che quando l'applicazione si chiude, ottengo l'errore non valida AV ... continuerò !!

EDIT 2: Ok, quindi è TWinControl.DestroyWindowHandle che solleva l'AV perché l'handle della finestra non esiste più. Sto cercando di pensare a una soluzione pulita.

risposta

9

Ricavare una nuova classe da TWinControl e sovrascrivere il metodo virtuale DestroyWindowHandle() per non liberare lo HWND fornito. L'implementazione predefinita di TWinControl.DestroyWindowHandle() chiama la funzione Win32 API DestroyWnd().

+0

Questa è una soluzione molto più elegante di quello che stavo facendo! Perfetto, grazie! – ThievingSix

+0

+1 dolce come può essere –

+0

+1. D'accordo con David - bello! –

Problemi correlati