PYTHON控制WINDOWS-句柄,鼠标,按键

发布于 2023-01-18  384 次阅读


  • api是一套用来控制windows的各个部件(从桌面的外观到为一个新进程分配的内存)的外观和行为的一套预先定义的windows函数.用户的每个动作都会引发一个或几个函数的运行以告诉windows发生了什么.
  • python的pywin32库提供函数利用api控制Windows
  • 安装方法
pip install pywin32
  • 调用方法:
import win32gui
import win32con
import win32api
import pyautogui 

一些简单操作

  • 下面是从获取句柄到利用句柄对窗体进行操控的方法
  • 在鼠标控制时,模拟位置是根据屏幕坐标来的,而程序框的大小改变,置顶,最小化,最大化都会导致程序模拟点击位置错位从而断开控制链,所以要先进行窗体操作
  • 对程序的操作需要找到程序的标识号,比如进程的pid,对窗体也需要知道窗体的标识号,也就是句柄
句柄是一个系统内部数据结构的引用,例如,当你操作一个窗口,或说是一个Delphi窗体时,系统会给你一个该窗口的句 
柄,系统会通知你:你正在操作142号窗口,就此,你的应用程序就能要求系统对142号窗口进行操作——移动窗口、改变窗口
大小、把窗口极小化为图标,等等。实际上许多Windows API函数把句柄作为它的第一个参数,如GDI(图形设备接口)句
柄、菜单句柄、实例句柄、位图句柄等等,不仅仅局限于窗口函数。
  • 根据名称获取句柄
首先获取所有窗体的句柄

def get_all_windows():
    hWnd_list = []
    win32gui.EnumWindows(lambda hWnd, param: param.append(hWnd), hWnd_list)
    #print(hWnd_list)
    return hWnd_list
根据窗体名称获取句柄

def get_title(hwnd):
    title = win32gui.GetWindowText(hwnd)
    #print('窗口标题:%s' % (title))
    return title
调用上面的两个函数,输入窗体名称,返回句柄

def gethandle(input):
    list=get_all_windows()
    for temphandle in list:
         if get_title(temphandle)==input:
            return temphandle
  • 获得句柄后就可以为所欲为了,相关函数有很多,想干什么可以自己查,这里写四个后面要用的
输入句柄,设置窗体保持最前端
这与置顶窗体不同,置顶窗体后可以被另一次置顶操作给消除置顶效果,但是保持最前端会使得程序始终保持最前端

def set_top(hwnd):
    win32gui.SetWindowPos(hwnd, win32con.HWND_TOPMOST, 0, 0, 0, 0,
                          win32con.SWP_NOMOVE | win32con.SWP_NOACTIVATE | win32con.SWP_NOOWNERZORDER | win32con.SWP_SHOWWINDOW | win32con.SWP_NOSIZE)
输入句柄,关闭窗体

def close(handle):
    win32gui.PostMessage(handle, win32con.WM_CLOSE, 0, 0)
输入句柄,做大话窗体

def max(handle):
    win32gui.ShowWindow(handle, win32con.SW_SHOWMAXIMIZED)
输入句柄,最小化窗体

def min(handle):
    win32gui.ShowWindow(handle, win32con.SW_SHOWMINIMIZED)

一些复杂操作

  • 接下来就是干正事的时候了,windows虽然提供了丰富的api,但是很多第三方软件是没有这些接口的,如果想实现对第三方软件的自动化控制(比如自动刷网课🐶狗头保命),就得模拟鼠标和模拟键盘操作了
  • pywin32库控制鼠标和键盘也是十分方便
鼠标移动

pyautogui.moveTo(500, 650,duration = 2)
  • 500是x坐标,650是y坐标(坐标轴在哪里自己试🤣)
  • duration控制的是鼠标移动的时间,比如设为2就是鼠标从当前位置移动到指定位置一共花两秒
  • 要注意的是,duration还可以起到增加容错率的作用,比如设置为5,在5秒内强行控制鼠标的行为会让光标在程序定位点和鼠标移动点之间来回跳转,5秒的那一刻光标定格的位置就是程序执行的最终位置,可能造成定位不准,导致整个自动控制断链,直接设置成0.1挺好
  • 坐标是根据电脑分辨率来的,有可能你的电脑上能用,换一个电脑就定位到别的地方去了
模拟点击

pyautogui.click(clicks = 2, button ='left', interval = 0.05)
  • clicks控制点击数,button控制左右键,interval是点击数之间的间隔,单击可以不设置
模拟输入

pyautogui.typewrite('82.157.252.246', 0.5)
  • 模拟输入你好啊!每个字符间隔0.5秒自动输入
pyautogui.typewrite('你好啊!', 0.5)
  • 模拟回车
pyautogui.typewrite('\n', 0.5)
  • 模拟热键组合,如win+i打开设置
pyautogui.hotkey('win', 'i')
  • 到这里,通过对上面的操作的组合就可以实现任何对电脑的自动控制了🤔
  • 在程序自动控制时应充分考虑电脑的反应时间,比如电脑打开文件需要2秒,但是在这两秒内程序已经完成模拟点击,就会出现控制连断裂问题,所以应该充分使用sleep()函数
导入库

import time
程序暂停2秒

time.sleep(2)

一个例子

  • 下面是我写的一个自动生成一个网络适配器的脚本,可以在这个基础上改一下
import os
from py_compile import _get_default_invalidation_mode
import time
from matplotlib.pyplot import get               
import win32gui
import win32con
import win32api
import pyautogui 
from tkinter import*

win32api.MessageBox(0, "程序运行过程中,请按照提示操作,不要操作鼠标或键盘,避免定位出错", "注意",win32con.MB_OK)

def get_all_windows():
    hWnd_list = []
    win32gui.EnumWindows(lambda hWnd, param: param.append(hWnd), hWnd_list)
    #print(hWnd_list)
    return hWnd_list

def get_title(hwnd):
    title = win32gui.GetWindowText(hwnd)
    #print('窗口标题:%s' % (title))
    return title

def gethandle():
    list=get_all_windows()
    for temphandle in list:
         if get_title(temphandle)=='网络和共享中心':
            return temphandle

def set_top(hwnd):
    win32gui.SetWindowPos(hwnd, win32con.HWND_TOPMOST, 0, 0, 0, 0,
                          win32con.SWP_NOMOVE | win32con.SWP_NOACTIVATE | win32con.SWP_NOOWNERZORDER | win32con.SWP_SHOWWINDOW | win32con.SWP_NOSIZE)

def close(handle):
    win32gui.PostMessage(handle, win32con.WM_CLOSE, 0, 0)

def max(handle):
    win32gui.ShowWindow(handle, win32con.SW_SHOWMAXIMIZED)

def min(handle):
    win32gui.ShowWindow(handle, win32con.SW_SHOWMINIMIZED)

os.system('control /name Microsoft.networkandsharingcenter')
time.sleep(3)

handle=gethandle()

set_top(handle)

max(handle)
time.sleep(3)

pyautogui.moveTo(500, 650,duration = 2) 
pyautogui.click(clicks = 2, button ='left', interval = 0.05)
close(handle)
time.sleep(2)

pyautogui.moveTo(700, 600,duration = 2) 
pyautogui.click(clicks = 2, button ='left', interval = 0.05)
time.sleep(2)
pyautogui.moveTo(600, 400,duration = 2)
pyautogui.click(clicks = 2, button ='left', interval = 0.05)
time.sleep(2)
pyautogui.typewrite('0.0.0.0', 0.5)
pyautogui.typewrite('\n', 0.5)
time.sleep(2)
os.system('ncpa.cpl')

time.sleep(2)
stepone=Tk()
stepone.title('步骤:')
stepone.geometry("300x400+630+80")  # (宽度x高度)+(x轴+y轴)
text = Text(stepone)
text.insert(INSERT, "请按下面步骤操作:\n\n1.喵喵喵")
text.pack()  
stepone.mainloop()

time.sleep(2)
pyautogui.hotkey('win', 'i')

time.sleep(2)
steptwo=Tk()
steptwo.title('步骤:')
steptwo.geometry("300x400+630+80")  # (宽度x高度)+(x轴+y轴)
text = Text(steptwo)
text.insert(INSERT, "请按下面步骤操作:\n\n1.汪汪汪")
text.pack()  
steptwo.mainloop()
届ける言葉を今は育ててる
最后更新于 2024-02-07