如何在 win32 应用程序中记录鼠标光标移动的距离?

How to record the distance travelled by my mouse cursor in win32 application?

我正在使用 win32 API 在 C++ 中进行 windows 桌面开发项目。在应用程序中,我试图计算鼠标光标移动的距离,或者你可以说鼠标抖动.

Thrashed Cursor(或 thrashing cursor or mouse)并不是对用户的双关语,因为他们非常沮丧,以至于他们在大喊大叫时失去了对手臂的控制。相反,Thrashed Cursor 是指用户不规律地来回移动光标。

在页面上快速移动光标可能表明用户对他们体验的某些方面感到恼火。也许网站性能很慢,或者他们正在努力解决问题。 Thrashed Cursor 就像是用户某种心理状态的物理流露——这种状态很可能是沮丧。与所有挫折信号一样,Thrashed Cursor 也有可能出现误报。例如。也许用户的鼠标坏了,或者他们的计算机速度太慢以至于他们用鼠标来抗议。推断 Thrashed Cursor 是否表示沮丧的唯一方法是观看会话并进行一些观察。

通过鼠标抖动我的意思是我想记录鼠标光标在搜索任何按钮或工具时的不稳定移动,所以我想记录在这种不稳定移动中移动的总距离。

我想记录本次会话的信息,并以 json 格式将其发送到我的服务器。

在此抖动期间,用户可能会单击鼠标,这可能会生成 WM_LBUTTONDOWN 但我正在使用该消息来执行某些功能,我不希望在用户因调用该特定功能而感到沮丧时进行单击。

如果有人能帮助我,我是 win32 桌面开发的新手。

我还不清楚问题是什么,但我在底部列出了几个猜测。

这里有一个基本思想的例子:

case WM_MOUSEMOVE:
    POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
    LogMouseMovementForTracking(pt);
    WhateverOtherStuffYouWantToDoWhenTheMouseMoves(pt);
    break;

case WM_LBUTTONDOWN:
    // You don't have to do tracking here.  You will almost certainly have
    // received a WM_MOUSEMOVE that brings you to the click before the
    // system sends you the WM_LBUTTONDOWN.
    WhateverYouWantToDoWhenTheButtonIsPressed();
    break;

我对您遇到的问题的一些猜测:

  • 当鼠标移到 child window 上(或被其捕获)时,您的 window 可能不会收到 WM_MOUSEMOVE 消息,但您想记录这些消息。
  • 您的 window 正在捕获鼠标(也许当您获得 WM_LBUTTONDOWN 时),这使得 WM_MOUSEMOVE 逻辑更加复杂。
  • 您试图区分抖动和 non-thrashing 并仅记录抖动,但我们(可能还有您)对抖动是什么没有准确的定义。
  • 您希望您的应用程序看到 Windows 会话的所有鼠标移动,而不仅仅是应用程序中的鼠标移动 window。
  • 您不小心让 switch 语句中的一个 case 落入另一个 case。

如果你能进一步澄清问题,我们可能会帮助你。

是的,这正是我想要做的,但我不知道如何实现,我想在鼠标移动时记录所有坐标并计算总距离。

SetWindowsHookEx and WH_MOUSE_LL可以帮你做到这一点。

可以安装mouse hook来监听鼠标移动,计算鼠标坐标之间的距离

代码:

#include <Windows.h>
#include <iostream>
#include <vector>

using namespace std;

HHOOK mouseHook;
std::vector<POINT> pt;
POINT p1 = { 0 };
BOOL flag = 1;
int x = 0, y = 0;
int dis = 0;
LRESULT __stdcall MouseHookCallback(int nCode, WPARAM wParam, LPARAM lParam)
{  
    if (nCode >= 0)
    {
        switch (wParam)
        {
        case WM_MOUSEMOVE:
            MSLLHOOKSTRUCT* MSLStruct = (MSLLHOOKSTRUCT*)lParam;
            pt.push_back(MSLStruct->pt);

            if (flag)
            {
                p1 = pt.back();
                flag = 0;
            }
            x = abs(pt.back().x - p1.x);
            y = abs(pt.back().y - p1.y);
            dis+=sqrt(x*x +y*y);
            p1 = pt.back();

            cout << dis << endl;

            return 0;
        }
    }
    return CallNextHookEx(mouseHook, nCode, wParam, lParam);
}

void SetHook()
{
    if (!(mouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookCallback, NULL, 0)))
    {
        cout << "Failed to install mouse hook!" << endl;
    }
}

void ReleaseHook()
{
    UnhookWindowsHookEx(mouseHook);
}


int main()
{   
    SetHook();
    MSG msg;

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;

    ReleaseHook();
}

调试:

更新:

.dll

// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include <windows.h>
#include <iostream>
#include <stdio.h>
#include <vector>

HINSTANCE hinst;
#pragma data_seg(".shared")
HHOOK hhk;
#pragma data_seg()

std::vector<POINT> pt;
POINT p1 = { 0 };
BOOL flag = 1;
int x = 0, y = 0;
int dis = 0;

LRESULT CALLBACK wiremouseProc(int code, WPARAM wParam, LPARAM lParam) {
    if (code >= 0)
    {
        switch (wParam)
        {
        case WM_MOUSEMOVE:
            MSLLHOOKSTRUCT* MSLStruct = (MSLLHOOKSTRUCT*)lParam;
            pt.push_back(MSLStruct->pt);

            if (flag)
            {
                p1 = pt.back();
                flag = 0;
            }
            x = abs(pt.back().x - p1.x);
            y = abs(pt.back().y - p1.y);
            dis += sqrt(x * x + y * y);
            p1 = pt.back();

            std::cout << dis << std::endl;

            return 0;
        }
    }
    return CallNextHookEx(hhk, code, wParam, lParam);
}

extern "C" __declspec(dllexport) void install(unsigned long threadID) {
    hhk = SetWindowsHookEx(WH_MOUSE, wiremouseProc, hinst, threadID);
}
extern "C" __declspec(dllexport) void uninstall() {
    UnhookWindowsHookEx(hhk);
}

BOOL WINAPI DllMain(__in HINSTANCE hinstDLL, __in  DWORD fdwReason, __in  LPVOID lpvReserved) {
    hinst = hinstDLL;
    return TRUE;
}

.cpp

#include <Windows.h>
#include <stdio.h>
#include <tchar.h>

unsigned long GetTargetThreadIdFromWindow(const char* className, const char* windowName)
{
    HWND targetWnd;
    HANDLE hProcess;
    unsigned long processID = 0;

    targetWnd = FindWindow(className, windowName);
    return GetWindowThreadProcessId(targetWnd, &processID);
}

int main() {
    unsigned long threadID = GetTargetThreadIdFromWindow("Notepad", "1.txt - Notepad"); // Use Notepad for test
    printf("TID: %i", threadID);

    HINSTANCE hinst = LoadLibrary(_T("D:\Test_WH_MOUSE\Mydll\Debug\Mydll.dll"));

    if (hinst) {
        typedef void (*Install)(unsigned long);
        typedef void (*Uninstall)();

        Install install = (Install)GetProcAddress(hinst, "install");
        Uninstall uninstall = (Uninstall)GetProcAddress(hinst, "uninstall");

        install(threadID);

        MSG msg = {};

        while (GetMessage(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        uninstall();
    }

    return 0;
}

调试:

这是我找到的方法,没有显式写.dll和获取进程线程的函数。 并且不使用鼠标挂钩。

  std::vector<POINT> pt;
    POINT p1 = { 0 };
    BOOL flag = 1;
    int x = 0, y = 0;
    int dis = 0;  



case WM_MOUSEMOVE:
            GetCursorPos(&point);
            pt.push_back(point);
            if (flag)
            {
                p1 = pt.back();
                flag = 0;   
            }
            x = abs(pt.back().x - p1.x);
            y = abs(pt.back().y - p1.y);
            dis += sqrt(x * x + y * y);
            p1 = pt.back();
            wchar_t waCoord1[20];
            wsprintf(waCoord1, _T("(%i)"), dis);
            OutputDebugString(waCoord1);