Как записать расстояние, пройденное курсором мыши в приложении win32?

Я работаю над проектом по разработке рабочего стола Windows на C ++ с использованием Win32 API. В приложении я пытаюсь вычислить расстояние, пройденное курсором мыши, или вы можете сказать, что мышь ломается.

Удар курсора - или бегающий курсор или мышь - не каламбур для пользователя, который настолько разочарован, что теряет контроль над своими руками, выкрикивая ругательства. Скорее, Thrashed Cursor возникает, когда пользователи беспорядочно перемещают курсор вперед и назад.

Быстрое перемещение курсора по странице может указывать на то, что пользователя раздражает какой-то аспект своего опыта. Возможно, сайт работает медленно или они пытаются что-то понять. Thrashed Cursor подобен физическому проявлению некоторого психического состояния пользователя - и это состояние, скорее всего, может быть разочарованием. Как и все сигналы разочарования, с Thrashed Cursor существует вероятность ложного срабатывания. Например. возможно, у пользователя сломана мышь или его компьютер настолько медленный, что он в знак протеста ломает мышь. Единственный способ определить, сигнализирует ли обрушившийся курсор на разочарование, - это посмотреть сеанс и сделать некоторые наблюдения.

под мышечным движением я имею в виду, что хочу записать беспорядочное движение курсора мыши в поисках любой кнопки или инструмента, поэтому я хочу зарегистрировать общее расстояние, пройденное при этом неустойчивом движении.

И я хочу зарегистрировать эту информацию об этом сеансе и отправить ее на свой сервер в формате json.

Во время этой обработки пользователь может щелкнуть мышью, которая может генерировать WM_LBUTTONDOWN, но я использую это сообщение для выполнения некоторой функции, я не хочу, чтобы этот щелчок, когда пользователь был разочарован, чтобы вызвать эту конкретную функцию.

Я новичок в win32 разработке настольных компьютеров, если кто-нибудь может мне помочь.


person Nurav    schedule 13.05.2020    source источник
comment
Комментарии не подлежат расширенному обсуждению; этот разговор был перешел в чат.   -  person Samuel Liew♦    schedule 15.05.2020


Ответы (3)


Да, это именно то, что я хочу сделать, но я не знаю, как реализовать, что я думал регистрировать все координаты при перемещении мыши и вычислять общее расстояние.

SetWindowsHookEx и WH_MOUSE_LL может помочь вам в этом это.

Вы можете установить крючок для мыши, чтобы отслеживать движения мыши и вычислять расстояние между координатами мыши.

Код:

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

Отлаживать:

введите здесь описание изображения

person Strive Sun    schedule 15.05.2020
comment
можем ли мы сделать это на уровне пользователя? - person Nurav; 17.05.2020
comment
@Nurav Вы имеете в виду использование крючка мыши для конкретного пользователя? - person Strive Sun; 18.05.2020
comment
Нет, на самом деле он записывает полный экран монитора, я хочу записать область приложения. - person Nurav; 18.05.2020
comment
@Nurav Да, внедрить в целевую программу dll, содержащую перехватчик мыши. Смотрите мой обновленный. - person Strive Sun; 18.05.2020
comment
@Nurav Рад помочь вам :) - person Strive Sun; 18.05.2020
comment
не могли бы вы перепроверить мой ответ - person Nurav; 11.06.2020

Я все еще не понимаю, в чем проблема, но я перечислил несколько догадок внизу.

Вот пример основной идеи:

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;

Некоторые из моих предположений относительно вашей проблемы:

  • Ваше окно может не получать WM_MOUSEMOVE сообщений, когда указатель мыши перемещается (или захватывается) дочерним окном, но вы хотите их зарегистрировать.
  • Ваше окно захватывает мышь (возможно, когда вы получаете WM_LBUTTONDOWN), и это усложняет WM_MOUSEMOVE логику.
  • Вы пытаетесь провести различие между обмолачиванием и обмолачиванием и записывать только обмолачивание, но у нас (и, возможно, у вас) нет точного определения того, что такое обмолачивание.
  • Вы хотите, чтобы ваше приложение видело все движения мыши в сеансе Windows, а не только движение мыши в окне вашего приложения.
  • У вас случайно есть один случай в вашем операторе switch, который попадает в другой.

Если бы вы могли прояснить вопрос подробнее, мы, вероятно, могли бы вам помочь.

person Adrian McCarthy    schedule 13.05.2020

Это метод, который я нашел без явного написания .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);
person Nurav    schedule 11.06.2020
comment
Если это собственное окно win32, это приемлемое решение. Но если это другое окно, как вы получите WM_MOUSEMOVE? - person Strive Sun; 12.06.2020