问题
Ok, so my previous question did not produce any useful answers, so I'll try to come from a different direction.
My application has, potentially, several windows. Given a point in screen coordinates, I need to find which window it "falls" onto - i.e. find the Window that is foremost of all windows containing said point.
If they were Visual
s inside one window, I would use VisualTreeHelper.HitTest
. But since they are different windows, it's not clear what to give as the first argument to that method.
回答1:
This is not possible using pure WPF, as WPF does not expose the Z Order of its windows. In fact, WPF works hard to maintain the illusion that windows never actually obscure one another.
If you're willing make Win32 calls, the solution is simple:
public Window FindWindowAt(Point screenPoint) // WPF units (96dpi), not device units
{
return (
from win in SortWindowsTopToBottom(Application.Current.Windows.OfType<Window>())
where new Rect(win.Left, win.Top, win.Width, win.Height).Contains(screenPoint)
select win
).FirstOrDefault();
}
public static IEnumerable<Window> SortWindowsTopToBottom(IEnumerable<Window> unsorted)
{
var byHandle = unsorted.ToDictionary(win =>
((HwndSource)PresentationSource.FromVisual(win)).Handle);
for(IntPtr hWnd = GetTopWindow(IntPtr.Zero); hWnd!=IntPtr.Zero; hWnd = GetWindow(hWnd, GW_HWNDNEXT))
if(byHandle.ContainsKey(hWnd))
yield return byHandle[hWnd];
}
const uint GW_HWNDNEXT = 2;
[DllImport("User32")] static extern IntPtr GetTopWindow(IntPtr hWnd);
[DllImport("User32")] static extern IntPtr GetWindow(IntPtr hWnd, uint wCmd);
If your windows may be transparent you should also use VisualTreeHelper.HitTest in the "where" clause of FindWindowAt().
来源:https://stackoverflow.com/questions/3473312/hittest-across-windows