开发者

HitTest across Windows?

Ok, so my previous question did not produce any useful answers, so I'll try t开发者_如何学Goo 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 Visuals 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.


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().

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜