如何检查窗口是否重叠?
我发现这个WinForms代码可以解决这个问题:
public static bool IsOverlapped(IWin32Window window)
{
if (window == null)
throw new ArgumentNullException("window");
if (window.Handle == IntPtr.Zero)
throw new InvalidOperationException("Window does not yet exist");
if (!IsWindowVisible(window.Handle))
return false;
IntPtr hWnd = window.Handle;
HashSet<IntPtr> visited = new HashSet<IntPtr> { hWnd };
// The set is used to make calling GetWindow in a loop stable by checking if we have already
// visited the window returned by GetWindow. This avoids the possibility of an infinate loop.
RECT thisRect;
GetWindowRect(hWnd, out thisRect);
while ((hWnd = GetWindow(hWnd, GW_HWNDPREV)) != IntPtr.Zero && !visited.Contains(hWnd))
{
visited.Add(hWnd);
RECT testRect, intersection;
if (IsWindowVisible(hWnd) && GetWindowRect(hWnd, out testRect) && IntersectRect(out intersection, ref thisRect, ref testRect))
return true;
}
return false;
}
[DllImport("user32.dll")]
private static extern IntPtr GetWindow(IntPtr hWnd, int uCmd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetWindowRect(IntPtr hWnd, [Out] out RECT lpRect);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool IntersectRect([Out] out RECT lprcDst, [In] ref RECT lprcSrc1, [In] ref RECT lprcSrc2);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool IsWindowVisible(IntPtr hWnd);
private const int GW_HWNDPREV = 3;
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
但我不确定如何让它在WPF上运行,有人可以帮助我吗? 我已经尝试了很多东西..
答案 0 :(得分:1)
如果要获取给定WPF窗口的句柄,可以使用System.Windows.Interop.WindowInteropHelper
类。对IsOverlapped
的更新将允许您与WinForms代码进行交互:
public static bool IsOverlapped(Window window)
{
if (window == null)
throw new ArgumentNullException("window");
var hWnd = new WindowInteropHelper(window).Handle;
if (hWnd == IntPtr.Zero)
throw new InvalidOperationException("Window does not yet exist");
if (!IsWindowVisible(hWnd))
return false;
HashSet<IntPtr> visited = new HashSet<IntPtr> { hWnd };
// The set is used to make calling GetWindow in a loop stable by checking if we have already
// visited the window returned by GetWindow. This avoids the possibility of an infinate loop.
RECT thisRect;
GetWindowRect(hWnd, out thisRect);
while ((hWnd = GetWindow(hWnd, GW_HWNDPREV)) != IntPtr.Zero && !visited.Contains(hWnd))
{
visited.Add(hWnd);
RECT testRect, intersection;
if (IsWindowVisible(hWnd) && GetWindowRect(hWnd, out testRect) && IntersectRect(out intersection, ref thisRect, ref testRect))
return true;
}
return false;
}
答案 1 :(得分:1)
我这样解决了:
<div>
答案 2 :(得分:0)
public static bool IsOverlappedElement(FrameworkElement element)
{
var hwndYourWindow = ((HwndSource)PresentationSource.FromVisual(Window.GetWindow(element))).Handle;
var controlRect = GetAbsolutePlacement(element);
var overlappingWindows = GetOverlappingWindowsRectangle(WindowsListFactory.Load(), hwndYourWindow, controlRect).ToList();
return overlappingWindows.Any();
}
GetOverlappingWindowsRectangle方法输入:
WindowsListFactory.Load()返回所有相关的活动Windows数据 (以下github存储库包含此功能... click here。)
hwndYourWindow 是包含UI元素的窗口。
下面的函数将返回(实际)与您的视觉元素(或窗口)重叠的窗口。
private IEnumerable<WindowEntry> GetOverlappingWindowsRectangle(IEnumerable<WindowEntry> filteredWindows, IntPtr interrupterHwnd, Rect displayedControl)
{
const uint GW_HWNDNEXT = 2;
var byHandle = filteredWindows.ToDictionary(win => win.HWnd);
for (IntPtr hWnd = GetTopWindow(IntPtr.Zero); hWnd != IntPtr.Zero; hWnd = GetWindow(hWnd, GW_HWNDNEXT))
{
if (interrupterHwnd == hWnd) break;
if (byHandle.ContainsKey(hWnd) == false) continue;
var result = GetWindowRect(new HandleRef(this, hWnd), out RECT rect);
if (result == false) continue;
byHandle[hWnd].Frame = CreateRectangle(rect);
if (displayedControl.IntersectsWith(byHandle[hWnd].Frame) == false) continue;
yield return byHandle[hWnd];
}
}
//Helper methods:
private Rect CreateRectangle(RECT rect)
{
var rectangle = new Rect();
rectangle.X = rect.Left;
rectangle.Y = rect.Top;
rectangle.Width = rect.Right - rect.Left + 1;
rectangle.Height = rect.Bottom - rect.Top + 1;
return rectangle;
}
private Rect GetAbsolutePlacement(FrameworkElement element, bool relativeToScreen = false)
{
var absolutePos = element.PointToScreen(new System.Windows.Point(0, 0));
if (relativeToScreen)
{
return new Rect(absolutePos.X, absolutePos.Y, element.ActualWidth, element.ActualHeight);
}
var posMW = Application.Current.MainWindow.PointToScreen(new System.Windows.Point(0, 0));
absolutePos = new System.Windows.Point(absolutePos.X - posMW.X, absolutePos.Y - posMW.Y);
return new Rect(absolutePos.X, absolutePos.Y, element.ActualWidth, element.ActualHeight);
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetWindowRect(HandleRef hWnd, out RECT lpRect);
[DllImport("user32.dll")]
private static extern IntPtr GetTopWindow(IntPtr hWnd);
[DllImport("User32")]
private static extern IntPtr GetWindow(IntPtr hWnd, uint wCmd);