8

I have a USB HID touchpad that collects input. By default, when I press on the touchpad it generates carriage return (Enter) and when I try to use it as a mouse it actually enters a dragging state.

What I want to do is to convert the carriage return into a mouse click event and the dragging state into a cursor move without the initial clicking part.

I found the raw input alternative. However, I don't know how to convert it into mouse click and cursor move.

Here is the code responsible with the mouse 'reading':

LRESULT CALLBACK mouseProc (int nCode, WPARAM wParam, LPARAM lParam)
{
    MOUSEHOOKSTRUCT * pMouseStruct = (MOUSEHOOKSTRUCT *)lParam;
    if (pMouseStruct != NULL)
    {
        if(wParam == WM_LBUTTONDOWN)
        {
            cout<<"clicked"<<endl;
        }
        printf("Mouse position X = %d  Mouse Position Y = %d\n", pMouseStruct->pt.x,pMouseStruct->pt.y);

        stringstream sx, sy;
        sx << (int) pMouseStruct->pt.x << endl;
        sy << (int) pMouseStruct->pt.y << endl;
    }
    return CallNextHookEx(hMouseHook, nCode, wParam, lParam);
}

then the keyboard part:

LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode < 0)
        return CallNextHookEx(NULL, nCode, wParam, lParam);

    tagKBDLLHOOKSTRUCT *str = (tagKBDLLHOOKSTRUCT *)lParam;

    cout<<str->vkCode<<endl;

    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

then the logging part:

DWORD WINAPI MyLogger(LPVOID lpParm)
{

    HINSTANCE hInstance = GetModuleHandle(NULL);
    hMouseHook = SetWindowsHookEx( WH_MOUSE_LL, mouseProc, hInstance, NULL );
    hKeyHook = SetWindowsHookEx( WH_KEYBOARD_LL, LowLevelKeyboardProc, hInstance, NULL );

    MSG message;
    while (GetMessage(&message,NULL,0,0))
    {
        TranslateMessage( &message );
        DispatchMessage( &message );
    }

    UnhookWindowsHookEx(hMouseHook);
    return 0;
}

Note: I don't know if this is relevant, but I want to use the HID to play in a Chromium instance on a windows system.

George Netu
  • 2,758
  • 4
  • 28
  • 49
  • 1
    How would your transparent window know, if it should send a `WM_MOUSEMOVE` or a `WM_NCMOUSEMOVE` to the window underneath? – IInspectable Jun 26 '15 at 09:42
  • 1
    I assumed the transparent window should 'know' send a `WM_NCMOUSEMOVE` (in order to have a better control over the 'output'), yet I didn't consider this to be very important. Should I worry about it? – George Netu Jun 26 '15 at 09:47
  • 1
    A window gets either all input, or none. If you wish to filter input, you'll have to pass some of that input on to windows underneath. `WM_MOUSEMOVE` is one of the messages you would want to pass on, and you'll have to decide, whether it should be `WM_MOUSEMOVE` or `WM_NCMOUSEMOVE`. `WM_MOUSELEAVE` is another message that's probably impossible to get right, given your proposed configuration with a transparent window. – IInspectable Jun 26 '15 at 10:12
  • I see, thank you. So your advice would be to rule that out and focus on the other two approaches? – George Netu Jun 26 '15 at 10:19
  • Your code examples are using low-level mouse/keyboard hooks, not raw input. If you open your device for raw input, do you get RIM_TYPEKEYBOARD structures, or RIM_TYPEHID structures? (You *should* be getting RIM_TYPEHID.) Once you've got the HID data, you should be able to parse it out (bypassing the drivers) and call SendInput as appropriate. – Eric Brown Jul 06 '15 at 21:44

3 Answers3

2

For mouse click and mouse move - when you handle the input from the HID use the SendInput method.

The click is easy, for the mouse move try to get the scaled drag coordinates and convert them to the current screen scale coordinates and also use the SendInput method.

Also you can track the displacement in x, y and make appropriate calibration to translate them to screen x, y

George Netu
  • 2,758
  • 4
  • 28
  • 49
ahmedsafan86
  • 1,776
  • 1
  • 26
  • 49
2

The touchpad is just a mouse like any other. It generates standard mouse events. Use a global WH_MOUSE hook via SetWindowsHookEx() to capture mouse events globally. To replay them, use mouse_event(). Alternatively, use WH_JOURNALRECORD and WH_JOURNALPLAYBACK hooks instead for capture and playback, respectively.

George Netu
  • 2,758
  • 4
  • 28
  • 49
Mihai
  • 57
  • 9
2

When you register the hook with WH_MOUSE_LL, the possible values of wparam are: WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MOUSEMOVE, WM_MOUSEWHEEL, WM_MOUSEHWHEEL, WM_RBUTTONDOWN, or WM_RBUTTONUP.

I'm expecting that once the WM_LBUTTONDOWN is issued, a corresponding WM_LBUTTONUP has to be issued to prevent the cursor from entering dragging state.

I don't have the device to test this but I would try the call below to prevent entering dragging state.

CallNextHookEx(hMouseHook, nCode, WM_LBUTTONUP, lParam);

or use mouse_event with MOUSEEVENTF_LEFTUP to inject the release of the left button.

I don't think that the raw input alternative is a good idea. I see it as a measure of last resort.

VAndrei
  • 5,420
  • 18
  • 43