Ruby implementation Win32API get mouse scroll/whee

2020-04-30 03:09发布

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')
p @state.call(0x0800)

But it keeps returning 0 no matter what I do with my mouse wheel.

I thought something is wrong with my mouse, so I tried to do:

@state = Win32API.new('user32','GetKeyState',['L'],'L')
p @state.call(0x01) #left key
p @state.call(0x02) #right key

It worked, so I'm not sure what's wrong with the mouse wheel.

Regards

Edit 2/20/2014: I tried to do the following:

GetActiveWindow = Win32API.new('user32','GetForegroundWindow','','i')
DefWindowProc = Win32API.new('user32','DefWindowProc','iiii','i')

DefWindowProc.call(GetActiveWindow.call,

Then, I got stuck with the UINT / Message (2nd argument).

Edit 2/20/2014:

I found the WM_MOUSEWHEEL message

Latest revision:

GetActiveWindow = Win32API.new('user32','GetForegroundWindow','','i')
DefWindowProc = Win32API.new('user32','DefWindowProc','iiii','i')

#WM_MOUSEWHEEL message 0x020A

DefWindowProc.call(GetActiveWindow.call, 0x020A,

Now I just need to figure out the 3rd and 4th argument.

标签: ruby winapi
1条回答
够拽才男人
2楼-- · 2020-04-30 03:29

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;

}
查看更多
登录 后发表回答