2012-01-24 63 views
1
#include <windows.h> 
#include <process.h> 

HWND MainHwnd; 
HHOOK MouseHook; 
LRESULT CALLBACK WndProc(HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam); 
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow) 
{ 
    static wchar_t szAppName[]=L"hooks"; 
    HWND hwnd; 
    MSG msg; 
    WNDCLASSEX wndclass; 

    wndclass.cbSize=sizeof(wndclass); 
    wndclass.style=CS_HREDRAW|CS_VREDRAW; 
    wndclass.lpfnWndProc=WndProc; 
    wndclass.cbClsExtra=0; 
    wndclass.cbWndExtra=0; 
    wndclass.hInstance=hInstance; 
    wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION); 
    wndclass.hCursor=LoadCursor(NULL,IDC_ARROW); 
    wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); 
    wndclass.lpszMenuName=NULL; 
    wndclass.lpszClassName=szAppName; 
    wndclass.hIconSm=LoadIcon(NULL,IDI_APPLICATION); 

    RegisterClassEx(&wndclass); 

    MainHwnd=hwnd=CreateWindow(szAppName,L"hooks",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, 
     CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL); 
    ShowWindow(hwnd,SW_MAXIMIZE); 
    UpdateWindow(hwnd); 

    while(GetMessage(&msg,NULL,0,0)) 
    { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 
    return msg.wParam; 
} 
LRESULT CALLBACK LowLevelMouseProc(int nCode,WPARAM wParam,LPARAM lParam) 
{ 
    if (nCode==HC_ACTION) 
     ((LPMSLLHOOKSTRUCT)lParam)->flags=0; 
    return CallNextHookEx(NULL,nCode,wParam,lParam); 
} 
void thread(void *param) 
{ 
    for (int i=0;i<3;i++) 
    { 
     UnhookWindowsHookEx(MouseHook); 
     MouseHook=SetWindowsHookEx(WH_MOUSE_LL,reinterpret_cast<HOOKPROC>(LowLevelMouseProc),(HINSTANCE)GetWindowLong(MainHwnd,GWL_HINSTANCE),NULL); 
     for (int j=0;j<100;j++) 
     { 
       mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_MOVE, (j)*(65535.0/500),(j)*(65535.0/500),0,0); 
       Sleep(10); 
     } 
     Sleep(2000); 
    } 
} 
LRESULT CALLBACK WndProc(HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam) 
{ 
    HDC hdc; 
    PAINTSTRUCT ps; 
    switch(iMsg) 
    { 
    case WM_CREATE: 
     { 
      MouseHook=SetWindowsHookEx(WH_MOUSE_LL,reinterpret_cast<HOOKPROC>(LowLevelMouseProc),(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),NULL); 
      _beginthread(thread,0,0); 
      return 0; 
     } 
    case WM_PAINT: 
     { 
      hdc=BeginPaint(hwnd,&ps); 
      EndPaint(hwnd,&ps); 
      return 0; 
     } 
    case WM_DESTROY: 
     UnhookWindowsHookEx(MouseHook); 
     PostQuitMessage(0); 
     return 0; 
    } 
    return DefWindowProc(hwnd,iMsg,wParam,lParam); 
} 

我使用_beginthread创建线程。此线程模拟鼠标的移动并呼叫Sleep(2000)。模拟移动后,我无法移动鼠标。但是,如果我在void thread(void *param)钩子和线程,鼠标阻塞

UnhookWindowsHookEx(MouseHook); 
MouseHook=SetWindowsHookEx(WH_MOUSE_LL,reinterpret_cast<HOOKPROC>(LowLevelMouseProc),(HINSTANCE)GetWindowLong(MainHwnd,GWL_HINSTANCE),NULL);` 

程序注释这行会工作的时候,没有鼠标“堵”。每个人都可以解释它的原因吗?

回答

5

调用SetWindowsHookEx()设置低级别鼠标挂钩的线程必须泵送消息循环。必需的,以便Windows可以调用您注册的回调,以便它可以通知您鼠标消息。哪一个是你的问题,你开始的线程设置了一个钩子,但是不会抽取消息循环。

Windows可以防止类似这样的行为异常的程序,当它必须等待很长时间才能进行回调时它会自动销毁挂钩。但是你的线程睡了2秒,没有足够长的时间来触发超时。然后,您调用UnhookWindowsHookEx()来取消阻止Windows。但立即再次钩住。

在那个线程中调用SetWindowsHookEx()没有任何意义。只要将其删除,您在主线程中设置的钩子将正常运行。很难看到一般顺便说一句。