2013-01-21 157 views
2

當我談到C++的時候,我很新手,所以對我一無所知。我正在嘗試創建一個小應用程序,該應用程序將檢測鼠標光標移動到屏幕邊緣並將其移動到相反的邊緣,以創建連續的桌面效果,如果這樣做合理的話。如何從Windows中的鼠標鉤子設置光標位置?

下面是我通過添加SetCursorPos將鼠標移動到固定位置的其他人的代碼(鼠標鉤子部分)。當我運行它時,SetCursorPos返回true,我認爲這意味着調用成功,但鼠標不移動。在稍後的Windows版本中,我在某處讀了一些關於安全限制的內容,以防止這樣的事情發生,這很有道理,但消息來源並不清楚這是多麼真實。有誰知道爲什麼這不起作用?

謝謝,下面的代碼:

#define _WIN32_WINNT 0x0400 
#pragma comment(lib, "user32.lib") 

#include <windows.h> 
#include <stdio.h> 

HHOOK hMouseHook; 

__declspec(dllexport) LRESULT CALLBACK KeyboardEvent (int nCode, WPARAM wParam, LPARAM lParam) 
{ 
    MOUSEHOOKSTRUCT * pMouseStruct = (MOUSEHOOKSTRUCT *)lParam; 
    if (pMouseStruct != NULL) 
    { 
     if (pMouseStruct->pt.x < -1900) 
     { 
      BOOL r = SetCursorPos(
       500, 
       500 
      ); 

      printf("Trigger %d. Response %d", pMouseStruct->pt.x, r); 
     } 
    } 

    return CallNextHookEx(hMouseHook, nCode, wParam, lParam); 
} 

void MessageLoop() 
{ 
    MSG message; 
    while (GetMessage(&message,NULL,0,0)) { 
     TranslateMessage(&message); 
     DispatchMessage(&message); 
    } 
} 

DWORD WINAPI MyMouseLogger(LPVOID lpParm) 
{ 
    HINSTANCE hInstance = GetModuleHandle(NULL); 
    if (!hInstance) hInstance = LoadLibrary((LPCSTR) lpParm); 
    if (!hInstance) return 1; 

    hMouseHook = SetWindowsHookEx ( 
     WH_MOUSE_LL, 
     (HOOKPROC) KeyboardEvent, 
     hInstance,     
     NULL      
     ); 
    MessageLoop(); 
    UnhookWindowsHookEx(hMouseHook); 
    return 0; 
} 

int main(int argc, char** argv) 
{ 
    HANDLE hThread; 
    DWORD dwThread; 

    hThread = CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE) 
     MyMouseLogger, (LPVOID) argv[0], NULL, &dwThread); 
    if (hThread) 
     return WaitForSingleObject(hThread,INFINITE); 
    else return 1; 
} 
+0

你是否從你的printfs得到任何輸出? – drescherjm

+0

你也可以嘗試一些比-1900更大的東西來測試。 – drescherjm

+0

@drescherjm這是-1900,因爲那是我的左手顯示器左側20個左右的像素。我的printf吐出下面的「觸發-1917。響應1」等。我拿「響應1」表示呼叫沒有失敗,但鼠標不移動。這可能與單獨的線程有關嗎?如果我在程序的開始處(掛鉤之前)將SetCursorPos呼叫保持正確,則呼叫成功。 –

回答

3

這似乎是一個問題,叫裏面SetCursorPos您勾手。我想這是明確禁止在Vista/Windows 7中,但我找不到任何文件來確認。我稍微修改了你的代碼,當它想要移動光標時發佈一條線程消息,並在你的消息過程中執行實際的SetCursorPos。一旦完成,它就可以正常工作。

在你的鉤子程序:

if (pMouseStruct->pt.x < -1900) 
    { 
     PostThreadMessage(GetCurrentThreadId(), WM_USER, 0, 0); 
     printf("Trigger %d. Response %d", pMouseStruct->pt.x, r); 
    } 

在您的消息循環:

while (GetMessage(&message,NULL,0,0)) { 
    if(message.hwnd == NULL) { 
     if(message.message == WM_USER) { 
      SetWindowPos(500, 500); 
     } 
    } else { 
     TranslateMessage(&message); 
     DispatchMessage(&message); 
    } 
} 

(注意:這僅僅是一個示範,並非實際修復)

話雖這麼說,你的代碼有很多嚴重的問題。我認爲不適合在這裏介紹所有這些內容,但我建議您將其張貼在https://codereview.stackexchange.com/上。

+0

謝謝彼得,試過這個,它工作。我意識到代碼是可怕的,它意味着我想稍後可能會做的一個不好的原型,但不知道什麼SetCursorPos不起作用。再次謝謝,史蒂夫。 PS不知道codereview,絕對有用! –

0

看起來你需要轉換座標。 根據文檔,您需要撥打ClientToScreenScreenToClient來翻譯這一點。我不知道哪個窗口是參考。您需要將該窗口句柄作爲參數傳遞(作爲out參數)。然後使用更改後的點與SetCursorPos

檢查example

如果你想在屏幕您需要做GetDC(NULL)和返回的句柄傳遞給ClientToScreen

+0

對不起,我不確定我的理解。你指的是哪些文檔?爲什麼我需要一個窗口?我只是想這是一個簡單的應用程序,監控全球鼠標位置。事件方法正確地在屏幕座標中接收鼠標位置。 SetCursorPos需要屏幕座標。爲什麼我需要翻譯? –

+0

http://msdn.microsoft.com/en-us/library/aa931003.aspx –