QB64 Phoenix Edition
kind of works? reading multiple mice: any c programmers want to look at this? - Printable Version

+- QB64 Phoenix Edition (https://qb64phoenix.com/forum)
+-- Forum: QB64 Rising (https://qb64phoenix.com/forum/forumdisplay.php?fid=1)
+--- Forum: Code and Stuff (https://qb64phoenix.com/forum/forumdisplay.php?fid=3)
+---- Forum: Help Me! (https://qb64phoenix.com/forum/forumdisplay.php?fid=10)
+---- Thread: kind of works? reading multiple mice: any c programmers want to look at this? (/showthread.php?tid=864)

Pages: 1 2 3 4 5 6 7 8 9


RE: kind of works? reading multiple mice: any c programmers want to look at this? - madscijr - 09-07-2022

(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

I don't know why the jstookey C examples aren't referencing "winuser.h" but that seems to be where these RawInput commands are defined.

To help with that, here are Microsoft's docs on the winuser.h header.


RE: kind of works? reading multiple mice: any c programmers want to look at this? - SpriggsySpriggs - 09-07-2022

I must say I forgot I had actually put that much work into it back then. It looks so foreign to me because it was made before I developed new coding habits lol! However, there is definitely a way to have two executables talk to each other or just have one read the output of the other. Personally, I wouldn't like to do that for this project in particular as it involves a parent-child scenario. I have faith that we can do this 100% in QB64 (well, more like 95% because there will be some C headers involved). I think I should have more time this week to look at this since I've hit a good spot with getting all my required documentation turned in for my mortgage loan. And, now that I know way more about Win32 API and have better coding habits, I think you and I can do this. I actually really appreciate the fact that you've hung on to the old code I wrote and that you've brought this project up yet again. It always excites me to use API in QB64.

I will take a look at this and try my best to get this going for ya.


RE: kind of works? reading multiple mice: any c programmers want to look at this? - SpriggsySpriggs - 09-07-2022

(09-07-2022, 06:35 PM)madscijr Wrote: I don't know why the jstookey C examples aren't referencing "winuser.h" but that seems to be where these RawInput commands are defined.

To help with that, here are Microsoft's docs on the winuser.h header.

Oh, I've had no issue hunting down these functions. I'm no stranger to the MSDN documentation pages. Besides, winuser.h, along with many other headers, are already included with QB64 so all I have to do is either a DECLARE LIBRARY or a DECLARE CUSTOMTYPE LIBARY without having to worry about where they're coming from. Also, Winuser.h is just User32.dll so I could even use DECLARE DYNAMIC LIBRARY "User32" to get the same results  Wink


RE: kind of works? reading multiple mice: any c programmers want to look at this? - madscijr - 09-07-2022

(09-07-2022, 06:39 PM)Spriggsy Wrote: I must say I forgot I had actually put that much work into it back then. It looks so foreign to me because it was made before I developed new coding habits lol! However, there is definitely a way to have two executables talk to each other or just have one read the output of the other. Personally, I wouldn't like to do that for this project in particular as it involves a parent-child scenario. I have faith that we can do this 100% in QB64 (well, more like 95% because there will be some C headers involved). I think I should have more time this week to look at this since I've hit a good spot with getting all my required documentation turned in for my mortgage loan. And, now that I know way more about Win32 API and have better coding habits, I think you and I can do this.

I know how you must feel, looking at code I've done in the past is always eye opening... "I used to do it THAT way?!" LoL

(09-07-2022, 06:39 PM)Spriggsy Wrote: I actually really appreciate the fact that you've hung on to the old code I wrote and that you've brought this project up yet again. It always excites me to use API in QB64.

I can be a bit of a pack rat. I'll keep a project on the backburner until I can make more progress, if it seems worthwhile. Sometimes you just have to put something down for a bit and then come back to it when your head is cleared.

(09-07-2022, 06:39 PM)Spriggsy Wrote: I will take a look at this and try my best to get this going for ya.

I am definitely in over my head and appreciate any help I can get!


RE: kind of works? reading multiple mice: any c programmers want to look at this? - SpriggsySpriggs - 09-08-2022

@madscijr
Hey! I converted that C program over to QB64 and it works well. A good start in the right direction.
Attached are the header files you need.

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

Const CS_HREDRAW = &H0002
Const CS_VREDRAW = &H0001

Const IDI_APPLICATION = 32512
Const IDC_ARROW = 32512
Const COLOR_WINDOW = 5

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_CHILD = &H40000000
Const WS_VISIBLE = &H10000000
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 WM_DESTROY = &H0002
Const WM_INPUT = &H00FF

Const SW_SHOW = 5

Const RID_INPUT = &H10000003
Const RIM_TYPEMOUSE = 0

Const MOUSE_MOVE_RELATIVE = &H00
Const MOUSE_MOVE_ABSOLUTE = &H01
Const MOUSE_VIRTUAL_DESKTOP = &H02
Const MOUSE_ATTRIBUTES_CHANGED = &H04
Const MOUSE_MOVE_NOCOALESCE = &H08

Const WM_PAINT = &H000F

Const DT_CENTER = &H00000001

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

Type POINT
    As Long x, y
End Type

Type MSG
    As Offset hwnd
    As Unsigned Long message
    As Unsigned Offset wParam
    As Offset lParam
    As Long time
    As POINT pt
    As Long lPrivate
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 RECT
    As Long left, top, right, bottom
End Type

Type PAINTSTRUCT
    As Offset hdc
    As Long fErase
    $If 64BIT Then
        As String * 4 alignment
    $End If
    As RECT rcPaint
    As Long fRestore, fIncUpdate
    As String * 32 rgbReserved
End Type

Type RAWINPUTHEADER
    As Unsigned Long dwType, dwSize
    As Offset hDevice
    As Unsigned Offset wParam
End Type

Type RAWMOUSE
    As Unsigned Integer usFlags
    $If 64BIT Then
        As String * 2 alignment
    $End If
    'As Unsigned Long ulButtons  'commented out because I'm creating this value using MAKELONG
    As Unsigned Integer 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

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 GetModuleHandle%& (ByVal lpModulename As Offset)
    Function LoadIcon%& (ByVal hInstance As Offset, Byval lpIconName As Offset)
    Function LoadCursor%& (ByVal hInstance As Offset, Byval lpCursorName As Offset)
    Function RegisterClassEx% (ByVal wndclassex As Offset)
    Function CreateWindowEx%& (ByVal dwExStyle As Unsigned Long, Byval lpClassName As Offset, Byval lpWindowName As Offset, Byval dwStyle As Unsigned 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)
    Sub ShowWindow (ByVal hWnd As Offset, Byval nCmdShow As Long)
    Sub UpdateWindow (ByVal hWnd As Offset)
    Function GetMessage& (ByVal lpMsg As Offset, Byval hWnd As Offset, Byval wMsgFilterMin As Unsigned Long, Byval wMsgFilterMax As Unsigned Long)
    Sub TranslateMessage (ByVal lpMsg As Offset)
    Sub DispatchMessage (ByVal lpMsg As Offset)
    Sub PostQuitMessage (ByVal nExitCode As Long)
    Function DefWindowProc%& (ByVal hWnd As Offset, Byval Msg As Unsigned Long, Byval wParam As Unsigned Offset, Byval lParam As Offset)
    Sub GetRawInputData (ByVal hRawInput As Offset, Byval uiCommand As Unsigned Long, Byval pData As Offset, Byval pcbSize As Offset, Byval cbSizeHeader As Unsigned Long)
    Function GetRawInputData~& (ByVal hRawInput As Offset, Byval uiCommand As Unsigned Long, Byval pData As Offset, Byval pcbSize As Offset, Byval cbSizeHeader As Unsigned Long)
    Sub InvalidateRect (ByVal hWnd As Offset, Byval lpRect As Offset, Byval bErase As Long)
    Sub SendMessage (ByVal hWnd As Offset, Byval Msg As Unsigned Long, Byval wParam As Unsigned Offset, Byval lParam As Offset)
    Function BeginPaint%& (ByVal hWnd As Offset, Byval lpPaint As Offset)
    Sub GetClientRect (ByVal hWnd As Offset, Byval lpRect As Offset)
    Sub DrawText (ByVal hdc As Offset, Byval lpchText As Offset, Byval cchText As Long, Byval lprc As Offset, Byval format As Unsigned Long)
    Sub OffsetRect (ByVal lprc As Offset, Byval dx As Long, Byval dy As Long)
    Sub EndPaint (ByVal hWnd As Offset, Byval lpPaint As Offset)
End Declare

Declare CustomType Library "makeint"
    Function MAKEINTRESOURCE%& Alias "MAKEINTRSC" (ByVal i As _Offset)
End Declare

Declare Library
    Function MAKELPARAM%& (ByVal l As Integer, Byval h As Integer)
    Function MAKELONG~& (ByVal l As Unsigned Integer, Byval h As Unsigned Integer)
End Declare

Declare Library "winproc"
    Function WindowProc%& ()
End Declare

Dim Shared As String * 256 mousemessage
Dim Shared As String * 256 rawinputdevices

System Val(Str$(WinMain))

Function MainWndProc%& (hwnd As Offset, nMsg As Unsigned Long, wParam As Unsigned Offset, lParam As Offset)
    Static As Offset hwndButton
    Static As Long cx, cy

    Dim As Offset hdc
    Dim As PAINTSTRUCT ps
    Dim As RECT rc

    Dim As MEM lpb
    Dim As Unsigned Long dwSize
    Dim As RAWINPUT raw
    Dim As Long tmpx, tmpy

    Static As Long maxx
    Select Case nMsg
        Case WM_DESTROY
            PostQuitMessage 0
            MainWndProc = 0
            Exit Function
        Case WM_INPUT
            Dim As RAWINPUTHEADER rih
            GetRawInputData lParam, RID_INPUT, 0, Offset(dwSize), Len(rih)

            lpb = MemNew(dwSize)
            If lpb.SIZE = 0 Then
                MainWndProc = 0
                Exit Function
            End If

            If GetRawInputData(lParam, RID_INPUT, lpb.OFFSET, Offset(dwSize), Len(rih)) <> dwSize Then
                Print "GetRawInputData doesn't return correct size!"
            End If

            MemGet lpb, lpb.OFFSET, raw
            If raw.header.dwType = RIM_TYPEMOUSE Then
                tmpx = raw.mouse.lLastX
                tmpy = raw.mouse.lLastY
                maxx = tmpx
                mousemessage = "Mouse:hDevice" + Str$(raw.header.hDevice) + " usFlags=" + Hex$(raw.mouse.usFlags) + " ulButtons=" + Hex$(MAKELONG(raw.mouse.usButtonFlags, raw.mouse.usFlags)) + " usButtonFlags=" + Hex$(raw.mouse.usButtonFlags) + " usButtonData=" + Hex$(raw.mouse.usButtonData) + " ulRawButtons=" + Hex$(raw.mouse.ulRawButtons) + " lLastX=" + Str$(raw.mouse.lLastX) + " lLastY=" + Str$(raw.mouse.lLastY) + " ulExtraInformation=" + Hex$(raw.mouse.ulExtraInformation) + Chr$(13) + Str$(maxx)
            End If
            InvalidateRect hwnd, 0, -1

            SendMessage hwnd, WM_PAINT, 0, 0

            MemFree lpb
            MainWndProc = 0
            Exit Function
        Case WM_PAINT
            hdc = BeginPaint(hwnd, Offset(ps))

            GetClientRect hwnd, Offset(rc)
            DrawText hdc, Offset(mousemessage), Len(mousemessage), Offset(rc), DT_CENTER
            OffsetRect Offset(rc), 0, 200
            DrawText hdc, Offset(rawinputdevices), Len(rawinputdevices), Offset(rc), DT_CENTER
            EndPaint hwnd, Offset(ps)
            MainWndProc = 0
            Exit Function
        Case Else
            MainWndProc = DefWindowProc(hwnd, nMsg, wParam, lParam)
    End Select
End Function

Function WinMain~%& ()
    Dim As Offset hwndMain, hInst: hInst = GetModuleHandle(0)
    Dim As MSG msg
    Dim As WNDCLASSEX wndclass

    Dim As String szMainWndClass: szMainWndClass = "WinTestWin" + Chr$(0)
    Dim As String szWinTitle: szWinTitle = "Hello" + Chr$(0)

    wndclass.lpszClassName = Offset(szMainWndClass)
    wndclass.cbSize = Len(wndclass)
    wndclass.style = CS_HREDRAW Or CS_VREDRAW
    wndclass.lpfnWndProc = WindowProc
    wndclass.hInstance = hInst 'GetModuleHandle(0) will return the hInstance of this EXE
    wndclass.hIcon = LoadIcon(0, MAKEINTRESOURCE(IDI_APPLICATION))
    wndclass.hIconSm = LoadIcon(0, MAKEINTRESOURCE(IDI_APPLICATION))
    wndclass.hCursor = LoadCursor(0, MAKEINTRESOURCE(IDC_ARROW))
    wndclass.hbrBackground = COLOR_WINDOW + 1

    Dim As Integer reg: reg = RegisterClassEx(Offset(wndclass)) 'I prefer to use the output of RegisterClassEx rather than the window name

    hwndMain = CreateWindowEx(0, MAKELPARAM(reg, 0), Offset(szWinTitle), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hInst, 0)

    ShowWindow hwndMain, SW_SHOW
    UpdateWindow hwndMain

    InitRawInput

    While GetMessage(Offset(msg), 0, 0, 0)
        TranslateMessage Offset(msg)
        DispatchMessage Offset(msg)
    Wend

    WinMain = msg.wParam
End Function

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

    rawinputdevices = "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
        mousemessage = "RawInput init failed"
    End If
End Sub



RE: kind of works? reading multiple mice: any c programmers want to look at this? - madscijr - 09-08-2022

(09-08-2022, 05:57 PM)Spriggsy Wrote: @madscijr
Hey! I converted that C program over to QB64 and it works well. A good start in the right direction.
Attached are the header files you need.

Thanks! I will give this a try.

I am attaching my attempt, which compiles, but doesn't really work right.
It keeps opening new windows without closing them, and I don't know how to stop it without restarting the PC!
I think the problem is in "mooltiMouse4.c", which is the EXE that mooltiMouse4.bas calls using your pipecom_lite$.
Even calling the EXE one time results in window after window opening until either the PC blows up
(I restarted before that happened) or you restart.

I'll give your code a look next.


RE: kind of works? reading multiple mice: any c programmers want to look at this? - SpriggsySpriggs - 09-08-2022

Oh. You are using this code wrong. This is the one based on that code you posted that has the batch file. The one that shows the device ID and then the info from the RAWINPUT struct.

I'm gettin' all confused lol. I'll have to take a peek at that zip file.


RE: kind of works? reading multiple mice: any c programmers want to look at this? - madscijr - 09-08-2022

(09-08-2022, 05:57 PM)Spriggsy Wrote: @madscijr
Hey! I converted that C program over to QB64 and it works well. A good start in the right direction.
Attached are the header files you need.

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

Const CS_HREDRAW = &H0002
Const CS_VREDRAW = &H0001

Const IDI_APPLICATION = 32512
Const IDC_ARROW = 32512
Const COLOR_WINDOW = 5

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_CHILD = &H40000000
Const WS_VISIBLE = &H10000000
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 WM_DESTROY = &H0002
Const WM_INPUT = &H00FF

Const SW_SHOW = 5

Const RID_INPUT = &H10000003
Const RIM_TYPEMOUSE = 0

Const MOUSE_MOVE_RELATIVE = &H00
Const MOUSE_MOVE_ABSOLUTE = &H01
Const MOUSE_VIRTUAL_DESKTOP = &H02
Const MOUSE_ATTRIBUTES_CHANGED = &H04
Const MOUSE_MOVE_NOCOALESCE = &H08

Const WM_PAINT = &H000F

Const DT_CENTER = &H00000001

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

Type POINT
    As Long x, y
End Type

Type MSG
    As Offset hwnd
    As Unsigned Long message
    As Unsigned Offset wParam
    As Offset lParam
    As Long time
    As POINT pt
    As Long lPrivate
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 RECT
    As Long left, top, right, bottom
End Type

Type PAINTSTRUCT
    As Offset hdc
    As Long fErase
    $If 64BIT Then
        As String * 4 alignment
    $End If
    As RECT rcPaint
    As Long fRestore, fIncUpdate
    As String * 32 rgbReserved
End Type

Type RAWINPUTHEADER
    As Unsigned Long dwType, dwSize
    As Offset hDevice
    As Unsigned Offset wParam
End Type

Type RAWMOUSE
    As Unsigned Integer usFlags
    $If 64BIT Then
        As String * 2 alignment
    $End If
    'As Unsigned Long ulButtons  'commented out because I'm creating this value using MAKELONG
    As Unsigned Integer 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

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 GetModuleHandle%& (ByVal lpModulename As Offset)
    Function LoadIcon%& (ByVal hInstance As Offset, Byval lpIconName As Offset)
    Function LoadCursor%& (ByVal hInstance As Offset, Byval lpCursorName As Offset)
    Function RegisterClassEx% (ByVal wndclassex As Offset)
    Function CreateWindowEx%& (ByVal dwExStyle As Unsigned Long, Byval lpClassName As Offset, Byval lpWindowName As Offset, Byval dwStyle As Unsigned 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)
    Sub ShowWindow (ByVal hWnd As Offset, Byval nCmdShow As Long)
    Sub UpdateWindow (ByVal hWnd As Offset)
    Function GetMessage& (ByVal lpMsg As Offset, Byval hWnd As Offset, Byval wMsgFilterMin As Unsigned Long, Byval wMsgFilterMax As Unsigned Long)
    Sub TranslateMessage (ByVal lpMsg As Offset)
    Sub DispatchMessage (ByVal lpMsg As Offset)
    Sub PostQuitMessage (ByVal nExitCode As Long)
    Function DefWindowProc%& (ByVal hWnd As Offset, Byval Msg As Unsigned Long, Byval wParam As Unsigned Offset, Byval lParam As Offset)
    Sub GetRawInputData (ByVal hRawInput As Offset, Byval uiCommand As Unsigned Long, Byval pData As Offset, Byval pcbSize As Offset, Byval cbSizeHeader As Unsigned Long)
    Function GetRawInputData~& (ByVal hRawInput As Offset, Byval uiCommand As Unsigned Long, Byval pData As Offset, Byval pcbSize As Offset, Byval cbSizeHeader As Unsigned Long)
    Sub InvalidateRect (ByVal hWnd As Offset, Byval lpRect As Offset, Byval bErase As Long)
    Sub SendMessage (ByVal hWnd As Offset, Byval Msg As Unsigned Long, Byval wParam As Unsigned Offset, Byval lParam As Offset)
    Function BeginPaint%& (ByVal hWnd As Offset, Byval lpPaint As Offset)
    Sub GetClientRect (ByVal hWnd As Offset, Byval lpRect As Offset)
    Sub DrawText (ByVal hdc As Offset, Byval lpchText As Offset, Byval cchText As Long, Byval lprc As Offset, Byval format As Unsigned Long)
    Sub OffsetRect (ByVal lprc As Offset, Byval dx As Long, Byval dy As Long)
    Sub EndPaint (ByVal hWnd As Offset, Byval lpPaint As Offset)
End Declare

Declare CustomType Library "makeint"
    Function MAKEINTRESOURCE%& Alias "MAKEINTRSC" (ByVal i As _Offset)
End Declare

Declare Library
    Function MAKELPARAM%& (ByVal l As Integer, Byval h As Integer)
    Function MAKELONG~& (ByVal l As Unsigned Integer, Byval h As Unsigned Integer)
End Declare

Declare Library "winproc"
    Function WindowProc%& ()
End Declare

Dim Shared As String * 256 mousemessage
Dim Shared As String * 256 rawinputdevices

System Val(Str$(WinMain))

Function MainWndProc%& (hwnd As Offset, nMsg As Unsigned Long, wParam As Unsigned Offset, lParam As Offset)
    Static As Offset hwndButton
    Static As Long cx, cy

    Dim As Offset hdc
    Dim As PAINTSTRUCT ps
    Dim As RECT rc

    Dim As MEM lpb
    Dim As Unsigned Long dwSize
    Dim As RAWINPUT raw
    Dim As Long tmpx, tmpy

    Static As Long maxx
    Select Case nMsg
        Case WM_DESTROY
            PostQuitMessage 0
            MainWndProc = 0
            Exit Function
        Case WM_INPUT
            Dim As RAWINPUTHEADER rih
            GetRawInputData lParam, RID_INPUT, 0, Offset(dwSize), Len(rih)

            lpb = MemNew(dwSize)
            If lpb.SIZE = 0 Then
                MainWndProc = 0
                Exit Function
            End If

            If GetRawInputData(lParam, RID_INPUT, lpb.OFFSET, Offset(dwSize), Len(rih)) <> dwSize Then
                Print "GetRawInputData doesn't return correct size!"
            End If

            MemGet lpb, lpb.OFFSET, raw
            If raw.header.dwType = RIM_TYPEMOUSE Then
                tmpx = raw.mouse.lLastX
                tmpy = raw.mouse.lLastY
                maxx = tmpx
                mousemessage = "Mouse:hDevice" + Str$(raw.header.hDevice) + " usFlags=" + Hex$(raw.mouse.usFlags) + " ulButtons=" + Hex$(MAKELONG(raw.mouse.usButtonFlags, raw.mouse.usFlags)) + " usButtonFlags=" + Hex$(raw.mouse.usButtonFlags) + " usButtonData=" + Hex$(raw.mouse.usButtonData) + " ulRawButtons=" + Hex$(raw.mouse.ulRawButtons) + " lLastX=" + Str$(raw.mouse.lLastX) + " lLastY=" + Str$(raw.mouse.lLastY) + " ulExtraInformation=" + Hex$(raw.mouse.ulExtraInformation) + Chr$(13) + Str$(maxx)
            End If
            InvalidateRect hwnd, 0, -1

            SendMessage hwnd, WM_PAINT, 0, 0

            MemFree lpb
            MainWndProc = 0
            Exit Function
        Case WM_PAINT
            hdc = BeginPaint(hwnd, Offset(ps))

            GetClientRect hwnd, Offset(rc)
            DrawText hdc, Offset(mousemessage), Len(mousemessage), Offset(rc), DT_CENTER
            OffsetRect Offset(rc), 0, 200
            DrawText hdc, Offset(rawinputdevices), Len(rawinputdevices), Offset(rc), DT_CENTER
            EndPaint hwnd, Offset(ps)
            MainWndProc = 0
            Exit Function
        Case Else
            MainWndProc = DefWindowProc(hwnd, nMsg, wParam, lParam)
    End Select
End Function

Function WinMain~%& ()
    Dim As Offset hwndMain, hInst: hInst = GetModuleHandle(0)
    Dim As MSG msg
    Dim As WNDCLASSEX wndclass

    Dim As String szMainWndClass: szMainWndClass = "WinTestWin" + Chr$(0)
    Dim As String szWinTitle: szWinTitle = "Hello" + Chr$(0)

    wndclass.lpszClassName = Offset(szMainWndClass)
    wndclass.cbSize = Len(wndclass)
    wndclass.style = CS_HREDRAW Or CS_VREDRAW
    wndclass.lpfnWndProc = WindowProc
    wndclass.hInstance = hInst 'GetModuleHandle(0) will return the hInstance of this EXE
    wndclass.hIcon = LoadIcon(0, MAKEINTRESOURCE(IDI_APPLICATION))
    wndclass.hIconSm = LoadIcon(0, MAKEINTRESOURCE(IDI_APPLICATION))
    wndclass.hCursor = LoadCursor(0, MAKEINTRESOURCE(IDC_ARROW))
    wndclass.hbrBackground = COLOR_WINDOW + 1

    Dim As Integer reg: reg = RegisterClassEx(Offset(wndclass)) 'I prefer to use the output of RegisterClassEx rather than the window name

    hwndMain = CreateWindowEx(0, MAKELPARAM(reg, 0), Offset(szWinTitle), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hInst, 0)

    ShowWindow hwndMain, SW_SHOW
    UpdateWindow hwndMain

    InitRawInput

    While GetMessage(Offset(msg), 0, 0, 0)
        TranslateMessage Offset(msg)
        DispatchMessage Offset(msg)
    Wend

    WinMain = msg.wParam
End Function

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

    rawinputdevices = "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
        mousemessage = "RawInput init failed"
    End If
End Sub

When I load the code into QB64, it complains with:

LIBRARY not found on line 142
Caused by (or after): DECLARE CUSTOMTYPE LIBRARY "makeint",7

I have "makeint.h" and "winproc.h" in the same folder as the BAS, and am guessing those need to go in one of these include folders? 

There are a ton of folders with .h files, so I'm not sure where they should go, maybe one of these? 

C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\x86_64-w64-mingw32\include\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\tr1\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\lib\gcc\x86_64-w64-mingw32\8.1.0\include\ssp\

Any help appreciated... 

[Image: error1b.png]


RE: kind of works? reading multiple mice: any c programmers want to look at this? - SpriggsySpriggs - 09-08-2022

You need to have both headers in the same directory as QB64. Or, you can just change the declarations to the relative or absolute path of the headers.


RE: kind of works? reading multiple mice: any c programmers want to look at this? - madscijr - 09-08-2022

(09-08-2022, 06:56 PM)Spriggsy Wrote: You need to have both headers in the same directory as QB64. Or, you can just change the declarations to the relative or absolute path of the headers.

Thanks. I see declarations on line 142 and 151:
  • Declare CustomType Library "makeint"
  • Declare Library "winproc"

which I updated to be hardcoded:
  • Declare CustomType Library "C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\x86_64-w64-mingw32\include\makeint"
  • Declare Library "C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\x86_64-w64-mingw32\include\winproc"

and the IDE stopped complaining. It works! Wow, thanks. 

PS I would prefer not having to hardcode the paths, and keep them where QB64's MinGW can find them. 

I tried moving them to 
  • C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\x86_64-w64-mingw32\include\
but still getting the error. 

There are a bunch of folders with .h files under 
  • C:\Users\maduser\Documents\Code\qb64\internal\c\

I could do trial and error but it could take a while. 
Is there any specific directory they should be under? 

Thanks again...


QB64 internal folders with header files:

Code: (Select All)
C:\Users\maduser\Documents\Code\qb64\internal\c\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\include\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\include\gdb\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\include\libiberty\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\lib\gcc\x86_64-w64-mingw32\8.1.0\32\finclude\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\lib\gcc\x86_64-w64-mingw32\8.1.0\finclude\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\lib\gcc\x86_64-w64-mingw32\8.1.0\include\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\backward\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\bits\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\debug\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\decimal\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\experimental\bits\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\ext\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\parallel\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\profile\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\profile\impl\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\tr1\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\x86_64-w64-mingw32\32\bits\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\x86_64-w64-mingw32\32\ext\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\x86_64-w64-mingw32\bits\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\x86_64-w64-mingw32\ext\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\lib\gcc\x86_64-w64-mingw32\8.1.0\include\ssp\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\lib\gcc\x86_64-w64-mingw32\8.1.0\include-fixed\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\lib\gcc\x86_64-w64-mingw32\8.1.0\install-tools\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\lib\gcc\x86_64-w64-mingw32\8.1.0\install-tools\include\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\opt\include\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\opt\include\ncursesw\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\opt\include\openssl\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\opt\include\python2.7\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\opt\include\readline\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\opt\include\X11\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\opt\lib\libffi-3.2.1\include\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\x86_64-w64-mingw32\include\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\x86_64-w64-mingw32\include\ddk\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\x86_64-w64-mingw32\include\gdiplus\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\x86_64-w64-mingw32\include\GL\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\x86_64-w64-mingw32\include\psdk_inc\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\x86_64-w64-mingw32\include\sdks\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\x86_64-w64-mingw32\include\sec_api\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\x86_64-w64-mingw32\include\sec_api\sys\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\x86_64-w64-mingw32\include\sys\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\x86_64-w64-mingw32\include\wrl\
C:\Users\maduser\Documents\Code\qb64\internal\c\c_compiler\x86_64-w64-mingw32\include\wrl\wrappers\
C:\Users\maduser\Documents\Code\qb64\internal\c\libqb\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\audio\conversion\src\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\audio\decode\mp3_mini\download\minimp3\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\audio\decode\mp3_mini\src\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\audio\out\AL\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\audio\out\download\openal-soft-1.14\examples\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\audio\out\download\openal-soft-1.14\include\AL\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\audio\out\download\openal-soft-1.14\OpenAL32\Include\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\audio\out\reference\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\audio\out\reference\wi\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\audio\out\src\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\audio\out\src\AL\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\core\download\freeglut-2.8.0\include\GL\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\core\download\freeglut-2.8.0\progs\demos\spaceball\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\core\download\freeglut-2.8.0\src\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\core\gl_header_for_parsing\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\core\gl_header_for_parsing\temp\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\core\gl_headers\glew\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\core\gl_headers\opengl_org_registery\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\core\glew\download\glew-1.10.0\auto\src\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\core\glew\download\glew-1.10.0\include\GL\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\core\glew\include\GL\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\core\glew\src\GL\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\core\glues\src\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\core\glues\src\libtess\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\core\src\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\input\game_controller\download\gamepad_1.4.0_pre1_source\source\gamepad\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\input\game_controller\src\gamepad\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\video\font\ttf\download\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\video\font\ttf\src\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\video\image\decode\bmp\download\EasyBMP_1.06\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\video\image\decode\bmp\src\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\video\image\decode\other\src\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\video\image\decode\png\download\
C:\Users\maduser\Documents\Code\qb64\internal\c\parts\video\image\decode\png\src\