هل الترتيب الذي يتم به إرجاع المقابض بواسطة EnumWindows له معنى؟

StackOverflow https://stackoverflow.com/questions/295996

سؤال

من بعض الاختبارات الأولية يبدو ذلك EnumWindows تقوم دائمًا بإرجاع النوافذ بترتيب إنشاء مثيل عكسي، على سبيل المثال.أحدث نافذة تم إنشاؤها أولاً.فهل هذه ملاحظة صحيحة؟إذا كان الأمر كذلك، فهل هذا صحيح في جميع إصدارات Windows؟وهل هذا افتراض موثوق، أي.هل تم توثيق هذا السلوك في مكان ما؟


سياق: أنا أتعامل مع موقف أقوم فيه بتشغيل تطبيق تابع لجهة خارجية لفتح عدة نوافذ غير مشروطة وأحتاج إلى إرسال بعض رسائل النوافذ إلى تلك النوافذ بمجرد فتحها، ومع ذلك ليس لدي طريقة مؤكدة لتحديد هويتها لهم حيث لن تختلف فئات النوافذ الخاصة بهم ولا التسميات التوضيحية الخاصة بهم ولا أعرف أيضًا إحداثياتهم المتوقعة.ومع ذلك، إذا كان بإمكاني الاعتماد على السلوك المذكور أعلاه EnumWindows يمكنني ببساطة استخدام المقبض الأول الذي تم إرجاعه بواسطة EnumWindows الذي يتطابق فصله والتسمية التوضيحية مع توقعاتي.لا يزال هذا يترك بعض الثغرات الافتراضية ولكن أعتقد أنها ستكون جيدة بما فيه الكفاية.ومع ذلك، نرحب بالاقتراحات البديلة.

هل كانت مفيدة؟

المحلول

يقوم بإعادتهم بالترتيب Z.أولاً النافذة العلوية مع WS_EX_TOPMOST اضبط حتى تظهر النافذة السفلية WS_EX_TOPMOST set, ، ثم النافذة العلوية بدون WS_EX_TOPMOST, ، على الرغم من النافذة السفلية بدونها WS_EX_TOPMOST.لاحظ أن الرؤية ليست عاملاً محددًا، لذا فإن النافذة غير المرئية التي تكون أعلى في الترتيب Z من النافذة المرئية ستظل تظهر أمامها.

يحرر:

من المستبعد جدًا أن تتمكن من استخدام هذا كما تريد، فقط تأخذ العائد الأول منه EnumWindows.ليس من غير المرجح أن تكون نافذتك الجديدة هي العودة الأولى فحسب، بل سيكون لديك حالة سباق حيث يمكن فتح نوافذ أخرى في هذه الأثناء.ومع ذلك، يمكنك الاحتفاظ بقائمة بجميع النوافذ المعروفة للتطبيق، وعندما تحتاج إلى العثور على نافذة مفتوحة حديثًا، اتصل EnumWindows وقارن مقابض النوافذ بتلك الموجودة في قائمتك.عندما تجد واحدة تحتوي على الفئة والتسمية التوضيحية الصحيحة (يمكنك حتى التحقق من أنها تنتمي إلى العملية الصحيحة باستخدام GetWindowThreadProcessID) إنه لا في قائمتك، ثم وجدت النافذة الجديدة.

ولأغراضك، على الرغم من ذلك، قد تحصل على خدمة أفضل عن طريق تثبيت خطاف CBT ومراقبة إشعار HCBT_CREATEWND.راجع تعليمات MSDN على SetWindowsHookEx() و ال CBTProc أتصل مرة أخرى للمزيد من المعلومات.

مستوى اليقين بشأن أمر التعداد:

لقد ذكر عدد من التعليقات والإجابات الأخرى على هذا السؤال عدم وجود وثائق دقيقة في MSDN حول الترتيب الذي EnumWindows إرجاع مقابض النوافذ.وبالفعل الصفحات EnumWindows و ال EnumWindowsProc أتصل مرة أخرى كلاهما صامت تمامًا بشأن هذه القضية.وأقدم الأدلة التالية:

  1. أ مقالة أسئلة وأجوبة حول C++ في مجلة MSDN هل يذكر على وجه التحديد:

    يقوم EnumWindows بتعداد النوافذ بترتيب Z من أعلى إلى أسفل

  2. الصفحة على EnumChildWindows يشير إلى الترتيب في قسم الملاحظات:

    سيتم تعداد النافذة الفرعية التي تم نقلها أو تغيير موضعها بالترتيب Z أثناء عملية التعداد بشكل صحيح.

    وهذا يعني أن الترتيب يعتمد على الترتيب Z.ومنذ ذلك الحين، في وصف hWndParent المعلمة تقول هذا:

    إذا كانت هذه المعلمة فارغة، فهذه الوظيفة تعادل EnumWindows.

    يمكن للمرء أن يفترض أن نفس المنطق والترتيب ينطبق على EnumWindows.

  3. هذا هو السلوك الملحوظ لهذه الوظيفة، والذي يجعل من تغييرها تغييرًا جذريًا.بشكل عام، كانت Microsoft جيدة جدًا فيما يتعلق بعدم إجراء تغييرات جذرية على السلوك الذي يمكن ملاحظته.وهذا ليس ضمانًا، لكنه رهان آمن جدًا.من المرجح أن تجد أنه في الإصدار التالي تم إهمال الوظيفة التي تستخدمها - واستبدالها بإصدار "Ex" آخر - بدلاً من اكتشاف أن سلوكها الملحوظ قد تغير.

بالطبع، كل هذا أكاديمي للغاية في هذه المرحلة، منذ ذلك الحين EnumWindows ربما لا يكون هذا هو الحل الأفضل لمشكلة OP، على أقل تقدير EnumThreadWindows من المحتمل أن يكون مناسبًا بشكل أفضل، لكنني أعتقد أنه من الجدير بالذكر للأشخاص الآخرين الذين قد يصادفون هذا المنشور.

نصائح أخرى

والأجوبة السابقة تحتاج الصقل كبير. التعداد النظام = Z النظام إلا إذا GetSystemMetrics (SM_IMMENABLED) = 0، أي إدارة أسلوب الإدخال / الإدخال ميزات محرر أسلوب معطلة. لأن كل نوافذ الطبقة "IME" (عنوان "الافتراضي IME") و "MSCTFIME UI" يتم تعداد بعد نافذة "PROGMAN" ( "مدير البرنامج")، - أي لا Z-النظام

ولم يتم تحديد الترتيب في API ( MSDN رابط ) حتى انها ليست مضمونة ليكون أي شيء على وجه الخصوص - إذا كان هناك ضمان أنه سيكون محدد بشكل واضح في API. ماذا يحدث، على سبيل المثال، إذا تم إنشاء نافذة في منتصف الطريق من خلال التعداد - أنها لا تحصل على تضمينها في التعداد؟ وهذا يسمح للمدير النوافذ حرية تغيير تنفيذه يجب أن تصبح أكثر كفاءة للقيام بذلك.

ومع ذلك، هناك قيمة فريدة التي يمكن استخدامها للتمييز بين النوافذ - نافذة التعامل مع نفسها. في طريقة EnumWindowProc الخاص بك، وتوفير مقبض نافذة لكل نافذة مطابقة - كنت في حاجة إليها على أي حال لإرسال رسائل إلى إطار

.

إذا كنت السيطرة على كل العمليات من الممكن أن ترسل من أول واحد SendMessage مع "HWND_BROADCAST" كمعلمة الأولى.

وبعد ذلك البرنامج الآخر عند استلام جي اس، ويمكن القيام SendMessage إلى ولده النوافذ.

إذا لم ثائق قول أي شيء حول ترتيب التعداد، وأود أن أقترح عليك بشدة الابتعاد عن أي افتراضات. ومن شأن زوجين من الوظائف على بلوق ريمون تشن (blogs.msdn.com/oldnewthing) تكشف لكم كم التطبيقات هناك التي تعتمد على كل هذه الأشياء لا يحملون وثائق / الملاحظة، وسارت الامور بشكل خطأ فادحا عندما يأتي الإصدار الجديد من نظام التشغيل Windows من أصل (إلا إذا المطورين MS يعرض بعد الرقائق آخر لبعد آخر التطبيق أن يتصرف بشكل سيء).

وأما عن الغرض الخاص، وهناك العديد من الوظائف، مثل GetWindowThreadProcessID، GetParent، EnumThreadWindows وEnumWindows التي يمكن أن تساعدك على تحقيق هذه المهمة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top