是否有可能检测到我以外的程序窗口是否完全可见,2)部分隐藏,或3)完全隐藏?如果窗口(基于检索到的句柄)不可见,我希望能够告诉我的应用程序不要做任何事情。我不关心窗口是否有焦点,z顺序是什么,或者其他什么,我只是对窗口显示的内容感兴趣。如果我需要别的东西来解决这个问题,我很好,但有可能吗?感谢。
答案 0 :(得分:6)
Raymond Chen几年前写过an article about this。
它的要点是你可以使用GetClipBox
来告诉你窗口的设备上下文有哪种裁剪区域。空区域意味着窗口完全被遮挡,复杂区域意味着它被部分遮挡。如果它是一个简单的(矩形)区域,那么可见性取决于可见矩形是否与窗口的边界重合。
DC一次只能由一个线程使用。因此,您不应为不属于您的应用程序获取窗口的DC。否则,您可能会遇到另一个应用程序 - 不知道您正在做什么 - 在您仍在使用它来检查剪切区域时尝试使用其DC的情况。不过,使用它来判断你自己的窗口应该是完全安全的。
答案 1 :(得分:4)
这是我用来确定表单是否实际可见(甚至只是部分)给用户的解决方案。您可以轻松适应您的确切用例。
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;