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 :

Citation Envoyé par minnesota Voir le message
Le message est envoyé par le système d'exploitation à ton application quand il le décide, du moins quand un contenu est disponible, en fonction de la priorité que tu as définie pour cette même application. Faut voir ça comme un télégramme qui transitera par la fonction que tu as défini, que tu pourras intercepter et analyser. N'hésite pas à expérimenter le programme que je t'ai donné en lien, tu pourras constater par toi même l'ampleur de ce système de communication dans ce système d'exploitation. Pour approfondir le sujet, il te suffit de faire une recherche sur "programmation Windows".
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.