2013-01-21 128 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 –