2010-08-13 11 views
6

ठीक है, तो मेरा previous question कोई उपयोगी उत्तर नहीं मिला, इसलिए मैं एक अलग दिशा से आने की कोशिश करूंगा।विंडोज़ में हिटटेस्ट?

मेरे आवेदन में, संभावित रूप से, कई खिड़कियां हैं। स्क्रीन निर्देशांक में एक बिंदु को देखते हुए, मुझे यह पता लगाने की ज़रूरत है कि यह कौन सी खिड़की "गिरती है" - यानी खिड़की को ढूंढें जो कि सभी बिंदुओं में सबसे महत्वपूर्ण विंडो है।

यदि वे एक खिड़की के अंदर Visual एस थे, तो मैं VisualTreeHelper.HitTest का उपयोग करूंगा। लेकिन चूंकि वे अलग-अलग खिड़कियां हैं, इसलिए यह स्पष्ट नहीं है कि उस विधि के पहले तर्क के रूप में क्या देना है।

उत्तर

7

शुद्ध 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); 

अपने विंडोज़ पारदर्शी आप भी FindWindowAt की "कहाँ" खंड में VisualTreeHelper.HitTest का उपयोग करना चाहिए हो सकता है()।

+0

आपके उत्तर के लिए बहुत बहुत धन्यवाद। मैं इसे स्वीकार करूंगा, क्योंकि यह अब तक का एकमात्र उत्तर है, और यह निश्चित रूप से काम करता है, अगर केवल पूर्ण ट्रस्ट की आवश्यकता के खर्च पर :-(एक सवाल बनी हुई है, हालांकि: आप वास्तव में क्यों सुनिश्चित हैं कि डब्ल्यूपीएफ इस अनुमति की अनुमति नहीं देता है? –

+3

कोई भी Win32 एप्लिकेशन SetWindowPos का उपयोग कर जेड ऑर्डर बदल सकता है। WPF से यह Z ऑर्डर जानकारी प्राप्त करने के दो तरीके हैं: GetTopWindow/GetNextWindow जैसा ऊपर दिखाया गया है, या WM_WINDOWPOSCHANGED और भंडारण स्थिति को संभालने के द्वारा। WPF असेंबली में GetTopWindow के कोई संदर्भ नहीं हैं। डीबगर में ऑब्जेक्ट्स का निरीक्षण करने से पता चलता है कि डब्ल्यूपीएफ जेड ऑर्डर की जानकारी को स्टोर नहीं करता है। डब्ल्यूपीएफ आपको यह नहीं बता सकता कि वह खुद को क्या नहीं जानता है। –