问题描述
我正在尝试在 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.
- 注册窗口类和从该类创建一个窗口,该窗口将是一个 Message-Only Window,所以它将不可见,没有 GUI.
- 使用 RegisterRawInputDevices API 请求原始来自鼠标设备的事件.
- 设置消息循环,使用标准的
GetMessage
/DispatchMessage
组合. - 在您的窗口过程中处理发送的
WM_INPUT
消息
4.1.为原始数据分配内存
4.2.检索原始数据
4.3.过滤鼠标事件和滚轮数据
4.4.处理(我只是打印车轮增量)
4.5.释放分配的内存.
- 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.
- Use the RegisterRawInputDevices API to ask for raw events from mouse devices.
- Set up a message loop, with the standard
GetMessage
/DispatchMessage
combo. - 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 获取鼠标滚动/滚轮输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!