Python ctypes 调用API函数模拟键盘鼠标事件

本文介绍了如何使用Python的ctypes模块调用API函数,实现模拟键盘和鼠标事件,包括按下、释放和点击等操作,适用于自动化测试、游戏控制等场景。内容涵盖导入ctypes模块、调用API函数、模拟键盘和鼠标事件的详细方法。
摘要由CSDN通过智能技术生成

在Python编程中, 有时需要模拟键盘或鼠标事件, 自动操作计算机, 比如玩游戏等。
本文介绍使用ctypes模块调用API函数, 模拟键盘鼠标事件的方法。

1.导入ctypes模块

ctypes 是 Python 的外部函数库,提供了与 C 兼容的数据类型,并且支持直接调用 DLL 中的函数 (这对于调用API函数非常有用)。

from ctypes import *

2.通过ctypes.windll调用api函数

可通过操作dll对象的属性来操作这些函数。如:

windll.user32.keybd_event(32,0,0,0) # 按下空格键

有时需要传递数据类型给函数 :

class PointAPI(Structure):
    #PointAPI类型,用于获取鼠标坐标
    _fields_ = [("x", c_ulong), ("y", c_ulong)]
def getpos():
    "获取当前鼠标位置。"
    po = PointAPI()
    windll.user32.GetCursorPos(byref(po)) # 传递数据类型的引用
    return int(po.x), int(po.y)

3.模拟键盘事件

模拟键盘事件主要用到了keybd_event() API函数, 用于在活动窗口生成一个键盘事件。
完整源代码见: qfcy_ / Python · GitCode

KEYEVENTF_KEYUP=2
VK_CODE = { # 定义按键代码
'backspace':0x08,
'tab':0x09,
'clear':0x0C,
'enter':0x0D,
'shift':0x10,
'ctrl':0x11,
'alt':0x12,
'pause':0x13,
'caps_lock':0x14,
'esc':0x1B,
'space':0x20,
'page_up':0x21,'pgup':0x21,
'page_down':0x22,'pgdn':0x22,
'end':0x23,
'home':0x24,
'left':0x25,
'up':0x26,
'right':0x27,
'down':0x28,
'+':0xBB,
',':0xBC,
'-':0xBD,
'.':0xBE,
'/':0xBF,
'`':0xC0,
';':0xBA,
'[':0xDB,
'\\':0xDC,
']':0xDD,
"'":0xDE,
'`':0xC0}
VK_CODE.update(
    dict([("f%d"%i,0x6F+i) for i in range(1,13)])
)
VK_CODE.update(
    dict([("numpad_%d"%i,0x60+i) for i in range(10)])
)
keybd_event=windll.user32.keybd_event

def __convert(keycode_or_keyname):
    #识别参数格式, 将按键名称转换为键码值
    if type(keycode_or_keyname) is str:
        keyname=keycode_or_keyname.lower().replace(' ','_')
        if keyname in VK_CODE:
            return VK_CODE[keyname]
        else:
            if not len(keycode_or_keyname)==1:
                raise ValueError(
                "{} is not a correct key name".format(keycode_or_keyname))
            return ord(keycode_or_keyname.upper())
    else:return keycode_or_keyname

def keydown(keycode_or_keyname):
    """模拟键按下。
keycode_or_keyname:按键名称或该按键的键码值"""
    keycode=__convert(keycode_or_keyname)
    keybd_event(keycode,0,0,0)

def keyup(keycode_or_keyname):
    """模拟键释放。
keycode_or_keyname:按键名称或该按键的键码值"""
    keycode=__convert(keycode_or_keyname)
    keybd_event(keycode,0,KEYEVENTF_KEYUP,0)

def keypress(keycode_or_keyname,delay=0.05):
    """模拟按键。
keycode_or_keyname:按键名称或该按键的键码值
delay:键按下与释放之间的的间隔时间,间隔时间越小,按键速度越快。"""
    keycode=__convert(keycode_or_keyname)
    keydown(keycode)
    time.sleep(delay)
    keyup(keycode)
    time.sleep(delay)

4.模拟鼠标事件

GetCursorPos(): 获得鼠标坐标。
SetCursorPos(): 设置鼠标坐标, 即移动鼠标。
mouse_event(): 在当前光标位置生成一个鼠标事件, 如鼠标按下、释放。

#API常量
MOUSEEVENTF_LEFTDOWN = 0x2
MOUSEEVENTF_LEFTUP = 0x4
MOUSEEVENTF_MIDDLEDOWN = 0x20
MOUSEEVENTF_MIDDLEUP = 0x40 
MOUSEEVENTF_RIGHTDOWN = 0x8
MOUSEEVENTF_RIGHTUP = 0x10 
MOUSEEVENTF_MOVE = 0x1

user32=windll.user32

class PointAPI(Structure):
    #PointAPI类型,用于获取鼠标坐标
    _fields_ = [("x", c_ulong), ("y", c_ulong)]

def get_screensize():
    "获取当前屏幕分辨率。"
    GetSystemMetrics = user32.GetSystemMetrics
    return GetSystemMetrics(0), GetSystemMetrics(1)

def getpos():
    """获取当前鼠标位置。
返回值为一个元组,以(x,y)形式表示。"""
    po = PointAPI()
    user32.GetCursorPos(byref(po))
    return int(po.x), int(po.y)

def goto(x,y):
    "将鼠标移动至指定位置(x,y)。"
    user32.SetCursorPos(x,y)
setpos=goto

def move(x,y):
    """模拟移动鼠标。
与goto不同,move()*产生*一个鼠标事件。"""
    goto(x,y)
    try:
        user32.mouse_event(MOUSEEVENTF_MOVE,x,y)
    # 忽略可能的ValueError: Procedure probably called with not enough arguments (16 bytes missing)
    except ValueError as err:
        warn("ValueError: "+str(err))

def click(delay=0):
    "模拟鼠标左键单击"
    try:
        user32.mouse_event(MOUSEEVENTF_LEFTDOWN)
    except ValueError as err: # 同上
        warn("ValueError: "+str(err))
    time.sleep(delay)
    try:
        user32.mouse_event(MOUSEEVENTF_LEFTUP)
    except ValueError as err:
        warn("ValueError: "+str(err))

def right_click(delay=0):
    "模拟鼠标右键单击"
    try:
        user32.mouse_event(MOUSEEVENTF_RIGHTDOWN)
    except ValueError as err:
        warn("ValueError: "+str(err))
    time.sleep(delay)
    try:
        user32.mouse_event(MOUSEEVENTF_RIGHTUP)
    except ValueError as err:
        warn("ValueError: "+str(err))

def dblclick(delay=0.25):
    "模拟鼠标左键双击"
    click()
    time.sleep(delay)
    click()

def middle_click(delay=0):
    "模拟单击鼠标中键"
    try:
        user32.mouse_event(MOUSEEVENTF_MIDDLEDOWN)
    except ValueError as err:
        warn("ValueError: "+str(err))
    time.sleep(delay)
    try:
        user32.mouse_event(MOUSEEVENTF_MIDDLEUP)
    except ValueError as err:
        warn("ValueError: "+str(err))

延伸阅读:Python ctypes模块调用API函数, 制作控制电脑其他窗口工具

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qfcy_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值