S.l.e!ep.¢%

像打了激速一样,以四倍的速度运转,开心的工作
简单、开放、平等的公司文化;尊重个性、自由与个人价值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

如何用全局Hook记录鼠标滚轮的动作?

Posted on 2010-01-13 21:34 S.l.e!ep.¢% 阅读(2067) 评论(0)  编辑 收藏 引用 所属分类: RootKit
1 旧 2006-08-02, 18:12 默认【已解决】如何用全局Hook记录鼠标滚轮的动作?
masmprogra 当前离线 添加 masmprogra 的声望 反映此帖

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

此帖于 2006-08-03 16:05 被 masmprogra 最后编辑
回复时引用此帖 多重引用本帖 快速回复此帖 返回顶端
masmprogra
级别:0 | 在线时长:1小时 | 升级还需:4小时

初级会员
初级会员

资 料:
注册日期: Jun 2006
帖子: 61masmprogra 品行端正
精华: 0
现金: 200 Kx
2 旧 2006-08-03, 09:41 默认
masmprogra 当前离线 添加 masmprogra 的声望 反映此帖

用来记录鼠标键盘动作的钩子:
SetWindowsHookEx(WH_JOURNALRECORD, (HOOKPROC)RecHookProc, AfxGetApp()->m_hInstance, 0);

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


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

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

请高手指点指点

此帖于 2006-08-03 10:01 被 masmprogra 最后编辑
回复时引用此帖 多重引用本帖 快速回复此帖 返回顶端
红火蚁
级别:1 | 在线时长:7小时 | 升级还需:5小时

普通会员
普通会员

资 料:
注册日期: May 2006
帖子: 62红火蚁 品行端正
精华: 3
现金: 200 Kx
3 旧 2006-08-03, 09:54 默认
红火蚁 当前离线 添加 红火蚁 的声望 反映此帖

看看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.

回复时引用此帖 多重引用本帖 快速回复此帖 返回顶端
北极星2003
级别:15 | 在线时长:312小时 | 升级还需:8小时 级别:15 | 在线时长:312小时 | 升级还需:8小时 级别:15 | 在线时长:312小时 | 升级还需:8小时 级别:15 | 在线时长:312小时 | 升级还需:8小时 级别:15 | 在线时长:312小时 | 升级还需:8小时 级别:15 | 在线时长:312小时 | 升级还需:8小时

『Win32/Win64编程』版主<br>『编程技术小组』组长
『Win32/Win64编程』版主
『编程技术小组』组长

资 料:
注册日期: Feb 2005
帖子: 1,224北极星2003 品行端正
精华: 25
现金: 1911 Kx
4 旧 2006-08-03, 09:59 默认
北极星2003 当前离线 添加 北极星2003 的声望 反映此帖

引用:
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)

回复时引用此帖 多重引用本帖 快速回复此帖 返回顶端
masmprogra
级别:0 | 在线时长:1小时 | 升级还需:4小时

初级会员
初级会员

资 料:
注册日期: Jun 2006
帖子: 61masmprogra 品行端正
精华: 0
现金: 200 Kx
5 旧 2006-08-03, 10:21 默认
masmprogra 当前离线 添加 masmprogra 的声望 反映此帖

谢谢楼上两位朋友的热心解答~~ 

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

我再看看"火红蚁"提供的函数,找下问题在哪?

回复时引用此帖 多重引用本帖 快速回复此帖 返回顶端
masmprogra
级别:0 | 在线时长:1小时 | 升级还需:4小时

初级会员
初级会员

资 料:
注册日期: Jun 2006
帖子: 61masmprogra 品行端正
精华: 0
现金: 200 Kx
6 旧 2006-08-03, 10:35 默认
masmprogra 当前离线 添加 masmprogra 的声望 反映此帖

请问"红火蚁":

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

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

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

初学钩子方面的知识,请包含

此帖于 2006-08-03 15:04 被 masmprogra 最后编辑
回复时引用此帖 多重引用本帖 快速回复此帖 返回顶端
红火蚁
级别:1 | 在线时长:7小时 | 升级还需:5小时

普通会员
普通会员

资 料:
注册日期: May 2006
帖子: 62红火蚁 品行端正
精华: 3
现金: 200 Kx
7 旧 2006-08-03, 11:18 默认
红火蚁 当前离线 添加 红火蚁 的声望 反映此帖

我帮你做了这个简易的钩子,基本实现了你的功能 
这个是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

回复时引用此帖 多重引用本帖 快速回复此帖 返回顶端
masmprogra
级别:0 | 在线时长:1小时 | 升级还需:4小时

初级会员
初级会员

资 料:
注册日期: Jun 2006
帖子: 61masmprogra 品行端正
精华: 0
现金: 200 Kx
8 旧 2006-08-03, 15:04 默认
masmprogra 当前离线 添加 masmprogra 的声望 反映此帖

我又查看了一下,

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

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

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

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

原因我还在查找中,谢谢"红火蚁"的热心帮助.

回复时引用此帖 多重引用本帖 快速回复此帖 返回顶端
masmprogra
级别:0 | 在线时长:1小时 | 升级还需:4小时

初级会员
初级会员

资 料:
注册日期: Jun 2006
帖子: 61masmprogra 品行端正
精华: 0
现金: 200 Kx
9 旧 2006-08-03, 16:05 默认
masmprogra 当前离线 添加 masmprogra 的声望 反映此帖

彻底郁闷了...   

在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
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理