2013-09-22 49 views
1

我想在我的屏幕上(客戶端窗口外)處理鼠標事件。我使用純粹的Win32 API。 我用SetWindowHookEx函數創建了單獨的DLL,並將其引用到我的Win32應用程序中。但是它只處理窗口事件,並且當鼠標在窗口或窗口之外時不活動。鼠標點擊手柄

//Hook.h

#ifndef _DEFINED_44E531B1_14D3_11d5_A025_006067718D04 
#define _DEFINED_44E531B1_14D3_11d5_A025_006067718D04 
#if _MSC_VER > 1000 
#pragma once 
#endif 
#ifdef __cplusplus 


extern "C" { 
#endif // __cplusplus 
#ifdef _COMPILING_44E531B1_14D3_11d5_A025_006067718D04 
#define LIBSPEC __declspec(dllexport) 
#else 
#define LIBSPEC __declspec(dllimport) 
#endif // _COMPILING_44E531B1_14D3_11d5_A025_006067718D04 




    LIBSPEC BOOL InstallHook(HWND hWnd); 
    LIBSPEC BOOL UnInstallHook(HWND hWnd); 





#undef LIBSPEC 
#ifdef __cplusplus 
} 

#define UWM_MOUSEMOVE_MSG (L"UWM_MOUSEMOVE_USER_MSG") 
#define UWM_MOUSELBUTTONUP_MSG (L"UWM_MOUSELBUTTONUP_USER_MSG") 
#define UWM_MOUSELBUTTONDOWN_MSG (L"UWM_MOUSELBUTTONDOWN_USER_MSG") 
#define UWM_MOUSERBUTTONUP_MSG (L"UWM_MOUSERBUTTONUP_USER_MSG") 
#define UWM_MOUSERBUTTONDOWN_MSG (L"UWM_MOUSERBUTTONDOWN_USER_MSG") 
#define UWM_MOUSELDBCLICK_MSG (L"UWM_MOUSERBUTTONDOWN_USER_MSG") 


#endif // __cplusplus 

#endif // _DEFINED_44E531B1_14D3_11d5_A025_006067718D04 

//Hook.cpp

// Hook.cpp:定義導出的函數爲DLL應用。 //

#include "stdafx.h" 
#include "Hook.h" 

#pragma data_seg() 
#pragma comment(linker, "/section:.Segment,rws") 


HWND hWndServer = NULL; 
UINT UWM_MOUSEMOVE; 
UINT UWM_MOUSELBUTTONUP; 
UINT UWM_MOUSELBUTTONDOWN; 
UINT UWM_MOUSERBUTTONUP; 
UINT UWM_MOUSERBUTTONDOWN; 
UINT UWM_MOUSELDBCLICK; 


HINSTANCE hInst; 
//HWND hWndServer = NULL; 
HHOOK hook; 

static LRESULT CALLBACK MouseMsgProc(UINT nCode, WPARAM wParam, LPARAM lParam) 
{ 
    if(nCode < 0) 
    { 
     CallNextHookEx(hook, nCode, wParam, lParam); 
     return 0; 
    } 
    LPMSG msg = (LPMSG)lParam; 
    switch(msg->message ) 
    { 
     case WM_LBUTTONDBLCLK: 
     SendMessage(hWndServer, UWM_MOUSELDBCLICK, 0 , 0); 
     break; 
     case WM_MOUSEMOVE: 
      SendMessage(hWndServer, UWM_MOUSEMOVE, 0, 0); 
     break; 

     case WM_NCMOUSEMOVE: 
      SendMessage(hWndServer, UWM_MOUSEMOVE, 0, 0); 
     break; 
     case WM_LBUTTONDOWN: 
      SendMessage(hWndServer, UWM_MOUSELBUTTONDOWN, 0 , 0); 
     break; 
     case WM_NCLBUTTONDOWN: 
      SendMessage(hWndServer, UWM_MOUSELBUTTONDOWN, 0 , 0); 
     break; 
     case WM_LBUTTONUP: 
      SendMessage(hWndServer, UWM_MOUSELBUTTONUP, 0 , 0); 
     break; 
     case WM_NCLBUTTONUP: 
      SendMessage(hWndServer, UWM_MOUSELBUTTONUP, 0 , 0); 
     break; 
     case WM_RBUTTONDOWN: 
      SendMessage(hWndServer, UWM_MOUSERBUTTONDOWN, 0 , 0); 
     break; 
     case WM_NCRBUTTONDOWN: 
      SendMessage(hWndServer, UWM_MOUSERBUTTONDOWN, 0 , 0); 
     break; 
     case WM_RBUTTONUP: 
      SendMessage(hWndServer, UWM_MOUSERBUTTONUP, 0 , 0); 
     break; 
     case WM_NCRBUTTONUP: 
      SendMessage(hWndServer, UWM_MOUSERBUTTONUP, 0 , 0); 
     break; 

    default: 
     break; 
    } 
    return CallNextHookEx(hook, nCode, wParam, lParam); 
} 

__declspec(dllexport) BOOL InstallHook(HWND hWndParent) 
{ 
    if(hWndServer != NULL) 
    return FALSE; // already hooked! 
    hook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)MouseMsgProc, 
          hInst, 0); 
if(hook != NULL) 
    { 
     hWndServer = hWndParent; 
     return TRUE; 
    } 
    return FALSE; 
} 


__declspec(dllexport) BOOL UnInstallHook( HWND hWndParent) 
{ 
    if(hWndParent != hWndServer || hWndParent == NULL) 
    return FALSE; 
    BOOL unhooked = UnhookWindowsHookEx(hook); 
    if(unhooked) 
    hWndServer = NULL; 
    return unhooked; 
    return TRUE; 
} 

BOOL APIENTRY DllMain(HMODULE hModule, 
         DWORD ul_reason_for_call, 
         LPVOID lpReserved 
        ) 
{ 
    switch (ul_reason_for_call) 
    { 
    case DLL_PROCESS_ATTACH: 
     hInst = hModule; 
      UWM_MOUSEMOVE = ::RegisterWindowMessage(UWM_MOUSEMOVE_MSG); 
      UWM_MOUSELBUTTONUP = ::RegisterWindowMessage(UWM_MOUSELBUTTONUP_MSG); 
      UWM_MOUSELBUTTONDOWN = ::RegisterWindowMessage(UWM_MOUSELBUTTONDOWN_MSG); 
      UWM_MOUSERBUTTONUP = ::RegisterWindowMessage(UWM_MOUSERBUTTONUP_MSG); 
      UWM_MOUSERBUTTONDOWN = ::RegisterWindowMessage(UWM_MOUSERBUTTONDOWN_MSG); 
      UWM_MOUSELDBCLICK = ::RegisterWindowMessage(UWM_MOUSELDBCLICK_MSG); 
    case DLL_THREAD_ATTACH: 
    case DLL_THREAD_DETACH: 
    case DLL_PROCESS_DETACH: 
     break; 
    } 
    return TRUE; 
} 

// Win32應用程序的main.cpp

#include "stdafx.h" 
#include "stdafx.h" 
#include <sstream> 
#include "strsafe.h" 
#include "../Hook/Hook.h" 


#define MAX_LOADSTRING 100 

// Global Variables: 
HINSTANCE hInst;        // current instance 
TCHAR szTitle[MAX_LOADSTRING];     // The title bar text 
TCHAR szWindowClass[MAX_LOADSTRING];   // the main window class name 

// Forward declarations of functions included in this code module: 
ATOM    MyRegisterClass(HINSTANCE hInstance); 
BOOL    InitInstance(HINSTANCE, int); 
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); 



//Mouse Events 
static UINT UWM_MOUSEDBCLICK = ::RegisterWindowMessage(UWM_MOUSELDBCLICK_MSG); 
static UINT UWM_MOUSELBUTTONUP = ::RegisterWindowMessage(UWM_MOUSELBUTTONUP_MSG);; 
static UINT UWM_MOUSELBUTTONDOWN = ::RegisterWindowMessage(UWM_MOUSELBUTTONDOWN_MSG); 
static UINT UWM_MOUSERBUTTONUP = ::RegisterWindowMessage(UWM_MOUSERBUTTONUP_MSG); 
static UINT UWM_MOUSERBUTTONDOWN = ::RegisterWindowMessage(UWM_MOUSERBUTTONDOWN_MSG); 
static UINT UWM_MOUSEMOVE = ::RegisterWindowMessage(UWM_MOUSEMOVE_MSG); 
// 
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, 
        _In_opt_ HINSTANCE hPrevInstance, 
        _In_ LPTSTR lpCmdLine, 
        _In_ int  nCmdShow) 
{ 
    UNREFERENCED_PARAMETER(hPrevInstance); 
    UNREFERENCED_PARAMETER(lpCmdLine); 

    // TODO: Place code here. 
    MSG msg; 
    HACCEL hAccelTable; 

    // Initialize global strings 
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); 
    LoadString(hInstance, IDC_ACTIONX, szWindowClass, MAX_LOADSTRING); 
    MyRegisterClass(hInstance); 

    // Perform application initialization: 
    if (!InitInstance (hInstance, nCmdShow)) 
    { 
     return FALSE; 
    } 

    hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_ACTIONX)); 

    // Main message loop: 
    while (GetMessage(&msg, NULL, 0, 0)) 
    { 
     if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
     { 
      TranslateMessage(&msg); 
      DispatchMessage(&msg); 
     } 

    } 

    return (int) msg.wParam; 
} 



// 
// FUNCTION: MyRegisterClass() 
// 
// PURPOSE: Registers the window class. 
// 
ATOM MyRegisterClass(HINSTANCE hInstance) 
{ 
    WNDCLASSEX wcex; 

    wcex.cbSize = sizeof(WNDCLASSEX); 

    wcex.style   = CS_HREDRAW | CS_VREDRAW; 
    wcex.lpfnWndProc = WndProc; 
    wcex.cbClsExtra  = 0; 
    wcex.cbWndExtra  = 0; 
    wcex.hInstance  = hInstance; 
    wcex.hIcon   = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ACTIONX)); 
    wcex.hCursor  = LoadCursor(NULL, IDC_ARROW); 
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); 
    wcex.lpszMenuName = MAKEINTRESOURCE(IDC_ACTIONX); 
    wcex.lpszClassName = szWindowClass; 
    wcex.hIconSm  = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); 

    return RegisterClassEx(&wcex); 
} 

// 
// FUNCTION: InitInstance(HINSTANCE, int) 
// 
// PURPOSE: Saves instance handle and creates main window 
// 
// COMMENTS: 
// 
//  In this function, we save the instance handle in a global variable and 
//  create and display the main program window. 
// 
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) 
{ 
    HWND hWnd; 

    hInst = hInstance; // Store instance handle in our global variable 

    hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, 
     CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); 

    if (!hWnd) 
    { 
     return FALSE; 
    } 

    ShowWindow(hWnd, nCmdShow); 
    UpdateWindow(hWnd); 


BOOL result=InstallHook(hWnd); 

    return TRUE; 
} 

// 
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM) 
// 
// PURPOSE: Processes messages for the main window. 
// 
// WM_COMMAND - process the application menu 
// WM_PAINT - Paint the main window 
// WM_DESTROY - post a quit message and return 
// 
// 
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    int wmId, wmEvent; 
    PAINTSTRUCT ps; 
    HDC hdc; 
//Global Mouse Move Handle 
    if(message==UWM_MOUSEMOVE){ 
    MessageBox(
     NULL, 
     (LPCWSTR)L"Resource not available\nDo you want to try again?", 
     (LPCWSTR)L"Account Details", 
     MB_ICONWARNING | MB_CANCELTRYCONTINUE | MB_DEFBUTTON2 
    ); 
    return 0; 
    } 
    switch (message) 
    { 

    case WM_COMMAND: 
     wmId = LOWORD(wParam); 
     wmEvent = HIWORD(wParam); 
     // Parse the menu selections: 
     switch (wmId) 
     { 
     case IDM_ABOUT: 
      DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); 
      break; 
     case IDM_EXIT: 
      DestroyWindow(hWnd); 
      break; 
       case IDM_PLAY: 
        PlayMouse(); 
      break; 
     default: 
      return DefWindowProc(hWnd, message, wParam, lParam); 
     } 
     break; 
    case WM_PAINT: 
     hdc = BeginPaint(hWnd, &ps); 
     // TODO: Add any drawing code here... 
     EndPaint(hWnd, &ps); 
     break; 
    case WM_DESTROY: 
     PostQuitMessage(0); 
     break; 
    default: 
     return DefWindowProc(hWnd, message, wParam, lParam); 
    } 
    return 0; 
} 

// Message handler for about box. 
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    UNREFERENCED_PARAMETER(lParam); 
    switch (message) 
    { 
    case WM_INITDIALOG: 
     return (INT_PTR)TRUE; 

    case WM_COMMAND: 
     if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
     { 
      EndDialog(hDlg, LOWORD(wParam)); 
      return (INT_PTR)TRUE; 
     } 
     break; 
    } 
    return (INT_PTR)FALSE; 
} 
+2

您還沒有標記一次回答你的問題。如果你不能得到你需要的答案,那麼在這裏繼續提問是沒有多大意義的。還有其他地方可以獲得幫助,例如你可以嘗試MSDN論壇。 –

+0

你有沒有遇到過這樣的問題?爲什麼Windows掛鉤僅處理應用程序消息?如何重拍它來處理全局鼠標消息?我見過這樣做的應用程序 –

+0

@TaronPro Hans完全不同一點:在本網站上詢問的25個問題中,您接受了4個答案。它似乎並沒有得到你在這個網站上找到的答案,所以你可能想在其他地方尋找幫助。 – IInspectable

回答

1

使用WH_MOUSE掛鉤僅掛鉤鼠標消息。

幾點建議:

  • 確保你鉤安裝成功(SetWindowsHookEx函數返回一個非NULL值)
  • 確保傳遞消息鉤子程序(設置斷點,以這些點或使用跟蹤功能)
  • 你或者需要將HWND的目標窗口發送到每個進程或發送廣播消息
  • 對於Windows Vista和更高版本的權限較低的進程無法發送消息以更高權限進行處理。您需要使用ChangeWindowMessageFilter必要的信息添加到過濾器
  • ,而不是SendMessage函數使用PostMesssage,你不需要在這裏阻塞調用反正
+0

設置鼠標捕捉用於不同的場景。設置鼠標捕捉時,您不會在窗口外部獲得鼠標**點擊**。 – IInspectable

+0

請提供在窗口外部獲得鼠標**點擊**的源代碼。 ** ** CLICKS。 – IInspectable

+0

好吧,你對鼠標的捕獲是正確的 – Andrey

-1

在定義你必須提供您想要攔截信號的窗口句柄掛鉤。也許傳遞桌面的句柄可以捕獲所有的鼠標事件,即使在客戶端窗口之外。

+0

在InstallHook函數中,我把參數hWndParent。是不是? –

+0

['SetWindowsHookEx'](http://msdn.microsoft.com/en-us/library/windows/desktop/ms644990.aspx)沒有'HWND'參數。你陳述的規則是完全組成的。 – IInspectable