Bonjour à tous,
Comme on me l'a conseillé à la suite d'un sujet que j'ai ouvert (Utilisation de deux souris), j'aurais besoin de renseignements quant au fonctionnement et à l'utilisation de l'objet RawInput sur C++ Builder.
Pour réexpliquer le sujet pour ceux qui ont la flemme de lire l'autre sujet, dans le cadre d'un projet, j'ai besoin de mesurer une vitesse de déplacement d'un chariot, et pour ça j'ai pensé à une solution : utiliser une souris !
Bien entendu, au final cela fait une souris pour la navigation, et une deuxième pour les mesures. Cependant comme vous vous en doutez, lors de l'acquisition de données de la souris de mesure (que nous appellerons N2 pour plus de facilité), le curseur se déplace, comme il le fait lors de l'utilisation de la première souris (N1).
Mon but : Pouvoir mesurer avec N2 sans que le curseur ne soit affecté, et à l'inverse, naviguer avec N1, sans que les mesures ne soient affectées (des tests avec DirectInput, qui utilise le périphérique "général" des souris, ont justement révélés ce problème ...).
J'ai bien vu que c'était possible en téléchargeant USBMonitor qui est un Sniffer USB, j'ai pu sélectionner sur quelle souris je souhaitais analyser les données (donc périphériques HID identifiables séparément), et j'ai également pu faire ce que je cherche à faire.
J'ai donc désactivé l'une de mes deux souris via le gestionnaire de périphériques (mais sans la déconnecter), et j'ai lancé l'acquisition de cette même souris (N2 donc). Lors des déplacements, le curseur ne bougeait pas (vu que périphérique désactivé), mais le Sniffer recevait tout de même les trames de données, tandis que lors des déplacements de N1, le curseur bougeait, mais aucune trame n'était analysée.
En gros, il me faut pouvoir intégrer ces mêmes fonctionnalités à mon API (et une fois réussi, il me faudra décoder les trames, qui sont brutes, mais ça c'est un autre problème).
Pour ce faire on m'a conseillé d'utiliser RawInput. Le problème est que j'ai un mal fou à en comprendre le fonctionnement.
N'étant qu'en licence professionnelle, je n'ai pas un niveau d'expert, autant DirectInput a été assez simple à mettre en œuvre, autant là j'en chie comme pas permis.
Bref, voici le code que j'ai pour le moment :
Unit1.cpp
Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 RAWINPUTDEVICE Rid[1]; HRESULT hResult; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { Rid[0].usUsagePage = 1; Rid[0].usUsage = 2; Rid[0].dwFlags = RIDEV_NOLEGACY; // adds HID mouse and also ignores legacy mouse messages Rid[0].hwndTarget = 0; hResult = RegisterRawInputDevices(Rid, 1, sizeof(Rid[0])); Edit1->Text=Rid[0].usUsage; if(hResult==0) ShowMessage("Erreur N°"+GetLastError()); } //--------------------------------------------------------------------------- void __fastcall TForm1::WMInput(TMessage &Message) { UINT dwSize; UCHAR szTempOutput[16]; szTempOutput[0]=0x00; GetRawInputData((HRAWINPUT)Message.LParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)); LPBYTE lpb = new BYTE[dwSize]; if (GetRawInputData((HRAWINPUT)Message.LParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize ) ShowMessage("GetRawInputData does not return correct size !"); RAWINPUT* raw = (RAWINPUT*)lpb; if (raw->header.dwType == RIM_TYPEMOUSE) { hResult = StringCchPrintf(szTempOutput, STRSAFE_MAX_CCH, TEXT("Mouse: usFlags=%04x ulButtons=%04x usButtonFlags=%04x usButtonData=%04x ulRawButtons=%04x lLastX=%04x lLastY=%04x ulExtraInformation=%04x\r\n"), raw->data.mouse.usFlags, raw->data.mouse.ulButtons, raw->data.mouse.usButtonFlags, raw->data.mouse.usButtonData, raw->data.mouse.ulRawButtons, raw->data.mouse.lLastX, raw->data.mouse.lLastY, raw->data.mouse.ulExtraInformation); if (FAILED(hResult)) ShowMessage("Erreur N°"+GetLastError()); OutputDebugString(szTempOutput); } delete[] lpb; TForm1::WMInput(Message); } //---------------------------------------------------------------------------
Unit1.h
Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 #define WM_INPUT 0x00FF //--------------------------------------------------------------------------- class TForm1 : public TForm { __published: // Composants gérés par l'EDI TButton *Button1; TEdit *Edit1; TTimer *Timer1; TEdit *Edit2; void __fastcall Button1Click(TObject *Sender); void __fastcall Timer1Timer(TObject *Sender); private: // Déclarations utilisateur public: // Déclarations utilisateur __fastcall TForm1(TComponent* Owner); void __fastcall WMInput(TMessage &Message); BEGIN_MESSAGE_MAP MESSAGE_HANDLER(WM_INPUT, TMessage, WMInput) END_MESSAGE_MAP(TForm) UINT WINAPI GetRegisteredRawInputDevices( __out_opt PRAWINPUTDEVICE pRawInputDevices, __inout PUINT puiNumDevices, __in UINT cbSize ); typedef struct tagRAWINPUTDEVICE { USHORT usUsagePage; USHORT usUsage; DWORD dwFlags; HWND hwndTarget; } RAWINPUTDEVICE, *PRAWINPUTDEVICE, *LPRAWINPUTDEVICE; typedef struct tagRAWINPUT { RAWINPUTHEADER header; union { RAWMOUSE mouse; RAWKEYBOARD keyboard; RAWHID hid; } data; } RAWINPUT, *PRAWINPUT, *LPRAWINPUT; typedef struct tagRAWMOUSE { USHORT usFlags; union { ULONG ulButtons; struct { USHORT usButtonFlags; USHORT usButtonData; }; }; ULONG ulRawButtons; LONG lLastX; LONG lLastY; ULONG ulExtraInformation; } RAWMOUSE, *PRAWMOUSE, *LPRAWMOUSE; };
Du coup je remet le dernier message que j'ai écrit sur l'ancien sujet :
En résumé :
J'ai fait pas mal de tests en mode pas à pas, et j'ai bien l'impression que codé comme je l'ai fait, la fonction n'est jamais appelée.
La variable "Message" a bien une valeur (qui change souvent d'ailleurs) mais j'arrive pas trop à en savoir davantage, du coup la fonction GetRawInputData n'est jamais appelée non plus, donc pas de données à analyser.
Malgré tes explications, j'ai quand même un peu de mal à saisir le concept, comment "apparaît" le message WM_INPUT ? Qu'entends-tu par le niveau de priorité défini à mon application ?
Pour ce qu'il me semble avoir compris, le bout de code que tu m'as montré renvoie le message WM_INPUT vers la fonction déclarée juste avant le BEGIN_MESSAGE_MAP dès réception de ce dernier ?
Et est-ce que c'est gênant que le driver de ma souris essaye de récupérer les mêmes infos que moi (sachant que RawInput est fait pour récupérer les données directement sur le port USB, avant le driver donc si j'ai bien compris) ?
Voilà, alors désolé du roman, mais je préfère prendre le temps de bien expliquer les choses, pour vous faciliter la tâche.
Cordialement.
Partager