Code archives/User Input/Multiple Keyboards Handling, Blitz3D version
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
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 | |||||
; Multiple Keyboard Handling ; by Juan Ignacio Odriozola ; ; based on 2 great works: ; http://www.codeproject.com/KB/system/rawinput.aspx << started with ; http://blitzbasic.com/Community/posts.php?topic=85660#969498 << looking for "how to get a handle to my window find this!!!! ; ; thak's sswift for your exelent work!!, i used much of your code here! ; ; ; ; One Computer, One Screen (probably big), many users: many Keyboards..., many mice too, but not implemented yet! ; Why not to have a cursor for each mouse instaled, the same for keyboards ; ; see: http://www.wunderworks.com/ ; ; I test: KeyBoards, NumericKeypads, WirelessPresenters (for PowerPoint and the like) ; please advice me about other devices ; ; I will use this idea for manage multiple keypads to get answers from the audience in congress, ; at this time i have implemented one system of this kind with dedicated microcontroler based hardware ; (200 kepads), time to time i redesign the system (hard or soft) but now i decided to use something already done! ; ; i hope that this has an application in game programming ; ;what the code does: ; First: signals the system to send us KeyBoard events (RegisterRID_KEYBOARD(hWnd:Int)) ; Second: Obtain the list of Keyboards on the system () ; wait for keyboard events and show what its received ; ;the bmax version is documented better ; ;needs some decls And the free FastPointer lib ; ;all came from User32.decls ; ; ;probably you have the original ones, there are some diferences depending on usage, so the postfix 1, 2.. ;api_GetRawInputDeviceList%(pRawInputDeviceList*, uiNumDevices*, cbSize%) : "GetRawInputDeviceList" ;<==== this is called ;api_GetRawInputDeviceList1%(pRawInputDeviceList, uiNumDevices*, cbSize%) : "GetRawInputDeviceList" ;<==== this is called ;api_GetRawInputDeviceInfo%(hDevice%, uiCommand%, pData*, pcbSize%) : "GetRawInputDeviceInfoA" ; not needed ;api_GetRawInputDeviceInfo1%(hDevice%, uiCommand%, pData%, pcbSize*) : "GetRawInputDeviceInfoA" ;<==== this is called ;api_GetRawInputDeviceInfo2%(hDevice%, uiCommand%, pData*, pcbSize*) : "GetRawInputDeviceInfoA" ;<==== this is called ;api_RegisterRawInputDevices%(pRawInputDevice*, uiNumDevices%, cbSize%) : "RegisterRawInputDevices" ;<==== this is called ;api_GetRawInputData%(hRawInput*, uiCommand%, pData*, pcbSize*, cbSizeHeader%) : "GetRawInputData" ;<==== not needed ;api_GetRawInputData1%(hRawInput%, uiCommand%, pData*, pcbSize*, cbSizeHeader%) : "GetRawInputData" ;<==== this is called ;api_SetWindowLong% (hwnd%, nIndex%, dwNewLong%) : "SetWindowLongA" ;<==== this is called ;api_CallWindowProc% (lpPrevWndFunc%, hWnd%, Msg%, wParam%, lParam%) : "CallWindowProcA" ;<==== this is called Graphics 640,480,0,2 ; ---------------------------------------------------------------------------------------------- ; constants ; ---------------------------------------------------------------------------------------------- Const RIDI_DEVICEINFO% = $2000000B Const RID_INPUT = $10000003 Const WM_KEYDOWN = $0100 Const WM_SYSKEYDOWN = $0104 Const WM_INPUT = $00FF Const RIDI_DEVICENAME% = $20000007 Const RIM_TYPEMOUSE% = 0 Const RIM_TYPEKEYBOARD% = 1 Const RIM_TYPEHID% = 2 ; ---------------------------------------------------------------------------------------------- ; type def ; ---------------------------------------------------------------------------------------------- Type tDevice Field DeviceNameAsIs$ Field deviceName$ ;sin los 4 del principio: \\?\ Field hDevice Field dwType Field ClassCode$ ; Field SubClassCode$ Field Protocol$ Field Guid$ End Type Type tKeyboard Field deviceName$ Field hDevice Field dwType Field ClassCode$ Field SubClassCode$ Field Protocol$ Field Guid$ Field DeviceNameAsIs$ Field KeyPressed Field Key ;estas deberian ser Short! Field ScanCode End Type Type tRawIK ;Raw Input Keyboard ;c programmers uses unions, here the union is by fact. ;RAWINPUTHEADER: ;first 16 bytes Field dwType Field dwSize Field hDevice Field WPARAM ;RAWINPUTKEYBOARD: ;struct for keyboard Field MakeCodeFlags ;Field Flags Field ReservedVKey ;Field VKey Field Message Field ExtraInformation End Type Type tRID ;Raw Input Device Field Usage ;blitz don't have 16 variables, in this field are 2 16 variables, be careful ;the hight word must be $0001, the low word 0006 to register keyboard input Field Flags Field hWnd ;my window End Type ;------------------------------------------------------------------------------------------------ ;Global raw.tRawIK = New tRawIK Global OldWinProc ;old handler Local hWnd = SystemProperty("AppHWND") ;my window Global WinProcPointer = FunctionPointer() ;our_handler, we call old_handler from our handler to continue the chain Goto skip WinProc(0,0,0,0) .skip varRid.tRID = New tRID varRid\hWnd = hWnd varRid\Flags = 256 varRid\Usage = $00060001 ;------------------------------------------------------------------------------------------------ ; say: i want to receive raw input, please! ;------------------------------------------------------------------------------------------------ Local Result = api_RegisterRawInputDevices(varRid,1,12) ;------------------------------------------------------------------------------------------------ ; ok, tell me wich of your Funtions i should call ;------------------------------------------------------------------------------------------------ If Result Then HookWinProc(hWnd) ;------------------------------------------------------------------------------------------------ Print "RegisterRawInputDevices: "+Result Local k.tKeyboard ;------------------------------------------------------------------------------------------------ ; Get the list of devices ;------------------------------------------------------------------------------------------------ nDevices = GetDeviceList() ;populates a list of tDevice objects If nDevices Then For d.tDevice = Each tDevice If d\dwType = RIM_TYPEKEYBOARD Then ;we only want Keyboards If d\ClassCode<>"ROOT" Then ;and not The Root device k = New tKeyboard ;simply translate the info from Device to Keyboard k\hDevice = d\hDevice ;this is the ID from wich we identify the keyboard k\dwType = d\dwType k\DeviceName = d\deviceName k\ClassCode = d\ClassCode$ k\SubClassCode = d\SubClassCode$ k\Protocol = d\Protocol$ k\Guid = d\Guid$ k\DeviceNameAsIs = d\DeviceNameAsIs End If End If Next For k=Each tKeyboard Print k\hDevice Print k\DeviceName Print k\ClassCode Print k\SubClassCode Print k\Protocol Print k\Guid Print Next Print hWnd + " - " + OldWinProc End If Print Print "press any key...." WaitKey ;this is only to see the list of detected keyboards ;in the main loop we see the ID, ascii and scan code for each device If nDevices Then While Not KeyHit(1) Cls n=0 For k=Each tKeyboard Text 30,30+n*20, k\hDevice + ": "+Asc(k\Key)+", Scan:"+k\ScanCode n=n+1 Next Wend End If End ; ---------------------------------------------------------------------------------------------- ; hWnd is the pointer To your window. ; ---------------------------------------------------------------------------------------------- Function HookWinProc(hWnd) Local GWL_WNDPROC = -4 OldWinProc = api_SetWindowLong(hWnd, GWL_WNDPROC, WinProcPointer) End Function ; ---------------------------------------------------------------------------------------------- ; This Function is called automatically. ; ---------------------------------------------------------------------------------------------- Function WinProc( hWnd, Msg, wParam, lParam ) Local Item.tKeyboard Local raw.tRawIK = New tRawIK Select Msg Case WM_INPUT SizeBank = CreateBank(4) PokeInt SizeBank,0,32 Result = api_GetRawInputData1(lParam, RID_INPUT, raw, SizeBank, 16) FreeBank SizeBank If LWord(Raw\Message) Then gwParam = LWord(Raw\Message) glParam = LWord(Raw\ReservedVKey) End If If ( LWord(Raw\Message = WM_KeyDown) Or LWord(Raw\Message = WM_SYSKEYDOWN) ) Then If HWord(Raw\ReservedVKey) < 254 Then For Item = Each tKeyboard If raw\hDevice = Item\hDevice Then Item\KeyPressed = True Item\Key = HWord(Raw\ReservedVKey) Item\ScanCode = LWord(Raw\MakeCodeFlags) End If Next End If End If End Select Delete raw If OldWinProc <> 0 Then Return api_CallWindowProc(OldWinProc, hWnd, Msg, wParam, lParam) End If End Function ;-------------------------------------------------------------------------------- Function GetDeviceList() Local dCount, Result, DeviceList, Count Local i, ii, hDevice, dwType, cbSizeBank, cbSize Local pData, DeviceName$, Ultimo, Primero, Parte1$, Parte2$, Parte3$, Parte4$ Local Pos, Root, DeviceNameAsIs$ Local d.tDevice Local DeviceCount = CreateBank(4) PokeInt DeviceCount,0,0 Result = api_GetRawInputDeviceList1(0,DeviceCount,8) If Result<>-1 Then DeviceList = CreateBank(DeviceCount*8) Count = api_GetRawInputDeviceList(DeviceList,DeviceCount,8) For i=0 To Count-1 hDevice = PeekInt(DeviceList,i*8) dwType = PeekInt(DeviceList,i*8+4) cbSizeBank=CreateBank(4) api_GetRawInputDeviceInfo1(hDevice, RIDI_DEVICENAME, 0, cbSizeBank) cbSize = PeekInt(cbSizeBank,0) If (cbSize > 0) Then pData = CreateBank(cbSize) Result = api_GetRawInputDeviceInfo2(hDevice, RIDI_DEVICENAME, pData, cbSizeBank) cbSize = PeekInt(cbSizeBank,0) DeviceName$ = "" For ii=0 To cbSize-1 DeviceName = DeviceName + Chr(PeekByte(pData,ii)) Next FreeBank pData Pos = Instr(DeviceName,"}",1) If Pos Then DeviceName = Left(DeviceName,Pos) DeviceNameAsIs$ = DeviceName DeviceName$ = Upper(Right(DeviceName,Len(DeviceName)-4)) Root = Instr(DeviceName,"ROOT",1) Ultimo=0 Primero=Ultimo+1 Ultimo=Instr(DeviceName,"#",Primero) Parte1$ = Mid(DeviceName,Primero,Ultimo-Primero) Primero=Ultimo+1 Ultimo=Instr(DeviceName,"#",Primero) Parte2$ = Mid(DeviceName,Primero,Ultimo-Primero) Primero=Ultimo+1 Ultimo=Instr(DeviceName,"#",Primero) Parte3$ = Mid(DeviceName,Primero,Ultimo-Primero) Primero=Ultimo+1 Ultimo=Instr(DeviceName,"#",Primero) Parte4$ = Mid(DeviceName,Primero,Ultimo-Primero) dCount = dCount+1 d.tDevice = New tDevice d\deviceName = DeviceName d\hDevice = hDevice d\dwType = dwType d\ClassCode$ = Parte1 d\SubClassCode$ = Parte2 d\Protocol$ = Parte3 d\Guid$ = Parte4 d\DeviceNameAsIs = DeviceNameAsIs End If FreeBank cbSizeBank Next FreeBank DeviceList FreeBank DeviceCount Return dCount Else FreeBank DeviceCount Return -1 End If End Function ;-------------------------------------------------------------------------------- Function LWord(I) ; Returns the Lower 16 bits of a 32 bit integer. Return I And $FF End Function Function HWord(I) ; Returns the Upper 16 bits of a 32 bit integer. Return I Shr 16 End Function ;-------------------------------------------------------------------------------- |
Comments
None.
Code Archives Forum