2009-03-14 13 views
8

Ho bisogno di un modo per un controllo personalizzato (discendente da TCustomControl) per dire se è attualmente visibile. Non sto parlando della proprietà .Visible; Intendo dire se è effettivamente visualizzato sullo schermo al momento. Qualcuno sa come fare questo?Come posso sapere se un controllo Delphi è attualmente visibile?

+0

Vuoi dire se sia o non è coperta da un'altra finestra? –

+0

Voglio dire se si sta disegnando o meno sullo schermo. Essere coperti potrebbe essere una delle ragioni. Un altro potrebbe essere se è stato inserito in un modulo che è stato creato ma non ancora mostrato. –

risposta

15

Alcuni anni fa ho avuto lo stesso tipo di problema per un modulo: stavo cercando un modo per determinare se un modulo è effettivamente visibile (anche solo parzialmente) all'utente.
In particolare quando doveva essere visibile e Mostrare era Vero ma la finestra era in realtà interamente dietro a un'altra.
Ecco il codice, potrebbe essere adattato per un WinControl ...

{----------------------------------------------------------} 
function IsMyFormCovered(const MyForm: TForm): Boolean; 
var 
    MyRect: TRect; 
    MyRgn, TempRgn: HRGN; 
    RType: Integer; 
    hw: HWND; 
begin 
    MyRect := MyForm.BoundsRect;   // screen coordinates 
    MyRgn := CreateRectRgnIndirect(MyRect); // MyForm not overlapped region 
    hw := GetTopWindow(0);     // currently examined topwindow 
    RType := SIMPLEREGION;     // MyRgn type 

// From topmost window downto MyForm, build the not overlapped portion of MyForm 
    while (hw<>0) and (hw <> MyForm.handle) and (RType <> NULLREGION) do 
    begin 
    // nothing to do if hidden window 
    if IsWindowVisible(hw) then 
    begin 
     GetWindowRect(hw, MyRect); 
     TempRgn := CreateRectRgnIndirect(MyRect);// currently examined window region 
     RType := CombineRgn(MyRgn, MyRgn, TempRgn, RGN_DIFF); // diff intersect 
     DeleteObject(TempRgn); 
    end; {if} 
    if RType <> NULLREGION then // there's a remaining portion 
     hw := GetNextWindow(hw, GW_HWNDNEXT); 
    end; {while} 

    DeleteObject(MyRgn); 
    Result := RType = NULLREGION; 
end; 

function IsMyFormVisible(const MyForm : TForm): Boolean; 
begin 
    Result:= MyForm.visible and 
      isWindowVisible(MyForm.Handle) and 
      not IsMyFormCovered(MyForm); 
end; 
+0

Grazie! Questo è esattamente quello che stavo cercando. –

2

È possibile allegare il codice all'evento OnPaint? Questo è chiamato molto spesso e penso che venga chiamato solo quando il controllo verrà effettivamente dipinto (ad es. È visibile nel modo in cui intendi).

+0

Direi che questo è un indicatore migliore. Non si può mai essere sicuri, perché in Vista tutte le app si disegnano su una bitmap fuori campo che viene poi composta nella scheda grafica con le sovrapposizioni ecc. – mj2008

+0

Ma presumibilmente è ancora disegnata solo se sarà mostrata sullo schermo al momento ? –

+1

Non penso che sia sicuro presumere che WM_PAINT arriverà solo quando quei pixel stanno per colpire lo schermo. Con Desktop Composition (http://msdn.microsoft.com/en-us/library/aa969540%28VS.85%29.aspx), Windows mantiene una cache di finestre disegnate per effetti come Windows Flip (http: // www. microsoft.com/windows/windows-vista/features/flip-3d.aspx) che potrebbe richiedere * tutte * le finestre contemporaneamente. Per questo motivo, mi aspetto che ci possa essere qualche aggiornamento in background della cache. –

1

Penso che questo sia ciò per cui TWinControl.Showing è. Non sono sicuro di quanto sia affidabile.

+1

Non funziona per un modulo, per esempio. Un modulo può essere completamente dietro a un altro e continuare a mostrare il vero. –

+0

Come ho detto, non avevo idea di quanto fosse approfondito. –

+2

Mostra solo indica se tutti i controlli padre sono visibili. Differenzia alcune situazioni in modalità progettazione, dove f.e. i componenti non visibili sono visibili. Quindi ti dice se il componente se mostrato al momento sarebbe visibile. –

Problemi correlati