【pyHook】

  pyHook是一个用来进行键盘、鼠标等层面事件监控的库。这个库的正常工作需要pythoncom等操作系统的API的支持。首先来说说如何安装。

  直接pip install pyHook是找不到相关包的,不知道是不是因为这个库可以被用于一些比较邪恶的目的。。于是就要去网上下,可以下源码编译安装,不过在https://www.lfd.uci.edu/~gohlke/pythonlibs/#pyhook这里可以直接下载到.whl文件,这个文件可以作为pip install 的参数来进行安装。也就是说pip install xxx.whl即可。

  安装完成后import pyHook无误,顺便可以检查一下import win32com和pythoncom两个库,确保支持的库都有安装。

■  键盘事件监听基本使用

  监测键盘事件主要用到了pyHook的KeyBoardEvent类,这个类的源码是这样的:

class KeyboardEvent(HookEvent):
'''
Holds information about a mouse event.
@ivar KeyID: Virtual key code
@type KeyID: integer
@ivar ScanCode: Scan code
@type ScanCode: integer
@ivar Ascii: ASCII value, if one exists
@type Ascii: string
'''
def __init__(self, msg, vk_code, scan_code, ascii, flags, time, hwnd, window_name):
'''Initializes an instances of the class.'''
HookEvent.__init__(self, msg, time, hwnd, window_name)
self.KeyID = vk_code
self.ScanCode = scan_code
self.Ascii = ascii
self.flags = flags
def GetKey(self):
'''
@return: Name of the virtual keycode
@rtype: string
'''
return HookConstants.IDToName(self.KeyID)
def IsExtended(self):
'''
@return: Is this an extended key?
@rtype: boolean
'''
return self.flags & 0x01
def IsInjected(self):
'''
@return: Was this event generated programmatically?
@rtype: boolean
'''
return self.flags & 0x10
def IsAlt(self):
'''
@return: Was the alt key depressed?
@rtype: boolean
'''
return self.flags & 0x20
def IsTransition(self):
'''
@return: Is this a transition from up to down or vice versa?
@rtype: boolean
'''
return self.flags & 0x80
Key = property(fget=GetKey)
Extended = property(fget=IsExtended)
Injected = property(fget=IsInjected)
Alt = property(fget=IsAlt)
Transition = property(fget=IsTransition)

  最下面的property函数可以设置一个类似java成员变量的类属性(之前在Python类结构中就提到过@property这个设置类属性的方法)。fget参数设置一个方法,这个方法的返回将被设置为这个类属性的值。那几个方法返回的内容在注释里面都说明了,而&这个位运算符,emmm…不说了吧

  接下来是一个简单的实例,当我们按下一个按键的时候stdout中打印出这个动作的信息,松开时再打印出松开的信息。注意,pyHook调用的是系统层面的钩子而不是这个进程自己范围内的东西。这也就是说,在系统中的任何地方(不论是python shell内外),按键时都会触发事件。

import pyHook
import pythoncom class KeyBoardManager():
keyIsPressed = False
def onKeyDown(self,event):
if self.keyIsPressed:
return True
print str(event.Key) + ' is pressed'
self.keyIsPressed = True
return True def onKeyUp(self,event):
self.keyIsPressed = False
print str(event.Key) + ' is released'
return True if __name__ == '__main__':
mykbmanager = KeyBoardManager()
hookmanager = pyHook.HookManager()
hookmanager.KeyDown = mykbmanager.onKeyDown
hookmanager.KeyUp = mykbmanager.onKeyUp
hookmanager.HookKeyboard()
pythoncom.PumpMessages()

  可以看到,HookManager是我们用的pyHook库中的一个类。这个类其实就是用来管理hook各种各样的事件的。通过它我们可以往不同的事件上绑定不同的函数(方法)从而实现监听的功能。另外定义了一个类作为充实HookManager的内容。至于为什么不用几个直接的函数而是用了一个类和类中的方法,这个之后再说。

  然后再来看KeyBoardManager类,实现了两个方法,分别都有一个event参数,这个参数就是指代了一个KeyBoardEvent的实例。这里主要用到了event.Key这个属性。这个属性就是指代了哪个键盘上的按键被按下,这里虽然用了str方法转化类型,但是似乎直接用event.Key也是一个字符串类型。这里特别需要注意的一点:需要搞清楚事件触发条件的定义。比如KeyDown事件并不是“按下键”,而是“按着键”,当我们规定一个方法,方法里print event.Key,然后我们关联了这个方法和hookmanager.KeyDown,这样只要我们按着某个键不松开,stdout就会源源不断地打印出这个键名。另外,事件响应函数必须在合适的地方进行返回,返回内容最好是True或者False,当返回True时,意思是除了我们规定的事件之外,原来按键本身就会发生的事件也会发生。比如在上面这段监听程序下,我们打开记事本准备输入,长按空格键,当onKeyDown方法两处都返回True时(如代码中一样),空格还是会被源源不断输入记事本。但是如果两处都返回False,则长按空格键只是打印出Space is pressed,而不会在记事本中输入任何空格。这么一来就好比是键盘被禁言了,无论在系统的什么地方输入什么都不会奏效。如果在下面的return处是True,而在上面设置return False可能是比较理想的情况,此时按键时的输入会被写到记事本,且只写一次,而按下和松开也有相应的信息输出。

  在这个实例中,我们的期望是按下按键之后打印出信息,然后松开的时候再打印一次,中途按着的时候不用打印。这时候就需要在方法的定义上下一些功夫,这也就是为什么我们不用简单的函数而是用类方法来定义事件响应函数。简单来说就是我们在类中维护了一个状态flag,当键被按下时首先置状态为True,之后在按着的过程中此状态一直保持True,所以一直不会在屏幕上输出,直到松开,状态被置回并且打印松开的信息(松开的事件是“送开键”而不是“送着键”,要不然什么都不干就有事件了。。)

  KeyBoardEvent类的属性,我们只用了Key,其实还有很多:

   print "MessageName:", event.MessageName
print "Message:", event.Message
print "Time:", event.Time
print "Window:", event.Window
print "WindowName:", event.WindowName
print "Ascii:", event.Ascii, chr(event.Ascii)
print "Key:", event.Key
print "KeyID:", event.KeyID
print "ScanCode:", event.ScanCode
print "Extended:", event.Extended
print "Injected:", event.Injected
print "Alt", event.Alt
print "Transition", event.Transition
'''
比如我按了下回车键,其返回就是:
MessageName: key down
Message: 256
Time: 195436180
Window: 329524
WindowName: TmpProjects - [D:\PythonProjects\TmpProjects] - ...\tmp.py - PyCharm 5.0.3
Ascii: 13
Key: Return
KeyID: 13
ScanCode: 28
Extended: 0
Injected: 0
Alt 0
Transition 0
---
'''

  其实这些里大多就是上面提到的KeyBoardEvent类中设置的一些属性。MessageName字段描述事件的名称,Message则是事件类型的编号,Time就是事件发生时间,Window是事件发生在的窗口的编号,Ascii是按键内容的ASCII码,如果不属于ASCII字符集则为0,Extended描述是否是拓展键(比如Fn+一些键用来调电脑音量,屏幕亮度等就是扩展键),Alt是指出了按键是否是Alt键(存疑。。)若是则值为32,等等……

■  鼠标事件监听基本使用

  和键盘事件类似的,鼠标事件用到了MouseEvent类,然后通过HookManager类的HookMouse方法进行监听,而关联钩子函数和事件响应函数之间的变量名可以类似于MouseLeftUp,MouseRightDown,MouseWheel,MouseMove之类的,如果不想设置这么细致也可以直接一个MouseAll来关联所有鼠标相关事件和响应函数。

  下面是一个类似于上面键盘事件监听的实例:

import pyHook
import pythoncom def onMouseEvent(event):
print "MessageName:",event.MessageName
print "Message:", event.Message
print "Time:", event.Time
print "Window:", event.Window
print "WindowName:", event.WindowName
print "Position:", event.Position
print "Wheel:", event.Wheel
print "Injected:", event.Injected
print"---" return True if __name__ == '__main__':
hookmanager = pyHook.HookManager()
hookmanager.MouseAll = onMouseEvent
hookmanager.Mouse
hookmanager.HookMouse()
pythoncom.PumpMessages() '''
部分输出结果是:
MessageName: mouse move
Message: 512
Time: 197121396
Window: 329524
WindowName: TmpProjects - [D:\PythonProjects\TmpProjects] - ...\tmp.py - PyCharm 5.0.3
Position: (786, 529)
Wheel: 0
Injected: 0
---
MessageName: mouse left down
Message: 513
Time: 197123690
Window: 329524
WindowName: TmpProjects - [D:\PythonProjects\TmpProjects] - ...\tmp.py - PyCharm 5.0.3
Position: (786, 529)
Wheel: 0
Injected: 0
---
MessageName: mouse left up
Message: 514
Time: 197123846
Window: 329524
WindowName: TmpProjects - [D:\PythonProjects\TmpProjects] - ...\tmp.py - PyCharm 5.0.3
Position: (786, 529)
Wheel: 0
Injected: 0
---
MessageName: mouse wheel
Message: 522
Time: 197126856
Window: 329524
WindowName: TmpProjects - [D:\PythonProjects\TmpProjects] - ...\tmp.py - PyCharm 5.0.3
Position: (786, 529)
Wheel: -1
Injected: 0
---
与上面这串输出对应的操作是先移动鼠标,然后点击一下左键,然后滑动了滚轮
'''

  和键盘事件响应函数类似的,返回必须要有,而且当返回是False的时候,默认的鼠标事件不发生。也就是说你即使移动了鼠标,光标也不会动,造成一种假死的感觉。

最后,还需要提一下性能方面,监听鼠标&键盘事件可能会另系统无法正常工作,比如上面监测键盘事件的时候,快速地(也就是我们正常打字速度吧。。)击打键盘的时候,有时会记录不全信息,有时也会发生记录了信息但是我们的按键没有达到目的。

【pyHook】 监测键盘鼠标事件等的更多相关文章

  1. Android查询:模拟键盘鼠标事件(adb shell 实现)

    1. 发送键盘事件: 命令格式1:adb shell input keyevent “value” 其中value以及对应的key code如下表所列: KeyEvent Value KEYCODE ...

  2. soeasy的键盘鼠标事件

    在web自动化中,我们可能会遇到需要通过键盘或者鼠标去操作某些元素,那么我们就需要用到键盘事件和鼠标事件了,今天对键盘和鼠标操作进行一个总结 鼠标事件 鼠标事件需要引入ActionChains类,查看 ...

  3. 【JS】键盘鼠标事件

    一,键盘 keydown 表示按下键盘 keypress 表示按下键盘 keyup 表示键盘弹起 这三者的区别分别表现在发生的 先后顺序,获取到的键盘按钮值,已经对输入框的文本取值这三方面 先后顺序: ...

  4. (转)C#模拟键盘鼠标事件

    原文 1.模拟键盘事件System.Windows.Forms.SendKeys以下是   SendKeys   的一些特殊键代码表.     键   代码       BACKSPACE   {BA ...

  5. linux 处理键盘 鼠标事件

    Linux下鼠标和键盘的模拟控制,也就是为手势和语音控制鼠标和键盘部分服务的. 有关于本系统构建的文章结构都会由三个部分来组织,一是该功能模块的介绍和在Linux下简单应用程序的实现:二是将该功能模块 ...

  6. C#模拟键盘鼠标事件 SendKeys 的特殊键代码表(转)

    使用 SendKeys 将键击和组合键击发送到活动应用程序.此类无法实例化.若要发送一个键击给某个类并立即继续程序流,请使用 Send.若要等待键击启动的任何进程,请使用 SendWait. 每个键都 ...

  7. Python——pyHook监听鼠标键盘事件

    pyHook包为Windows中的全局鼠标和键盘事件提供回调. 底层C库报告的信息包括事件的时间,事件发生的窗口名称,事件的值,任何键盘修饰符等. 而正常工作需要pythoncom等操作系统的API的 ...

  8. winform中键盘和鼠标事件的捕捉和重写(转)

    在 编写winform应用程序时,有时需要无论在哪个控件获取焦点时,对某一个键盘输入或者鼠标事件都进行同样的操作.比如编写一个处理图片的应用程序时, 希望无论当前哪个控件获得焦点,当用户按上.下.左. ...

  9. Selenium2+python自动化12-操作元素(键盘和鼠标事件)

    前言 在前面的几篇中重点介绍了一些元素的到位方法,到位到元素后,接下来就是需要操作元素了.本篇总结了web页面常用的一些操作元素方法,可以统称为行为事件 有些web界面的选项菜单需要鼠标悬停在某个元素 ...

随机推荐

  1. dm642的视频口输出

    void VP1_EDMA(int displayMode,unsigned int w,unsigned int h) {      unsigned int i=0,k=0;  EDMA_Hand ...

  2. 视频显示格式720p

    720p是一种视频显示格式.字母p意为逐行扫描(progressive scan),数字720则表示水平方向有720条扫描线. 通常720p的画面分辨率为1280×720,一般亦可称为高画质(HD). ...

  3. stm32开发之串口的调试

    总的函数如下 void USART1Configuration(void){    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Peri ...

  4. Parallel中分区器Partitioner的简单使用

    Partitioner.Create(1,10,4).GetDynamicPartitions() 为长度为10的序列创建分区,每个分区至多4个元素,分区方法及结果:Partitioner.Creat ...

  5. C#连接oracle数据库步骤

    1.  确认操作系统类型,操作系统是64位还是32位: 2.  按对应版本安装oralce客户端版本(64位还是32位): 3.  安装oralce管理员模块,同时赋予安装目录权限 4.  注册old ...

  6. TensorFlow MNIST初级学习

    MNIST MNIST 是一个入门级计算机视觉数据集,包含了很多手写数字图片,如图所示: 数据集中包含了图片和对应的标注,在 TensorFlow 中提供了这个数据集,我们可以用如下方法进行导入: f ...

  7. Duplicate entry '0' for key 'PRIMARY'的一种可能的解决办法

    在MySQL设计好数据库往往数据库中插入数据的时候, 因为主键ID默认是不赋值的,只给其他项目赋值了,相关的SQL代码是这样的 StringBuilder strSql = new StringBui ...

  8. Xampp apache与mySQL开不了 解决办法

    Xampp安装后,打开Xampp control panel. 点击Apache对应的Start,开不了.原因是系统的服务占用了80端口,所以要么结束系统服务,要么修改apache端口. 个人比较喜欢 ...

  9. jquery的过滤学习

    $("p").eq(1)  匹配下标为1的p标签        $("p").hasClass("a")匹配所有p标签class中包含a的 ...

  10. 【BZOJ3262】陌上花开(CDQ分治)

    [BZOJ3262]陌上花开(CDQ分治) 题解 原来放过这道题目,题面在这里 树套树的做法也请点上面 这回用CDQ分治做的 其实也很简单, 对于第一维排序之后 显然只有前面的对后面的才会产生贡献 那 ...