VC++ Hook截取鼠标点击窗口消息的问题!全局钩子,高手进!

悬赏分:0 - 提问时间: 2010年05月19日 06时20分
我在做毕业设计,现在遇到一个问题,像求教高手:
我想实现如下功能,当鼠标点击一个按钮的时候,实现一个功能,然后把这个鼠标的消息在传递下去,继续传给原来的应用程序,需要说明的是按钮的句柄已知,设为hwnd,并且这个按钮不是本应用程序的按钮,访问其他的进程需要全局钩子,所以编译出的应该是dll文件;
如何实现这个功能,求教高手,我这两天有点晕,呵呵,代码或工程请发到ipconfig@163.com,或粘贴到网页上都可以,毕业设计很重要,还可以继续再加400分;
提问者: 苏璇璇 - 中级魔法师 六级   发消息   加为好友

相关内容

搜狐推广服务

相关内容加载中...
  • {question.title}
  • 查看更多相关问题>>
 
相关搜索 {hint}

回答 共 7 条

你需要截获 按钮 HWND 的 WM_LBUTTONDOWN 函数。

好几种方法实现。

比较简单的一种:

采用SetWindowLong子类化该HWND,即设置该窗口的消息处理函数,然后判断消息是不是按钮被按下了,做好处理之后再去调用老的消息处理函数。
但是,每个进程都有各自的私有4G空间,而你要截获的是远进程窗口消息,因此,你不能简单的直接使用SetWindowLong,因为你传过去的参数,对于远进程来说,是没有意义的。
因此,第一步,你需要将实现写入DLL,然后将DLL注入远进程。(注,DLL的DLLMain函数中实现SetWindowLong等实现)。

这种方法要比全局钩子的方法效率高。而且也很容易写。

回答者: 金刚战舰 - 魔法学徒 一级   发消息   加为好友   06-14 13:25

全局钩子在后边介绍。源码已发送至邮箱。请查收。

1. 鼠标模拟技术

几乎所有的游戏中都使用了鼠标来改变角色的位置和方向,玩家仅用一个小小的鼠
标,就可以使角色畅游天下。

那么,我们如何实现在没有玩家的参与下角色也可以自动行走呢。其实实现这个并不
难,仅仅几个Windows API函数就

可以搞定,让我们先来认识认识这些API函数。

(1) 模拟鼠标动作API函数mouse_event,它可以实现模拟鼠标按下和放开等动作。

VOID mouse_event(
DWORD dwFlags, // 鼠标动作标识。
DWORD dx, // 鼠标水平方向位置。
DWORD dy, // 鼠标垂直方向位置。
DWORD dwData, // 鼠标轮子转动的数量。
DWORD dwExtraInfo // 一个关联鼠标动作辅加信息。
);

其中,dwFlags表示了各种各样的鼠标动作和点击活动,它的常用取值如下:

MOUSEEVENTF_MOVE 表示模拟鼠标移动事件。

MOUSEEVENTF_LEFTDOWN 表示模拟按下鼠标左键。

MOUSEEVENTF_LEFTUP 表示模拟放开鼠标左键。

MOUSEEVENTF_RIGHTDOWN 表示模拟按下鼠标右键。

MOUSEEVENTF_RIGHTUP 表示模拟放开鼠标右键。

MOUSEEVENTF_MIDDLEDOWN 表示模拟按下鼠标中键。

MOUSEEVENTF_MIDDLEUP 表示模拟放开鼠标中键。

(2)、设置和获取当前鼠标位置的API函数。获取当前鼠标位置使用GetCursorPos()
函数,设置当前鼠标位置使用SetCursorPos()函数。

BOOL GetCursorPos(
LPPOINT lpPoint // 返回鼠标的当前位置。
);
BOOL SetCursorPos(
int X, // 鼠标的水平方向位置。
int Y //鼠标的垂直方向位置。
);

通常游戏角色的行走都是通过鼠标移动至目的地,然后按一下鼠标的按钮就搞定
了。下面我们使用上面介绍的API

函数来模拟角色行走过程。

CPoint oldPoint,newPoint;
GetCursorPos(&oldPoint); //保存当前鼠标位置。
newPoint.x = oldPoint.x+40;
newPoint.y = oldPoint.y+10;
SetCursorPos(newPoint.x,newPoint.y); //设置目的地位置。
mouse_event(MOUSEEVENTF_RIGHTDOWN,0,0,0,0);//模拟按下鼠标右键。
mouse_event(MOUSEEVENTF_RIGHTUP,0,0,0,0);//模拟放开鼠标右键。

2. 键盘模拟技术

在很多游戏中,不仅提供了鼠标的操作,而且还提供了键盘的操作,在对攻击对象
进行攻击时还可以使用快捷键

。为了使这些攻击过程能够自动进行,外挂程序需要使用键盘模拟技术。像鼠标模拟技
术一样,Windows API也提供了

一系列API函数来完成对键盘动作的模拟。

模拟键盘动作API函数keydb_event,它可以模拟对键盘上的某个或某些键进行按下
或放开的动作。

VOID keybd_event(
BYTE bVk, // 虚拟键值。
BYTE bScan, // 硬件扫描码。
DWORD dwFlags, // 动作标识。
DWORD dwExtraInfo // 与键盘动作关联的辅加信息。
);

其中,bVk表示虚拟键值,其实它是一个BYTE类型值的宏,其取值范围为1-254。有
关虚拟键值表请在MSDN上使用

关键字“Virtual-Key Codes”查找相关资料。bScan表示当键盘上某键被按下和放开
时,键盘系统硬件产生的扫描码

,我们可以MapVirtualKey()函数在虚拟键值与扫描码之间进行转换。dwFlags表示各种
各样的键盘动作,它有两种取

值:KEYEVENTF_EXTENDEDKEY和KEYEVENTF_KEYUP。

下面我们使用一段代码实现在游戏中按下Shift+R快捷键对攻击对象进行攻击。

keybd_event(VK_CONTROL,MapVirtualKey(VK_CONTROL,0),0,0); //按下CTRL
键。
keybd_event(0x52,MapVirtualKey(0x52,0),0,0);//键下R键。
keybd_event(0x52,MapVirtualKey(0x52,0), KEYEVENTF_KEYUP,0);//放开R键。
keybd_event(VK_CONTROL,MapVirtualKey(VK_CONTROL,0),
KEYEVENTF_KEYUP,0);//放开CTRL键。

3.激活

上面介绍的鼠标和键盘模拟技术实现了对游戏角色的动作部分的模拟,但要想外挂
能工作于游戏之上,还需要将其与游戏的场景窗口联系起来或者使用一个激活键,就象按键精灵的那个激活键一样。我们可以用GetWindow函数来枚举窗口,也可以用Findwindow函数来查找特定的窗口。另外还有一个FindWindowEx函数可以找到窗口的子窗口,当游戏切换场景的时候我们可以用FindWindowEx来确定一些当前窗口的特征,从而判断是否还在这个场景,方法很多了,比如可以GetWindowInfo来确定一些东西,比如当查找不到某个按钮的时候就说明游戏场景已经切换了等等办法。当使用激活键进行关联,需要使用Hook技术开发一个全局键盘钩子,在这里就不具体介绍全局钩子的开发过程了,在后面的实例中我们将会使用到全局钩子,到时将学习到全局钩子的相关知识。

4. 实例实现

通过上面的学习,我们已经基本具备了编写动作式游戏外挂的能力了。下面我们将
创建一个画笔程序外挂,它实现自动移动画笔字光标的位置并写下一个红色的“R”字。以这个实例为基础,加入相应的游戏动作规则,就可以实现一个完整的游戏外挂。这里作者不想使用某个游戏作为例子来开发外挂(因没有游戏商家的授权啊!),如读者感兴趣的话可以找一个游戏试试,最好仅做测试技术用。

首先,我们需要编写一个全局钩子,使用它来激活外挂,激活键为F10。创建全局
钩子步骤如下:

(1).选择MFC AppWizard(DLL)创建项目ActiveKey,并选择MFC Extension DLL
(共享MFC拷贝)类型。

(2).插入新文件ActiveKey.h,在其中输入如下代码:

#ifndef _KEYDLL_H
#define _KEYDLL_H

class AFX_EXT_CLASS CKeyHook:public CObject
{
public:
CKeyHook();
~CKeyHook();
HHOOK Start(); //安装钩子
BOOL Stop(); //卸载钩子
};
#endif

(3).在ActiveKey.cpp文件中加入声明”#include ActiveKey.h”。

(4).在ActiveKey.cpp文件中加入共享数据段,代码如下:

//Shared data section
#pragma data_seg("sharedata")
HHOOK glhHook=NULL; //钩子句柄。
HINSTANCE glhInstance=NULL; //DLL实例句柄。
#pragma data_seg()

(5).在ActiveKey.def文件中设置共享数据段属性,代码如下:

SETCTIONS
shareddata READ WRITE SHARED

(6).在ActiveKey.cpp文件中加入CkeyHook类的实现代码和钩子函数代码:

//键盘钩子处理函数。
extern "C" LRESULT WINAPI KeyboardProc(int nCode,WPARAM wParam,LPARAM
lParam)
{
if( nCode >= 0 )
{
if( wParam == 0X79 )//当按下F10键时,激活外挂。
{
//外挂实现代码。
CPoint newPoint,oldPoint;
GetCursorPos(&oldPoint);
newPoint.x = oldPoint.x+40;
newPoint.y = oldPoint.y+40;
mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);//模拟按下鼠标左键。
SetCursorPos(newPoint.x,newPoint.y);

mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);//模拟放开鼠标左键。
}
}
return CallNextHookEx(glhHook,nCode,wParam,lParam);
}

CKeyHook::CKeyHook(){}
CKeyHook::~CKeyHook()
{
if( glhHook )
Stop();
}
//安装全局钩子。
HHOOK CKeyHook::Start()
{
glhHook = SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,glhInstance,0);//设置键
盘钩子。
return glhHook;
}
//卸载全局钩子。
BOOL CKeyHook::Stop()
{
BOOL bResult = TRUE;
if( glhHook )
bResult = UnhookWindowsHookEx(glhHook);//卸载键盘钩子。
return bResult;
}

(7).修改DllMain函数,代码如下:

extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
//如果使用lpReserved参数则删除下面这行
UNREFERENCED_PARAMETER(lpReserved);

if (dwReason == DLL_PROCESS_ATTACH)
{
TRACE0("NOtePadHOOK.DLL Initializing!/n");
//扩展DLL仅初始化一次
if (!AfxInitExtensionModule(ActiveKeyDLL, hInstance))
return 0;
new CDynLinkLibrary(ActiveKeyDLL);
//把DLL加入动态MFC类库中
glhInstance = hInstance;
//插入保存DLL实例句柄
}
else if (dwReason == DLL_PROCESS_DETACH)
{
TRACE0("NotePadHOOK.DLL Terminating!/n");
//终止这个链接库前调用它
AfxTermExtensionModule(ActiveKeyDLL);
}
return 1;
}

(8).编译项目ActiveKey,生成ActiveKey.DLL和ActiveKey.lib。

接着,我们还需要创建一个外壳程序将全局钩子安装了Windows系统中,这个外壳
程序编写步骤如下:

(1).创建一个对话框模式的应用程序,项目名为Simulate。

(2).在主对话框中加入一个按钮,使用ClassWizard为其创建CLICK事件。

(3).将ActiveKey项目Debug目录下的ActiveKey.DLL和ActiveKey.lib拷贝到
Simulate项目目录下。

(4).从“工程”菜单中选择“设置”,弹出Project Setting对话框,选择Link标
签,在“对象/库模块”中输入ActiveKey.lib。

///
5).将ActiveKey项目中的ActiveKey.h头文件加入到Simulate项目中,并在
Stdafx.h中加入#includeActiveKey.h。

(6).在按钮单击事件函数输入如下代码:

void CSimulateDlg::OnButton1()
{
// TODO: Add your control notification handler code here
if( !bSetup )
{
m_hook.Start();//激活全局钩子。
}
else
{
m_hook.Stop();//撤消全局钩子。
}
bSetup = !bSetup;

}

(7).编译项目,并运行程序,单击按钮激活外挂。

(8).启动画图程序,选择文本工具并将笔的颜色设置为红色,将鼠标放在任意位置
后,按F10键,画笔程序自动移动。

回答者: 金庸爷爷的FANS - 魔法学徒 一级   发消息   加为好友   06-14 13:25

SetWindowsHookEx
回答者: zyxxs3344 - 见习魔法士 二级   发消息   加为好友   06-14 13:25

我写了一个框架,你只需把响应动作添加到回调函数中即可。
导出函数都已经写好了,可以在主程序中LoadLibrary动态加载调用。

#include <windows.h>

// 建立数据段
#pragma data_seg("HookData")
HHOOK g_hHook = NULL; // 钩子句柄
HINSTANCE g_hInstDLL = NULL; // 模块句柄
#pragma data_seg()

// 设置数据段为可读可写可共享
#pragma comment(linker,"/SECTION:HookData,RWS")

// 入口函数
BOOL APIENTRY DllMain(HINSTANCE hInstDLL,
DWORD fdwReason,
LPVOID lpvReserved)
{
if(fdwReason == DLL_PROCESS_ATTACH)
g_hInstDLL = hInstDLL; // 初始化模块句柄
return TRUE;
}

// 钩子回调函数
LRESULT WINAPI HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
// TODO: 在这里添加响应动作

// 将事件传递到下一个钩子
return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}

// 安装钩子
extern "C" __declspec(dllexport) DWORD InstallHook(void)
{
DWORD dwRet = 0;
g_hHook = SetWindowsHookEx(WH_MOUSE, HookProc, g_hInstDLL, 0);
if(g_hHook == NULL)
dwRet = GetLastError();
return dwRet;
}

// 卸载钩子
extern "C" __declspec(dllexport) DWORD KillHook(void)
{
if(UnhookWindowsHookEx(g_hHook))
return 0;
else
return GetLastError();
}

回答者: 二元论者 - 魔法学徒 一级   发消息   加为好友   06-14 13:25

4125
回答者: 金月华913 - 魔法学徒 一级   发消息   加为好友   06-14 13:25

程序发你邮箱,如果有用,请加分;谢谢!
回答者: 薇Via - 魔法学徒 一级   发消息   加为好友   06-14 13:25

用findwindow函数获得句柄,再postmessage一下

VC++ Hook截取鼠标点击窗口消息的问题!全局钩子相关推荐

  1. QT鼠标点击窗口外的部分使窗口隐藏

    使用事件过滤器来实现 protected:bool eventFilter(QObject *o, QEvent *e);//事件过滤器bool chatEmotion::eventFilter(QO ...

  2. VC++通过SetWindowHookEx去实时拦截窗口消息,实现视频会议中桌面共享图像的实时拖动(附源码)

    目录 1.桌面共享的概念 2.实现高清共享视频画面的需求调研 3.功能实现

  3. [vb]一些窗口消息的详解

    代码: Public Const WM_NULL = &H0 '空消息 Public Const WM_NCCREATE = &H81 '当窗口第一次被创建时,此消息在WM_CREAT ...

  4. python pygame鼠标点击_Python中pygame的mouse鼠标事件用法实例

    本文实例讲述了Python中pygame的mouse鼠标事件用法.分享给大家供大家参考,具体如下: pygame.mouse提供了一些方法获取鼠标设备当前的状态 ''' pygame.mouse.ge ...

  5. python pygame鼠标点击_pygame系列_mouse鼠标事件

    pygame.mouse提供了一些方法获取鼠标设备当前的状态 '''pygame.mouse.get_pressed - get the state of the mouse buttons get ...

  6. 处理鼠标连续点击的问题

    处理鼠标连续点击的问题 //上次点击时间点 DWORD m_tmClick; //初始化变量 m_tmClick = time(NULL);在鼠标点击事件消息中添加如下代码:DWORD dwTime ...

  7. VC6系统托盘类|崩溃自动重建图标|HOOK窗口消息|气泡效果更新SDK

    解决制作托盘气泡提示中遇到的'NIF_INFO' : undeclared identifier VC6下实现托盘气泡提示的关键是要更新SDK,实际上应该就是要更新SHELLAPI.h,SHELL32 ...

  8. OpenCV-Python根据鼠标点击位置截取ROI

    OpenCV-Python根据鼠标点击位置截取ROI 文章目录 OpenCV-Python根据鼠标点击位置截取ROI 前言 一.实现过程 1.引入库 2. 获取鼠标位置 使用方法 实例展示 前言 基于 ...

  9. python截取图片的ROI+OpenCV 在坐标中显示图片+鼠标点击图片显示点坐标

    又来做下笔记了.现在我的毕业设计进行到数据处理的阶段,要在乳腺图像上截取4张相同大小的1024*1024图片,并且每张图片都必须覆盖微钙化点,以下是我现在用到的一些简单程序. 1.首先是截图程序如下: ...

最新文章

  1. 黑马程序员 交通灯案例
  2. ZBar与ZXing使用后感觉
  3. Visual Studio 2005 Web Deployment Projects版本不同引发的问题
  4. 【Dual-Path-RNN-Pytorch源码分析】loss函数:SI-SNR
  5. Apache安装及jboss部署说明文档
  6. 招聘webgis开发经理和程序员
  7. C# 向listbox添加大量数据项的实践心得
  8. java 使用string_java中string怎么使用
  9. Corn Fields(POJ-3254)
  10. HDU 1828:Picture(扫描线+线段树 矩形周长并)
  11. 三星note3 android4.3,三星N9002 (Note3联通双卡版 Android4.3)一键救砖教程,轻松刷回官方系统...
  12. 2015/10/19总结:ajax传参、jquery.validate自定义日期校验
  13. 将html代码部署到阿里云服务器,并进行域名解析,以及在部署过程中遇到的问题和解决方法
  14. 【python】装饰器小结(被装饰函数有/无返回值情况,保留被装饰函数信息)
  15. Spring操作数据库几十次后就JDBC begin transaction failed
  16. 分布式事务处理框架之LCN
  17. 读取计算机内存卡,手机内存卡无法读取怎么办 读取手机内存卡详细方法【详细步骤】...
  18. Markdown 并排显示图片
  19. bat:windows bat脚本修改文件内容
  20. Codeforces Round #439 (Div. 2) E. The Untended Antiquity

热门文章

  1. python判断今天周几_python 如何判断当天为周几?判断当天是否为工作日?
  2. 软考高级证书可以积分50分
  3. Aspose.PDF for Java 20.x
  4. HTML层叠样式表(CSS)
  5. appollo-参考线平滑设定
  6. VPX信号处理板VPX3U-2DSP-C6678
  7. git checkout恢复文件
  8. jquery.min.js:2 Uncaught Error: Syntax error, unrecognized expression: unsupported pseudo: blank
  9. 实现textarea不自动换行
  10. JavaScript聊天器