HitTest через Windows? - PullRequest
       11

HitTest через Windows?

7 голосов
/ 13 августа 2010

Хорошо, поэтому мой предыдущий вопрос не дал никаких полезных ответов, поэтому я попытаюсь прийти в другом направлении.

У моего приложения есть несколько окон.Учитывая точку в экранных координатах, мне нужно найти, в какое окно она «падает», то есть найти окно, которое является главным из всех окон, содержащих указанную точку.Я бы использовал VisualTreeHelper.HitTest.Но поскольку они являются разными окнами, неясно, что следует указывать в качестве первого аргумента этого метода.

1 Ответ

8 голосов
/ 13 августа 2010

Это невозможно при использовании чистого 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); 

Если ваши окна могут быть прозрачными, вам также следует использовать VisualTreeHelper.HitTest в предложении "where" функции FindWindowAt ().

...