Ruby implementation Win32API get mouse scroll/wheel input

后端 未结 1 1494
不知归路
不知归路 2021-01-23 10:31

I\'m trying to use win32api on user32.dll to get mouse wheel input.

I tried the following:

@state = Win32API.new(\'user32\',\'DefWindowProc\',[\'i\'],\'i         


        
相关标签:
1条回答
  • 2021-01-23 10:53

    As I don't know Ruby, I will give here a solution in C/C++ using only standard Win32 APIs. If you can call Win32 APIs from Ruby, that will work.

    Note that the solution involves "callback" and "pointer". I know that's possible in Python (for example, with the ctypes module) and hope that same thing is possible with Ruby.

    1. Register a Window Class and create a Window from that class, the window will be a Message-Only Window, so it will be invisible, with no GUI.
    2. Use the RegisterRawInputDevices API to ask for raw events from mouse devices.
    3. Set up a message loop, with the standard GetMessage/DispatchMessage combo.
    4. Process the sent WM_INPUT message in your Window Procedure
      4.1. Allocate memory for the raw datas
      4.2. Retrieve the raw datas
      4.3. Filter for mouse event and wheel datas
      4.4. Process (I just print the wheel delta)
      4.5. Free allocated memory.

    Below, full source code. Build with VS2012 Express on Windows 7.

    #include <Windows.h>
    #include <stdio.h>
    
    LRESULT CALLBACK MyWindowProc( HWND, UINT, WPARAM, LPARAM );
    
    int main( void ) {
    
        WNDCLASS WndClass;
        memset( &WndClass, 0, sizeof( WndClass ) );
        WndClass.hInstance = GetModuleHandle( NULL );
        WndClass.lpszClassName = L"MyRawInputClass";
        WndClass.lpfnWndProc = MyWindowProc;
        RegisterClass( &WndClass );
    
        HWND hWnd = CreateWindow( WndClass.lpszClassName, NULL, 0, 0, 0, 0, 0,
                                  HWND_MESSAGE, 0, WndClass.hInstance, 0 );
    
        RAWINPUTDEVICE RawInputDevice;
        RawInputDevice.usUsagePage = 0x01; // Generic Desktop Controls
        RawInputDevice.usUsage = 0x02; // Mouse
        RawInputDevice.dwFlags = RIDEV_INPUTSINK;
        RawInputDevice.hwndTarget = hWnd; 
        BOOL bWin32Success = RegisterRawInputDevices( &RawInputDevice, 1,
                                                      static_cast<UINT>( sizeof( RAWINPUTHEADER ) ) );
    
        BOOL bRet;
        MSG msg;
        while( ( bRet = GetMessage( &msg, hWnd, 0, 0 ) ) != 0 ) {
            if (bRet != -1) {
                DispatchMessage(&msg); 
            }
        }
    
        // NO GUI, UNREACHABLE
        DestroyWindow( hWnd );
        UnregisterClass( WndClass.lpszClassName, WndClass.hInstance );
    
        return 0;
    
    }
    
    LRESULT CALLBACK MyWindowProc( HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam ) {
    
        switch ( uiMsg ) {
    
            case WM_INPUT: {
                UINT dwSize;
                HRAWINPUT hRawInput = reinterpret_cast<HRAWINPUT>( lParam );
                UINT uiRetCode = GetRawInputData( hRawInput, RID_INPUT, NULL, &dwSize,
                                                  static_cast<UINT>( sizeof( RAWINPUTHEADER ) ) );
                if ( uiRetCode != 0xffffffff ) {
                    LPBYTE lpb = new BYTE[ dwSize ];
                    uiRetCode = GetRawInputData( hRawInput, RID_INPUT, lpb, &dwSize,
                                                 static_cast<UINT>( sizeof( RAWINPUTHEADER ) ) );
                    if ( uiRetCode > 0 ) {
                        RAWINPUT* praw = reinterpret_cast<RAWINPUT*>( lpb );
                        if ( praw->header.dwType == RIM_TYPEMOUSE ) {
                            if ( praw->data.mouse.usButtonFlags & RI_MOUSE_WHEEL ) {
                                signed int siDelta = static_cast<SHORT>( praw->data.mouse.usButtonData );
                                printf( "WHEEL EVENT: Delta = %d\n", siDelta );
                            }
                        }
                    }
                    delete[] lpb;
                }
                break;
    
            } // WM_INPUT
    
            default:
                return DefWindowProc( hWnd, uiMsg, wParam, lParam );
        }
    
        return 0;
    
    }
    
    0 讨论(0)
提交回复
热议问题