Pywin32基础使用

因为看到pywin32这个模块可以调用Windows API,所以我也想来学习一下。

安装

据说可以直接使用pip install pywin32来安装,但我没装上,下载了该网站中的文件,注意要和自己的系统以及安装的Python版本对应。

第一次安装的时候没办法选择路径,因为它是根据注册表中的Python路径来安装的,可以参考python路径写入注册表,导入三方模块win32来修改。

使用了上面网站中提供的脚本,在Pycharm中运行之后确实成功装上了pywin32,但是之后在命令行中运行Python脚本的时候报错了。如果有相应需求的话,一定要在注册表中把路径改回去。

Hello World

还不太熟悉里面的各种参数,先照着别人的写了个Helloworld

image-20220419210208040

什么是DC

没有找到详细介绍,但每篇提及DC的博文内容都差不多一样。根据我的理解,大概是pywin32可以通过DC来操作窗口。

基础使用

示例1:截图

使用了该教程中的代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def get_windows(windowsname, filename):
    # 获取窗口句柄
    handle = win32gui.FindWindow(None, windowsname)
    # 将窗口放在前台,并激活该窗口(窗口不能最小化)
    win32gui.SetForegroundWindow(handle)
    # 获取窗口DC
    hdDC = win32gui.GetWindowDC(handle)
    # 根据句柄创建一个DC
    newhdDC = win32ui.CreateDCFromHandle(hdDC)
    # 创建一个兼容设备内存的DC
    saveDC = newhdDC.CreateCompatibleDC()
    # 创建bitmap保存图片
    saveBitmap = win32ui.CreateBitmap()
    # 获取窗口的位置信息
    left, top, right, bottom = win32gui.GetWindowRect(handle)
    # 窗口长宽
    width = right - left
    height = bottom - top
    # bitmap初始化
    saveBitmap.CreateCompatibleBitmap(newhdDC, width, height)
    saveDC.SelectObject(saveBitmap)
    saveDC.BitBlt((0, 0), (width, height), newhdDC, (0, 0), win32con.SRCCOPY)
    saveBitmap.SaveBitmapFile(saveDC, filename)


get_windows("新建文本文档 - 记事本", "screenshot.png")

大概了解了一下里面的几个函数:

1
win32gui.FindWindow(param1, param2) //参数1为传入窗口的类名参数2为传入窗口的标题

配合Spy++使用

在搜索中查找窗口,拖动查找程序工具来获取窗口信息

image-20220421155523024

1
2
3
CreateCompatibleBitMap(hdc, nWidth, nHeight)
# hdc: 设备环境句柄, nWidth: 指定位图的宽度,单位为像素, nHeight: 高度
# 如果函数执行成功则返回位图句柄,失败则返回NULL。

参考:详解CreateCompatibleBitmap 的使用

1
saveDC.BitBlt((0, 0), (width, height), newhdDC, (0, 0), win32con.SRCCOPY)

不太懂这个函数,搜了下

The BitBlt function performs a bit-block transfer of the color data corresponding to a rectangle of pixels from the specified source device context into a destination device context.

根据该文档中的描述,BitBlt函数用于把源设备环境中存放色彩信息的像素进行位块转换,再传入目标设备环境。

而SRCCOPY的定义如下:

SRCCOPY — Copies the source rectangle directly to the destination rectangle.

示例2:遍历句柄

同样来自上个示例中的教程

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import win32gui

hwnd_title = dict()


def get_all_hwnd(hwnd, mouse):
    if win32gui.IsWindow(hwnd) and win32gui.IsWindowEnabled(hwnd) and win32gui.IsWindowVisible(hwnd):
        hwnd_title.update({hwnd: win32gui.GetWindowText(hwnd)})


win32gui.EnumWindows(get_all_hwnd, 0)

for h, t in hwnd_title.items():
    if t is not "":
        print(h, t)

遍历所有已被激活的窗口并打印标题信息。

示例3:启动程序

示例来自使用pywin32制作Windows自动化工具

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def start_app(path):
    win32api.ShellExecute(0, 'open', path,'','',1)
    # os.startfile(path)  # 也可用这条
    
notepad_path = r'C:\Windows\notepad.exe'
start_app(notepad_path)
while True:
    win = win32gui.FindWindow('Notepad','')
    if win != 0:
        win32api.Sleep(200) # 因为程序启动需要时间,防止出现查询时窗口还没完全打开的情况。
        break

启动记事本并获取主窗口handle。