2009-04-19 7 views
11

Trong một ứng dụng Win32 C++, chúng tôi bắt đầu một vòng lặp tin nhắn tìm nạp các thông điệp từ một hàng đợi, dịch chúng và sau đó gửi chúng. Cuối cùng, mỗi thông báo đến WndProc của chúng tôi, nơi sự kiện liên quan có thể được xử lý.Lập trình hướng sự kiện Win32 được thực hiện như thế nào dưới mui xe?

Tôi hiểu phần đó. Những gì tôi không hiểu là ở giữa goings-on. Cụ thể:

  1. Các loại trình xử lý gián đoạn hệ điều hành khác nhau phải đặt thông điệp trong hàng đợi thông báo '' nhưng không nằm trong khoảng không địa chỉ của quy trình này? Làm thế nào là nó tiếp xúc với mã xử lý ngắt?
  2. Có nghĩa là gì để 'dịch' thư? Cuộc gọi đến TranslateMessage() thực sự làm gì?
  3. Sau khi được gửi bởi DispatchMessage(), mọi thông điệp sẽ chuyển đến đâu trước khi tiếp cận WndProc của tôi (tức là hệ điều hành sẽ làm gì với nó)?

Nếu có ai biết câu trả lời ở trên, vui lòng thỏa mãn sự tò mò của tôi. Cảm ơn.

Trả lời

6

Hệ điều hành duy trì hàng đợi thư, nơi nó đặt sự kiện (ví dụ: từ gián đoạn hoặc các nguồn khác). Sau đó, nó sẽ gửi tin nhắn từ hàng đợi đó đến tất cả các cửa sổ, tùy thuộc vào thông báo (ví dụ: nó sẽ không gửi thông điệp chính đến cửa sổ không có tiêu điểm).

Ứng dụng có thể có hàng đợi riêng để xử lý thư. Những hàng đợi đó được tạo ra on request (chỉ khi cần thiết).

Dịch thư được sử dụng để tạo thư không phải là sự kiện 'thực'. Ví dụ, thông điệp WM_CONTEXTMENU được 'dịch' từ một con chuột phải, hoặc phím menu ngữ cảnh, hoặc shift-F10. WM_CHAR được dịch từ các tin nhắn WM_KEYDOWN. Và tất nhiên nhiều thông điệp khác được dịch ra theo cách đó.

Thông báo được đăng lên mọi cửa sổ sẽ nhận được thông báo. Hệ điều hành quyết định tùy thuộc vào loại tin nhắn cho dù một cửa sổ sẽ nhận được tin nhắn đó hay không. Hầu hết các thư được hệ thống chờ đợi, tức là thư sẽ không được đăng lên cửa sổ khác cho đến khi cửa sổ được xử lý.Điều này có tác động lớn đối với tin nhắn quảng bá: nếu một cửa sổ không trả lại khi xử lý thông báo đó, hàng đợi là blocked và các cửa sổ khác sẽ không nhận được tin nhắn nữa.

+3

Tất cả đều sai. Các phần của nó là chính xác, là chính xác chỉ khi câu hỏi là về Win16, nơi toàn bộ hệ điều hành và các ứng dụng được hợp tác operativly theo lịch trình trên một chủ đề duy nhất. –

1

Không hoàn toàn tích cực về vấn đề này nhưng tôi đoán tốt nhất nói:

  1. Hàng đợi là một đối tượng hệ thống mà bạn truy cập với các cuộc gọi Win32 API. Nó không nằm trong không gian địa chỉ quy trình của bạn. Vì vậy, các trình xử lý ngắt có thể truy cập nó (có thể thông qua HAL (Lớp trừu tượng phần cứng) của hạt nhân).

  2. Trong Win16, cuộc gọi đó lấy các phần phụ khác nhau của một thư lớn hơn và nghiền chúng thành một tổng thể. Vì vậy, TranslateMessage sẽ thêm WM_KEYPRESS khi nó tìm thấy trình tự WM_KEYDOWN WM_KEYUP tương ứng. Nó cũng sẽ biến các thông báo nhấp vào nút khác nhau thành các tin nhắn DoubleClick dựa trên cài đặt nội bộ và dấu thời gian của các tin nhắn. Cho dù nó vẫn làm điều này trong Win32, tôi không biết.

  3. DispatchMessage có thể là nơi các móc thông báo cửa sổ được xử lý. Vì vậy, nếu có một cái móc trên cửa sổ của bạn, nó được gọi là ở đây hoặc khi GetMessage được gọi. Tôi không chắc. Ngoài ra, DispatchMessage chỉ tra cứu địa chỉ WndProc liên kết với cửa sổ và gọi nó. Không còn gì khác để làm.

Hy vọng điều đó sẽ hữu ích.

6

Tùy thuộc vào cách gửi thư của bạn và cách thư được xử lý.

Khi bạn gọi SendMessage, nếu cửa sổ đích được sở hữu bởi luồng hiện tại, cuộc gọi sẽ bỏ qua hàng đợi tin nhắn cho cửa sổ và trình quản lý cửa sổ gọi trực tiếp windowproc trên cửa sổ mục tiêu. Nếu cửa sổ đích được sở hữu bởi một luồng khác, trình quản lý cửa sổ sẽ gọi PostMessage một cách hiệu quả và bơm các thông điệp cửa sổ cho đến khi cửa sổ đích trả về từ cửa sổ proc.

Khi bạn gọi PostMessage, trình quản lý cửa sổ sẽ sắp xếp các thông số thư và chèn đối tượng tương ứng vào hàng đợi thư cho cửa sổ đích. Khi nó tiếp theo gọi GetMessage tin nhắn được lấy ra từ hàng đợi tin nhắn.

Trình quản lý cửa sổ cũng đăng ký các sự kiện nhập thô từ thiết bị nhập (bàn phím và/hoặc chuột) và nó tạo thông báo cho các sự kiện nhập đó. Sau đó nó chèn các thông điệp đó vào hàng đợi khi thích hợp (việc xử lý các sự kiện đầu vào phức tạp bởi vì nó phụ thuộc vào những thông điệp nào đã có trong hàng đợi thông báo cho cửa sổ).

Như Stefan đã chỉ ra, TranslateMessage chỉ dịch các phím tăng tốc - ví dụ: nó chuyển đổi các chuỗi khóa thành các tin nhắn WM_COMMAND.

1

Để giải quyết Câu hỏi con cuối cùng, một tin nhắn gửi đi sẽ đi đến WindowProc của bạn sau khi nó được cấp nước tập trung thông qua tất cả các móc (WH_CALLWNDPROC)

4

loại khác nhau của hệ điều hành xử lý ngắt phải đặt tin nhắn trong 'hàng đợi thông điệp nói ', nhưng ở đâu trong không gian địa chỉ quy trình, hàng đợi này có tồn tại không? Làm thế nào là nó tiếp xúc với mã xử lý ngắt?

Windows được liên kết với chủ đề. Mỗi luồng với một cửa sổ có một hàng đợi luồng trong không gian địa chỉ của tiến trình. Hệ điều hành có một hàng đợi nội bộ trong không gian địa chỉ riêng của nó cho các sự kiện do phần cứng tạo ra. Sử dụng các chi tiết của sự kiện và thông tin trạng thái khác (ví dụ: cửa sổ nào có tiêu điểm), hệ điều hành dịch các sự kiện phần cứng thành các thông điệp sau đó được đặt trong hàng đợi luồng thích hợp.

Thư được đăng được đặt trực tiếp trong hàng đợi chuỗi cho cửa sổ mục tiêu.

Thư được gửi thường được xử lý trực tiếp (bỏ qua hàng đợi).

Chi tiết có được lông. Ví dụ, hàng đợi chủ đề có nhiều hơn danh sách thư - chúng cũng duy trì một số thông tin trạng thái. Một số tin nhắn (như WM_PAINT) không thực sự xếp hàng đợi, nhưng được tổng hợp từ thông tin trạng thái bổ sung khi bạn truy vấn hàng đợi và nó trống. Tin nhắn được gửi đến các cửa sổ thuộc sở hữu của các chủ đề khác thực sự được gửi lên hàng đợi của người nhận thay vì được xử lý trực tiếp, nhưng hệ thống làm cho nó xuất hiện như một sự chặn thường xuyên gửi từ quan điểm của người gọi. Hilarity xảy ra nếu điều này có thể gây ra bế tắc (vì vòng tròn gửi trở lại luồng ban đầu).

Sách Jeffrey Richter có rất nhiều (tất cả?) Của các chi tiết đẫm máu. Ấn bản của tôi là cũ (Advanced Windows). Ấn bản hiện tại có vẻ được gọi là Windows via C/C++.

Hệ điều hành làm rất nhiều công việc để làm cho luồng thông điệp xuất hiện hợp lý (và tương đối đơn giản) cho người gọi.

Điều gì có nghĩa là 'dịch' thư? Cuộc gọi tới TranslateMessage() thực sự làm gì?

Nó đồng hồ cho thông điệp chính ảo và khi nhận ra tổ hợp phím/khóa, nó sẽ thêm thông điệp ký tự. Nếu bạn không gọi số TranslateMessage, bạn sẽ không nhận được tin nhắn ký tự như WM_CHAR.

Tôi nghi ngờ nó sẽ gửi thông điệp nhân vật trực tiếp trước khi trở về (trái ngược với việc đăng chúng). Tôi chưa bao giờ kiểm tra, nhưng tôi dường như nhớ lại rằng các tin nhắn WM_CHAR đến ngay trước WM_KEYUP.

Sau khi được gửi bởi DispatchMessage(), mọi thông điệp sẽ chuyển đến đâu trước khi tiếp cận WndProc của tôi (tức là hệ điều hành sẽ làm gì với nó)?

DispatchMessage chuyển thư đến WndProc cho cửa sổ mục tiêu. Trên đường đi, một số móc có thể có cơ hội nhìn thấy thông điệp (và có thể can thiệp vào nó).