2009-03-14 33 views
8

Necesito una forma de para un control personalizado (desciende de TCustomControl) para decir si está actualmente visible. No estoy hablando de la propiedad .Visible; Quiero decir si realmente se muestra o no en pantalla en este momento. ¿Alguien sabe como hacer esto?¿Cómo puedo saber si un control Delphi está actualmente visible?

+0

¿Quieres decir si es o no está cubierta por otra ventana? –

+0

Quiero decir si se está o no atrayendo a la pantalla. Estar cubierto podría ser una razón. Otro podría ser si se ha colocado en un formulario que se ha creado pero que aún no se muestra. –

Respuesta

15

Hace unos años tuve el mismo tipo de problema para un Formulario: estaba buscando una forma de determinar si un Formulario es realmente visible (aunque sea solo parcialmente) para el usuario.
En particular, cuando se suponía que era visible y Mostrar era verdadero, pero la ventana estaba completamente detrás de otra.
Aquí está el código, podría ser adaptado para una 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

¡Gracias! Eso es precisamente lo que estaba buscando. –

2

¿Podría adjuntar código al evento OnPaint? Esto se llama con mucha frecuencia y creo que solo se usa cuando el control va a pintarse (por ejemplo, es visible en la forma en que te refieres).

+0

Me gustaría ir con esto como un mejor indicador. Nunca se puede estar seguro porque en Vista todas las aplicaciones se dibujan en un mapa de bits fuera de la pantalla que luego se compone en la tarjeta gráfica con las superposiciones, etc. – mj2008

+0

Pero presumiblemente solo se saca de la pantalla si se va a mostrar en pantalla en este momento ? –

+1

No creo que sea seguro suponer que WM_PAINT solo vendrá cuando esos píxeles estén a punto de tocar la pantalla. Con Desktop Composition (http://msdn.microsoft.com/en-us/library/aa969540%28VS.85%29.aspx), Windows mantiene un caché de ventanas dibujadas para efectos como Windows Flip (http: // www. microsoft.com/windows/windows-vista/features/flip-3d.aspx) que pueden requerir * todas * ventanas a la vez. Debido a esto, espero que haya algunas actualizaciones de caché de fondo. –

1

Creo que esto es para lo que TWinControl.Showing es. No estoy seguro de qué tan confiable es.

+1

No funciona para un formulario, por ejemplo. Un formulario puede estar completamente detrás de otro y aún así mostrarse verdadero. –

+0

Como dije, no tenía idea de lo completo que era. –

+2

Mostrar solo le indica si todos los controles principales están visibles. Diferencia algunas situaciones en modo de diseño, donde f.e. los componentes no visibles son visibles. Entonces le dice si el componente si se muestra en este momento sería visible. –

Cuestiones relacionadas