2010-08-13 24 views
6

Ok, vì vậy, previous question của tôi không tạo ra bất kỳ câu trả lời hữu ích nào, vì vậy tôi sẽ cố gắng đi theo một hướng khác.HitTest trên Windows?

Ứng dụng của tôi có khả năng là một số cửa sổ. Với một điểm trong tọa độ màn hình, tôi cần phải tìm cửa sổ mà nó "rơi" vào - nghĩa là tìm Cửa sổ quan trọng nhất trong tất cả các cửa sổ có chứa điểm được nói.

Nếu chúng là Visual s bên trong một cửa sổ, tôi sẽ sử dụng VisualTreeHelper.HitTest. Nhưng vì chúng là các cửa sổ khác nhau, nên không rõ ràng những gì cần đưa ra làm đối số đầu tiên cho phương pháp đó.

Trả lời

7

Điều này là không thể sử dụng WPF tinh khiết, vì WPF không hiển thị thứ tự Z cửa sổ của nó. Trong thực tế, WPF làm việc chăm chỉ để duy trì ảo tưởng rằng các cửa sổ không bao giờ thực sự che khuất lẫn nhau.

Nếu bạn sẵn sàng làm cho Win32 gọi, giải pháp rất đơn giản:

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); 

Nếu cửa sổ của bạn có thể được minh bạch bạn cũng nên sử dụng VisualTreeHelper.HitTest trong "ở đâu" khoản của FindWindowAt().

+0

Cảm ơn bạn rất nhiều vì câu trả lời của bạn. Tôi sẽ chấp nhận nó, vì nó là câu trả lời duy nhất cho đến nay, và nó chắc chắn hoạt động, nếu chỉ bằng chi phí đòi hỏi Full Trust :-(Một câu hỏi vẫn còn, tuy nhiên: tại sao chính xác bạn có chắc chắn rằng WPF không cho phép điều này? –

+3

Bất kỳ ứng dụng Win32 nào cũng có thể thay đổi thứ tự Z bằng cách sử dụng SetWindowPos Có hai cách mà WPF có thể nhận được thông tin Z Order từ Win32: GetTopWindow/GetNextWindow như được hiển thị ở trên, hoặc bằng cách xử lý WM_WINDOWPOSCHANGED và lưu trữ trạng thái không có tham chiếu đến GetTopWindow trong các hội đồng WPF. Kiểm tra các đối tượng trong trình gỡ lỗi cho thấy rằng WPF không lưu trữ thông tin Z Order, WPF không thể cho bạn biết những gì nó không biết chính nó. –