gpt4 book ai didi

.net - 给定一个 hwnd,确定该窗口是否未被其他窗口隐藏(Z-Ordering)

转载 作者:行者123 更新时间:2023-12-04 23:42:16 31 4
gpt4 key购买 nike

我有一个 NativeWindow , 我已经覆盖了 WndProc处理函数 WM_WINDOWPOSCHANGING 移动我的窗口时的消息,我会将其粘贴到桌面中最近的窗口的边框上。

我遇到的问题是我的窗口停靠在其他顶部窗口的背景中的窗口上,例如,如果我打开了一个资源管理器窗口并且在资源管理器窗口下方有其他窗口,那么我的窗口可以停靠到那个窗口在另一个窗口的下方,这是一个低于资源管理器窗口的 z 顺序级别。我想避免这种情况。

问题的演示:

enter image description here

在上面的 GIF 中,有我的窗口 (Form1)、Visual Studio IDE 窗口、资源管理器窗口和名为“Hot Corners”的应用程序窗口。当我将“热角”窗口发送到背景时,我仍然可以将我的窗口粘附到“热角”边框上。我想避免这种情况。

注意捕获的 中的调试信息输出 Visual Studio 的窗口。

我在 上阅读了有关 Z-Ordering 的信息Wikipedia ,我也看到了 this 示例和 微软 文档 here here ,但是,我仍然不明白如何实现这一点。

当我尝试将我的窗口粘附到其他窗口时,我需要确定该目标窗口是否低于其他窗口,以避免我解释的问题。

我希望我能很好地解释这个问题并且清楚我需要什么,在我的窗口上方的 GIF 中不应该坚持“热角”窗口,因为它不可见,因为资源管理器窗口在上面。

这是相关代码,该方法将我的窗口(Form)作为参数, 的句柄WINDOWPOS 过滤 WM_WINDOWPOSCHANGING 时得到的结构WndProc 中的消息我的窗口的过程和最后一个参数 threshold , 是我的窗口到其他窗口的边界之间的最小空间来坚持它。

Protected Overridable Sub DockToNearestWindowBorder(ByVal window As IWin32Window,
ByVal windowPosHandle As IntPtr,
ByVal threshold As Integer)

Dim windowPos As WindowPos =
CType(Marshal.PtrToStructure(windowPosHandle, GetType(WindowPos)), WindowPos)

If (windowPos.Y = 0) OrElse (windowPos.X = 0) Then
' Nothing to do.
Exit Sub
End If

' Enumerate all the visible windows in the current desktop.
Dim desktopWindows As New List(Of IntPtr)()

Dim callBack As EnumWindowsProc =
Function(hwnd As IntPtr, lParam As IntPtr) As Boolean
If (NativeMethods.IsWindowVisible(hwnd)) Then
desktopWindows.Add(hwnd)
End If
Return True
End Function

If (NativeMethods.EnumDesktopWindows(IntPtr.Zero, callBack, IntPtr.Zero)) Then

' Window rectangles
Dim srcRect As Rectangle
Dim tgtRect As Rectangle

NativeMethods.GetWindowRect(window.Handle, srcRect)

For Each hwnd As IntPtr In desktopWindows

' This is just for testing purposes.
Dim pid As Integer
NativeMethods.GetWindowThreadProcessId(hwnd, pid)
If Process.GetProcessById(pid).ProcessName.EndsWith("vshost") Then
Continue For
End If

NativeMethods.GetWindowRect(hwnd, tgtRect)

' Right border of the source window
If ((windowPos.X + srcRect.Width) <= (tgtRect.Left + threshold)) AndAlso
((windowPos.X + srcRect.Width) >= (tgtRect.Left - threshold)) AndAlso
((windowPos.Y) <= (tgtRect.Y + tgtRect.Height)) AndAlso
((windowPos.Y + srcRect.Height) >= (tgtRect.Y)) Then

windowPos.X = (tgtRect.Left - srcRect.Width)
Console.WriteLine("Window adhered to: " & Process.GetProcessById(pid).ProcessName)

' This is not working as expected.
' If hwnd = NativeMethods.GetWindow(window.Handle, GetWindowCmd.HwndNext) Then
' windowPos.X = (tgtRect.Left - srcRect.Width)
' Exit For
' End If

End If

Next hwnd

End If

' Marshal it back.
Marshal.StructureToPtr(structure:=windowPos, ptr:=windowPosHandle, fDeleteOld:=True)

End Sub

请注意,在上面的代码中,我只显示了将窗口的右边框粘附到其他窗口的威胁,这是为了避免增加此问题的代码,以及丢失 P/Invokes 的相同原因。

最佳答案

给定一个窗口句柄,您应该能够使用一些 Win32 函数来确定该窗口是完全还是部分被其他窗口遮挡:

  • 调用 GetWindowDC()检索包含整个窗口的设备上下文句柄(HDC),包括非客户区(例如,标题栏、菜单、边框等)
  • 调用 GetClipBox()HDC上面返回。这将返回实际可见的最小边界矩形(即在屏幕上且未被其他窗口覆盖)。此外,返回值可以告诉您窗口是否完全被遮挡( NULLREGION )。
  • 别忘了调用ReleaseDC() .

  • API引用:
    https://msdn.microsoft.com/en-us/library/dd144865%28v=vs.85%29.aspx

    关于.net - 给定一个 hwnd,确定该窗口是否未被其他窗口隐藏(Z-Ordering),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34025833/

    31 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com