Ruby实现Win32API获取鼠标滚动/滚轮输入

时间:2014-02-20 06:25:04

标签: ruby winapi

我正在尝试在user32.dll上使用win32api来获取鼠标滚轮。

我尝试了以下内容:

@state = Win32API.new('user32','DefWindowProc',['i'],'i')
p @state.call(0x0800)

但无论我用鼠标滚轮做什么,它都会一直返回0。

我认为我的鼠标有问题,所以我试着这样做:

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

它有效,所以我不确定鼠标滚轮有什么问题。

此致

编辑2014年2月20日: 我试着做以下事情:

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

DefWindowProc.call(GetActiveWindow.call,

然后,我遇到了UINT / Message(第二个参数)。

编辑2014年2月20日:

我找到了WM_MOUSEWHEEL消息

最新修订:

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

#WM_MOUSEWHEEL message 0x020A

DefWindowProc.call(GetActiveWindow.call, 0x020A,

现在我只需要找出第3和第4个参数。

1 个答案:

答案 0 :(得分:1)

由于我不了解Ruby,我将仅使用标准的Win32 API在C / C ++中提供解决方案。如果你可以从Ruby调用Win32 API,那将会有效。

请注意,解决方案涉及“回调”和“指针”。我知道这在Python中是可能的(例如,使用ctypes模块)并且希望Ruby可以做到同样的事情。

  1. Register a Window Classcreate a Window from that class,窗口将是Message-Only Window,因此它将是不可见的,没有GUI。
  2. 使用RegisterRawInputDevices API向鼠标设备请求原始事件。
  3. 使用标准GetMessage / DispatchMessage组合设置消息循环。
  4. 处理窗口过程中发送的WM_INPUT消息  4.1。为原始数据分配内存
     4.2。检索原始数据
     4.3。过滤鼠标事件和车轮数据
     4.4。过程(我只是打印轮三角形)
     4.5。免费分配内存。
  5. 下面是完整的源代码。在Windows 7上使用VS2012 Express进行构建。

    #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;
    
    }