Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
kind of works? reading multiple mice: any c programmers want to look at this?
#1
Thanks to the help from the kind folks here with compiling C with QB64's built in compiler, I made some progress compiling this Raw Input API multi-mouse code, and got 2 of the examples "HelloRawInput.c" and "ShowMultipleMiceValues.c" to compile and run.

If you run HelloRawInput (see attached "HelloRawInput_minimal.zip", run the batch file to compile with QB64), it counts the system devices. When you plug in a 2nd USB mouse, the count increases.

If you run ShowMultipleMiceValues (see attached "ShowMultipleMiceValues.zip", run the batch file to compile with QB64), with 2 USB mice plugged in, and move one, it displays the device ID and some values. Then if you move the second mouse, the device ID changes. Running it from Windows, where 2 USB mice plugged in both control the same mouse pointer, there is only one set of x/y coordinates. So this example doesn't show separate x/y coordinates for each mouse. 

However JStookey provides a raw mouse API to read separate coordinates from multiple mice (see attached "raw_mouse_test_(attempt_1).zip", and "raw_mouse_test_(attempt_2).zip" where I tried to clean up code putting compound IF statements inside braces, etc.), but either way compiling gives errors (see "errors1.txt").

I am not C-savvy enough to really understand the erorrs but I did see some comments on the page about needing to convert libraries and massage header files to make it work for MinGW. They talk about using a program called, "reimp" (part of MinGW tools) on the MS Platform SDK "user32.lib" file. I don't think I have "reimp" and don't know what this MS Platform SDK is, so I haven't gotten far enough along to try and do the things they are talking about to make it work, and was hoping someone more familiar with that stuff might be able to help figure it out or guide me through some/any of it? 

The hope is that this version (or one slightly modified) could read separate coordinates for each mouse, and QB64 could talk to it and get back separate input for each mouse plugged in. Think of the multiplayer Pong and puzzle games you could make! LoL

Then there is an example program that lists all the raw input devices on the computer (see attached "ListRawInputDevices_vc++.zip") which similarly doesn't compile. That one is in C++, which I have even less of a clue about making work, but GCC should be able to handle C++ so maybe it can work?

Anyway, at least 2 of these examples compile right out of the box, and if anyone has got any interest & spare time to help get the raw mouse API example to work, we could have a way to read 2 or more mice as separate input devices from QB64 (how to get QB64 to talk to a C program is a separate problem, I figure we can tackle another day!)

Meanwhile I will try to mess around with converting libraries / header files as time allows, to see if I can figure it out, but I am sure someone who actually knows what they're doing with the C stuff would have a better chance at succeeding...

Also, I think this RawInput method can be used for reading multiple keyboards as separate devices, which would open up some other interesting possibilities.

That's all I have for now!


Attached Files
.zip   HelloRawInput_minimal.zip (Size: 2.14 KB / Downloads: 65)
.zip   ShowMultipleMiceValues.zip (Size: 4.08 KB / Downloads: 61)
.zip   raw_mouse_test_(attempt_1).zip (Size: 10.42 KB / Downloads: 53)
.zip   raw_mouse_test_(attempt_2).zip (Size: 10.45 KB / Downloads: 56)
.zip   ListRawInputDevices_vc++.zip (Size: 53.78 KB / Downloads: 56)
Reply
#2
(09-06-2022, 08:08 PM)madscijr Wrote: Thanks to the help from the kind folks here with compiling C with QB64's built in compiler, I made some progress compiling this Raw Input API multi-mouse code, and got 2 of the examples "HelloRawInput.c" and "ShowMultipleMiceValues.c" to compile and run.

If you run HelloRawInput (see attached "HelloRawInput_minimal.zip", run the batch file to compile with QB64), it counts the system devices. When you plug in a 2nd USB mouse, the count increases.

If you run ShowMultipleMiceValues (see attached "ShowMultipleMiceValues.zip", run the batch file to compile with QB64), with 2 USB mice plugged in, and move one, it displays the device ID and some values. Then if you move the second mouse, the device ID changes. Running it from Windows, where 2 USB mice plugged in both control the same mouse pointer, there is only one set of x/y coordinates. So this example doesn't show separate x/y coordinates for each mouse. 

However JStookey provides a raw mouse API to read separate coordinates from multiple mice (see attached "raw_mouse_test_(attempt_1).zip", and "raw_mouse_test_(attempt_2).zip" where I tried to clean up code putting compound IF statements inside braces, etc.), but either way compiling gives errors (see "errors1.txt").

I am not C-savvy enough to really understand the erorrs but I did see some comments on the page about needing to convert libraries and massage header files to make it work for MinGW. They talk about using a program called, "reimp" (part of MinGW tools) on the MS Platform SDK "user32.lib" file. I don't think I have "reimp" and don't know what this MS Platform SDK is, so I haven't gotten far enough along to try and do the things they are talking about to make it work, and was hoping someone more familiar with that stuff might be able to help figure it out or guide me through some/any of it? 

The hope is that this version (or one slightly modified) could read separate coordinates for each mouse, and QB64 could talk to it and get back separate input for each mouse plugged in. Think of the multiplayer Pong and puzzle games you could make! LoL

Then there is an example program that lists all the raw input devices on the computer (see attached "ListRawInputDevices_vc++.zip") which similarly doesn't compile. That one is in C++, which I have even less of a clue about making work, but GCC should be able to handle C++ so maybe it can work?

Anyway, at least 2 of these examples compile right out of the box, and if anyone has got any interest & spare time to help get the raw mouse API example to work, we could have a way to read 2 or more mice as separate input devices from QB64 (how to get QB64 to talk to a C program is a separate problem, I figure we can tackle another day!)

Meanwhile I will try to mess around with converting libraries / header files as time allows, to see if I can figure it out, but I am sure someone who actually knows what they're doing with the C stuff would have a better chance at succeeding...

Also, I think this RawInput method can be used for reading multiple keyboards as separate devices, which would open up some other interesting possibilities.

That's all I have for now!

Looking at the errors, raw_mouse.c has no WinMain function, so it needs to be compiled to an object (".o") file, then linked to a Windows GUI program which uses it.  In this case, that Windows GUI program is raw_mouse_test.c.

I've modified the batch file to get everything compiled.  The compiler issues a few warnings, but finishes compilation.  raw_mouse_test.exe seems to work, although I only have one mouse to test it on.  ZIP file attached to post.


[Image: 2022-09-06-153904.png]



In regards to ListRawInputDevices_vc++.zip, that is a Visual C++ project, which I am not equipped to handle.  I was able to compile it with MinGW after one small change, but it immediately exits without displaying anything.  No luck for me.


Attached Files
.zip   raw_mouse_test_(attempt_2)_compiles.zip (Size: 17.46 KB / Downloads: 58)
Reply
#3
(09-06-2022, 09:07 PM)JRace Wrote:
(09-06-2022, 08:08 PM)madscijr Wrote: Thanks to the help from the kind folks here with compiling C with QB64's built in compiler, I made some progress compiling this Raw Input API multi-mouse code, and got 2 of the examples "HelloRawInput.c" and "ShowMultipleMiceValues.c" to compile and run.
...
and was hoping someone more familiar with that stuff might be able to help figure it out or guide me through some/any of it? 

Looking at the errors, raw_mouse.c has no WinMain function, so it needs to be compiled to an object (".o") file, then linked to a Windows GUI program which uses it.  In this case, that Windows GUI program is raw_mouse_test.c.

I've modified the batch file to get everything compiled.  The compiler issues a few warnings, but finishes compilation.  raw_mouse_test.exe seems to work, although I only have one mouse to test it on.  ZIP file attached to post.
...

Thanks so much for taking the time to look at this and get it compiling. 
I'm away from the PC, but can't wait to give raw_mouse_test a spin with both mice plugged in!

UPDATE: Well, it runs! But due to Windows having one mouse pointer, it seems to be writing the values for whichever was the last mouse moved, for all the mice. At least it can differentiate between them - I'm going to play with the code and try to get it to track the values for each mouse individually, and only update mouse n's value when that mouse is the one being moved. Wish me good luck :-)
Reply
#4
@madscijr might be determined to use a C program but could this be tried with QB64?

https://qb64phoenix.com/qb64wiki/index.php/DEVICEINPUT

Once I wanted to buy a mouse with six buttons but two of the "buttons" was nudging the mousewheel which was a no-go for me. WTF was I going to do with four extra buttons?! Ah well at least the square one in front of the mousewheel would have been enough for me instead of pressing that darned wheel down.
Reply
#5
(09-07-2022, 04:08 AM)mnrvovrfc Wrote: @madscijr might be determined to use a C program but could this be tried with QB64?

https://qb64phoenix.com/qb64wiki/index.php/DEVICEINPUT

Once I wanted to buy a mouse with six buttons but two of the "buttons" was nudging the mousewheel which was a no-go for me. WTF was I going to do with four extra buttons?! Ah well at least the square one in front of the mousewheel would have been enough for me instead of pressing that darned wheel down.

Yeah, I did experiments with DEVICEINPUT, it no workie. I can dig up the various tests & post here if it helps, but I'm pretty sure that for reading separate input from multiple mice in Windows, the RawInputAPI is the way. Unless there's a way to replicate the C code that calls the API in QB64, I need to take a crash course in C basics like reading command line parameters (maybe an input value for which mouse to return coords for) and how to call or shell out to the C mouse exe from QB64 and how the mouse exe would return the coordinates to QB64.
Reply
#6
Hmmmm.  Dav's QBasic Site ( http://www.qbasicnews.com/dav/qb64.php ) has some tutorials/samples of making API calls in QB64.  You might look at some of those.

Here's one that uses several API calls: http://www.qbasicnews.com/dav/files/dirinfo-api.bas


Another place to begin is in the wiki: https://qb64phoenix.com/qb64wiki/index.p..._Libraries


I'm still learning the all the QB64 esoterica, so I'm going to be tinkering with API calls myself.
Reply
#7
I'll have to take a look at this again sometime to see if I can be of assistance. I had some trouble with the API last time but I'm more experienced now. That's no guarantee that I'd be able to get anywhere with it, however. I think the main issue last time was struct sizes, maybe? I've got a foolproof way of getting those set up now.
Tread on those who tread on you

Reply
#8
Adding this reply as a way to keep track of this source as I work on converting what you've done so far. I'll have to pull up my Win32 Video Player code to bring in all my junk for the callbacks and window functions but the InitRawInput function works as expected  Smile

Code: (Select All)
Option Explicit
$NoPrefix
$Console:Only

Type RAWINPUTDEVICE
    As Unsigned Integer usUsagePage, usUsage
    As Unsigned Long dwFlags
    As Offset hwndTarget
End Type

Type RAWINPUTDEVICELIST
    As Offset hDevice
    As Unsigned Long dwType
    $If 64BIT Then
        As String * 4 alignment
    $End If
End Type

Declare CustomType Library
    Function GetRawInputDeviceList~& (ByVal pRawInputDeviceList As Offset, Byval puiNumDevices As Offset, Byval cbSize As Unsigned Long)
    Sub GetRawInputDeviceList (ByVal pRawInputDeviceList As Offset, Byval puiNumDevices As Offset, Byval cbSize As Unsigned Long)
    Function RegisterRawInputDevices& (ByVal pRawInputDevices As Offset, Byval uiNumDevices As Unsigned Long, Byval cbSize As Unsigned Long)
    Function GetLastError~& ()
End Declare

InitRawInput

Sub InitRawInput ()
    Dim As RAWINPUTDEVICE Rid(0 To 49)
    Dim As Unsigned Long nDevices
    Dim As RAWINPUTDEVICELIST RawInputDeviceList

    If GetRawInputDeviceList(0, Offset(nDevices), Len(RawInputDeviceList)) <> 0 Then
        Exit Sub
    End If

    Dim As MEM pRawInputDeviceList: pRawInputDeviceList = MemNew(Len(RawInputDeviceList) * nDevices)
    GetRawInputDeviceList pRawInputDeviceList.OFFSET, Offset(nDevices), Len(RawInputDeviceList)

    'This small block of commented code proves that we've got the device list
    'Dim As RAWINPUTDEVICELIST rawdevs(0 To nDevices - 1)
    'MemGet pRawInputDeviceList, pRawInputDeviceList.OFFSET, rawdevs()
    'Dim As Unsigned Long x
    'For x = 0 To UBound(rawdevs)
    '    Print rawdevs(x).hDevice, rawdevs(x).dwType
    'Next

    Print "Number of raw input devices:"; nDevices

    MemFree pRawInputDeviceList

    Rid(0).usUsagePage = &H01
    Rid(0).usUsage = &H02
    Rid(0).dwFlags = 0
    Rid(0).hwndTarget = 0

    If RegisterRawInputDevices(Offset(Rid()), 1, Len(Rid(0))) = 0 Then
        Print "RawInput init failed"
    End If
End Sub
Tread on those who tread on you

Reply
#9
@Spriggsy
@JRace

Next I will check out these examples of calling an API directly from QB64 - thanks!

In the meantime I was trying to figure out how to get QB64 to talk to the C program, I tried SHELL but it doesn't seem to be working:
calling an external C program from QB64 & getting back results? 

Also, here is some more crazy stuff, a c++ project for reading multiple input devices that is supposedly cross-platform? 
I'm only including this for reference, I have zero chance of getting this to work, but if anyone does, do tell!
https://github.com/NoobsArePeople2/manymouse
Reply
#10
(09-07-2022, 03:18 PM)Spriggsy Wrote: Adding this reply as a way to keep track of this source as I work on converting what you've done so far. I'll have to pull up my Win32 Video Player code to bring in all my junk for the callbacks and window functions but the InitRawInput function works as expected  Smile

Code: (Select All)
Option Explicit
$NoPrefix
$Console:Only

Type RAWINPUTDEVICE
    As Unsigned Integer usUsagePage, usUsage
    As Unsigned Long dwFlags
    As Offset hwndTarget
End Type

Type RAWINPUTDEVICELIST
    As Offset hDevice
    As Unsigned Long dwType
    $If 64BIT Then
        As String * 4 alignment
    $End If
End Type

Declare CustomType Library
    Function GetRawInputDeviceList~& (ByVal pRawInputDeviceList As Offset, Byval puiNumDevices As Offset, Byval cbSize As Unsigned Long)
    Sub GetRawInputDeviceList (ByVal pRawInputDeviceList As Offset, Byval puiNumDevices As Offset, Byval cbSize As Unsigned Long)
    Function RegisterRawInputDevices& (ByVal pRawInputDevices As Offset, Byval uiNumDevices As Unsigned Long, Byval cbSize As Unsigned Long)
    Function GetLastError~& ()
End Declare

InitRawInput

Sub InitRawInput ()
    Dim As RAWINPUTDEVICE Rid(0 To 49)
    Dim As Unsigned Long nDevices
    Dim As RAWINPUTDEVICELIST RawInputDeviceList

    If GetRawInputDeviceList(0, Offset(nDevices), Len(RawInputDeviceList)) <> 0 Then
        Exit Sub
    End If

    Dim As MEM pRawInputDeviceList: pRawInputDeviceList = MemNew(Len(RawInputDeviceList) * nDevices)
    GetRawInputDeviceList pRawInputDeviceList.OFFSET, Offset(nDevices), Len(RawInputDeviceList)

    'This small block of commented code proves that we've got the device list
    'Dim As RAWINPUTDEVICELIST rawdevs(0 To nDevices - 1)
    'MemGet pRawInputDeviceList, pRawInputDeviceList.OFFSET, rawdevs()
    'Dim As Unsigned Long x
    'For x = 0 To UBound(rawdevs)
    '    Print rawdevs(x).hDevice, rawdevs(x).dwType
    'Next

    Print "Number of raw input devices:" + Str$(nDevices)

    MemFree pRawInputDeviceList

    Rid(0).usUsagePage = &H01
    Rid(0).usUsage = &H02
    Rid(0).dwFlags = 0
    Rid(0).hwndTarget = 0

    If RegisterRawInputDevices(Offset(Rid()), 1, Len(Rid(0))) = 0 Then
        Print "RawInput init failed:"
    End If
End Sub

We talked about this a while back, and I found this code on my PC, named "manymouse.SpriggsySpriggs.20210331_123656.bas". 
I don't think I ever got it working, but I see some RAWINPUT and RAWMOUSE declarations in there, that might be used for this... 
Any recollection of any of this? 

Code: (Select All)
Option _Explicit
$Console:Only

Declare CustomType Library
    Function LoadLibrary%& (lpLibFileName As String)
    Function GetProcAddress%& (ByVal hModule As _Offset, lpProcName As String)
    Sub FreeLibrary (ByVal hLibModule As _Offset)
    Sub InitializeCriticalSection (ByVal lpCriticalSection As _Offset)
    Sub EnterCriticalSection (ByVal lpCriticalSection As _Offset)
    Sub LeaveCriticalSection (ByVal lpCriticalSection As _Offset)
    Function GetRawInputData~& (ByVal hRawInput As _Offset, Byval uiCommand As _Unsigned Long, Byval pData As _Offset, Byval pcbSize As _Offset, Byval cbSize As _Unsigned Long)
    Function DefWindowProc%& Alias "DefWindowProcA" (ByVal hWnd As _Offset, Byval Msg As _Unsigned Long, Byval wParam As _Unsigned _Offset, Byval lParam As _Offset)
    Function GetModuleHandle%& Alias "GetModuleHandleA" (ByVal lpModuleName As _Offset)
    Function RegisterClass% Alias "RegisterClassExA" (ByVal unnamedParam1 As _Offset)
    Function CreateWindow%& Alias "CreateWindowExA" (ByVal dwExStyle As Long, Byval lpClassName As _Offset, Byval lpWindowName As _Offset, Byval dwStyle As Long, Byval X As Long, Byval Y As Long, Byval nWidth As Long, Byval nHeight As Long, Byval hWndParent As _Offset, Byval hMenu As _Offset, Byval hInstance As _Offset, Byval lpParam As _Offset)
End Declare

Declare Dynamic Library "Kernel32"
    Sub CopyMemory Alias "RtlCopyMemory" (ByVal Destination As _Offset, Byval Source As _Offset, Byval Length As _Offset)
End Declare

Const WIN32_WINNT = &H0501
Const WM_INPUT = &H00FF

Const MAX_MICE = 32
Const MAX_EVENTS = 1024

Const RIM_TYPEMOUSE = 0

Const MOUSE_MOVE_ABSOLUTE = 1

Const MANYMOUSE_EVENT_ABSMOTION = 0
Const MANYMOUSE_EVENT_RELMOTION = 1
Const MANYMOUSE_EVENT_BUTTON = 2
Const MANYMOUSE_EVENT_SCROLL = 3
Const MANYMOUSE_EVENT_DISCONNECT = 4
Const MANYMOUSE_EVENT_MAX = 5

Const RI_MOUSE_WHEEL = &H0400

Const RID_HEADER = &H10000005
Const RID_INPUT = &H10000003

Const WM_INPUT = &H00FF
Const WM_DESTROY = &H0002

Const WS_OVERLAPPED = &H00000000
Const WS_CAPTION = &H00C00000
Const WS_SYSMENU = &H00080000
Const WS_THICKFRAME = &H00040000
Const WS_MINIMIZEBOX = &H00020000
Const WS_MAXIMIZEBOX = &H00010000
Const WS_OVERLAPPEDWINDOW = WS_OVERLAPPED Or WS_CAPTION Or WS_SYSMENU Or WS_THICKFRAME Or WS_MINIMIZEBOX Or WS_MAXIMIZEBOX

Const CW_USEDEFAULT = &H80000000
Const HWND_MESSAGE = -3

Type LIST_ENTRY
    As _Offset Flink, Blink
End Type

Type RTL_CRITICAL_SECTION_DEBUG
    As Integer Type, CreatorBackTraceIndex
    As _Offset CriticalSection
    As LIST_ENTRY ProcessLocksList
    As _Unsigned Long EntryCount, ContentionCount, Flags
    As Integer CreatorBackTraceIndexHigh, SpareUSHORT
End Type

Type CRITICAL_SECTION
    As _Offset DebugInfo
    As Long LockCount, RecursionCount
    As _Offset OwningThread, LockSemaphore
    As _Unsigned Long SpinCount
End Type

Type ManyMouseEvent
    As Long type
    As _Unsigned Long device, item
    As Long value, minval, maxval
End Type

Type MouseStruct
    As _Offset handle
    As String * 256 name
End Type

Type RAWINPUTHEADER
    As Long dwType, dwSize
    As _Offset hDevice
    As _Unsigned _Offset wParam
End Type

Type RAWMOUSE
    As _Unsigned Integer usFlags, usButtonFlags, usButtonData
    As _Unsigned Long ulRawButtons
    As Long lLastX, lLastY
    As _Unsigned Long ulExtraInformation
End Type

Type RAWINPUT
    As RAWINPUTHEADER header
    As RAWMOUSE mouse
End Type

Type WNDCLASSEX
    As _Unsigned Long cbSize, style
    As _Offset lpfnWndProc
    As Long cbClsExtra, cbWndExtra
    As _Offset hInstance, hIcon, hCursor, hbrBackground, lpszMenuName, lpszClassName, hIconSm
End Type

Type RAWINPUTDEVICE
    As _Unsigned Integer usUsagePage, usUsage
    As Long dwFlags
    As _Offset hwndTarget
End Type

Dim Shared As ManyMouseEvent input_events(MAX_EVENTS)
Dim Shared As Long input_events_read
Dim Shared As Long input_events_write
Dim Shared As Long available_mice
Dim Shared As Long did_api_lookup
Dim Shared As _Offset raw_hwnd
Dim Shared As String class_name: class_name = "ManyMouseRawInputCatcher"
Dim Shared As String win_name: win_name = "ManyMouseRawInputMsgWindow"
Dim Shared As Integer class_atom
Dim Shared As CRITICAL_SECTION mutex

Dim Shared As _Offset hWnd
Dim Shared As _Unsigned Long Msg
Dim Shared As _Unsigned _Offset wParam
Dim Shared As _Offset lParam

Dim Shared As MouseStruct mice(MAX_MICE)


Print find_api_symbols
Sleep

Function symlookup%& (dll As _Offset, sym As String) Static
    Dim As _Offset addr
    addr = GetProcAddress(dll, sym)
    If addr = 0 Then
        Call FreeLibrary(dll)
        symlookup = 0
        Exit Function
    End If
    symlookup = addr
    Exit Function
End Function

Function find_api_symbols& () Static
    FunctionList:
    Data "GetRawInputDeviceInfoA","RegisterRawInputDevices","GetRawInputDeviceList","DefRawInputProc","GetRawInputBuffer","GetRawInputData","CreateWindowExA"
    Data "RegisterClassExA","UnregisterClassA","DefWindowProcA","PeekMessageA","TranslateMessage","DispatchMessageA","DestroyWindow","GetModuleHandleA"
    Data "GetLastError","InitializeCriticalSection","EnterCriticalSection","LeaveCriticalSection","DeleteCriticalSection","SetupDiGetClassDevsA","SetupDiEnumDeviceInfo"
    Data "SetupDiGetDeviceInstantIdA","SetupDiGetDeviceRegistryPropertyA","SetupDiDestroyDeviceInfoList"

    dllList:
    Data "user32.dll","kernel32.dll","setupapi.dll"

    Dim As _Offset dll
    If did_api_lookup Then
        find_api_symbols = 1
        Exit Function
    End If
    Dim As String dllList(1 To 3), functionList(1 To 25)
    Dim As Integer x, y
    Restore dllList
    For x = 1 To 3
        Read dllList(x)
    Next
    Restore FunctionList
    For x = 1 To 25
        Read functionList(x)
    Next
    x = 1
    y = 1
    Do
        If y = 15 Then x = 2
        If y = 21 Then x = 3
        dll = LoadLibrary(dllList(x))
        If symlookup(dll, functionList(y)) <> 0 Then
            If dll = 0 Then
                find_api_symbols = 0
                Exit Function
            End If
        End If
        'Print dllList(x), functionList(y), dll
        y = y + 1
    Loop Until y = 25
    did_api_lookup = 1
    find_api_symbols = 1
End Function

Sub queue_event (event As ManyMouseEvent) Static
    Call CopyMemory(_Offset(input_events(input_events_write)), _Offset(event), Len(event))
    input_events_write = (input_events_write + 1) Mod MAX_EVENTS
    If input_events_write = input_events_read Then
        input_events_read = (input_events_read + 1) Mod MAX_EVENTS
    End If
End Sub

Sub queue_from_rawinput (raw As RAWINPUT) Static
    Dim As Long i
    Dim As RAWINPUTHEADER header: header = raw.header
    Dim As RAWMOUSE mouse: mouse = raw.mouse
    Dim As ManyMouseEvent event
    If raw.header.dwType <> RIM_TYPEMOUSE Then
        Exit Sub
    End If
    For i = 0 To available_mice
        If mice(i).handle = header.hDevice Then Exit For
    Next
    If i = available_mice Then Exit Sub
    event.device = i
    Call EnterCriticalSection(_Offset(mutex))
    If mouse.usFlags And MOUSE_MOVE_ABSOLUTE Then
        event.type = MANYMOUSE_EVENT_ABSMOTION
        event.item = 0
        event.value = mouse.lLastX
        Call queue_event(event)
    Else
        event.type = MANYMOUSE_EVENT_RELMOTION
        If mouse.lLastX <> 0 Then
            event.item = 0
            event.value = mouse.lLastX
            Call queue_event(event)
        End If
        If mouse.lLastY <> 0 Then
            event.item = 1
            event.value = mouse.lLastY
            Call queue_event(event)
        End If
    End If
    event.type = MANYMOUSE_EVENT_BUTTON
    RI_MOUSE_BUTTON:
    Data &H0001,&H0002,&H0004,&H0008,&H0010,&H0020,&H0040,&H0080,&H0100,&H0200
    Dim As Integer x
    Dim As Long MOUSE_BUTTON
    Restore RI_MOUSE_BUTTON
    For x = 1 To 5
        Read MOUSE_BUTTON
        If mouse.usButtonFlags And MOUSE_BUTTON Then
            event.item = MOUSE_BUTTON - 1
            event.value = 1
            Call queue_event(event)
        End If
        Read MOUSE_BUTTON
        If mouse.usButtonFlags And MOUSE_BUTTON Then
            event.item = MOUSE_BUTTON - 1
            event.value = 0
            Call queue_event(event)
        End If
    Next
    If mouse.usButtonFlags And RI_MOUSE_WHEEL Then
        If mouse.usButtonData <> 0 Then
            event.type = MANYMOUSE_EVENT_SCROLL
            event.item = 0
            If mouse.usButtonData > 0 Then event.value = 1 Else event.value = -1
            Call queue_event(event)
        End If
    End If
    Call LeaveCriticalSection(_Offset(mutex))
End Sub

Sub wminput_handler (wParam As _Unsigned _Offset, lParam As _Offset) Static
    Dim As _Unsigned Long dwSize, getrawinput
    Dim As RAWINPUT lpb
    Dim As RAWINPUTHEADER rawinputheader
    getrawinput = GetRawInputData(lParam, RID_INPUT, 0, _Offset(dwSize), Len(rawinputheader))
    If dwSize < Len(rawinputheader) Then Exit Sub
    If GetRawInputData(lParam, RID_INPUT, _Offset(lpb), _Offset(dwSize), Len(rawinputheader)) <> dwSize Then Exit Sub
    Call queue_from_rawinput(lpb)
End Sub

Function RawWndProc%& Static
    If Msg = WM_INPUT Then
        Call wminput_handler(wParam, lParam)
    ElseIf Msg = WM_DESTROY Then
        RawWndProc = 0
        Exit Function
    End If
    RawWndProc = DefWindowProc(hWnd, Msg, wParam, lParam)
End Function

Function init_event_queue& () Static
    Dim As _Offset hInstance: hInstance = GetModuleHandle(0)
    Dim As WNDCLASSEX wce
    Dim As RAWINPUTDEVICE rid
    input_events_read = 0: input_events_write = 0
    wce.cbSize = Len(wce)
    wce.lpfnWndProc = RawWndProc
    wce.lpszClassName = _Offset(class_name)
    wce.hInstance = hInstance
    class_atom = RegisterClass(_Offset(wce))
    If class_atom = 0 Then Exit Function
    raw_hwnd = CreateWindow(0, _Offset(class_name), _Offset(win_name), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_MESSAGE, 0, hInstance, 0)
    If raw_hwnd = 0 Then
        init_event_queue = 0
        Exit Function
    End If
    Call InitializeCriticalSection(_Offset(mutex))
    'Got more junk to write here. Good grief. Left off on line 374 of windows_wminput.c
End Function
Reply




Users browsing this thread: 5 Guest(s)