Windows上的HitTest?

Fyo*_*kin 7 wpf hittest

好的,所以我之前的问题没有产生任何有用的答案,所以我会尝试从不同的方向来.

我的应用程序可能有几个窗口.给定屏幕坐标中的一个点,我需要找到它"落入"哪个窗口 - 即找到包含所述点的所有窗口中最重要的窗口.

如果他们Visual在一个窗口内,我会用VisualTreeHelper.HitTest.但由于它们是不同的窗口,因此不清楚该方法的第一个参数是什么.

Ray*_*rns 8

使用纯WPF是不可能的,因为WPF不会公开其窗口的Z顺序.事实上,WPF努力维护窗户从未真正模糊对方的错觉.

如果您愿意进行Win32调用,解决方案很简单:

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); 
Run Code Online (Sandbox Code Playgroud)

如果您的窗口可能是透明的,您还应该在FindWindowAt()的"where"子句中使用VisualTreeHelper.HitTest.

  • 任何Win32应用程序都可以使用SetWindowPos更改Z Order.WPF可以通过两种方式从Win32接收此Z Order信息:GetTopWindow/GetNextWindow,如上所示,或者通过处理WM_WINDOWPOSCHANGED和存储状态.WPF程序集中没有对GetTopWindow的引用.检查调试器中的对象显示WPF也不存储Z Order信息.WPF无法告诉你它不知道自己的意义. (3认同)