首页
论坛
课程
招聘
[已解决]如何用全局Hook记录鼠标滚轮的动作?
2006-8-2 18:12 8676

[已解决]如何用全局Hook记录鼠标滚轮的动作?

2006-8-2 18:12
8676
我能记录鼠标移动,左右键单双击等动作,只有滚轮滚动无法记录,求教高手指点怎么捕获此动作

[培训] 优秀毕业生寄语:恭喜id咸鱼炒白菜拿到远超3W月薪的offer,《安卓高级研修班》火热招生!!!

收藏
点赞0
打赏
分享
最新回复 (8)
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
masmprogra 活跃值 2006-8-3 09:41
2
0
用来记录鼠标键盘动作的钩子:
SetWindowsHookEx(WH_JOURNALRECORD, (HOOKPROC)RecHookProc, AfxGetApp()->m_hInstance, 0);

用来播放鼠标键盘动作的钩子:
SetWindowsHookEx(WH_JOURNALPLAYBACK, (HOOKPROC)PlayHookProc, AfxGetApp()->m_hInstance, 0);

因为单位里完全没有测试人员导致修复软件问题时,好了这边坏了那边
我就想写个钩子程序出来,记录一次完整的黑盒测试过程,然后每次改动程序,都用此过程进行测试.

现在就是无法记录鼠标滚轮的事件,郁闷一天了

请高手指点指点
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
红火蚁 活跃值 3 2006-8-3 09:54
3
0
看看MSDN
LRESULT CALLBACK LowLevelMouseProc(
  int nCode,     // hook code
  WPARAM wParam, // message identifier
  LPARAM lParam  // pointer to structure with message data
);
它下面有一句话
wParam
Specifies the identifier of the mouse message. This parameter can be one of the following messages:WM_LBUTTONDOWN,WM_LBUTTONUP,WM_MOUSEMOVE,WM_MOUSEWHEEL,WM_RBUTTONDOWN, orWM_RBUTTONUP.

看到没有
WM_MOUSEWHEEL
The WM_MOUSEWHEEL message is sent to the focus window when the mouse wheel is rotated. The DefWindowProc function propagates the message to the window's parent. There should be no internal forwarding of the message, since DefWindowProc propagates it up the parent chain until it finds a window that processes it.

WM_MOUSEWHEEL
fwKeys = LOWORD(wParam);    // key flags
zDelta = (short) HIWORD(wParam);    // wheel rotation
xPos = (short) LOWORD(lParam);    // horizontal position of pointer
yPos = (short) HIWORD(lParam);    // vertical position of pointer

Parameters
fwKeys
Value of the low-order word of wParam. Indicates whether various virtual keys are down. This parameter can be any combination of the following values: Value Description
MK_CONTROL Set if the ctrl key is down.
MK_LBUTTON Set if the left mouse button is down.
MK_MBUTTON Set if the middle mouse button is down.
MK_RBUTTON Set if the right mouse button is down.
MK_SHIFT Set if the shift key is down.

zDelta
The value of the high-order word of wParam. Indicates the distance that the wheel is rotated, expressed in multiples or divisions of WHEEL_DELTA, which is 120. A positive value indicates that the wheel was rotated forward, away from the user; a negative value indicates that the wheel was rotated backward, toward the user.
xPos
Value of the low-order word of lParam. Specifies the x-coordinate of the pointer, relative to the upper-left corner of the screen.
yPos
Value of the high-order word of lParam. Specifies the y-coordinate of the pointer, relative to the upper-left corner of the screen.
Remarks
The zDelta parameter will be a multiple of WHEEL_DELTA, which is set at 120. This is the threshold for action to be taken, and one such action (for example, scrolling one increment) should occur for each delta.

The delta was set to 120 to allow Microsoft or other vendors to build finer-resolution wheels in the future, including perhaps a freely-rotating wheel with no notches. The expectation is that such a device would send more messages per rotation, but with a smaller value in each message. To support this possibility, you should either add the incoming delta values until WHEEL_DELTA is reached (so for a given delta-rotation you get the same response), or scroll partial lines in response to the more frequent messages. You could also choose your scroll granularity and accumulate deltas until it is reached.
雪    币: 1613
活跃值: 活跃值 (33)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
北极星2003 活跃值 25 2006-8-3 09:59
4
0

FROM MSDN
The JournalRecordProc hook procedure is an application-defined or library-defined callback function used with the SetWindowsHookEx function. The function records messages the system removes from the system message queue. Later, an application can use a JournalPlaybackProc hook procedure to play back the messages.


原理是从系统消息队列中移出消息并保存
既然你能实现键盘,鼠标,同样滚轮也应该能实现(WM_MOUSEWHEEL)
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
masmprogra 活跃值 2006-8-3 10:21
5
0
谢谢楼上两位朋友的热心解答~~

开始我也认为WM_MOUSEWHEEL应该和WM_MOUSEMOVE等消息类似,但弄了老半天就是截获不了

我再看看"火红蚁"提供的函数,找下问题在哪?
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
masmprogra 活跃值 2006-8-3 10:35
6
0
请问"红火蚁":

你的意思是调用---
SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)RecKeyProc, AfxGetApp()->m_hInstance, 0);

SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)RecMouseProc, AfxGetApp()->m_hInstance, 0);

那么他们会通过 lParam 返回 KBDLLHOOKSTRUCT 和 MSLLHOOKSTRUCT 指针,这两种结构体能转换为 EVENTMSG 结构类型吗?

初学钩子方面的知识,请包含
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
红火蚁 活跃值 3 2006-8-3 11:18
7
0
我帮你做了这个简易的钩子,基本实现了你的功能
这个是dll代码
#include "stdafx.h"
#include "GetMouseMessage.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//
//        Note!
//
//                If this DLL is dynamically linked against the MFC
//                DLLs, any functions exported from this DLL which
//                call into MFC must have the AFX_MANAGE_STATE macro
//                added at the very beginning of the function.
//
//                For example:
//
//                extern "C" BOOL PASCAL EXPORT ExportedFunction()
//                {
//                        AFX_MANAGE_STATE(AfxGetStaticModuleState());
//                        // normal function body here
//                }
//
//                It is very important that this macro appear in each
//                function, prior to any calls into MFC.  This means that
//                it must appear as the first statement within the
//                function, even before any object variable declarations
//                as their constructors may generate calls into the MFC
//                DLL.
//
//                Please see MFC Technical Notes 33 and 58 for additional
//                details.
//

/////////////////////////////////////////////////////////////////////////////
// CGetMouseMessageApp

BEGIN_MESSAGE_MAP(CGetMouseMessageApp, CWinApp)
        //{{AFX_MSG_MAP(CGetMouseMessageApp)
                // NOTE - the ClassWizard will add and remove mapping macros here.
                //    DO NOT EDIT what you see in these blocks of generated code!
        //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CGetMouseMessageApp construction

CGetMouseMessageApp::CGetMouseMessageApp()
{
        // TODO: add construction code here,
        // Place all significant initialization in InitInstance
}

/////////////////////////////////////////////////////////////////////////////
// The one and only CGetMouseMessageApp object

CGetMouseMessageApp theApp;

// 定义钩子变量
HHOOK g_hook = NULL;
extern "C" _declspec(dllexport) void EndHook(void);
// 低级鼠标钩子函数
LRESULT CALLBACK LowLevelMouseProc(
                                                                          int nCode,     // hook code
                                                                          WPARAM wParam, // message identifier
                                                                          LPARAM lParam  // pointer to structure with message data
                                                                  )
{
    if (nCode == HC_ACTION)
        {
                // 如果是滚动滑轮,弹出消息框,卸载钩子函数
                if (wParam == WM_MOUSEWHEEL)
                {
                        MessageBox(NULL, "Get the mousewheel message", NULL, MB_OK);
                        EndHook();
                }
        }

        return CallNextHookEx(g_hook, nCode, wParam, lParam);
}

// 安装钩子
extern "C" _declspec(dllexport) void SetHook(void)
{
        g_hook = SetWindowsHookEx(
                                                          WH_MOUSE_LL,         // type of hook to install
                                                          LowLevelMouseProc,   // address of hook procedure
                                                          theApp.m_hInstance,  // handle to application instance
                                                          0                    // identity of thread to install hook for
                                                        );
        if (g_hook == NULL)
        {
                MessageBox(NULL, "SetWindowsHookEx Failed", NULL, MB_OK);
                return ;
        }

        return ;
}
// 卸载钩子
extern "C" _declspec(dllexport) void EndHook(void)
{
        if (g_hook != NULL)
                UnhookWindowsHookEx(g_hook);
}

注意,您必须在stdAfx.h中加上
#define _WIN32_WINNT  0x0500
因为在winuser.h中只有定义了上面的才定义的WH_MOUSE_LL

然后您在另外建一对话框工程
加一个按钮
在工程目录下加进上面的GetMouseMessage.dll和GetMouseMessage.lib

在按钮事件中写
extern "C" _declspec(dllimport) void SetHook(void);
extern "C" _declspec(dllimport) void EndHook(void);

void CTestGetMessageDlg::OnButton1()
{
        // TODO: Add your control notification handler code here
        SetHook();
}

我试过
完全ok
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
masmprogra 活跃值 2006-8-3 15:04
8
0
我又查看了一下,

SetWindowsHookEx(WH_JOURNALRECORD, (HOOKPROC)RecHookProc, AfxGetApp()->m_hInstance, 0);

能捕获WM_MOUSEWHEEL消息,问题是出在

SetWindowsHookEx(WH_JOURNALPLAYBACK, (HOOKPROC)PlayHookProc, AfxGetApp()->m_hInstance, 0);

无法播放录制下来的滚轮动作.

原因我还在查找中,谢谢"红火蚁"的热心帮助.
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
masmprogra 活跃值 2006-8-3 16:05
9
0
彻底郁闷了...

在codeproject的帖子里找到了答案,详情如下:

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
WM_MOUSEWHEEL cannot work ?

I downloaded and use it to test out Notepad.
It seems like the WM_MOUSEWHEEL can be recorded, but when it is played back in NotePad, the playback does not "wheel" or scroll the notepad app.

You can easily try it out in notepad. just type in many line to make Notepad scrollbar appear. Record the mouse wheel and play it back.

Any idea how to make Mouse Wheel work?
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Re: WM_MOUSEWHEEL cannot work ?

Yes, this is a bug  in the journal playback system. Unfortunately, there's nothing I can do

Regards
Senthil
游客
登录 | 注册 方可回帖
返回