2022-04-30

Having trouble using winapi to read input from a device

I followed the steps here to try and read some input from a device. I've been trying for a couple hours now to figure out why GetMessage doesn't return anything. Originally I was trying to read from a certain device, but seeing as that wasn't working, I wanted to just try reading keyboard or mouse inputs. However, I've had no luck in doing so.

Edit: Some more info. I'm on Windows 10. I'm running the code in cmder (not sure if that makes any difference) with python main.py. There are no error messages and the output is Successfully registered input device! before the program just waits to receive a message from GetMessage.

Here's the running code:

main.py:

from ctypes import windll, sizeof, WinDLL, pointer, c_uint, create_string_buffer, POINTER
from ctypes.wintypes import *
from structures import *
from constants import *  # I put a comment specifying the value for each variable used from here


k32 = WinDLL('kernel32')
GetRawInputDeviceInfo = windll.user32.GetRawInputDeviceInfoA
GetRawInputDeviceInfo.argtypes = HANDLE, UINT, LPVOID, PUINT
RegisterRawInputDevices = windll.user32.RegisterRawInputDevices
RegisterRawInputDevices.argtypes = (RawInputDevice * 7), UINT, UINT
GetMessage = windll.user32.GetMessageA
GetMessage.argtypes = POINTER(Message), HWND, UINT, UINT


def print_error(code=None):
    print(f"Error code {k32.GetLastError() if code is None else code}")


def register_devices(hwnd_target=None):
    # Here I added all usages just to try and get any kind of response from GetMessage
    page = 0x01
    # DW_FLAGS is 0
    devices = (RawInputDevice * 7)(
        RawInputDevice(page, 0x01, DW_FLAGS, hwnd_target),
        RawInputDevice(page, 0x02, DW_FLAGS, hwnd_target),
        RawInputDevice(page, 0x04, DW_FLAGS, hwnd_target),
        RawInputDevice(page, 0x05, DW_FLAGS, hwnd_target),
        RawInputDevice(page, 0x06, DW_FLAGS, hwnd_target),
        RawInputDevice(page, 0x07, DW_FLAGS, hwnd_target),
        RawInputDevice(page, 0x08, DW_FLAGS, hwnd_target),
    )
    if not RegisterRawInputDevices(devices, len(devices), sizeof(devices[0])):
        print_error()
    else:
        print("Successfully registered input device!")


def get_message(h_wnd=None):
    msg = pointer(Message())
    # WM_INPUT is 0
    return_value = GetMessage(msg, h_wnd, WM_INPUT, WM_INPUT)
    if return_value == -1:
        print_error()
    elif return_value == 0:
        print("WM_QUIT message received.")
    else:
        print("Successfully got message!")
        return msg


register_devices()
print(get_message().contents.message)

structures.py:

from ctypes import Structure
from ctypes.wintypes import *


class RawInputDevice(Structure):
    _fields_ = [
        ("usUsagePage", USHORT),
        ("usUsage", USHORT),
        ("dwFlags", DWORD),
        ("hwndTarget", HWND),
    ]


class Message(Structure):
    _fields_ = [
        ("hwnd", HWND),
        ("message", UINT),
        ("wParam", WPARAM),
        ("lParam", LPARAM),
        ("time", DWORD),
        ("pt", POINT),
        ("lPrivate", DWORD)
    ]

I'd appreciate it if anyone helped me figure out what's going wrong, or I'd also be fine if someone can point out an alternative to reading input from an HID device on Windows.



No comments:

Post a Comment