2010-07-06 23 views
39

(सभी मतलब प्रासंगिक प्रौद्योगिकी के साथ फिर से टैग कर: मैं कौन सा वे कर रहे हैं :)विंडोज़: सभी दृश्यमान विंडो की सूची कैसे प्राप्त करें?

मैं शायद और अधिक विस्तृत सवाल, के बारे में विशिष्ट विवरण के साथ बाद में आते हैं, लेकिन जाएगा पता नहीं है अब के लिए मैं मैं "बड़ी तस्वीर" को समझने की कोशिश कर रहा हूं: मैं विंडोज़ पर "वास्तविक दृश्य विंडो" को गिनने का एक तरीका ढूंढ रहा हूं। "वास्तविक दृश्य विंडो" से मेरा मतलब है कि: उपयोगकर्ता "विंडो" कहलाएगा। मुझे ज़ेड-ऑर्डर में इन सभी दृश्यमान विंडो की सूची प्राप्त करने का एक तरीका चाहिए।

ध्यान दें कि मैं वास्तव में ऐसा करने की आवश्यकता है। मैंने इसे ओएस एक्स पर पहले ही कर लिया है (जहां यह एक असली सिरदर्द है, खासकर यदि आप ओएस एक्स 10.4 का समर्थन करना चाहते हैं, क्योंकि ओएस एक्स में सुविधाजनक विंडोज एपीआई नहीं है) और अब मुझे इसे विंडोज के तहत करना है।

यहाँ एक उदाहरण है, मान लीजिए वहाँ इस तरह स्क्रीन पर तीन दिखाई खिड़कियां हैं,: फिर अगर

windows B is at (210,40) 
windows A is at (120,20) 
windows C is at (0,0) 

:

+------------------------------------------+ 
|           | 
|   +=============+    | 
|   |    |    | 
|   | A +--------------------------+ 
|   |  |       | 
| C  |  |    B   | 
|   |  +--------------------------+ 
|   |    |    | 
+-----------|    |----------------+ 
      |    | 
      +-------------+ 

तब मैं इस प्रकार की सूची वापस प्राप्त करने की आवश्यकता उपयोगकर्ता (या ओएस) विंडो ए को सामने लाता है, यह बन जाता है:

+------------------------------------------+ 
|           | 
|   +=============+    | 
|   |    |    | 
|   | A  |---------------------+ 
|   |    |      | 
| C  |    |  B   | 
|   |    |---------------------+ 
|   |    |    | 
+-----------|    |----------------+ 
      |    | 
      +-------------+ 

और मैं मिल (आदर्श) एक कॉलबैक मुझे दे रही है यह:

windows A is at (120,20) 
windows B is at (210,40) 
windows C is at (0,0) 

ओएस एक्स के तहत ऐसा करने से आश्चर्यजनक अजीब हैक्स के उपयोग की आवश्यकता (चालू करने के लिए उपयोगकर्ता की अनिवार्यता की तरह "सहायक उपकरण के लिए पहुँच सक्षम करें"!), लेकिन मैं इसे ओएस एक्स के तहत किया गया है और यह काम करता है (ओएस एक्स के तहत, जब भी कुछ खिड़की में परिवर्तन होता है तो मैं कॉलबैक प्राप्त नहीं करता था, इसलिए मैं मतदान कर रहा हूं, लेकिन मुझे इसे काम करने के लिए मिला)।

अब मैं Windows के तहत ऐसा करना चाहते हैं (मैं वास्तव में इसके बारे में, कोई सवाल ही नहीं करते हैं) और मैं कुछ सवाल है:

  • यह किया जा सकता है?

  • क्या अच्छी तरह से विंडोज एपीआई दस्तावेज (और उनके चश्मा के अनुसार काम कर रहे हैं) ऐसा करने की इजाजत दे रहे हैं?

  • क्या हर बार एक विंडो में बदलाव करने के लिए कॉलबैक पंजीकृत करना आसान है? (यदि इसका आकार बदल दिया गया है, स्थानांतरित किया गया है, वापस/सामने लाया गया है या यदि कोई नई विंडो पॉप-अप, आदि)

  • गॉर्च क्या होगा?

मैं जानता हूँ कि इस सवाल का जिसके कारण मैं के रूप में स्पष्ट रूप से संभव के रूप में मेरी समस्या का वर्णन करने के (अच्छा ASCII आर्ट जिसके लिए आप इस वोट दें सकता सहित) की कोशिश की है, विशिष्ट नहीं है: अब मैं कम से देख रहा हूँ के लिए बड़ी तस्वीर"। मैं जानना चाहता हूं कि विंडोज़ के तहत ऐसी चीज क्या कर रही है।

बोनस प्रश्न: कल्पना करें कि आपको एक छोटे से लिखने की आवश्यकता होगी। EXE स्क्रीन पर विंडो बदलने पर हर बार विंडोज़ नाम/स्थिति/आकार को अस्थायी फ़ाइल में लिखना होगा, इस तरह का कोई प्रोग्राम आपके पास कितना समय लगेगा पसंद की भाषा और आपको इसे कब लिखना होगा?

+0

कोई नहीं? पहले से ही +1 अपवॉट और 1 पसंदीदा ... :) – NoozNooz42

+0

ठीक है, मुझे लगता है कि आप ZW ऑर्डर में सभी विंडो को गिनाने के लिए FindWindowEx से शुरू करेंगे और फिर विंडो शैली प्राप्त करने के लिए GetWindowLong का उपयोग करें। जाहिर है आप केवल WS_VISIBLE के साथ खिड़कियों पर विचार करेंगे, और शायद WS_CAPTION या कुछ। – Luke

+0

क्या नेट फ्रेमवर्क एक विकल्प है? मेरे पास इसके लिए एक आसान समाधान है, दस सेकंड की तरह लगता है। ASCII कला के लिए – Cyclone

उत्तर

23

उच्च-स्तरीय खिड़कियों की गणना करने के लिए, आप के बाद से EnumWindows एक सुसंगत दृश्य देता है, बल्कि GetTopWindow/GetNextWindow से EnumWindows उपयोग करना चाहिए:

इसके अलावा निम्नलिखित लायक जाँच हो सकता है खिड़की की स्थिति का। जब आप पुनरावृत्ति के दौरान जेड-ऑर्डर बदलते हैं, तो आप GetTopWindow/GetNextWindow का उपयोग करते हुए असंगत जानकारी (जैसे हटाए गए विंडोज़ पर रिपोर्टिंग) या अनंत लूप प्राप्त करने का जोखिम लेते हैं।

EnumWindows कॉलबैक का उपयोग करता है। कॉलबैक के प्रत्येक कॉल पर आपको एक विंडो हैंडल मिलता है। विंडो के स्क्रीन समन्वय को GetWindowRect पर उस हैंडल को पास करके लाया जा सकता है। आपका कॉलबैक जेड-ऑर्डर में विंडो की स्थिति की एक सूची बनाता है।

आप मतदान का उपयोग कर सकते हैं, और बार-बार विंडो सूची बना सकते हैं। या, आपने विंडो परिवर्तनों की अधिसूचनाएं प्राप्त करने के लिए सीबीटीयूक सेट अप किया है। सभी सीबीटी अधिसूचनाओं के परिणामस्वरूप शीर्ष स्तर की खिड़कियों के क्रम, स्थिति या दृश्यता में परिवर्तन नहीं होंगे, इसलिए एनएमविंडोज को ज़ेड-ऑर्डर में विंडो पोजिशन की एक नई सूची बनाने के लिए पुन: चालू करना और सूची को आगे संसाधित करने से पहले पिछली सूची में इसकी तुलना करना, ताकि भविष्य में एक वास्तविक परिवर्तन होने पर भविष्य में प्रसंस्करण किया जा सके।

ध्यान दें कि हुकिंग के साथ, आप 32- और 64-बिट मिश्रण नहीं कर सकते हैं। यदि आप 32-बिट ऐप चला रहे हैं, तो आपको 32-बिट प्रक्रियाओं से अधिसूचनाएं मिलेंगी। इसी प्रकार 64-बिट के लिए। इस प्रकार, यदि आप 64-बिट मशीन पर पूरी प्रणाली की निगरानी करना चाहते हैं, तो ऐसा लगता है कि दो ऐप्स चलाने के लिए आवश्यक है। मेरा तर्क यह पढ़ने से आता है:

SetWindowsHookEx को एक अन्य प्रक्रिया में डीएलएल इंजेक्ट करने के लिए उपयोग किया जा सकता है। 32-बिट डीएलएल को 64-बिट प्रक्रिया में इंजेक्शन नहीं दिया जा सकता है, और 64-बिट DLL 32-बिट प्रक्रिया में इंजेक्शन नहीं किया जा सकता है। एक आवेदन अन्य प्रक्रियाओं में हुक के उपयोग की आवश्यकता है, यह आवश्यक है है कि एक 32-बिट अनुप्रयोग कॉल SetWindowsHookEx 32-बिट प्रक्रियाओं में एक 32-बिट DLL सुई, और एक 64-बिट आवेदन कॉल SetWindowsHookEx 64-बिट DLL को 64-बिट प्रक्रियाओं में इंजेक्ट करने के लिए। 32-बिट और 64-बिट DLL के पास नाम अलग-अलग होना चाहिए। (। SetWindowsHookEx API पृष्ठ से)

आप जावा में इस लागू कर रहे हैं के रूप में, आप JNA को देखने के लिए चाहते हो सकता है - यह देशी पुस्तकालयों बहुत सरल (जावा में कोड बुला) के लिए उपयोग लेखन बनाता है और निकालता है अपने मूल जेएनआई डीएलएल की आवश्यकता है।

संपादित करें: आपने पूछा कि यह कितना कोड है और कितना समय लिखना है। यहाँ जावा

import com.sun.jna.Native; 
import com.sun.jna.Structure; 
import com.sun.jna.win32.StdCallLibrary; 

import java.util.ArrayList; 
import java.util.Collections; 
import java.util.Comparator; 
import java.util.List; 

public class Main 
{ 
public static void main(String[] args) { 
    Main m = new Main(); 
    final List<WindowInfo> inflList = new ArrayList<WindowInfo>(); 
    final List<Integer> order = new ArrayList<Integer>(); 
    int top = User32.instance.GetTopWindow(0); 
    while (top!=0) { 
     order.add(top); 
     top = User32.instance.GetWindow(top, User32.GW_HWNDNEXT); 
    } 
    User32.instance.EnumWindows(new WndEnumProc() 
    { 
     public boolean callback(int hWnd, int lParam) 
     { 
     if (User32.instance.IsWindowVisible(hWnd)) { 
      RECT r = new RECT(); 
      User32.instance.GetWindowRect(hWnd, r); 
      if (r.left>-32000) {  // minimized 
       byte[] buffer = new byte[1024]; 
       User32.instance.GetWindowTextA(hWnd, buffer, buffer.length); 
       String title = Native.toString(buffer); 
       inflList.add(new WindowInfo(hWnd, r, title)); 
      } 
     } 
     return true; 
    } 
    }, 0); 
    Collections.sort(inflList, new Comparator<WindowInfo>() 
    { 
     public int compare(WindowInfo o1, WindowInfo o2) { 
      return order.indexOf(o1.hwnd)-order.indexOf(o2.hwnd); 
     } 
    }); 
    for (WindowInfo w : inflList) { 
    System.out.println(w); 
    } 
} 

    public static interface WndEnumProc extends StdCallLibrary.StdCallCallback { 
     boolean callback (int hWnd, int lParam); 
    } 

    public static interface User32 extends StdCallLibrary 
    { 
     final User32 instance = (User32) Native.loadLibrary ("user32", User32.class); 
     boolean EnumWindows (WndEnumProc wndenumproc, int lParam); 
     boolean IsWindowVisible(int hWnd); 
     int GetWindowRect(int hWnd, RECT r); 
     void GetWindowTextA(int hWnd, byte[] buffer, int buflen); 
     int GetTopWindow(int hWnd); 
     int GetWindow(int hWnd, int flag); 
     final int GW_HWNDNEXT = 2; 
    } 

    public static class RECT extends Structure { 
     public int left,top,right,bottom; 
    } 
    public static class WindowInfo { 
     int hwnd; 
     RECT rect; 
     String title; 
     public WindowInfo(int hwnd, RECT rect, String title) 
     { this.hwnd = hwnd; this.rect = rect; this.title = title; } 

     public String toString() { 
      return String.format("(%d,%d)-(%d,%d) : \"%s\"", 
       rect.left,rect.top,rect.right,rect.bottom,title); 
     } 
    } 
} 

मैं उदाहरण के कॉम्पैक्ट और तत्काल संकलन के लिए pasteable रखने के लिए संबंधित वर्गों और इंटरफेस इनर क्लासों सबसे बनाया है में कोड है। एक वास्तविक कार्यान्वयन में, वे नियमित रूप से शीर्ष-स्तरीय कक्षाएं होंगी। कमांड लाइन ऐप दृश्यमान विंडो और उनकी स्थिति को प्रिंट करता है। मैंने इसे 32-बिट जेवीएम और 64-बिट दोनों पर चलाया, और प्रत्येक के लिए एक ही परिणाम मिला।

EDIT2: जेड-ऑर्डर को शामिल करने के लिए अद्यतन कोड। यह GetNextWindow का उपयोग करता है।एक उत्पादन अनुप्रयोग में, आपको शायद अगले और पिछले मानों के लिए GetNextWindow को दो बार कॉल करना चाहिए और जांचें कि वे लगातार हैं और वैध विंडो हैंडल हैं।

+0

बस यह सुनिश्चित करने के लिए, अगर मैं बस मतदान करता हूं तो मैं केवल EnumWindows का उपयोग कर सकता हूं और 32-/64-बिट समस्या नहीं है? जेएनए योजना थी (उनके पास विंडोज बीटीडब्ल्यू पर खिड़कियों की गणना करने का एक उदाहरण था, मुझे बस इसे वापस ढूंढना होगा) लेकिन पहले मैं जानना चाहता था कि "हुड के नीचे" क्या शामिल था। मुझे अभी भी पता नहीं है कि मेरे पास ऐसा करने के लिए कौशल होगा (मैंने कभी भी विंडोज प्रोग्रामिंग नहीं की है) लेकिन ये सभी उत्तर मुझे समझने में बहुत मदद कर रहे हैं कि इसमें क्या शामिल है! – NoozNooz42

+0

@ NoozNooz42 - यह सही है, मतदान हुक के उपयोग से बचाता है और 32/64 बिट मुद्दा। यहां एक लेख है जो जेएनए से एनमविंडोज को कॉल करता है। http://javajeff.mb.ca/cgi-bin/mp.cgi?/java/javase/articles/mjnae – mdma

+0

@mdna: EnumWindows के साथ समस्या यह है कि यह ज़ेड ऑर्डर में विंडो वापस नहीं करता है। (या कम से कम इसके दस्तावेज के अनुसार नहीं है) –

7

यह किया जा सकता है (एक बार फिर से, मैं "बड़ी तस्वीर" समझने के लिए यहां काम पर है पाने के लिए कोशिश कर रहा हूँ)?

हां, हालांकि आपको कॉलबैक के संबंध में जो कुछ चाहिए, उसे प्राप्त करने के लिए आपको hook पंजीकृत करना होगा। , बनाने को नष्ट करने, कम से कम, अधिकतम, चलती है, या एक खिड़की आकार,

सक्रिय;: आप शायद एक CBTProc Callback Hook है, जो जब भी कहा जाता है का उपयोग करने की आवश्यकता होगी सिस्टम कमांड पूरा करने से पहले; सिस्टम संदेश कतार से माउस या कीबोर्ड ईवेंट को हटाने से पहले; कीबोर्ड फोकस सेट करने से पहले; या सिस्टम संदेश कतार के साथ सिंक्रनाइज़ करने से पहले

नोट हालांकि मुझे विश्वास नहीं है कि ऐसे हुक कंसोल विंडोज़ पर काम करते हैं क्योंकि वे कर्नेल का डोमेन हैं, Win32 नहीं।

क्या अच्छी तरह से विंडोज एपीआई दस्तावेज (और उनके चश्मा के अनुसार काम कर रहे हैं) ऐसा करने की इजाजत दे रहे हैं?

हां। आप सही जेड ऑर्डर में डेस्कटॉप पर सभी विंडो हैंडल प्राप्त करने के लिए GetTopWindow और GetNextWindow फ़ंक्शंस का उपयोग कर सकते हैं।

क्या हर बार एक विंडो में बदलाव करने के लिए कॉलबैक पंजीकृत करना आसान है? (अगर यह आकार दिया जाता है, वापस करने के लिए/सामने लाया ले जाया गया या एक नई विंडो पॉप-अप करता है, तो, आदि)

पहले उत्तर :)

gotchas क्या होगा देखते हैं?

पहले उत्तर :) देखें

बोनस सवाल: कल्पना करें कि आप स्क्रीन पर एक खिड़की परिवर्तन होता है एक छोटे से .exe अस्थायी फ़ाइल हर करने के लिए खिड़कियों नाम/स्थिति/आकार लेखन लिखने के लिए आवश्यकता होगी , इस तरह का कार्यक्रम आपकी पसंद की भाषा में कितना समय लगेगा और आपको इसे कब तक लिखना होगा?

सी की कुछ सौ लाइनें, और कुछ घंटों। हालांकि मुझे कुछ प्रकार के मतदान का उपयोग करना होगा - मैंने कभी अपने आप से पहले हुक नहीं किया है। अगर मुझे हुक की आवश्यकता होगी तो इसमें कुछ और समय लगेगा।

+0

इस उत्तर के लिए बहुत बहुत धन्यवाद ... इसलिए यदि मैं आपको सही ढंग से समझता हूं तो आप मतदान करेंगे (यही वह है जो मैं ओएस एक्स के तहत करता हूं) और फिर कोई हुक नहीं और कोई कॉलबैक ** या ** आप हुक का उपयोग नहीं करेंगे, कॉलबैक करने की इजाजत है? (एक बार फिर, ओएस एक्स AFAICT में कॉलबैक का उपयोग करके ऐसा करने का कोई आसान तरीका नहीं है, यही कारण है कि मैं मतदान कर रहा हूं)। – NoozNooz42

+1

@Nooz: एक हुक * एक कॉलबैक है। –

+1

@Nooz: एक और तरीका रखो, हाँ। आप या तो मतदान कर सकते हैं या आप कॉलबैक के रूप में हुक का उपयोग कर सकते हैं। हुक बेहतर है, लेकिन मैं बस उस समय का अनुमान लगा रहा था जब मैंने पहले कभी हुक का उपयोग नहीं किया था। –

1

मुझे 2006 में याद है कि एक उपयोगिता WinObj sysinternals के हिस्से के रूप में संभवतः संभवतः आप जो चाहते थे वह किया था। इन यूटिलिटीज का हिस्सा लेखक (मार्क रसेलिनोविच) द्वारा स्रोत कोड प्रदान किया गया था।

उस समय से, उनकी कंपनी माइक्रोसॉफ्ट द्वारा खरीदी गई थी, इसलिए मुझे नहीं पता कि स्रोत अभी भी उपलब्ध होगा या नहीं।

http://msdn.microsoft.com/en-us/library/aa264396(VS.60).aspx

http://www.codeproject.com/KB/dialog/windowfinder.aspx

संबंधित मुद्दे