Ruby 实现 Win32API 获取鼠标滚动/滚轮输入 [英] Ruby implementation Win32API get mouse scroll/wheel input

查看:126
本文介绍了Ruby 实现 Win32API 获取鼠标滚动/滚轮输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

我尝试了以下方法:

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

但是无论我用鼠标滚轮做什么,它都会返回 0.

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.

问候

编辑 2/20/2014:我尝试执行以下操作:

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,

然后,我被 UINT/Message(第二个参数)困住了.

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

编辑 2/20/2014:

Edit 2/20/2014:

我找到了 WM_MOUSEWHEEL 消息

I found the WM_MOUSEWHEEL message

最新版本:

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,所以我将在这里给出一个仅使用标准 Win32 API 的 C/C++ 解决方案.如果您可以从 Ruby 调用 Win32 API,那就行了.

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.

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

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. 注册窗口类从该类创建一个窗口,该窗口将是一个 Message-Only Window,所以它将不可见,没有 GUI.
  2. 使用 RegisterRawInputDevices API 请求原始来自鼠标设备的事件.
  3. 设置消息循环,使用标准的 GetMessage/DispatchMessage 组合.
  4. 在您的窗口过程中处理发送的 WM_INPUT 消息
    4.1.为原始数据分配内存
    4.2.检索原始数据
    4.3.过滤鼠标事件和滚轮数据
    4.4.处理(我只是打印车轮增量)
    4.5.释放分配的内存.
  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.

下面是完整的源代码.在 Windows 7 上使用 VS2012 Express 构建.

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;

}

这篇关于Ruby 实现 Win32API 获取鼠标滚动/滚轮输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆