如何在Windows中从鼠标挂钩设置光标位置?

How can I set cursor position from mouse hook in Windows?

本文关键字:置光标 位置 鼠标 Windows      更新时间:2023-10-16

我正在尝试创建一个小应用程序,它将检测当鼠标光标移动到屏幕的边缘,并将其移动到相反的边缘,以创建一个连续的桌面效果,如果这是有意义的。

下面是其他人的一些代码(鼠标钩子部分),我通过添加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;
}

这似乎是在钩子子程中调用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/.

看起来您需要转换坐标。根据文档,您需要调用ClientToScreenScreenToClient来翻译点。我不知道哪个窗口是参考。您需要将该窗口句柄作为点(作为输出参数)作为参数传递。然后用SetCursorPos

改变点

检查示例

如果您想要屏幕您需要执行GetDC(NULL)并将返回的句柄传递给ClientToScreen