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

瘦欲@ 提交于 2019-12-24 00:54:13

问题


I'm trying to create a little app that will detect when the mouse cursor moves to the edge of the screen and will move it to the opposite edge, to create a continuous desktop effect, if that makes sense.

Below is some code from someone else (the mouse hook part) I adapted by added the SetCursorPos to move the mouse to a fixed position for now. When I run it, SetCursorPos returns true, which I assume means the call succeeded, but the mouse does not move. I read somewhere something about security constraints in later Windows version preventing stuff like this, which would make sense, but the source was unclear to how true this is. Does anyone know why this would not work?

Thanks, code below:

#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;
}

回答1:


This appears to be a problem with calling SetCursorPos inside your hook proceedure. I guess this is explicitly prohibted in Vista/Windows 7, but I couldn't find any documentation to confirm that. I modified your code slightly to post a thread message when it wants to move the cursor, and do the actual SetCursorPos inside your message proceedure. It works fine once this is done.

In your hook procedure:

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

In your message loop:

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

(Note this is just a demonstration, not an actual fix.)

That being said, there are numerous, serious problems with your code. I don't think it's appropriate to go into all of them here, but I recommend you post it on https://codereview.stackexchange.com/.




回答2:


Looks like you need to translate coordinates. as per docs you need to call ClientToScreen or ScreenToClient to translate the point. I don't know which Window is the reference. You need to pass that window handle as point (as out parameter) as parameter. and then use the altered point with SetCursorPos

check example

If you want the Screen You need to do GetDC(NULL) and pass the returned handle to ClientToScreen



来源:https://stackoverflow.com/questions/14439491/how-can-i-set-cursor-position-from-mouse-hook-in-windows

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!