2011-09-18 43 views
11

Tôi đã cố gắng một số điều với lưỡi câu, và tôi không hiểu tại sao móc phải được sử dụng với một hàng đợi thông điệpTại sao phải SetWindowsHookEx được sử dụng với một hàng đợi thông điệp cửa sổ

hook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, NULL, 0); 
MSG msg; 
while(GetMessage(&msg, NULL, 0, 0) > 0) 
{ 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
} 
UnhookWindowsHookEx(hook); 

Tại sao không làm điều gì đó như công việc này?

hook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, NULL, 0); 
cin >> aKey; 
UnhookWindowsHookEx(hook); 

Sử dụng chủ đề tăng cường và rào cản không hoạt động. Tại sao không thể chờ đợi giữa móc và chưa được thực hiện theo cách khác?

EDIT:

tôi đã phạm sai lầm khi tôi tạo ra mẫu này, tôi tạo ra một cái móc WH_KEYBOARD_LL, không WH_KEYBOARD, (tôi không nghĩ rằng nó làm cho một sự khác biệt lớn)

Ngoài ra vòng lặp không bao giờ thực hiện chỉ đợi hàm GetMessage.

Vòng lặp chỉ thực hiện khi tôi đăng thông báo thoát PostThreadMessage(id, WM_QUIT, 2323, NULL); vì vậy tôi không hiểu nó làm gì bên cạnh chờ đợi, có một số xử lý nội bộ không?

CÓ LIÊN QUAN:

C++ SetWindowsHookEx WH_KEYBOARD_LL Correct Setup

How can I set up a CBT hook on a Win32 console window?

Trả lời

26

Các móc ở mức độ thấp, WH_KEYBOARD_LL và WH_MOUSE_LL khác với tất cả các móc khác. Họ không yêu cầu một DLL để được tiêm vào quá trình mục tiêu. Thay vào đó, Windows gọi trực tiếp hook callback của bạn, bên trong tiến trình của riêng bạn. Để thực hiện công việc đó, một vòng lặp tin nhắn là bắt buộc. Không có cơ chế nào khác cho Windows để thực hiện cuộc gọi lại trên chủ đề chính của bạn, cuộc gọi lại chỉ có thể xảy ra khi bạn đã gọi Get/PeekMessage() để Windows kiểm soát được.

Móc tổng thể như WH_KEYBOARD rất khác. Nó đòi hỏi một DLL và gọi lại xảy ra trong quá trình xử lý tin nhắn bàn phím. Bạn cần một số loại giao tiếp liên ngành để cho chương trình của riêng bạn nhận thức được điều này. Ống có tên là lựa chọn thông thường. Trong trường hợp khác, tất nhiên đòi hỏi quá trình tiêm này bơm một vòng lặp tin nhắn. Nó sẽ không nhận được tin nhắn bàn phím nếu không.

Ủng hộ móc cấp thấp, chúng là nhiều dễ dàng hơn để bắt đầu.Nhưng làm máy bơm hoặc nó sẽ không hoạt động. Và hãy cẩn thận với thời gian chờ, nếu bạn không đủ đáp ứng thì Windows sẽ giết móc của bạn mà không cần thông báo.

Understanding the low-level mouse and keyboard hook (win32)

+0

Vì vậy, nếu tôi hiểu điều này một cách chính xác, Windows chỉ có thể gọi lại cuộc gọi của tôi trong khi gọi Get/PeekMessage()? – Ha11owed

+2

Bạn hiểu chính xác. Không có cách nào khác để tiêm một cách an toàn các cuộc gọi vào một chủ đề, nó phải được nhàn rỗi. Đây là lý do tại sao các vòng tin nhắn tồn tại. –

+0

@HansPassant để làm rõ, bạn có gợi ý rằng cho móc toàn cầu như WH_KEYBOARD tên ống có thể được sử dụng để "vượt qua" thông tin trở lại chương trình của riêng tôi và chương trình đó không cần một máy bơm tin nhắn? – dave

4

của Windows Hooks treo thông điệp loop Windows: http://msdn.microsoft.com/en-us/library/ms644959#wh_keyboardhook

Móc WH_KEYBOARD cho phép một ứng dụng để giám sát lưu lượng tin nhắn cho WM_KEYDOWN và WM_KEYUP tin nhắn sắp được trả lại bởi Hàm GetMessage hoặc PeekMessage. Bạn có thể sử dụng móc WH_KEYBOARD để theo dõi đầu vào bàn phím được đăng vào hàng đợi tin nhắn.

Ứng dụng bảng điều khiển không tự bơm thông điệp - quy trình bảng điều khiển thực hiện. Vì vậy, nó sẽ không hoạt động trừ khi quá trình có một vòng lặp tin nhắn.

Xem:

How can I set up a CBT hook on a Win32 console window?

C++ SetWindowsHookEx WH_KEYBOARD_LL Correct Setup

+0

nhờ cho các liên kết, tôi đã đi máng tất cả trong số họ nhưng tôi vẫn không hiểu những gì GetMessage không bên cạnh chờ đợi. Trong trường hợp của tôi (giao diện điều khiển ứng dụng) thời gian duy nhất nó thực hiện nó khi tôi gửi tin nhắn bỏ thuốc lá cho chủ đề. – Ha11owed

+0

Ngoài ra, kể từ khi GetMessage chờ đợi, điều này có nghĩa là giao diện điều khiển không bơm bất kỳ tin nhắn nào cho đến khi thông báo thoát của tôi không? – Ha11owed

+0

Xem câu trả lời của Han - Windows sẽ chỉ gọi lại chủ đề của bạn khi nó biết rằng nhàn rỗi của nó. Và nếu thread bị chặn trong GetMesasge() Windows biết rằng nó không làm bất cứ điều gì – shf301

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