如何通过Windows获得(真正的)鼠标位移

时间:2012-01-01 22:24:13

标签: c++ winapi

我想知道如何通过Windows获得真正的鼠标位移。

例如,我可以保存前一个鼠标位置的位置,并请求新位置,并从前一个位置减去后一个位置。但这不会给我真正的鼠标移位。

想象一下,前一个光标位置是屏幕分辨率的最大x坐标,用户将鼠标移到右侧。还有办法捕获真正的鼠标移位吗?

由于

6 个答案:

答案 0 :(得分:2)

尽管可能实际读取传感器数据(在所有鼠标本身仅报告移动而不是位置之后),我不知道如何做到这一点。我认为在非常低级别的窗口中,位移信息会转换为屏幕上的光标位置,从那时起,您将始终受到屏幕分辨率的限制。

无论你想做什么,鼠标光标是否仍然可见?

不久前,我编写了一个WPF数字编辑框控件,模仿了这些控件在Expression Blend中的工作方式。您可以从编辑框本身拖动鼠标,它将更改值。我遇到了与您发现的完全相同的问题,我的解决方案是隐藏鼠标光标,检测每个刻度上的位移并将光标重置到屏幕中心。然后,当用户放开按钮停止拖动时,我会将光标放回到拖动前我找到的位置。这非常好,Expression Blend在隐藏光标时也表现得这样。

答案 1 :(得分:1)

据我所知,DirectX有自己的API与外围设备进行交互,建议游戏开发人员使用。您应该调查一下 - 例如DirectX 8 and the Mouse,您可以找到更详细的文档on MSDN

答案 2 :(得分:0)

这种位移? :http://en.wikipedia.org/wiki/Differential_calculus

尝试俯仰/偏航:How could simply calling Pitch() and Yaw() cause the camera to eventually Roll()?

FPS风格:http://cboard.cprogramming.com/game-programming/94944-mouse-input-aiming-fps-style-using-glut.html

并且:Jittering when moving mouse

伪代码:

int mouseX, mouseY;     
int oldMouseX, oldMouseY;

while(game_is_Running)
{
    oldMouseX = mouseX;
    oldMouseY = mouseY;

    mouseX = get_new_mouse_from_windows_X();
    mouseY = get_new_mouse_from_windows_Y();

    if ((mouseX - oldMouseX) > 0) 
    {
       // mouse moved to the right
    }

    else if ((mouseX - oldMouseX) < 0) 
    {
        // mouse moved to the left
    }



    if ((mouseY - oldMouseY) < 0)
    {
        // mouse moved  down 


    }

    else if ((mouseY - oldMouseY) > 0)   
    {
        // mouse moved    up  


    }

}

答案 3 :(得分:0)

这种常见方法(在游戏中):

游戏的每一帧,获取鼠标的位置,然后使用操作系统功能将鼠标重新放在窗口中间。对于除第一帧以外的每个帧,这应该为您提供准确的位移信息。关键是每帧重新定位鼠标,使其永远不会到达屏幕的阻挡外边界。

编辑:Woops,没有意识到DXM已经说过这个。

答案 4 :(得分:0)

最可靠的方法是使用窗口挂钩。这是一个使用C(++)

的极简主义样本
LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam){
    MSLLHOOKSTRUCT* hookStruct = (MSLLHOOKSTRUCT*)lParam;
    int ScreenWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN); 
    int ScreenHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
    int x = hookStruct->pt.x * ScreenWidth / 65536);
    int y = hookStruct->pt.y * ScreenHeight / 65536);
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

HHOOK LowLevelMouseProcHook = NULL;

void hook_window_procedure()
{
    if (LowLevelMouseProcHook == NULL)
        LowLevelMouseProcHook = SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)LowLevelMouseProc, (HINSTANCE)NULL, NULL);    
}

void unhook_window_procedure()
{
    if (LowLevelMouseProcHook != NULL)
        UnhookWindowsHookEx(LowLevelMouseProcHook);     
}

你可以勾住调用hook_window_procedure();的鼠标,并通过调用unhook_window_procedure();取消挂钩

只要鼠标移动,您就会收到void LowLevelMouseProc(...)的来电。 lParam包含指向MSLLHOOKSTRUCT的指针,您可以在其结构中找到所有需要的鼠标信息。这里最有趣的是POINT pt;,它在相对屏幕坐标中,假设屏幕的1/65536。通过乘以int ScreenWidthint ScreenHeight并除以65536

,将它们转换为实际像素

如果您难以被屏幕边框夹住,可以在每次调用时将鼠标设置回窗口中心。这在老游戏中经常出现。如果您不想仅使用Windows API,我会尝试使用直接输入。

另一种方法是直接在WindowProc中评估WM_INPUT。这直接从人机接口设备(HID)堆栈读取数据,并且其中应包含原始鼠标数据。以下是MS-Documentation

的链接

答案 5 :(得分:-1)

使用Windows API无法跟踪物理鼠标位移。但是,DirectInput提供了跟踪它的功能。你也可以使用Windows API来“伪造”它,使用SO用户DXM答案中的巧妙小技巧