IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++Builder Discussion :

Utilisation de RawInput [Système/Fichiers/API]


Sujet :

C++Builder

  1. #1
    Membre actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2012
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2012
    Messages : 58
    Par défaut Utilisation de RawInput
    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.

  2. #2
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 070
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 070
    Par défaut
    En Delphi, comme Andnotor te l'a fait remarqué dans l'autre sujet, on a un sujet sur l'utilisation de lecteur de code comme second clavier, avec justement RAW Input, je pense que GetRawInputDeviceList devrait t'intéresser pour savoir qui est qui (savoir quel hDevice devant être filtrer)

    Regarde mieux le code Andnotor qui surveille deux claviers et justement gère un affichage séparé pour chacun grâce à raw->header.hDevice.
    Et justement, tu ne gère pas hDevice qui est l’élément clé pour séparer les données

    Sinon, tu n'es pas obligé de déclarer les types à la main, un include de "windows.h" devrait les fournir !

    Je n'ai pas tout compris, dans ton sujet, est-ce que WMInput est appelé ?

    Les Messages WM_INPUT, c'est Windows qui les envoie à ton programme (voir Application->Run(), WaitMessage et PeekMessage) ensuite en fonction du Handle, ils sont dispatchés

    C'est la qu'entre en jeu, BEGIN_MESSAGE_MAP qui va créer un WndProc pour filtrer les messages recensés et appeler les méthodes pour chacun

    EDIT

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TForm1::WMInput(Message);
    Cela me choque, tu vas faire une récursivité !
    Premier Message, tu tournes en rond ?

    Evite ShowMessage, effectivement, OutputDebugString est moins instrusif !
    Si tu ne sais pas voir ce que donne OutputDebugString, fait CTRL+ALT+V pour afficher le journal d'évènements !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2005
    Messages
    401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2005
    Messages : 401
    Par défaut
    Hello,

    Essaie ceci pour ton RegisterRawInputDevice:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      Rid[0].dwFlags = RIDEV_NOLEGACY | RIDEV_INPUTSINK;   // adds HID mouse and also ignores legacy mouse messages
      Rid[0].hwndTarget = Handle;
    Et sinon, fait gaffe à la taille de ton buffer quand tu formates ton message (16, c'est quand même peu...):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      TCHAR szTempOutput[200];
      ZeroMemory(szTempOutput, sizeof(szTempOutput));
      hResult = StringCchPrintf(szTempOutput, 199, TEXT("Mouse: usFlags=%04x ulButtons=%04x usButtonFlags=%04x usButtonData=%04x ulRawButtons=%04x lLastX=%04x lLastY=%04x ulExtraInformation=%04x\r\n"),
    Ces petites modifs m'ont permi de voir passer les messages souris...

    Edit: +1 pour la remarque de ShaiLeTroll au sujet de TForm1::WMInput(Message);

  4. #4
    Rédacteur
    Avatar de blondelle
    Homme Profil pro
    Inscrit en
    Mars 2006
    Messages
    2 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 738
    Par défaut
    Salut chapitre37
    Pour detecter le deplacement de la souris essai de remplacer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    MESSAGE_HANDLER(WM_INPUT, TMessage, WMInput)
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    MESSAGE_HANDLER(WM_MOUSEMOVE, TMessage, WMInput)

  5. #5
    Membre Expert
    Inscrit en
    Avril 2010
    Messages
    1 495
    Détails du profil
    Informations forums :
    Inscription : Avril 2010
    Messages : 1 495
    Par défaut
    Salut,

    Il veut faire une capture à un plus bas niveau, d'où l'usage de wm_input (en majuscule) en préférence à wm_mousemove (en maj.) Cf première discussion

    Citation Envoyé par ShaiLeTroll Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TForm1::WMInput(Message);
    Cela me choque, tu vas faire une récursivité !
    Premier Message, tu tournes en rond ?
    Citation Envoyé par totoche76 Voir le message
    Edit: +1 pour la remarque de ShaiLeTroll au sujet de TForm1::WMInput(Message);
    En effet, à la fin de la fonction, il faut appeler le gestionnaire hérité et non le gestionnaire en cours (TForm1::WMInput(Message) c'est pas bon), Conf exemple donné dans l'autre discussion. Sauf que s'agissant de ta fenêtre principale, tu ne peux pas écrire non plus TForm::WMInput(Message), mais il convient quand même de rendre la main proprement, même si c'est déjà implémenté dans la macro du gestionnaire, il faut prendre l'habitude de terminer ta fonction (ou méthode, je sais plus qu'elle est le terme approprie) par TForm::Dispatch(&Message) quand le paramètre de ta fonction de gestion du message est une référence ou TForm::Dispatch(Message) quand c'est un pointeur, ou encore TForm::DefaultHandler(Message) quand on sait ce qu'on fait, TForm étant le nom de ta classe de base et est bien sur remplaçable par le nom de la classe effectivement héritée, enfin bref ici c'est TForm::Dispatch(&Message) qu'il faut écrire. (tout est plus ou moins ici -> http://docwiki.embarcadero.com/RADSt...ssages_-_Index)

    Je mets également l'implémentation de la macro sur laquelle j'ai pu mettre la main :

    Code : 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
    #define BEGIN_MESSAGE_MAP   virtual void __fastcall Dispatch(void *Message) \
            {                                           \
              switch  (((PMessage)Message)->Msg)        \
              {
     
    #define VCL_MESSAGE_HANDLER(msg,type,meth)          \
              case    msg:                              \
                meth(*((type *)Message));               \
                break;
     
    // NOTE: ATL defines a MESSAGE_HANDLER macro which conflicts with VCL's macro. The
    //       VCL macro has been renamed to VCL_MESSAGE_HANDLER. If you are not using ATL,
    //       MESSAGE_HANDLER is defined as in previous versions of BCB.
    //
    #if !defined(USING_ATL) && !defined(USING_ATLVCL) && !defined(INC_ATL_HEADERS)
    #define MESSAGE_HANDLER  VCL_MESSAGE_HANDLER
    #endif // ATL_COMPAT
     
    #define END_MESSAGE_MAP(base)           default:    \
                            base::Dispatch(Message);    \
                            break;                      \
              }                                         \
            }
    et

    un extrait de code source que j'ai trouvé également, en mfc, mais qui ne pose à priori pas de problèmes pour les parties qui intéressent :

    Code : 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
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
     
     void CMouDevDetectDlg::InitRawInput()   
     {   
         CString str;   
         int mouseNo=0;        if(GetRawInputDeviceList(NULL,&nDevices,sizeof(RAWINPUTDEVICELIST))!=0)   
         {   
             MessageBox(_T("获取鼠标设备数目失败!"));   
             return ;       
         }   
         pRawInputDeviceList = (RAWINPUTDEVICELIST *)malloc(sizeof(RAWINPUTDEVICELIST) * nDevices);   
         GetRawInputDeviceList(pRawInputDeviceList, &nDevices, sizeof(RAWINPUTDEVICELIST));   
         for(int i=0; i< nDevices;i++)   
         {   
             if(pRawInputDeviceList[i].dwType==RIM_TYPEMOUSE)   
             {   
                 mouseNo++;   
                 str.Format(_T("%d"),pRawInputDeviceList[i].hDevice);   
                 m_rmouseList.AddString(str);   
             }   
         }   
         str.Format(_T("%d"),mouseNo);   
         rMouseNo=str;   
         UpdateData(false);   
     
         // after the job, free the RAWINPUTDEVICELIST   
         free(pRawInputDeviceList);   
         //str.Format(_T("%d"),nDevices);   
         //MessageBox(str);   
         Rid[0].usUsagePage=0x01;   
         Rid[0].usUsage=0x02;   
         //只要这个设置成下面值就可以在后台监视了,主要要设hWndTarget   
         Rid[0].dwFlags =RIDEV_INPUTSINK;// RIDEV_NOLEGACY;   // adds HID mouse and also ignores legacy mouse messages   
         Rid[0].hwndTarget =this->m_hWnd/*NULL*/;   
         if (RegisterRawInputDevices(Rid, 1, sizeof (Rid [0])) == FALSE) {   
             MessageBox(_T("注册监视鼠标设备失败!"));   
             return ;   
         }   
     }
     
     
     //Raw Mouse Message Dilling Functions   
     LRESULT CMouDevDetectDlg::OnInPut(WPARAM wParam, LPARAM lParam)   
     {   
         UINT dwSize;   
         RAWINPUT *raw;   
         LPBYTE lpb;   
         char mousemessage[256];    
     
         GetRawInputData((HRAWINPUT)lParam,RID_INPUT,NULL, &dwSize,sizeof(RAWINPUTHEADER));   
         lpb = (unsigned char *)malloc(sizeof(LPBYTE) * dwSize);   
         if (lpb == NULL)    
         {   
             return 0;   
         }   
         if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize,    
                      sizeof(RAWINPUTHEADER)) != dwSize )   
         {   
             MessageBox(_T("GetRawInputData doesn't return correct size !"));    
             return 0;   
         }   
         raw = (RAWINPUT*)lpb;   
         if(raw->header.dwType==RIM_TYPEMOUSE)   
         {   
             m_rmouUsing=(const int)(raw->header.hDevice);   
             if(flag==1)   
             {   
                 touch_count++;   
                 if(touch_count==20)   
                 {   
                     ctldata();   
                     sendctldata(theSocket,saServer,m_sendData);   
                     touch_count=0;   
                 }   
             }   
             //UpdateData(false);   
             sprintf_s(mousemessage,"hDevice ID:%d \n usFlags=%04x \nulButtons=%04x \nusButtonFlags=%04x \nusButtonData=%04x \nulRawButtons=%04x \nlLastX=%ld \nlLastY=%ld \nulExtraInformation=%04x\n",   
                 raw->header.hDevice,   
                 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);   
             CString str(mousemessage);   
             //str=(CString)mousemessage;   
             //以下是绘图的函数   
             CRect rect;   
             CWnd *pWnd=GetDlgItem(IDC_DRAW);   
             CDC *pdc=pWnd->GetDC();   
             pWnd->GetClientRect(&rect);   
             //pdc->TextOutW(rect.left+10,rect.top+10,str,256);   
             //pdc->DrawText(mousemessage,strlen(mousemessage),&rect,DT_CENTER);   
             pdc->FillSolidRect(0,0,rect.Width(),rect.Height(),RGB(255,255,255));    
             pdc->DrawText(str,str.GetLength(),&rect,DT_CENTER);   
             //pdc->DeleteDC();   
             ReleaseDC(pdc);   
         }   
     
         free(lpb);   
         //delete lpb;   
         return 0;
    L'ennui c'est juste que là tu t'attaques à trois aspects nouveau pour toi à la fois, ce qui n'est peut-être pas des plus facile : une nouvelle api, la vcl, et la gestion des messages. Mais bon, je pense qu'avec ces nouvelles informations (plus les liens msdn de la précédente discussion) + les messages du dessus tu peux aller de l'avant...

    Moi même je ne code plus depuis 2006, et en plus j'ai pas c++ builder, donc je ne pourrais être plus utile.
    Sur ce, bon courage.

  6. #6
    Membre actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2012
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2012
    Messages : 58
    Par défaut
    Alors tout d'abord, merci à tous pour ces réponses complètes, ça m'a permis de commencer à comprendre un peu mieux les fonctions liées à RawInput.

    J'ai effectué quelques tests avec ce que vous m'avez proposé, @totoche76, tes modifications ne m'ont pas permis de faire fonctionner le programme, lorsque je compile et que je clique sur le bouton, j'ai le ShowMessage (j'utilise ShowMessage surtout pour avoir le code d'erreur correspondant si besoin) "GetRawInputData does not return correct size !" qui s'affiche, et qui se valide dès que je bouge la souris (ce qui bien sûr, ferme le programme).

    J'ai regardé un peu en mode pas à pas, apparemment c'est simplement le Message qui contient 0 à chacun de ses paramètres (d'où l'erreur).

    Pour le moment, comme vous l'avez souligné, le seul truc sur lequel je galère un peu niveau compréhension, c'est la détection du WM_INPUT. En gros, dès que la souris envoie une information au PC, le WndProc est appelé, et renvoie un WM_INPUT, qui appelle la fonction WMInput ?

    Par ailleurs, en mode pas à pas, j'ai regardé certaines valeurs de certaines fonctions, et j'ai remarqué que le PID et VID de mon HID étaient tout deux à 0 ... est-ce normal que je n'ai pas les ID correspondants à ma souris ?

    EDIT : Alors en fait j'ai viré le "TForm1:ispatch(&Message)" qui était dans ma fonction WMInput, ça compile bien, j'ai bien les valeurs de déplacement de la souris.

    Du coup c'est bon, ça éclaircit un peu le tout, je pense avoir à peu près compris.

    Mais, car il y a un mais et non des moindre, ce que je récupère, c'est exactement la même chose qu'avec DirectInput, les valeurs ne sont pas les valeurs "brutes" qui n'ont pas encore été traitées par Windows, ce qui fait que même si le périphérique paramétré est un périphérique particulier, que je bouge la souris, ou le pad, les valeurs bougent, et que lorsque je désactive la souris sans la déconnecter, plus rien ne bouge.

    Pour que vous voyiez vraiment ce que je souhaite réussir à faire, téléchargez USBMonitor, désactivez l'une des deux souris, choisissez la souris désactivée pour récupérer les données, lancez l'acquisition, et vous verrez que même désactivée, les trames de cette souris et uniquement cette souris là seront reçues.

    EDIT 2 : Pour le moment je n'arrive pas vraiment à faire en sorte de ne récupérer les données que d'une seule souris en particulier =/

  7. #7
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2005
    Messages
    401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2005
    Messages : 401
    Par défaut
    Il va peut-être falloir que tu tapes "plus fort", en attaquant directement les devices HID (de la lecture à prévoir dans MSDN, dans le Windows Driver Kit...)

    Regardes ensuite du côté des JVCL (composant TJvHidDeviceController, TJvHidDevice), ça pourra t'aider (genre: est-ce que tu vois ta souris désactivée avec l'exemple CollectionDemo qui se trouve dans les JVCL ?).

    A voir aussi: http://www.lvr.com/hidpage.htm

    http://www.signal11.us/oss/hidapi/

  8. #8
    Membre actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2012
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2012
    Messages : 58
    Par défaut
    Bon, j'ai continué sur la lancée de ce que tout le monde m'a dit, j'ai réussi à récupérer les valeurs hDevice de mes périphériques HID, et j'ai remarqué que le PAD a constamment la même valeur (65607), et que chacune des souris a une valeur nettement supérieure (de l'ordre de plusieurs dizaines de millions).

    J'ai donc regardé dans un if, si le hDevice du message reçu n'est pas le PAD, je fais le traitement, sinon je passe.

    Pour ce qui est de la gestion du curseur, j'ai réussi à bidouiller.

    Lorsque le message reçu vient de la souris de mesure, je force la position du curseur à la position avant message, sinon je le laisse se déplacer, du coup ça marche niquel.

    Maintenant tout marche à peu près comme je le souhaitais.

    Au cas où ça intéresserait du monde, voici donc le code :

    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
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    //---------------------------------------------------------------------------
    #include <vcl.h>
    #include <Winuser.h>
    #include <Strsafe.h>
    #pragma hdrstop
    #include "Unit1.h"
    #include "Unit2.h"
    #include <windef.h>
    #include <windows.h>
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    RAWINPUTDEVICE Rid[1];
    HRESULT hResult;
    POINT cursor;
    float X = 0;
    float Y = 0;
    float K = 0;
    static float CursorX, CursorY;
    //---------------------------------------------------------------------------
    __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 | RIDEV_INPUTSINK;   // adds HID mouse and also ignores legacy mouse messages
    	Rid[0].hwndTarget = Handle;
    	hResult = RegisterRawInputDevices(Rid, 1, sizeof(Rid[0]));
     
    	if(hResult==false)
    		ShowMessage("Erreur N°"+GetLastError());
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::WMInput(TMessage &Message)
    {
    	UINT dwSize;
    	TCHAR szTempOutput[200];
    	ZeroMemory(szTempOutput, sizeof(szTempOutput));
    	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 )
    		 {}
     
    	RAWINPUT* raw = (RAWINPUT*)lpb;
     
    	if (raw->header.dwType == RIM_TYPEMOUSE)
    	{
    		hResult = StringCchPrintf(szTempOutput, 199, 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((int)raw->header.hDevice>65607)
    		{
    			SetCursorPos(CursorX, CursorY);
     
    			X+=raw->data.mouse.lLastX;
    			Y+=raw->data.mouse.lLastY;
     
    			K = sqrt((X * X) + (Y * Y));
    			K = (K * 2.54) / 1000;
     
    			if(X+Y<0)
    				K=-K;
    		}
     
    		else
    		{
    			hResult = GetCursorPos(&cursor);
    			CursorX = cursor.x;
    			CursorY = cursor.y;
    		}
     
    		if((int)raw->header.hDevice>65607 && raw->data.mouse.usButtonFlags!=0)
    		{
    		   Form1->Close() ;
    		}
     
    		Edit2->Text=-K;
     
    		if (FAILED(hResult))
    			ShowMessage("Erreur N°"+GetLastError());
     
    		OutputDebugString(szTempOutput);
    	}
     
    	delete[] lpb;
    }
    //---------------------------------------------------------------------------

    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
    //---------------------------------------------------------------------------
    #ifndef Unit1H
    #define Unit1H
    #define WM_INPUT 0x00FF
    //---------------------------------------------------------------------------
    #include <System.Classes.hpp>
    #include <Vcl.Controls.hpp>
    #include <Vcl.StdCtrls.hpp>
    #include <Vcl.Forms.hpp>
    #include <Vcl.ExtCtrls.hpp>
    #include <Vcl.Grids.hpp>
    #include <Vcl.ValEdit.hpp>
    #include <Data.DB.hpp>
    #include <Data.FMTBcd.hpp>
    #include <Data.SqlExpr.hpp>
    //---------------------------------------------------------------------------
    class TForm1 : public TForm
    {
    __published:	// Composants gérés par l'EDI
    	TButton *Button1;
    	TEdit *Edit2;
    	void __fastcall Button1Click(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)
    };
    //---------------------------------------------------------------------------
    extern PACKAGE TForm1 *Form1;
    //---------------------------------------------------------------------------
    #endif

    En tout cas je vous remercie, ça me retire une énorme épine du pied ! Et maintenant j'ai à peu près bien saisi comment fonctionne RawInput, c'est toujours ça de gagné.

    (Je marque le topic en résolu !)

  9. #9
    Rédacteur
    Avatar de blondelle
    Homme Profil pro
    Inscrit en
    Mars 2006
    Messages
    2 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 738
    Par défaut
    Quelle version de BCB utilise tu car chez moi
    MESSAGE_HANDLER(WM_INPUT, TMessage, WMInput)
    ne fonctionne pas, il ne faut essayer une autre solution pour recuperer " WM_INPUT "
    je suis sous BCB6 & Window7

  10. #10
    Membre actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2012
    Messages
    58
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2012
    Messages : 58
    Par défaut
    RAD Sudio XE2 (C++ Builder), qui est d'ailleurs pas mal.

  11. #11
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2005
    Messages
    401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2005
    Messages : 401
    Par défaut
    Citation Envoyé par blondelle Voir le message
    Quelle version de BCB utilise tu car chez moi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MESSAGE_HANDLER(WM_INPUT, TMessage, WMInput)
    ne fonctionne pas, il ne faut essayer une autre solution pour recuperer " WM_INPUT "
    je suis sous BCB6 & Window7
    Pourtant on trouve ceci dans le winuser.h fourni avec Builder 6:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #if(_WIN32_WINNT >= 0x0501)
    #define WM_INPUT                        0x00FF
    #endif /* _WIN32_WINNT >= 0x0501 */
    Mais _WIN32_WINNT doit valoir 0x0500 dans Builder 6....
    Donc mets undans tes définitions conditionnelles (options du projet)



    Edit (histoire de faire le psychopathe qui veut absolument être précis!) :

    sous BCB6, fichier windows.h:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #if defined(__BORLANDC__)
    #    ifndef _WIN32_WINNT
    #        define _WIN32_WINNT 0x0500  /* If not set, assume NT 5.00  */
    #    endif
    #    if defined(__cplusplus)
    #       define NOMINMAX              /* for WINDEF.H */
    #    else
    #        define NONAMELESSUNION      /* for OAIDL.H, OBJIDL.H,...  */
    #    endif
    #    if defined(_UNICODE)
    #        define UNICODE
    #    endif
    #endif
    Sous BCB2007, fichier sdkddkver.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #if !defined(_WIN32_WINNT) && !defined(_CHICAGO_)
    #define  _WIN32_WINNT   0x0600
    #endif
    Et ensuite ça évolue au fil des versions de Builder

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. utiliser les tag [MFC] [Win32] [.NET] [C++/CLI]
    Par hiko-seijuro dans le forum Visual C++
    Réponses: 8
    Dernier message: 08/06/2005, 15h57
  2. Réponses: 4
    Dernier message: 05/06/2002, 14h35
  3. utilisation du meta type ANY
    Par Anonymous dans le forum CORBA
    Réponses: 1
    Dernier message: 15/04/2002, 12h36
  4. [BCB5] Utilisation des Ressources (.res)
    Par Vince78 dans le forum C++Builder
    Réponses: 2
    Dernier message: 04/04/2002, 16h01
  5. Réponses: 2
    Dernier message: 20/03/2002, 23h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo