November 25, 2020, 05:15:35 AM

Author Topic: [bb] Multiple Keyboards Handling, Blitz3D version by Charrua [ 1+ years ago ]  (Read 591 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
Title : Multiple Keyboards Handling, Blitz3D version
Author : Charrua
Posted : 1+ years ago

Description : If you have more than one keyboard, a numeric keypad for instance, or, a notebook with a keyboard connected,
you can enter the number "123" typing one digit on each diferent keyboard and the application receives "123".
Windows normal handling gives you the input but you don't know from where. It should become form a "Remote presenter
for power point".

This code scans the list of keyboards and get handles to them, registers the application to receive keyboard input
and then, windows call us, every time a key is pressed and calling the apropiate RawInput function we get the Handle
of the keyboard propietary of that keystroke.

No graphical interface, only Print instructions, first appears a list of detected devices (input, hid) some are
filtered, and finally appears the list of "Listed Devices"
press a key, and an Id appears and the code received.

Blitz still receives the char, so you can use normal blitz functions to read keyboard.

Hope you may found this useful.

Juan


Code :
Code: BlitzBasic
  1. ;       Multiple Keyboard Handling
  2. ;       by Juan Ignacio Odriozola
  3. ;
  4. ;       based on 2 great works:
  5. ;               http://www.codeproject.com/KB/system/rawinput.aspx                      << started with
  6. ;               http://blitzbasic.com/Community/posts.php?topic=85660#969498    << looking for "how to get a handle to my window find this!!!!
  7. ;
  8. ;       thak's sswift for your exelent work!!, i used much of your code here!
  9. ;
  10. ;
  11. ;
  12. ;       One Computer, One Screen (probably big), many users: many Keyboards..., many mice too, but not implemented yet!
  13. ;       Why not to have a cursor for each mouse instaled, the same for keyboards
  14. ;
  15. ;       see: http://www.wunderworks.com/
  16. ;
  17. ;       I test: KeyBoards, NumericKeypads, WirelessPresenters (for PowerPoint and the like)
  18. ;       please advice me about other devices
  19. ;
  20. ;       I will use this idea for manage multiple keypads to get answers from the audience in congress,
  21. ;       at this time i have implemented one system of this kind with dedicated microcontroler based hardware
  22. ;       (200 kepads), time to time i redesign the system (hard or soft) but now i decided to use something already done!
  23. ;
  24. ;       i hope that this has an application in game programming
  25. ;
  26. ;what the code does:
  27. ;       First:  signals the system to send us KeyBoard events (RegisterRID_KEYBOARD(hWnd:Int))
  28. ;       Second: Obtain the list of Keyboards on the system    ()
  29. ;       wait for keyboard events and show what its received
  30. ;
  31. ;the bmax version is documented better
  32. ;
  33. ;needs some decls And the free FastPointer lib
  34. ;
  35. ;all came from User32.decls
  36. ;
  37. ;
  38. ;probably you have the original ones, there are some diferences depending on usage, so the postfix 1, 2..
  39.  
  40. ;api_GetRawInputDeviceList%(pRawInputDeviceList*, uiNumDevices*, cbSize%) : "GetRawInputDeviceList"     ;<====  this is called
  41. ;api_GetRawInputDeviceList1%(pRawInputDeviceList, uiNumDevices*, cbSize%) : "GetRawInputDeviceList"     ;<====  this is called
  42.  
  43. ;api_GetRawInputDeviceInfo%(hDevice%, uiCommand%, pData*, pcbSize%) : "GetRawInputDeviceInfoA"          ;               not needed
  44. ;api_GetRawInputDeviceInfo1%(hDevice%, uiCommand%, pData%, pcbSize*) : "GetRawInputDeviceInfoA"         ;<====  this is called
  45. ;api_GetRawInputDeviceInfo2%(hDevice%, uiCommand%, pData*, pcbSize*) : "GetRawInputDeviceInfoA"         ;<====  this is called
  46.  
  47. ;api_RegisterRawInputDevices%(pRawInputDevice*, uiNumDevices%, cbSize%) : "RegisterRawInputDevices"     ;<====  this is called
  48.  
  49. ;api_GetRawInputData%(hRawInput*, uiCommand%, pData*, pcbSize*, cbSizeHeader%) : "GetRawInputData"      ;<====  not needed
  50. ;api_GetRawInputData1%(hRawInput%, uiCommand%, pData*, pcbSize*, cbSizeHeader%) : "GetRawInputData"     ;<====  this is called
  51.  
  52. ;api_SetWindowLong% (hwnd%, nIndex%, dwNewLong%) : "SetWindowLongA"                                                                     ;<====  this is called
  53. ;api_CallWindowProc% (lpPrevWndFunc%, hWnd%, Msg%, wParam%, lParam%) : "CallWindowProcA"                        ;<====  this is called
  54.  
  55. Graphics 640,480,0,2
  56.  
  57. ; ----------------------------------------------------------------------------------------------
  58. ;       constants
  59. ; ----------------------------------------------------------------------------------------------
  60.  
  61.  
  62. Const RIDI_DEVICEINFO%  = $2000000B
  63. Const RID_INPUT                 = $10000003
  64.  
  65. Const WM_KEYDOWN                = $0100
  66. Const WM_SYSKEYDOWN             = $0104
  67. Const WM_INPUT                  = $00FF
  68.  
  69. Const RIDI_DEVICENAME%  = $20000007
  70.  
  71. Const RIM_TYPEMOUSE%    = 0
  72. Const RIM_TYPEKEYBOARD% = 1    
  73. Const RIM_TYPEHID%              = 2    
  74.  
  75. ; ----------------------------------------------------------------------------------------------
  76. ;       type def
  77. ; ----------------------------------------------------------------------------------------------
  78.  
  79. Type tDevice
  80.         Field DeviceNameAsIs$
  81.         Field deviceName$               ;sin los 4 del principio: \?
  82.         Field hDevice
  83.         Field dwType
  84.         Field ClassCode$                ;
  85.         Field SubClassCode$
  86.         Field Protocol$
  87.         Field Guid$
  88. End Type
  89.  
  90.  
  91. Type tKeyboard
  92.         Field deviceName$
  93.         Field hDevice
  94.         Field dwType
  95.         Field ClassCode$
  96.         Field SubClassCode$
  97.         Field Protocol$
  98.         Field Guid$
  99.         Field DeviceNameAsIs$
  100.         Field KeyPressed
  101.         Field Key                       ;estas deberian ser Short!
  102.         Field ScanCode
  103. End Type
  104.  
  105. Type tRawIK     ;Raw Input Keyboard             ;c programmers uses unions, here the union is by fact.
  106.        
  107.         ;RAWINPUTHEADER:        ;first 16 bytes
  108.                 Field dwType
  109.                 Field dwSize
  110.                 Field hDevice
  111.                 Field WPARAM
  112.         ;RAWINPUTKEYBOARD:      ;struct for keyboard
  113.                 Field MakeCodeFlags
  114.                 ;Field Flags
  115.                 Field ReservedVKey
  116.                 ;Field VKey
  117.                 Field Message
  118.                 Field ExtraInformation
  119. End Type
  120.  
  121. Type tRID       ;Raw Input Device
  122.         Field Usage     ;blitz don't have 16 variables, in this field are 2 16 variables, be careful
  123.                                 ;the hight word must be $0001, the low word 0006 to register keyboard input
  124.         Field Flags
  125.         Field hWnd      ;my window
  126. End Type
  127.  
  128.  
  129. ;------------------------------------------------------------------------------------------------
  130.  
  131.  
  132. ;Global raw.tRawIK = New tRawIK
  133.  
  134.  
  135. Global OldWinProc                                                               ;old handler
  136.  
  137. Local hWnd = SystemProperty("AppHWND")                          ;my window
  138.  
  139. Global WinProcPointer = FunctionPointer()               ;our_handler, we call old_handler from our handler to continue the chain
  140.         Goto skip
  141.         WinProc(0,0,0,0)
  142.         .skip
  143.  
  144. varRid.tRID = New tRID
  145. varRidhWnd = hWnd
  146. varRidFlags = 256
  147. varRidUsage = $00060001
  148.  
  149. ;------------------------------------------------------------------------------------------------
  150. ;       say: i want to receive raw input, please!
  151. ;------------------------------------------------------------------------------------------------
  152.  
  153. Local Result = api_RegisterRawInputDevices(varRid,1,12)
  154.  
  155. ;------------------------------------------------------------------------------------------------
  156. ;       ok, tell me wich of your Funtions i should call
  157. ;------------------------------------------------------------------------------------------------
  158.  
  159. If Result Then HookWinProc(hWnd)
  160.  
  161. ;------------------------------------------------------------------------------------------------
  162.  
  163.  
  164. Print "RegisterRawInputDevices: "+Result
  165.  
  166.  
  167. Local k.tKeyboard
  168.  
  169. ;------------------------------------------------------------------------------------------------
  170. ;       Get the list of devices
  171. ;------------------------------------------------------------------------------------------------
  172.  
  173. nDevices = GetDeviceList()      ;populates a list of tDevice objects
  174.  
  175. If nDevices Then
  176.  
  177.         For d.tDevice = Each tDevice
  178.                 If ddwType = RIM_TYPEKEYBOARD Then      ;we only want Keyboards
  179.                         If dClassCode<>"ROOT" Then              ;and not The Root device
  180.                                 k = New tKeyboard                       ;simply translate the info from Device to Keyboard
  181.                                 khDevice = dhDevice             ;this is the ID from wich we identify the keyboard
  182.                                 kdwType = ddwType
  183.                                 kDeviceName = ddeviceName
  184.                                 kClassCode = dClassCode$
  185.                                 kSubClassCode = dSubClassCode$
  186.                                 kProtocol = dProtocol$
  187.                                 kGuid = dGuid$
  188.                                 kDeviceNameAsIs = dDeviceNameAsIs
  189.                         End If
  190.                 End If
  191.         Next           
  192.  
  193.         For k=Each tKeyboard
  194.                 Print khDevice
  195.                 Print kDeviceName
  196.                 Print kClassCode
  197.                 Print kSubClassCode
  198.                 Print kProtocol
  199.                 Print kGuid
  200.                 Print
  201.         Next
  202.        
  203.         Print hWnd + " - " + OldWinProc
  204.                
  205. End If
  206.  
  207. Print
  208. Print "press any key...."
  209. WaitKey         ;this is only to see the list of detected keyboards
  210.  
  211.  
  212. ;in the main loop we see the ID, ascii and scan code for each device
  213.  
  214. If nDevices Then
  215.  
  216.         While Not KeyHit(1)
  217.        
  218.                 Cls
  219.  
  220.                 n=0
  221.                 For k=Each tKeyboard
  222.                         Text 30,30+n*20, khDevice + ": "+Asc(kKey)+", Scan:"+kScanCode
  223.                         n=n+1
  224.                 Next
  225.                        
  226.         Wend
  227.        
  228. End If
  229.  
  230. End
  231.  
  232.  
  233. ; ----------------------------------------------------------------------------------------------
  234. ; hWnd is the pointer To your window.
  235. ; ----------------------------------------------------------------------------------------------
  236.  
  237. Function HookWinProc(hWnd)
  238.         Local GWL_WNDPROC = -4
  239.         OldWinProc = api_SetWindowLong(hWnd, GWL_WNDPROC, WinProcPointer)
  240. End Function  
  241.  
  242.  
  243. ; ----------------------------------------------------------------------------------------------
  244. ; This Function is called automatically.
  245. ; ----------------------------------------------------------------------------------------------
  246.  
  247.  
  248. Function WinProc( hWnd, Msg, wParam, lParam )
  249.  
  250.         Local Item.tKeyboard
  251.         Local raw.tRawIK = New tRawIK
  252.        
  253.         Select Msg
  254.  
  255.                 Case WM_INPUT
  256.                
  257.                         SizeBank = CreateBank(4)
  258.                         PokeInt SizeBank,0,32
  259.                        
  260.                         Result = api_GetRawInputData1(lParam, RID_INPUT, raw, SizeBank, 16)
  261.                        
  262.                         FreeBank SizeBank
  263.                        
  264.                         If LWord(RawMessage) Then
  265.                                 gwParam = LWord(RawMessage)
  266.                                 glParam = LWord(RawReservedVKey)
  267.                         End If
  268.  
  269.                         If ( LWord(RawMessage = WM_KeyDown) Or LWord(RawMessage = WM_SYSKEYDOWN) ) Then
  270.                                 If HWord(RawReservedVKey) < 254 Then
  271.                                         For Item = Each tKeyboard
  272.                                                 If rawhDevice = ItemhDevice Then
  273.                                                         ItemKeyPressed = True
  274.                                                         ItemKey = HWord(RawReservedVKey)
  275.                                                         ItemScanCode = LWord(RawMakeCodeFlags)
  276.                                                 End If
  277.                                         Next
  278.                                 End If
  279.                         End If
  280.                        
  281.         End Select
  282.        
  283.         Delete raw
  284.        
  285.         If OldWinProc <> 0 Then
  286.                 Return api_CallWindowProc(OldWinProc, hWnd, Msg, wParam, lParam)
  287.         End If
  288.                
  289. End Function
  290.  
  291. ;--------------------------------------------------------------------------------
  292.  
  293.  
  294. Function GetDeviceList()
  295.  
  296.         Local dCount, Result, DeviceList, Count
  297.         Local i, ii, hDevice, dwType, cbSizeBank, cbSize
  298.         Local pData, DeviceName$, Ultimo, Primero, Parte1$, Parte2$, Parte3$, Parte4$
  299.         Local Pos, Root, DeviceNameAsIs$
  300.         Local d.tDevice
  301.         Local DeviceCount = CreateBank(4)
  302.        
  303.        
  304.         PokeInt DeviceCount,0,0
  305.         Result = api_GetRawInputDeviceList1(0,DeviceCount,8)
  306.        
  307.         If Result<>-1 Then
  308.                 DeviceList = CreateBank(DeviceCount*8)
  309.                 Count = api_GetRawInputDeviceList(DeviceList,DeviceCount,8)
  310.                 For i=0 To Count-1
  311.                         hDevice = PeekInt(DeviceList,i*8)
  312.                         dwType = PeekInt(DeviceList,i*8+4)
  313.                         cbSizeBank=CreateBank(4)
  314.                         api_GetRawInputDeviceInfo1(hDevice, RIDI_DEVICENAME, 0, cbSizeBank)
  315.                         cbSize = PeekInt(cbSizeBank,0)
  316.                         If (cbSize > 0) Then
  317.                                 pData = CreateBank(cbSize)
  318.                                 Result = api_GetRawInputDeviceInfo2(hDevice, RIDI_DEVICENAME, pData, cbSizeBank)
  319.                                 cbSize = PeekInt(cbSizeBank,0)
  320.                                 DeviceName$ = ""
  321.                                 For ii=0 To cbSize-1
  322.                                         DeviceName = DeviceName + Chr(PeekByte(pData,ii))
  323.                                 Next
  324.                                 FreeBank pData
  325.                                
  326.                                 Pos = Instr(DeviceName,"}",1)
  327.                                 If Pos Then DeviceName = Left(DeviceName,Pos)
  328.                                 DeviceNameAsIs$ = DeviceName
  329.                                 DeviceName$ = Upper(Right(DeviceName,Len(DeviceName)-4))
  330.                                 Root = Instr(DeviceName,"ROOT",1)
  331.                                 Ultimo=0
  332.                                 Primero=Ultimo+1
  333.                                 Ultimo=Instr(DeviceName,"#",Primero)
  334.                                 Parte1$ = Mid(DeviceName,Primero,Ultimo-Primero)
  335.                                 Primero=Ultimo+1
  336.                                 Ultimo=Instr(DeviceName,"#",Primero)
  337.                                 Parte2$ = Mid(DeviceName,Primero,Ultimo-Primero)
  338.                                 Primero=Ultimo+1
  339.                                 Ultimo=Instr(DeviceName,"#",Primero)
  340.                                 Parte3$ = Mid(DeviceName,Primero,Ultimo-Primero)
  341.                                 Primero=Ultimo+1
  342.                                 Ultimo=Instr(DeviceName,"#",Primero)
  343.                                 Parte4$ = Mid(DeviceName,Primero,Ultimo-Primero)
  344.                                 dCount = dCount+1
  345.                                 d.tDevice = New tDevice
  346.                                 ddeviceName = DeviceName
  347.                                 dhDevice = hDevice
  348.                                 ddwType = dwType
  349.                                 dClassCode$ = Parte1
  350.                                 dSubClassCode$ = Parte2
  351.                                 dProtocol$ = Parte3
  352.                                 dGuid$ = Parte4
  353.                                 dDeviceNameAsIs = DeviceNameAsIs
  354.                                
  355.                         End If
  356.                         FreeBank cbSizeBank
  357.                 Next
  358.                
  359.                 FreeBank DeviceList
  360.                 FreeBank DeviceCount
  361.                 Return dCount
  362.                
  363.         Else
  364.                
  365.                 FreeBank DeviceCount
  366.                 Return -1
  367.                
  368.         End If
  369.        
  370. End Function
  371.  
  372.  
  373. ;--------------------------------------------------------------------------------
  374.  
  375. Function LWord(I) ; Returns the Lower 16 bits of a 32 bit integer.
  376.         Return I And $FF
  377. End Function
  378.  
  379. Function HWord(I) ; Returns the Upper 16 bits of a 32 bit integer.
  380.         Return I Shr 16
  381. End Function
  382.  
  383. ;--------------------------------------------------------------------------------


Comments : none...

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal