delphicustom-controlsvisiblepaint

How can I tell if a Delphi control is currently visible?


I need a way to for a custom control (descended from TCustomControl) to tell if it is currently visible. I'm not talking about the .Visible property; I mean whether or not it's actually being displayed on-screen at the moment. Does anyone know how to do this?


Solution

  • A few years back I had the same kind of problem for a Form: I was looking for a way to determine if a Form is actually visible (even only partially) to the user.
    In particular when it was supposed to be visible and Showing was True but the window was actually entirely behind another one.
    Here's the code, it could be adapted for a 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;