Utiliser 2 souris

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Utiliser 2 souris

Message par Thyphoon »

Après pas mal de recherche, j'ai finalement trouvé un code de Lunasole sur le forum anglais. Qui permet d'avoir les informations RawInputs 🥰
https://www.purebasic.fr/english/viewt ... st#p494812
J'ai modifié rapidement le code pour tester... mais je pense qu'il y a moyen de faire un module facile a utiliser pour l'utiliser dans les jeux
et utiliser 2 souris en même temps.
Si vous voulez essayer branchez 2 souris et bougez les ! :P

Code : Tout sélectionner


EnableExplicit

;{ Raw Input }

	; GetRawInputData() command flags
	#RID_HEADER			= $10000005 ; get header structure
	#RID_INPUT			= $10000003 ; get whole RAWINPUT structure
	
	; Types of raw input data
	#RIM_TYPEMOUSE    	= 0
	#RIM_TYPEKEYBOARD	= 1
	#RIM_TYPEHID		= 2
	
	; RAWINPUTDEVICE flags
	#RIDEV_REMOVE 		= $00000001 
	#RIDEV_EXCLUDE		= $00000010
	#RIDEV_PAGEONLY 	= $00000020
	#RIDEV_NOLEGACY		= $00000030
	#RIDEV_INPUTSINK  	= $00000100
	#RIDEV_CAPTUREMOUSE	= $00000200
	#RIDEV_NOHOTKEYS	= $00000200
	#RIDEV_APPKEYS		= $00000400
	#RIDEV_EXINPUTSINK	= $00001000
	#RIDEV_DEVNOTIFY	= $00002000
	

	; GetRawInputDeviceInfo() flags
	#RIDI_PREPARSEDDATA = $20000005 ; returns previously parsed data 
	#RIDI_DEVICENAME 	= $20000007	;- a string containing the device name
	#RIDI_DEVICEINFO 	= $2000000b	;- an RIDI_DEVICE_INFO Structure
	
		
	Prototype GetRawInputData(hRawInput, uiCommand, *pData.RAWINPUT, *pcbSize, cbSizeHeader)
	Prototype RegisterRawInputDevices(*pRawInputDevices.RAWINPUTDEVICE, *uiNumDevices, cbSize)
	Prototype GetRawInputDeviceList(*pRawInputDeviceList.RAWINPUTDEVICELIST, *uiNumDevices, cbSize)
	Prototype GetRawInputDeviceInfo(hDevice, uiCommand, *pData, *pcbSize)
	


	; import functions
	Global User32_dll = OpenLibrary(#PB_Any, "user32.dll")
	If IsLibrary(User32_dll)
		Global RegisterRawInputDevices.RegisterRawInputDevices	= GetFunction(User32_dll, "RegisterRawInputDevices")
		Global GetRawInputData.GetRawInputData					= GetFunction(User32_dll, "GetRawInputData")
		Global GetRawInputDeviceList.GetRawInputDeviceList		= GetFunction(User32_dll, "GetRawInputDeviceList")
		Global GetRawInputDeviceInfo.GetRawInputDeviceInfo		= GetFunction(User32_dll, "GetRawInputDeviceInfoW")
	EndIf

;}

Structure myRawMouse
  X.l
  Y.l
  
EndStructure

Global NewMap MyRawMouse.myRawMouse()

; windows message processing
Procedure WinCallback (hWnd, Message, WParam, LParam)
	Select Message 		
		Case #WM_INPUT: ; Raw Input
		
			Protected pcbSize.l
			Protected *pRawData.RAWINPUT
			If GetRawInputData(lParam, #RID_INPUT, #Null, @pcbSize, SizeOf(RAWINPUTHEADER)) = 0
				*pRawData = AllocateMemory(pcbSize) ; If input is from HID-device, data size can vary
				If *pRawData
					GetRawInputData(lParam, #RID_INPUT, *pRawData, @pcbSize, SizeOf(RAWINPUTHEADER))
					Select *pRawData\header\dwType
						Case #RIM_TYPEMOUSE:
							; here input is collected
						  ;Debug "Vk " + Str(*pRawData\mouse\ulButtons) + " from device " + Str(*pRawData\header\hDevice)
						  If Not FindMapElement(MyRawMouse(), Str(*pRawData\header\hDevice))
						    AddMapElement(MyRawMouse(), Str(*pRawData\header\hDevice))
						  EndIf
						  MyRawMouse()\X=MyRawMouse()\X+*pRawData\mouse\lLastX
						  MyRawMouse()\Y=MyRawMouse()\Y+*pRawData\mouse\lLastY
						  Debug Str(*pRawData\header\hDevice)+" "+Str(MyRawMouse()\X)+","+Str(MyRawMouse()\Y)
					EndSelect
					
					FreeMemory(*pRawData)
				EndIf
				
			EndIf
	EndSelect
	
	ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure




Procedure Main ()

Protected WndMain = 123
Protected hWnd = OpenWindow(WndMain, #PB_Ignore, #PB_Ignore, 300, 200, "SOME RAW INPUT HOOK", #PB_Window_Invisible)

	; capture window messages
	SetWindowCallback(@WinCallback())
	
	; set raw input capture for all mouses and keyboards
	Dim Rid.RAWINPUTDEVICE(0)
	Rid(0)\usUsagePage  = 1
	Rid(0)\usUsage      = 0
	Rid(0)\hwndTarget   = hWnd
	Rid(0)\dwFlags   	= #RIDEV_INPUTSINK | #RIDEV_PAGEONLY

	If RegisterRawInputDevices (@Rid(), ArraySize(Rid()) + 1, SizeOf(RAWINPUTDEVICE)) = #True
		Debug "Press any key on any keyboard ..."
		
		Repeat
		Until WaitWindowEvent() = #PB_Event_CloseWindow
		
	Else
; 		Msg("Failed to register devices: " + NameLastError())
	EndIf

	If IsLibrary(User32_dll)
		CloseLibrary(User32_dll)
	EndIf
EndProcedure

;;;;;;;;;
Main()
End
Avatar de l’utilisateur
Ar-S
Messages : 9540
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Utiliser 2 souris

Message par Ar-S »

J'ai pas testé mais le principe me plaît bien.
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
falsam
Messages : 7324
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Utiliser 2 souris

Message par falsam »

Merci pour ce code. Sur un ordinateur portable, J'ai ajouté une souris sans fil. Le pad et la souris sont bien détectés. J'aime bien :wink:
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
falsam
Messages : 7324
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Utiliser 2 souris

Message par falsam »

Le code qui va suivre affiche un sprite pour chaque souris connectée.

J'ai modifié quelques petites choses dans le code de Thyphoon.

■ Ajout d'un sprite id dans la structure myRawMouse.

Code : Tout sélectionner

 Structure myRawMouse
  SpriteID.i
  X.l
  Y.l
EndStructure
■ Ajout d'un compteur de sprite dans la procédure WinCallback

Code : Tout sélectionner

Procedure WinCallback (hWnd, Message, WParam, LParam)
  Static SpriteID
  Protected pcbSize.l
  ... 
■ Chaque fois que la procédure WinCallBack trouve une souris, on incrémente le numéro de sprite.

Code : Tout sélectionner

If Not FindMapElement(MyRawMouse(), Str(*pRawData\header\hDevice))
      AddMapElement(MyRawMouse(), Str(*pRawData\header\hDevice))
      MyRawMouse()\SpriteID = SpriteID
      SpriteId + 1
EndIf
:!: Un probléme : La gestion du clavier ne fonctionne pas

Code : Tout sélectionner

If ExamineKeyboard()
  If KeyboardReleased(#PB_Key_Escape)
    Exit()
  EndIf 
EndIf
■ Pour ce test j'ai connecté trois souris. Enjoy.

Code : Tout sélectionner

EnableExplicit

Enumeration window
  #mf
EndEnumeration

Enumeration gadget
EndEnumeration

;{ Raw Input }

; GetRawInputData() command flags
#RID_HEADER			= $10000005 ; get header structure
#RID_INPUT			= $10000003 ; get whole RAWINPUT structure

; Types of raw input data
#RIM_TYPEMOUSE    	= 0
#RIM_TYPEKEYBOARD	= 1
#RIM_TYPEHID		= 2

; RAWINPUTDEVICE flags
#RIDEV_REMOVE 		= $00000001 
#RIDEV_EXCLUDE		= $00000010
#RIDEV_PAGEONLY 	= $00000020
#RIDEV_NOLEGACY		= $00000030
#RIDEV_INPUTSINK  	= $00000100
#RIDEV_CAPTUREMOUSE	= $00000200
#RIDEV_NOHOTKEYS	= $00000200
#RIDEV_APPKEYS		= $00000400
#RIDEV_EXINPUTSINK	= $00001000
#RIDEV_DEVNOTIFY	= $00002000


; GetRawInputDeviceInfo() flags
#RIDI_PREPARSEDDATA = $20000005 ; returns previously parsed data 
#RIDI_DEVICENAME 	= $20000007   ; a string containing the device name
#RIDI_DEVICEINFO 	= $2000000b   ; an RIDI_DEVICE_INFO Structure

Prototype GetRawInputData(hRawInput, uiCommand, *pData.RAWINPUT, *pcbSize, cbSizeHeader)
Prototype RegisterRawInputDevices(*pRawInputDevices.RAWINPUTDEVICE, *uiNumDevices, cbSize)
Prototype GetRawInputDeviceList(*pRawInputDeviceList.RAWINPUTDEVICELIST, *uiNumDevices, cbSize)
Prototype GetRawInputDeviceInfo(hDevice, uiCommand, *pData, *pcbSize)

; Import functions
Global User32_dll = OpenLibrary(#PB_Any, "user32.dll")
If IsLibrary(User32_dll)
  Global RegisterRawInputDevices.RegisterRawInputDevices	= GetFunction(User32_dll, "RegisterRawInputDevices")
  Global GetRawInputData.GetRawInputData					        = GetFunction(User32_dll, "GetRawInputData")
  Global GetRawInputDeviceList.GetRawInputDeviceList		  = GetFunction(User32_dll, "GetRawInputDeviceList")
  Global GetRawInputDeviceInfo.GetRawInputDeviceInfo		  = GetFunction(User32_dll, "GetRawInputDeviceInfoW")
EndIf
;}

Structure myRawMouse
  SpriteID.i
  X.l
  Y.l
EndStructure
Global NewMap MyRawMouse.myRawMouse()

Global Event

;Sommaire
Declare Start()
Declare WinCallback (hWnd, Message, WParam, LParam)
Declare Exit()

Start()

Procedure Start()
  Protected hWnd
  
  hWnd = OpenWindow(#mf, 0, 0, 800, 600, "Deux souris", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  
  ; Capture window messages
  SetWindowCallback(@WinCallback())
  
  ; Set raw input capture for all mouses and keyboards
  Dim Rid.RAWINPUTDEVICE(0)
  Rid(0)\usUsagePage  = 1
  Rid(0)\usUsage      = 0
  Rid(0)\hwndTarget   = hWnd
  Rid(0)\dwFlags    	= #RIDEV_INPUTSINK | #RIDEV_PAGEONLY
  
  If RegisterRawInputDevices (@Rid(), ArraySize(Rid()) + 1, SizeOf(RAWINPUTDEVICE)) = #True
  EndIf
  
  If IsLibrary(User32_dll)
    CloseLibrary(User32_dll)
  EndIf
  
  
  ; Initialisation environnement 2D
  If InitSprite() = 0 Or InitMouse() = 0 Or InitKeyboard() = 0
    MessageRequester("Information", "Impossible d'ouvrir un environnement 2D", 0)
    Exit()
  EndIf
  
  OpenWindowedScreen(WindowID(#mf), 0, 0, 800, 600)
  
  ; Loop
  Repeat
    Repeat
      Event = WindowEvent()
      
      Select Event 
        Case #PB_Event_Gadget
          
        Case #PB_Event_CloseWindow
          Exit() 
      EndSelect
    Until Event = 0
    
    FlipBuffers() 
    ClearScreen(RGB(0, 0, 0))
    
    ; Evénement souris
    If ExamineMouse()      
      If MapSize(MyRawMouse()) <> 0    
        ForEach MyRawMouse()
          If Not IsSprite(MyRawMouse()\SpriteID)
            
            CreateSprite(MyRawMouse()\SpriteID, 40, 40)
            If StartDrawing(SpriteOutput(MyRawMouse()\SpriteID))
              Box(0, 0, 40, 40, RGB(Random(255), Random(215), Random(255)))
              StopDrawing()
            EndIf
          EndIf   
          DisplaySprite(MyRawMouse()\SpriteID, MyRawMouse()\X, MyRawMouse()\Y) 
        Next
      EndIf
    EndIf    
    
    ; Evenement clavier
    If ExamineKeyboard()
      If KeyboardReleased(#PB_Key_Escape)
        Exit()
      EndIf 
    EndIf
  ForEver
EndProcedure

; windows message processing
Procedure WinCallback (hWnd, Message, WParam, LParam)
  Static SpriteID
  Protected pcbSize.l
  Protected *pRawData.RAWINPUT
  
  Select Message 		
    Case #WM_INPUT ; Raw Input      
      If GetRawInputData(lParam, #RID_INPUT, #Null, @pcbSize, SizeOf(RAWINPUTHEADER)) = 0
        *pRawData = AllocateMemory(pcbSize) ; If input is from HID-device, data size can vary
        If *pRawData
          GetRawInputData(lParam, #RID_INPUT, *pRawData, @pcbSize, SizeOf(RAWINPUTHEADER))
          Select *pRawData\header\dwType
            Case #RIM_TYPEMOUSE:              
              If Not FindMapElement(MyRawMouse(), Str(*pRawData\header\hDevice))
                AddMapElement(MyRawMouse(), Str(*pRawData\header\hDevice))
                MyRawMouse()\SpriteID = SpriteID
                SpriteId + 1
              EndIf
              MyRawMouse()\X  = MyRawMouse()\X + *pRawData\mouse\lLastX
              MyRawMouse()\Y  = MyRawMouse()\Y + *pRawData\mouse\lLastY
          EndSelect
          
          FreeMemory(*pRawData)
        EndIf   
      EndIf
  EndSelect
  
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

Procedure Exit()
  End
EndProcedure
Alt + F4 pour quitter l'application.
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
case
Messages : 1546
Inscription : lun. 10/sept./2007 11:13

Re: Utiliser 2 souris

Message par case »

pour le clavier j'avais fait ça.suite a un bug pb sur la gestion clavier voir ce post

https://www.purebasic.fr/english/viewto ... 93#p376693
bug toujours pas résolu d’ailleurs


si ca peux servir :)

Code : Tout sélectionner



; +--------------------------------------+
; |   code par case @ purebasic forums   |
; |   case[at]moonshade.org              |
; +--------------------------------------+
; |                                      |
; |     procedures  d'interrogation      |
; |              clavier                 |
; |                                      |
; +--------------------------------------+
; |                                      |
; |    PROCEDURES ET DOCUMENTATION       |
; |                                      |
; +--------------------------------------+
; |   RefreshKeyboard()                  |
; |   *****************                  |
; |   Récupere l'etat du clavier         |
; |   equivalent d'examineKEYBOARD()      |
; |                                      |
; |   returnchar(key)                    |
; |   ***************                    |
; |   renvoi le caractere ascii de la    |
; |   touche 'key'                       |
; |                                      |
; |   Keydown(key)                       |
; |   ************                       |
; |   renvoi 1 si la touche est enfoncee |
; |                                      |
; |   Keyup(key)                         |
; |   **********                         |
; |   renvoi 1 si la touche est relachée |
; |                                      |
; |   keypushed(key)                     |
; |   **************                     |
; |   renvoi 1 si la touche est appuyée  |
; |   mais ne l'etait pas avant          |
; |                                      |
; |   keyon(key)                         |
; |   **********                         |
; |   renvoi 1 si al touche est allumée  |
; |   numlock par exemple                |
; |                                      |
; +--------------------------------------+


InitSprite()
ExamineDesktops()
main=OpenWindow(#PB_Any,0,0,DesktopWidth(0),DesktopHeight(0),"",#PB_Window_BorderLess)
OpenWindowedScreen(WindowID(main),0,0,DesktopWidth(0),DesktopHeight(0),0,0,0)
;
;
;
;
; les deux lignes suivantes sont inutiles mais permettent de bloquer les touches menu de windows.
;
;
;
;
;
; InitKeyboard()
; KeyboardMode(#PB_Keyboard_International)

;+--------------------------------------+
;|           BUFFERS CLAVIER            |
;+--------------------------------------+
Global *buffer=AllocateMemory(256)
Global *state=AllocateMemory(256)
;+--------------------------------------+
;|  CONSTANTES DEFINITION DES TOUCHES   |
;+--------------------------------------+
#AltKey_windows         =91
#AltKey_Shift           =16
#AltKey_LeftShift       =160
#AltKey_RightShift      =161
#AltKey_Alt             =17
#AltKey_Left_Alt        =164
#AltKey_AltGr           =165
#AltKey_Esc             =27
#AltKey_tilde           =222
#AltKey_F1              =112
#AltKey_F2              =113
#AltKey_F3              =114
#AltKey_F4              =115
#AltKey_F5              =116
#AltKey_F6              =117
#AltKey_F7              =118
#AltKey_F8              =119
#AltKey_F9              =120
#AltKey_F10             =121
#AltKey_F11             =122
#AltKey_F12             =123
#AltKey_0               =48
#AltKey_1               =49
#AltKey_2               =50
#AltKey_3               =51
#AltKey_4               =52
#AltKey_5               =53
#AltKey_6               =54
#AltKey_7               =55
#AltKey_8               =56
#AltKey_9               =57 
#AltKey_parenthese      =219 
#AltKey_egal            =187
#AltKey_backspace       =8
#AltKey_windows         =91
#AltKey_Tab             =9
#AltKey_A               =65
#AltKey_B               =66
#AltKey_C               =67
#AltKey_D               =68
#AltKey_E               =69
#AltKey_F               =70
#AltKey_G               =71
#AltKey_H               =72
#AltKey_I               =73
#AltKey_J               =74
#AltKey_K               =75
#AltKey_L               =76
#AltKey_M               =77
#AltKey_N               =78
#AltKey_O               =79
#AltKey_P               =80
#AltKey_Q               =81
#AltKey_R               =82
#AltKey_S               =83
#AltKey_T               =84
#AltKey_U               =85
#AltKey_V               =86
#AltKey_W               =87
#AltKey_X               =88
#AltKey_Y               =89
#AltKey_Z               =90
#AltKey_circ            =221
#AltKey_dollar          =186
#AltKey_return          =13
#AltKey_caps            =20
#AltKey_percent         =192
#AltKey_multiply        =220
#AltKey_compare         =226
#AltKey_space          =32
#altKey_left           =37
#altKey_up             =38
#altKey_right          =39
#altKey_down           =40
#AltKey_del             =46
#AltKey_pageup          =33
#altKey_pagedown        =34
#altKey_fin             =35
#altKey_debut           =36
#AltKey_inser           =45
#AltKey_prtscr          =44
#AltKey_pause           =19
#AltKey_mute            =173
#AltKey_voldwn          =174
#AltKey_volup           =175
#AltKey_numlock         =144
#AltKey_0num            =96
#AltKey_1num            =97
#AltKey_2num            =98
#AltKey_3num            =99
#AltKey_4num            =100
#AltKey_5num            =101
#AltKey_6num            =102
#AltKey_7num            =103
#AltKey_8num            =104
#AltKey_9num            =105
#Altkey_minnum          =109
#Altkey_addnum          =107
#altKey_leftmouse       =1
#altKey_rightmouse      =2
#AltKey_Left_Ctrl      =162
#altKey_right_Ctrl      =163
#altKey_middlemouse     =4 ; pas sur que la valeur soit la meme suivant les souris a tester

Procedure RefreshKeyboard()          ;rafraichis l'etat du clavier
  CopyMemory(*buffer,*state,256)     ; sauvegarde l'etat precedent pour comparaison (keyup)
  GetKeyboardState_(*buffer)         
EndProcedure
Procedure.s returnchar(key)          ; renvoi le caractere saisi
  r.s=Space(4)
  ToAscii_(key,0,*buffer,@r,0) 
  ProcedureReturn r;Mid(r,1,1)
EndProcedure
Procedure Keydown(key)               ; teste si une touche est enfoncée (continue)
  If PeekB(*buffer+key)<0
    ProcedureReturn 1
  EndIf
EndProcedure
Procedure keyup(key)                 ; teste si une touche est lachée
  If PeekB(*buffer+key)>=0 And PeekB(*state+key)<0
    RefreshKeyboard()                 ;rafraichis le clavier pour eviter un clic fantome
    ProcedureReturn 1
  EndIf
EndProcedure
Procedure keypushed(key)             ; teste si une touche est poussée (instant)
  If PeekB(*buffer+key)<0 And PeekB(*state+key)>=0
    RefreshKeyboard()                    ;rafraichis le clavier pour eviter un clic fantome
    ProcedureReturn 1
  EndIf
EndProcedure
Procedure keyon(key)                 ; teste si une touche  est 'on' ver maj, num lock etc...
  ProcedureReturn PeekB(*buffer+key) &%00000001;1 
EndProcedure

;
;
;
;
;
;
; exemple d'utilisation
;
;
;
;
;
;
;
Repeat
  ClearScreen(0)
  RefreshKeyboard()
  StartDrawing(ScreenOutput())
  b=0
  For y=0 To 15
    For x=0 To 15
      If Keydown(b)
        col=$0000ff        
      Else
        col=$ff00ff
      EndIf
      DrawText(x*100+40,y*20,Chr(MapVirtualKeyEx_(b,2,0)),$00ffff)   
      DrawText(x*100+56,y*20,returnchar(b),$ffff00)               
      DrawText(x*100,y*20,"["+RSet(Str(b),3,"0")+"]",col)
      b+1
    Next
  Next
  If keydown(#AltKey_circ)   
    Debug returnchar(#AltKey_circ)
  EndIf
  If keyup(#AltKey_return)
    Debug "released"
  EndIf
  If keyon(#AltKey_numlock)
    Debug "numlock"
  EndIf
  If keypushed(#AltKey_return)
    Debug "touche #AltKey_return pushed "
  EndIf
  If Keydown(#AltKey_del)
    Debug "touche del down "
  EndIf
    If keyon(#AltKey_Left_Ctrl)
    Debug "ctrl"
  EndIf
  
  
  StopDrawing()
  FlipBuffers()
  WaitWindowEvent(0)
Until keydown(#AltKey_Esc)

ImageImage
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Re: Utiliser 2 souris

Message par Thyphoon »

excellent merci à tous ! ^_^
Répondre