2011-01-27 41 views
6

Microsoft không khuyến nghị DirectInput cho đầu vào bàn phím và chuột. Như vậy, tôi đã viết một lớp quản lý đầu vào có sử dụng SetWindowsHookEx để nối vào WndProc và GetMsg. Tôi tin rằng các móc được đặt một cách thích hợp, mặc dù chúng có vẻ là nguyên nhân của nhiều vấn đề khác nhau.Tại sao Windows không nhận được một số tin nhắn nhất định?

Cả WndProc lẫn GetMsg của tôi đều không nhận được bất kỳ thông báo nào mà WndProc thực nhận được. Trình quản lý đầu vào của tôi không bao giờ nhận được các tin nhắn WM_INPUT, WM_ BUTTON, WM_MOUSEWHEEL và WM_KEY * mà bạn cần.

Điều gì mang lại?

tiêu đề từng phần:

namespace InputManager 
{ 
    class CInputManager 
    { 
     HWND m_Window; 
     HHOOK m_WndProcHook; 
     HHOOK m_GetMessageHook; 
     static LRESULT CALLBACK WindowsProcedureHookProcedure(int Code, WPARAM WParameter, LPARAM LParameter); 
     static LRESULT CALLBACK GetMessageHookProcedure(int Code, WPARAM WParameter, LPARAM LParameter); 
     static LRESULT CALLBACK MessageHandler(HWND Window, UINT Message, WPARAM wParameter, LPARAM lParameter); 
    }; 
} 

nguồn từng phần:

namespace InputManager 
{ 
    bool CInputManager::Initialize(HWND Window) 
    { 
     m_Window = Window; 

     // Hook into the sent messages of the target window to intercept input messages. 
     m_WndProcHook = SetWindowsHookEx(WH_CALLWNDPROC, &(WindowsProcedureHookProcedure), NULL, GetCurrentThreadId()); 
     // Hook into the posted messages of the target window to intercept input messages. 
     m_GetMessageHook = SetWindowsHookEx(WH_GETMESSAGE, &(GetMessageHookProcedure), NULL, GetCurrentThreadId()); 

     // Register mouse device for raw input. 
     RAWINPUTDEVICE RawInputDevice; 
     RawInputDevice.usUsagePage = HID_USAGE_PAGE_GENERIC; 
     RawInputDevice.usUsage = HID_USAGE_GENERIC_MOUSE; 
     RawInputDevice.dwFlags = RIDEV_INPUTSINK; 
     RawInputDevice.hwndTarget = m_Window; 
     return RegisterRawInputDevices(&(RawInputDevice), 1, sizeof(RawInputDevice)); 
    } 

    void CInputManager::Shutdown() 
    { 
     // Unhook from the posted messages of the target window. 
     UnhookWindowsHookEx(m_GetMessageHook); 
     // Unhook from the sent messages of the target window. 
     UnhookWindowsHookEx(m_WndProcHook); 
    } 

    LRESULT CALLBACK CInputManager::WindowsProcedureHookProcedure(int nCode, WPARAM wParameter, LPARAM lParameter) 
    { 
     if(nCode == HC_ACTION) 
     { 
      // Forward to message handler. 
      CWPSTRUCT* Message = reinterpret_cast<CWPSTRUCT*>(lParameter); 
      MessageHandler(Message->hwnd, Message->message, Message->wParam, Message->lParam); 
     } 
     return CallNextHookEx(NULL, nCode, wParameter, lParameter); 
    } 

    LRESULT CALLBACK CInputManager::GetMessageHookProcedure(int nCode, WPARAM wParameter, LPARAM lParameter) 
    { 
     if(nCode == HC_ACTION) 
     { 
      // Forward to message handler. 
      CWPSTRUCT* Message = reinterpret_cast<CWPSTRUCT*>(lParameter); 
      MessageHandler(Message->hwnd, Message->message, Message->wParam, Message->lParam); 
     } 
     return CallNextHookEx(NULL, nCode, wParameter, lParameter); 
    } 
} 

Tôi không bao gồm mã cho xử lý tin nhắn như nó bao gồm 149 dòng, hầu hết trong số đó là công tắc cho loại tin nhắn. Các giá trị tin nhắn nhận được trong WndProc không giống như các giá trị trong callback của tôi.

+0

Cửa sổ mục tiêu có nằm trong cùng một quy trình không? –

+0

Vâng, đúng vậy. Mọi thứ đều ở dạng nhị phân đơn. –

Trả lời

4

Tôi khá muộn với bữa tiệc ở đây, nhưng tôi đã dành rất nhiều giờ để tìm ra cùng một vấn đề, và hy vọng một người khác sẽ thấy điều này hữu ích.

Kết luận thực nghiệm của tôi là DispatchMessage không kích hoạt WH_CALLWNDPROC móc. Nói cách khác, các thư được đăng trong hàng đợi thư của chuỗi và đi qua vòng lặp thư (GetMessage -> DispatchMessage) sẽ không bị WH_CALLWNDPROC bắt giữ. Nó chỉ bắt thông điệp gửi trực tiếp đến các thủ tục cửa sổ với SendMessage vv .. Và khi bạn nhìn vào các tài liệu, đó là kinda những gì nó nói:

Đơn xác định hoặc hàm callback thư viện xác định sử dụng với Hàm SetWindowsHookEx. Hệ thống gọi chức năng này trước khi gọi thủ tục cửa sổ để xử lý một tin nhắn gửi đến chủ đề.

Và tất nhiên điều ngược lại là đúng đối với móc WH_GETMESSAGE. Nó sẽ bắt các tin nhắn được đăng nhưng không gửi tin nhắn. Để có được tất cả các thư bạn có phải sử dụng cả hai móc, hoặc sử dụng subclassing để treo các thủ tục cửa sổ trực tiếp:

WNDPROC realProc; 
LRESULT CALLBACK hookProc(HWND h, UINT msg, WPARAM wp, LPARAM lp) 
{ 
    return CallWindowProc(realProc, h, msg, wp, lp); 
} 
... 
realProc = (WNDPROC)SetWindowLongPtr(hwnd, GWL_WNDPROC, (LONG_PTR)hookProc); 

Ngoài ra, lý do móc GetMessage của OP đã không làm việc có lẽ là bởi vì lParameter nên được đúc để MSG* và không phải CWPSTRUCT*.

+0

Cuối cùng trở lại vấn đề này và thử lại lần nữa. Thật vậy, có vẻ như là 'CWPSTRUCT * 'là vấn đề. –

6

tôi dường như không thể để thêm một bình luận dưới câu hỏi ban đầu của bạn mà là nơi tôi muốn đặt này nhưng:

Từ những gì có vẻ như bạn đang cố gắng làm, sẽ không phải là một WH_KEYBOARD và WH_MOUSE móc thích hợp hơn?

+0

Bạn cần 50 đại diện để có thể nhận xét về các câu hỏi của người khác. Nhận xét này thực sự tạo ra một câu trả lời hợp lý và sẽ giúp bạn trên con đường xây dựng đại diện của bạn. –

+0

Aye, đó sẽ là trường hợp, nhưng tôi cần phải sử dụng các phiên bản LL. Ngoài ra, tôi cần chụp các sự kiện đã thay đổi trong khi ở chế độ cửa sổ để nhả nút nếu người dùng rời khỏi cửa sổ. Đây có thể là một công việc hợp lệ, nhưng tôi vẫn không hiểu tại sao tôi không nhận được tin nhắn. Tài liệu dường như không gợi ý * bất cứ điều gì * về hai móc không nhận được thông báo đầu vào. –

+0

Trên thực tế, ngay cả những móc đó cũng không làm tôi tốt, vì chúng thiếu bất kỳ hình thức xác định cửa sổ nào mà chúng nhắm tới, mà là không thể thiếu đối với người quản lý đầu vào của tôi ... –

0

Tôi đã từng gặp vấn đề tương tự. Im không hoàn toàn shure những gì nó được (tôi nghĩ rằng nó đã được tiêu thụ một nơi nào đó trong PreTranslateMessage nhưng tôi không shure) nhưng tôi biết làm thế nào tôi phát hiện ra nó:

Tôi tạo ra một trong những biến mất bản thân mình và gỡ lỗi theo cách của nó thông qua MFC. Nếu tôi nhớ chính xác, tôi vừa quay trở lại đâu đó BOOLEAN không đúng. Tuy nhiên, cách tiếp cận này có thể cung cấp cho bạn manh mối thực tế.

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