2008-11-17 28 views
16

Từ một vài thử nghiệm sơ bộ, có vẻ như EnumWindows luôn trả về các cửa sổ theo thứ tự sắp xếp ngược, tức là cửa sổ được tạo gần đây nhất trước tiên. Đó có phải là một quan sát hợp lệ không? Nếu vậy, nó có đúng trên tất cả các phiên bản của Windows không? Và đây có phải là giả định đáng tin cậy, tức là hành vi đó được ghi lại ở đâu đó?Thứ tự mà EnumWindows trả về có xử lý nào không?


Bối cảnh: Tôi đang đối phó với một tình huống mà tôi đang kích hoạt một ứng dụng của bên thứ ba để mở nhiều cửa sổ phi modal và tôi cần phải gửi một số thông điệp cửa sổ để những cửa sổ khi họ đang mở, nhưng tôi không có cách nào chắc chắn để xác định chúng vì không phải lớp cửa sổ cũng như chú thích của chúng sẽ khác nhau và tôi cũng không biết tọa độ mong đợi của chúng. Tuy nhiên, nếu tôi có thể dựa vào hành vi trên của EnumWindows tôi có thể chỉ cần sử dụng tay cầm đầu tiên được trả về bởi EnumWindows có lớp và chú thích khớp với kỳ vọng của tôi. Điều đó vẫn còn để lại một số lỗ hổng giả định nhưng tôi nghĩ nó sẽ đủ tốt. Tuy nhiên, các đề xuất thay thế vẫn được chào đón.

Trả lời

23

Nó trả về chúng theo thứ tự Z. Đầu tiên là cửa sổ cao nhất với WS_EX_TOPMOST được đặt, cho đến cửa sổ phía dưới cùng với WS_EX_TOPMOST set, sau đó là cửa sổ cao nhất mà không có WS_EX_TOPMOST, mặc dù đến cửa sổ dưới cùng bên dưới mà không có WS_EX_TOPMOST. Lưu ý rằng khả năng hiển thị không phải là yếu tố quyết định, do đó cửa sổ vô hình cao hơn trong thứ tự Z so với cửa sổ hiển thị sẽ vẫn xuất hiện trước nó.

EDIT:

Đó là chắc chắn rằng bạn có thể sử dụng điều này như bạn muốn, chỉ cần tham gia sự trở lại đầu tiên từ EnumWindows. Cửa sổ mới của bạn không chỉ là cửa sổ đầu tiên mà không phải là cửa sổ đầu tiên, nhưng bạn sẽ có một điều kiện chạy đua nơi các cửa sổ khác có thể được mở trong thời gian chờ đợi. Tuy nhiên, bạn có thể giữ một danh sách tất cả các cửa sổ đã biết cho ứng dụng và khi bạn cần tìm một cửa sổ mới mở, hãy gọi EnumWindows và so sánh các cửa sổ xử lý với các cửa sổ trong danh sách của bạn. Khi bạn tìm thấy một lớp có chú thích và lớp học chính xác (bạn thậm chí có thể kiểm tra xem nó thuộc về đúng quy trình với GetWindowThreadProcessID) là không trong danh sách của bạn, sau đó bạn đã tìm thấy cửa sổ mới.

Vì mục đích của bạn, bạn có thể phục vụ tốt hơn bằng cách cài đặt móc nối CBT và xem thông báo HCBT_CREATEWND. Xem trợ giúp MSDN trên SetWindowsHookEx()the CBTProc callback để biết thêm thông tin.

Mức độ chắc chắn về thứ tự liệt kê:

Một số ý kiến ​​và câu trả lời khác cho câu hỏi này đã đề cập đến một thiếu tài liệu chính xác trong MSDN về thứ tự trong đó cửa sổ EnumWindows lợi nhuận xử lý. Và thực sự, các trang trên EnumWindowsthe EnumWindowsProc callback đều khá im lặng về vấn đề này.Tôi cung cấp làm bằng chứng sau:

  1. Một C++ Q&A article in MSDN magazine làm nhà nước cụ thể:

    EnumWindows liệt kê các cửa sổ ở trên xuống Z-trật tự

  2. Các trang trên EnumChildWindows ám chỉ đơn đặt hàng trong phần nhận xét:

    Một cửa sổ con được di chuyển hoặc định vị lại theo thứ tự Z trong quá trình liệt kê sẽ được liệt kê đúng.

    Điều này ngụ ý rằng thứ tự là phụ thuộc vào Z. Và từ đó, trong mô tả của các tham sốhWndParent, nó nói này:

    Nếu tham số này là NULL, chức năng này tương đương với EnumWindows.

    người ta có thể giả định cùng một logic và thứ tự áp dụng cho EnumWindows.

  3. Đây là hành vi quan sát được của hàm này, làm cho nó trở thành một thay đổi đột phá để thay đổi nó. Nói chung, Microsoft đã rất tốt về việc không thực hiện các thay đổi đột phá đối với hành vi có thể quan sát được. Đó không phải là một sự đảm bảo, nhưng đó là một cược khá an toàn. Bạn có nhiều khả năng thấy rằng trong phiên bản tiếp theo, chức năng bạn đang sử dụng đã không còn được dùng nữa và thay thế bằng một phiên bản "Ex" khác — hơn là nhận thấy hành vi quan sát của nó đã thay đổi.

Tất nhiên, đây là tất cả rất học vào thời điểm này, vì EnumWindows có lẽ không phải là giải pháp tốt nhất cho của OP vấn ít nhất EnumThreadWindows có lẽ sẽ là một sự phù hợp-nhưng tốt hơn tôi nghĩ rằng nó là đáng nói cho những người khác có thể gặp phải bài đăng này.

+0

Điều đó nghe có vẻ hợp lý. Bạn có liên kết đến tài liệu về hành vi này ở đâu đó không? Tôi đã mong đợi điều này trong tài liệu 'EnumWindows' ... –

+1

Lưu ý rằng tôi đã viết" xử lý đầu tiên được trả về bởi EnumWindows * có lớp và chú thích khớp với kỳ vọng của tôi * ". Tôi biết rằng các cửa sổ khác phù hợp với các tiêu chí tương tự có thể được mở trong thời gian chờ đợi nhưng trong trường hợp này tôi tin tưởng 95% rằng điều này là khá giả định. –

+1

vấn đề với việc giữ một danh sách các xử lý được biết là (cho đến nay) Tôi không có cách nào để nói khi một cửa sổ được đóng lại để loại bỏ nó khỏi danh sách một lần nữa. điều này một lần nữa có thể là giả thuyết, nhưng làm thế nào tôi biết rằng tay cầm (có khả năng giải phóng) đã không được gán lại cho một cửa sổ mới trong thời gian chờ đợi? –

1

Đơn đặt hàng không được chỉ định trong API (MSDN link) nên không được đảm bảo là bất kỳ điều gì cụ thể - nếu có bảo đảm, nó sẽ được chỉ định rõ ràng trong API. Điều gì sẽ xảy ra, ví dụ, nếu một cửa sổ được tạo ra nửa chừng thông qua việc liệt kê - nó có được bao gồm trong điều tra không? Điều này cho phép người quản lý cửa sổ tự do thay đổi việc thực hiện nó nếu nó trở nên hiệu quả hơn để làm như vậy.

Tuy nhiên, có một giá trị duy nhất có thể được sử dụng để phân biệt giữa các cửa sổ - cửa sổ tự xử lý. Trong phương thức EnumWindowProc của bạn, hãy lưu xử lý cửa sổ cho từng cửa sổ phù hợp - bạn vẫn cần nó để gửi tin nhắn đến cửa sổ.

+0

tôi không chỉ cần phân biệt giữa chúng. tôi cần phải biết đó là cái mà tôi vừa mới kích hoạt vào cuộc sống .... –

0

Nếu bạn kiểm soát cả hai quy trình bạn có thể gửi từ lần đầu tiên, SendMessage có "HWND_BROADCAST" làm thông số đầu tiên.

Sau đó, chương trình khác khi nhận tin nhắn, có thể gửi một SendMessage tới cửa sổ con của anh ấy.

+0

xin lỗi, tôi không kiểm soát được chương trình tạo cửa sổ, ít nhất là không theo ý tôi có thể gửi tin nhắn. –

0

Nếu tài liệu không nói bất cứ điều gì về thứ tự liệt kê, tôi chắc chắn sẽ đề nghị bạn tránh xa mọi giả định. Một vài bài đăng trên blog của Raymond Chen (blogs.msdn.com/oldnewthing) sẽ cho bạn biết có bao nhiêu ứng dụng ở đó dựa vào tất cả các công cụ/quan sát không có giấy tờ này, và một điều gì đó cực kỳ sai khi một phiên bản Windows mới xuất hiện (trừ khi các nhà phát triển MS giới thiệu một ứng dụng khác cho một ứng dụng khác hoạt động kém)).

Vì mục đích của bạn, có một số chức năng, như GetWindowThreadProcessID, GetParent, EnumThreadWindows và EnumWindows có thể giúp bạn đạt được nhiệm vụ.

2

Câu trả lời trước cần sàng lọc đáng kể. Enum-order = Z-order chỉ khi GetSystemMetrics (SM_IMMENABLED) = 0, tức là các tính năng của Trình quản lý phương thức nhập/Phương thức nhập đã được tắt. Vì tất cả các cửa sổ lớp "IME" (tiêu đề "IME mặc định") và "MSCTFIME UI" được liệt kê sau cửa sổ "Progman" ("Trình quản lý chương trình"), tức là không theo thứ tự Z.

Các vấn đề liên quan