如何判断一个 Delphi 控件当前是否可见?

daolsyd0  于 2023-10-18  发布在  其他
关注(0)|答案(3)|浏览(171)

我需要一个自定义控件(从TCustomControl继承而来)的方法来判断它当前是否可见。我说的不是有形财产我的意思是它是否真的在屏幕上显示。有人知道怎么做吗?

cyvaqqii

cyvaqqii1#

几年前,我在一个表单上遇到了同样的问题:我正在寻找一种方法来确定一个表单是否对用户实际可见(即使只是部分可见)。
特别是当它应该是可见的,显示是真的,但窗口实际上完全在另一个后面。
下面是代码,它可以适用于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;
hgtggwj0

hgtggwj02#

您可以将代码附加到OnPaint事件吗?这是非常经常调用,我认为只有当控件实际上要被绘制时才调用(例如,以您的意思可见)。

eqqqjvef

eqqqjvef3#

弗朗西丝卡的公认答案适用于大多数情况。但是,如果窗体移动到屏幕边界之外,则此方法无效。
以下是更好的答案:

function IsMyFormCovered(const MyForm: TForm): Boolean;
var
  RectForm, RectForeground: TRect;
  hWndForeground: HWND;
begin
  GetWindowRect(MyForm.Handle, RectForm);
  hWndForeground := GetForegroundWindow;
  if (hWndForeground <> MyForm.Handle) and (hWndForeground <> 0) then
  begin
    GetWindowRect(hWndForeground, RectForeground);
    if (RectForm.Left < RectForeground.Right) and
       (RectForm.Right > RectForeground.Left) and
       (RectForm.Top < RectForeground.Bottom) and
       (RectForm.Bottom > RectForeground.Top) then
      Result := True
    else
      Result := False;
  end else
    Result := False;
end;

相关问题