Russian Qt Forum

Qt => Вопросы новичков => Тема начата: virtual_root от Июль 02, 2012, 13:34



Название: События перемещения мыши
Отправлено: virtual_root от Июль 02, 2012, 13:34
Добрый день. Ребята подскажите,пожалуйста, как мне решить следующую задачу:
Требуется ловить события перемещения мыши вне моей программы. Не по таймеру, а каждое перемещение отлавливать и вызывать соответствующую функцию. Может в QT есть решения для этого,чтобы WinAPI не использовать?


Название: Re: События перемещения мыши
Отправлено: Bepec от Июль 02, 2012, 13:39
Это платформо зависимый код нужен.
Qt это вроде как не позволяет, кроме как таймером.

И вообще - чем тебе winApi ненравится???


Название: Re: События перемещения мыши
Отправлено: Alex Custov от Июль 02, 2012, 14:04
только через платформо-зависимый код


Название: Re: События перемещения мыши
Отправлено: virtual_root от Июль 03, 2012, 09:25
А может вы подскажите как это через winAPI реализовать? С помощью хуков не подходит, так как попросили без перехвата мыши...
Я читала что можно через системные события сделать. Кто-нибудь работал с системными событиями, можете,пожалуйста, подсказать, как с ними работать.


Название: Re: События перемещения мыши
Отправлено: Bepec от Июль 03, 2012, 09:35
Уважаемый. Как вы собираетесь ПЕРЕХВАТЫВАТЬ события передвижения мыши, БЕЗ ПЕРЕХВАТА событий мыши?


Название: Re: События перемещения мыши
Отправлено: virtual_root от Июль 03, 2012, 09:49
мне нужно как-бы подписаться на это событие. Завести соответствующее событие в системе и ловить, а как мне это сделать?
Я наверное чего-то не понимаю. Для создания события в windows я использую:
Код:
event = CreateEvent( NULL, FALSE, FALSE, NULL );
А где мне указать что меня интересует событие перемещения мыши, чтобы можно было допутим в бесконечном цикле его ожидать?


Название: Re: События перемещения мыши
Отправлено: Bepec от Июль 03, 2012, 10:06
Кхм... Вы походу многое путаете...
Чтобы перехватить событие нужен хук.
КреатеЕвент - создаёт событие. Не перехватывает, не изменяет, не подписывается, а создаёт.

Вы или многого не понимаете, или знаете что-то о чём незнаю я (ну и заодно со мной msdn :D)


Название: Re: События перемещения мыши
Отправлено: virtual_root от Июль 03, 2012, 10:24
Верес, помогите мне пожалуйста разобраться!) Как мне получать событие перемещения мыши без её перехвата? Или это попросту не возможно? Я думала, что нужно просто подписаться на это событие,правда не знаю как...) в гугле что-то не могу найти похожего решения, только с хуками.


Название: Re: События перемещения мыши
Отправлено: Bepec от Июль 03, 2012, 10:42
Уважаемый. Как вы собираетесь ПЕРЕХВАТЫВАТЬ события передвижения мыши, БЕЗ ПЕРЕХВАТА событий мыши?

Прочитайте слова, выделенные синим :) Если они вас не смутят, тогда вы аки бог.

Чтобы получать события мыши - нужно поставить хук. В вашем случае нужен глобальный хук.

Хук - это как раз функция, которая вызывается при перехвате событий, указанных в её параметрах(ну при инициализации).
Собственно хук вам и нужен.

А "Строить не строя" и "Ломать не ломая" - это уже к всевышнему. Он такие чудеса может делать :)


Название: Re: События перемещения мыши
Отправлено: virtual_root от Июль 03, 2012, 10:49
спасибо большое!)


Название: Re: События перемещения мыши
Отправлено: virtual_root от Июль 03, 2012, 12:45
Ребята, помогите, кто знает разобраться с хуками.
Мне нужно создать хук, который перехватывает событие перемещения мыши вне области программы.
Почитав на форумах и в msdn, я написала следующий код:
dll библиотека, в которой содержится фун-я обработчик события для хука:
файл .h:
Код:
#ifndef HOOKFUNCTIONS_H
#define HOOKFUNCTIONS_H

#include "hookFunctions_global.h"


class HOOKFUNCTIONSSHARED_EXPORT HookFunctions {
public:
    int cxPoint;
    int cyPoint;
    HookFunctions();
    LRESULT CALLBACK MouseHook(int nCode,WPARAM wParam,LPARAM lParam);
    int x();
    int y();
    FILE *file;
    long buffer[100];
    int numwritten;

};

#endif // HOOKFUNCTIONS_H

файл .cpp:
Код:
#include "hookfunctions.h"


HookFunctions::HookFunctions()
{
}
 // функция-фильтр, которая обрабатывает наш хук.
LRESULT CALLBACK HookFunctions::MouseHook(int nCode,WPARAM wParam,LPARAM lParam)
{
 if((HC_ACTION == nCode))
 {
     cxPoint = LOWORD(lParam);  // извлекаем младший байт, это и есть координата х мыши
     cyPoint = HIWORD(lParam); // извлекаем старший байт, это и есть координата у мыши
     if (fopen("test.txt","a+")){
         numwritten = fwrite((char *)buffer, sizeof(long), 100,file);
         fclose(file);
     }
 }
 return CallNextHookEx(0, nCode, wParam, lParam);
}

int HookFunctions::x(){
    return cxPoint;
}

int HookFunctions::y(){
    return cyPoint;
}

файл main.cpp в котором я и создаю хук:
Код:
#include <iostream>
#include <windows.h>

using namespace std;

int main()
{
  
    HOOKPROC hkprcSysMsg;
    static HINSTANCE hinstDLL;
    static HHOOK hhookSysMsg;

    hinstDLL = LoadLibrary(TEXT("hookFunctions.dll"));
    hkprcSysMsg = (HOOKPROC)GetProcAddress(hinstDLL, "MouseHook"); // MouseHook функция из библиотеки

    hhookSysMsg = SetWindowsHookEx(
                        WH_MOUSE,
                        hkprcSysMsg,
                        hinstDLL,
                        0);

    return 0;
}

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


Название: Re: События перемещения мыши
Отправлено: Bepec от Июль 03, 2012, 13:14
Да можно.
Вот только что вы тут творите я не очень понимаю :D

Даже не так - вообще не понимаю :D И мейн у вас закрывается мгновенно, не так ли?
А то, что функция для хука у вас в классе - ну незнаю. Никогда так не делал :D
И функция в dll у вас не экспортирована похоже...

Что сказать - эммм... откуда вы это содрали? :D


Название: Re: События перемещения мыши
Отправлено: virtual_root от Июль 03, 2012, 13:37
Вы не поверите, не откуда, сама написала. Я совсем запуталась с этими хуками. Просто прочла в msdn и здесь http://www.rsdn.ru/article/baseserv/apicallsintercepting.xml
И как мне показалось что нужно обязательно dll-ку делать. Если можно без неё я буду счастлива, только как это сделать? Я просто создала консольный проектик, чтоб поучиться работать с хуками.
Переписала код так:
Код:
#include <iostream>
#include <windows.h>


using namespace std;
LRESULT CALLBACK MouseHook(int nCode, WPARAM wParam, LPARAM lParam)
{
    int x = LOWORD(lParam);  // извлекаем младший байт, это и есть координата х мыши
    int y = HIWORD(lParam); // извлекаем старший байт, это и есть координата у мыши
    cout<< x <<y;
    return 0;
}
int main()
{
    static HHOOK hhookSysMsg;

    hhookSysMsg = SetWindowsHookEx(WH_MOUSE,MouseHook,GetModuleHandle(NULL),0);

    return 0;
}
Проект собирается, но результата никакого. Координаты мыши в консоль не выводятся...
Что я не так снова сделала?  :)
Может нужно вместо WH_MOUSE что-то другое указать, чтобы отлавливать перемещения мыши ?


Название: Re: События перемещения мыши
Отправлено: Bepec от Июль 03, 2012, 13:41
Ожидайте ответа через ммм... 15-20 минут. Не раньше )


Название: Re: События перемещения мыши
Отправлено: virtual_root от Июль 03, 2012, 13:46
буду ждать) спасибо вам за терпение)) :)


Название: Re: События перемещения мыши
Отправлено: Bepec от Июль 03, 2012, 14:34
Это  код устанавливающий хук.
Код:
   
/*static HINSTANCE hLib;
    static HHOOK hHook;*/
HOOKPROC hProc = NULL;
   
    hLib = LoadLibrary("keyhook");
    _ASSERTE(hLib);

    hProc = (HOOKPROC)GetProcAddress(hLib, "HookProcMouse"); 
    _ASSERTE(hProc);

    hHook = SetWindowsHookEx(WH_MOUSE, hProc, hLib, NULL);                     
    _ASSERTE(hHook);
Файл библиотечки (у меня dl.cpp)
Код:
#include "stdafx.h"
#include <atltypes.h>
#include <fstream>

#define __GLOBAL_HOOK

extern "C" __declspec(dllexport)
LRESULT CALLBACK HookProcMouse(int nCode, WPARAM wParam, LPARAM lParam)
{
// если сообщение не удалено из очереди(не особо заморачивайтесь по этому поводу)
if (nCode != HC_ACTION ) 
return CallNextHookEx(NULL, nCode, wParam, lParam);

// Если событие передвижения мыши
if (wParam == WM_MOUSEMOVE)
{
// то получаем указатель на структуру
MOUSEHOOKSTRUCT *tmp = (MOUSEHOOKSTRUCT*)lParam;
// открываем файл для записи, записываем и закрываем(координаты x и y)
std::ofstream out("c:/123", std::ios::app);
out << xs << tmp->pt.x << tmp->pt.y << std::endl;
out.close();

}
else
{
// иначе если сообщение другого типа, создаём 321, пишем, закрываем
std::ofstream out("c:/321", std::ios::app);
           char xs = wParam;
           out << xs  << std::endl;
              out.close();
}


// передаём следующему хуку по цепочке(не вашим хукам, а уже чужим)
return CallNextHookEx(NULL, nCode, wParam, lParam);
}

Деф файл dl.def - он позволяет задать точные имена экспортируемым функциям. Если его не будет, название ф-ции будет что-то типа 1@HookProcMouse1@2 рандомно.
Код:
LIBRARY "dl"
DESCRIPTION  'keyhook Windows Dynamic Link Library'

EXPORTS
    ; Explicit exports can go here
HookProcMouse

В принципе и всё )


Название: Re: События перемещения мыши
Отправлено: virtual_root от Июль 03, 2012, 15:16
спасибо большое, сейчас буду пробовать к себе в qt это всё применить.


Название: Re: События перемещения мыши
Отправлено: virtual_root от Июль 04, 2012, 10:25
Верес, подскажите мне ещё разок пожалуйста. Я сделала снова библиотеку как у вас. Но я не знаю как мне в Qt .def файл привязать к библиотеки, как это сделать? У меня проект вылетает с ошибкой на assert(hProc). Я так понимаю это он не может найти функцию?
и ещё мне пришлось так заменить строку с подключением библиотеки:
Код:
hLib = LoadLibrary(L"libMouseAPI");
Ну думаю это ничего не меняет? Сам dll файл лежит рядом с .exe файлом программы где я подключаю его.


Название: Re: События перемещения мыши
Отправлено: Bepec от Июль 04, 2012, 10:48
LoadLibrary загружает библиотеку из файла с названием, которое вы укажете :) Название должно совпадать с названием dll.

hProc выдаёт ассерт - значит у вас не находится функция, экспортируемая из dll.

Откройте тоталкоммандер и нажмите ф3 на вашей dll. Там должна вкладочка быть import/export. В нижнем поле указано будет название вашей функции. Если def  не подцепился, то оно будет отличаться от заданного в программе.

Если нет Тотала, то dependency walker вам в помощь.

Почитать про деф файл:
http://msdn.microsoft.com/ru-ru/library/d91k01sh.aspx


Название: Re: События перемещения мыши
Отправлено: virtual_root от Июль 04, 2012, 12:32
У меня ничего не выходит.. уже два дня бьюсь над ней..
Переписала в таком виде:
Код:
#include <QtCore/QCoreApplication>
#include <windows.h>
#include <assert.h>
#include <cassert>
#include <QLibrary>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    
    QLibrary myLib("./libMouseAPI");

    myLib.load();
    myLib.loadHints();

    if (!myLib.isLoaded())
        exit(0);

    typedef LRESULT CALLBACK (*MyPrototype)(int, WPARAM, LPARAM);
    MyPrototype myFunction = (MyPrototype) myLib.resolve("HookProcMouse");

    if (!myFunction)
        exit(0);

    static HHOOK hHook;

        hHook = SetWindowsHookEx(WH_MOUSE, myFunction, GetModuleHandle(NULL), NULL);
        assert(hHook);

    return a.exec();
}

Проверила под дебагом, библиотека загружается, фун-ю видит, но когда запускаю падаю в
Код:
assert(hHook);
Наверное я что-то неправильно указываю в фун-и:
Код:
SetWindowsHookEx(WH_MOUSE, myFunction, GetModuleHandle(NULL), NULL);
Как мне её правильно оформить, чтобы она принимала мой указатель на функцию?
И ещё вопросик, Верес, вы не подскажите, а можно как-то без dll обойтись всё в одном файле сделать?
И то что у меня консольный проект не играет никакой роли?


Название: Re: События перемещения мыши
Отправлено: Bepec от Июль 04, 2012, 12:40
Консольный - вообще никакой разницы.
Dll необлходима для глобального хука. Без dll глобальный хук не сделашь. Только в своей программе.

Выкладывайте свой проект, будем смотреть.


Название: Re: События перемещения мыши
Отправлено: virtual_root от Июль 04, 2012, 12:50
ой, спасибо :)
Вот библиотека и проект. Буду ждать)


Название: Re: События перемещения мыши
Отправлено: Bepec от Июль 04, 2012, 13:18
А вы уверены, что второй проект у вас компилится?


Название: Re: События перемещения мыши
Отправлено: virtual_root от Июль 04, 2012, 13:33
да, компилировался. Но когда запускался падал с assert(hHook);
Сейчас сделала локальный хук, в том же проекте изменила файл main.cpp. Вот что получилось:
Код:
#include <QtCore/QCoreApplication>
#include <windows.h>
#include <assert.h>
#include <cassert>
#include <QLibrary>
#include <fstream>
#include <QDebug>

LRESULT CALLBACK HookProcMouse(int nCode, WPARAM wParam, LPARAM lParam)
{
// если сообщение не удалено из очереди(не особо заморачивайтесь по этому поводу)
    if (nCode != HC_ACTION )
        return CallNextHookEx(NULL, nCode, wParam, lParam);

// Если событие передвижения мыши
    if (wParam == WM_MOUSEMOVE)
    {
// то получаем указатель на структуру
        MOUSEHOOKSTRUCT *tmp = (MOUSEHOOKSTRUCT*)lParam;
// открываем файл для записи, записываем и закрываем(координаты x и y)
        char xs = wParam;
        std::ofstream out("c:/123", std::ios::app);
        out << xs << tmp->pt.x << tmp->pt.y << std::endl;
        out.close();
        int x =  tmp->pt.x;  // извлекаем младший байт, это и есть координата х мыши
        int y =  tmp->pt.y; // извлекаем старший байт, это и есть координата у мыши
        qDebug()<<x << y;
    }
    else
    {
// иначе если сообщение другого типа, создаём 321, пишем, закрываем
        std::ofstream out("c:/321", std::ios::app);
               char xs = wParam;
               out << xs  << std::endl;
                out.close();
    }


// передаём следующему хуку по цепочке(не вашим хукам, а уже чужим)
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
   
 /*   QLibrary myLib("./libMouseAPI");

    myLib.load();
    myLib.loadHints();

    if (!myLib.isLoaded())
        exit(0);

    typedef LRESULT CALLBACK (*MyPrototype)(int, WPARAM, LPARAM);
    MyPrototype myFunction = (MyPrototype) myLib.resolve("HookProcMouse");

    if (!myFunction)
        exit(0);*/


    static HHOOK hHook;


        hHook = SetWindowsHookEx(WH_MOUSE_LL, HookProcMouse, GetModuleHandle(NULL), NULL);
        assert(hHook);

    return a.exec();
}


Всё работает, координаты приходят! Хоть какой-то успех за два дня! Но вот с глобальным всё так же плохо...
Пожалуйста, Верес, помогите)


Название: Re: События перемещения мыши
Отправлено: virtual_root от Июль 04, 2012, 15:42
Я нашла решение. Можно использовать локальные и с помощью сигналов пересылать данные. Спасибо вам большое)


Название: Re: События перемещения мыши
Отправлено: virtual_root от Июль 04, 2012, 16:33
Верес, вы не подскажите а как антивирусник Касперского обойти? Он ругается на хуки?
Хакеры это как-то же делают ;)


Название: Re: События перемещения мыши
Отправлено: virtual_root от Июль 04, 2012, 16:46
Ещё вопросик. Я так же написала класс который отлавливает все нажатия на клавиатуре, правда с хуками. А можно это как-то средствами qt сделать? Мне собственно нужно подсчитывать сколько было нажато клавиш в каждую минуту времени. Подскажите пожалуйста кроссплатформенное решение кто-нибудь.


Название: Re: События перемещения мыши
Отправлено: Bepec от Июль 04, 2012, 16:48
Мне уже начинает надоедать :D

Вы хотите перехватывать нажатия клавиш без перехвата? :)

Перечитайте третий помоему ответ на ваш вопрос в этой теме.

PS вы видимо неправильно ставите хуки, или же творите что-то страшное. Ибо каспер на правильно поставленный глобальный хук не ругается.


Название: Re: События перемещения мыши
Отправлено: lighting от Июль 05, 2012, 09:02
Bepec ты решил тут мастер-класс по троянописанию устроить? :)


Название: Re: События перемещения мыши
Отправлено: Bepec от Июль 05, 2012, 10:16
lighting - если Windows описала механизм создания хуков, описала их Api, использует их везде где только можно и РЕКОМЕНДУЕТ их использовать, это можно назвать троянописанием? :D

PS вот методы сокрытия хука я раскрывать не собираюсь :D А так это - необходимые основы для многих программ.


Название: Re: События перемещения мыши
Отправлено: virtual_root от Июль 05, 2012, 16:08
А может всё-таки раскроете методы сокрытия хуков? ???


Название: Re: События перемещения мыши
Отправлено: Bepec от Июль 05, 2012, 23:35
-
это не тема для разработки обычных программ.