2016-05-06 4 views
0

Après avoir travaillé sur this et QAbstractNativeEventFilter classe j'ai finalement obtenu des événements natifs de HID (à la fois la souris et le clavier).Obtenir le mouvement de la souris brute dans Qt

J'ai lu beaucoup de questions similaires mais aucune n'a résolu mon problème. J'essaie d'obtenir le mouvement de la souris en fonction de dpi. Je travaille sur Qt 5.5 car tout mon projet y est construit.

Je ne peux pas séparer les événements de mouvement de la souris d'autres événements HID (souris et clavier) même avec l'indicateur RIM_TYPEMOUSE.

Voici une partie de ma mise en œuvre:

bool MouseRawMovement::nativeEventFilter(const QByteArray &eventType, void *message, long *result) 
{ 
    if(eventType == "windows_generic_MSG") 
    { 
     MSG *msg = reinterpret_cast<MSG*>(message); 
     qDebug()<<msg->message; // It prints numbers such as 6,26,28,141 on each event 
     if(msg->message == WM_INPUT) //it never gets in 
     { 
     UINT dwSize = 40; 
     static BYTE lpb[40]; 
     GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, 
         lpb, &dwSize, sizeof(RAWINPUTHEADER)); 

     RAWINPUT* raw = (RAWINPUT*)lpb; 
     if (raw->header.dwType == RIM_TYPEMOUSE) 
     { 
      int xPosRelative = raw->data.mouse.lLastX; 
      int yPosRelative = raw->data.mouse.lLastY; 

      qDebug()<<xPosRelative<<yPosRelative ; 
     } 
     } 
    } 
    return false; 
} 

Aussi voici mon constructeur

MouseRawMovement::MouseRawMovement() 
    { 
     Rid[0].usUsagePage = 0x01; 
     Rid[0].usUsage = 0x02; 
     Rid[0].dwFlags = RIDEV_INPUTSINK; 
     Rid[0].hwndTarget = 0; 
     if(!RegisterRawInputDevices(Rid, 1, sizeof(Rid[0]))) 
      qDebug()<<QString::number(GetLastError()); //I see error msg 6 - Ref. ERROR_INVALID_HANDLE 
    } 

sortie me montre des zéros (0) tout le temps.

Ce qui se passe avec hWnd. J'ai essayé de donner ceci:

HWND hWnd =::GetConsoleWindow();

mais j'ai eu le même résultat.

En main.cpp j'installer le filtre natif

MainWindow w; 
a.installNativeEventFilter(&w.mm); 

J'essaie de jours et je ne pouvais pas trouver la solution. Y at-il ... (???)

+0

Mais quel est votre problème? Que voulez-vous dire par "ne peut pas séparer"? –

+0

Soit j'ai RIM_TYPEMOUSE vérifier soit pas le même. Quand j'appuie sur une touche de la souris ou du clavier, j'ai une sortie ... Deuxièmement, je ne vois que des zéros. – thanasispap

Répondre

0

@nnatarr votre aide était substantielle! Je vous remercie!!!

Je trouve enfin la solution.

J'ai dû appeler RegisterRawInputDevices dans main.cpp et changer beaucoup de choses.

Voici main.cpp

#include "mainwindow.h" 
#include <QApplication> 
#include <windows.h> 

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 
    MainWindow w; 
    a.installNativeEventFilter(&w.mm); 
    w.show(); 

    UINT nDevices; 
    PRAWINPUTDEVICELIST pRawInputDeviceList; 

    if (!GetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST))) 
    { 
     qDebug() << "ERROR -- GetRawInputDeviceList ..."; 
     return 1; 
    } 

    if (!(pRawInputDeviceList = (PRAWINPUTDEVICELIST)malloc(sizeof(RAWINPUTDEVICELIST) * nDevices))) 
    { 
     qDebug() << "Initialization failed..."; 
     return 1; 
    } 

    RAWINPUTDEVICE Rid[1]; 
    Rid[0].usUsagePage = HID_USAGE_PAGE_GENERIC; 
    Rid[0].usUsage = HID_USAGE_GENERIC_MOUSE; 
    Rid[0].dwFlags = RIDEV_INPUTSINK; 
    Rid[0].hwndTarget = (HWND)w.effectiveWinId(); 
    if(!RegisterRawInputDevices(Rid, 1, sizeof(Rid[0]))) 
     qDebug()<<"Huston Problem."; 
    qDebug()<<QString::number(GetLastError()); 

    return a.exec(); 
} 

Et voici une partie de la souris Handlig classe

bool MouseRawMovement::nativeEventFilter(const QByteArray &eventType, void *message, long *result) 
{ 
    if(eventType == "windows_generic_MSG") 
    { 
     MSG *msg = reinterpret_cast<MSG*>(message); 

     if(msg->message == WM_INPUT) 
     { 
      UINT dwSize = 40; 
      static BYTE lpb[40]; 
      if(!GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT,lpb, &dwSize, sizeof(RAWINPUTHEADER))) 
       qDebug()<<"Error GetRawInputData"; 
      else 
      { 
       RAWINPUT* raw = (RAWINPUT*)lpb; 
       if (raw->header.dwType == RIM_TYPEMOUSE) 
       { 
        int xPosRelative = raw->data.mouse.lLastX; 
        int yPosRelative = raw->data.mouse.lLastY; 
        //qDebug()<<xPosRelative<<yPosRelative; 
       } 
      } 

     } 
    } 
    return false; 
} 
0

Comme les GetRawInputData MSDN états de page, premier paramètre de cette fonction est

hRawInput [en]
Type: HRAWINPUT
Une poignée à la structure RAWINPUT. Cela vient de lParam dans WM_INPUT.

Donc, vous devez d'abord vérifier si le message que vous traitez est un message WM_INPUT (msg->message == WM_INPUT) et seulement ensuite essayer d'extraire des données d'entrée brutes. Ensuite, le lParam de messages WM_INPUT est

lParam
Une poignée à la structure RAWINPUT qui contient la première entrée du dispositif.

comme il est dit sur WM_INPUT MSDN page. Vous devez utiliser ce handle dans la fonction GetRawInputData. Pour l'instant, vous utilisez un gestionnaire de données incorrect, GetRawInputData ne vous renvoie aucune information valide (il ne sait pas où prendre les données à traiter).

Vous devriez lire l'article MSDN: Using Raw Input. Vous pouvez y trouver un exemple de code pour le traitement des entrées brutes keybaord et mouse.

Liens utiles:

Encore une chose. Vous pouvez utiliser l'opérateur d'égalité pour comparer l'instance de QByteArray à une chaîne, dans votre cas, cela ressemblera à ceci: if (eventType == "windows_generic_MSG") {...}. En effet, QByteArray a l'opérateur d'égalité surchargé:

bool QByteArray::operator==(const QString & str) const 

Vous pouvez lire à ce sujet à cette page: QByteArray::operator==.

MISE À JOUR

MSDN: RAWINPUTDEVICE note que la page

RIDEV_INPUTSINK 0x00000100
Si elle est définie, ce qui permet à l'appelant de recevoir l'entrée même lorsque l'appelant est pas au premier plan. Notez que hwndTarget doit être spécifié.

Vous avez le INVALID_HANDLE_ERROR erreur car vous devez spécifier hWnd de la fenêtre. Qu'est-ce que la classe MainWindow? Héritez-vous de QMainWindow ou de QWidget? Chaque widget dans Qt possède la propriété winId (WId QWidget::winId() const) qui est la propriété que vous recherchez. Donc, vous devez prendre winId() de votre fenêtre, jeter à HWND et écrire dans la structure Rid comme ceci:

Rid[0].hwndTarget = (HWND)w->winId(); 

Si elle ne va pas aider, alors vous devez fournir un Minimal, Complete, and Verifiable example pour une enquête plus approfondie.

+0

Merci pour votre réponse! Je définis le lParam comme ce (HRAWINPUT) msg-> lParam. L'association d'application avec WM_INPUT est implémentée dans le constructeur. Je vais le mettre sur ma question. Lorsque je ne commente pas l'instruction if pour WM_INPUT, elle ne s'affiche pas. Je modifie ma question avec plus d'infos ... J'ai vérifié les liens que vous avez mis en évidence dans votre réponse car je les avais déjà passés dans mes recherches pour ce problème. Merci encore pour votre temps – thanasispap

+0

@thanasispap a mis à jour la réponse. –