Python之点到为止: 调用Windows API
上一期讲过如何调用dll: Python之点到为止: 调用动态链接库(DLL), 这期进一步深入Windows.
Windows API
Note that this was formerly called the Win32 API. The name Windows API more accurately reflects its roots in 16-bit Windows and its support on 64-bit Windows.
之前叫做Win32 API, 后来更名为Windows API. 随着64位操作系统以及软件的普及, 原来的名字已经不合适了, 已经囊括了对16位、64位系统得支持所以叫现在得名字更合理. 有了这些API才有得现在Windows上所有得软件.
然而这些API不需要去记住, 只是用到得时候去查文档就好了(详见文章末尾).
模块
- ctypes —— Python 的外部函数库
- pywin32 —— Python对Windows的扩展
前面也说了, 这些Windows API, 不需要去记太多了. 模块部分也不介绍太多, 直接演示代码.
实操
假如有个需求, 需要执行某些操作后给个提示弹窗. 当然有知道GUI库的童鞋会想到用他们, 很好可以联想到. 但是如果仅仅是一个弹窗就用上GUI库是不是有点浪费了. 当然本期主题是调用Windows API, 自然再Windows环境上操作.
首先我们去查一下, Windows API中哪个函数是信息框. https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messageboxw , 直接发给大家有兴趣可以按照微软的文档查看其他API.
扩展: ANSI编码, 还是Windows上使用的默认编码, 例如中文以GBK编码标准. 各个国家文字不同编码标准也不同, 乱糟糟也不能互相转换. 所以有了UNICODE编码, 但是默认编码1个字符占用16 bit, 如果是简单的一串英文很显然是ANSI的两倍, 然后UTF-8编码标准就来了, 这个大哥来了就说”你们ANSI之前那些字符我要了还占用6 bit, 然后其他的字符按情况往上加.”, 哎这就解决了占用大的问题, 还可以完美显示全字符.
int MessageBoxW( HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);看到API定义之后就好办了, 文档下面也解释了对应参数的作用.
- hWnd: 窗口句柄, 来判断这个信息框是从哪个窗口弹出来的
- lpText: 你提示的信息
- lpCaption: 信息框标题
- uType: 信息框的类型
ctypes实现
from ctypes import *messagebox = windll.user32.MessageBoxWret = messagebox(0, '提示信息', '提示标题', 0)print(ret)
user32 = windll.LoadLibrary('user32.dll')messageboxA = user32.MessageBoxAret = messageboxA(0, '提示信息'.encode('ansi'), '提示标题'.encode('ansi'), 1)print(ret)
messageboxW = user32.MessageBoxWret = messageboxW(0, '提示信息', '提示标题', 2)print(ret)
为了观看方便, 将三个截图拼接了一下. 实际是一个一个弹出的
A和W的区别不在多说, 大家可以动手试试. 对于这三个信息框不同的地方那就是按钮了, https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messageboxw#parameters 可以看下 参数 uType 值得范围. 使用方法就是这些数直接加在一起.
新需求来了, 一段代码执行之后出错了提示一下是否重新执行.
from ctypes import *
user32 = windll.LoadLibrary('user32.dll')messageboxW = user32.MessageBoxW
def todo(): try: assert False, '执行出错' # 出错代码 except Exception as e: # 5代表重试和取消按钮, int('20', 16) 是叹号提示(16进制的20转10进制) ret = messageboxW(0, '错误:{}, 是否要重试?'.format(e), '出错', 5 + int('20', 16)) if ret == 4: print('重试执行') todo()
if __name__ == "__main__": todo()其中要注意的就是文档中给的值都是16进制. 返回值文档中也有, 不想看的话代码跑一下print或者debug就知道了. 这样你就有一个稍微人性化点的提示了(只是某个方面上).
那么用pywin32来实现呢?
from win32api import MessageBoxfrom win32con import MB_RETRYCANCEL, MB_ICONQUESTION, IDRETRY
def todo(): try: assert False, '执行出错' # 出错代码 except Exception as e: ret = MessageBox(0, '错误:{}, 是否要重试?'.format(e), '出错', MB_RETRYCANCEL + MB_ICONQUESTION) if ret == IDRETRY: print('重试执行') todo()
if __name__ == "__main__": todo()这就更简单了, API名字包括常量名字都和微软文档的一摸一样, 你直接从文档中复制过来直接 import 就OK了.
总结
本文讲的一个非常简单的例子, 只是可能扩展部分有点多, 选择性观看. 这只是Windows API中的冰山一角哦. 曾经的一个朋友(易语言患者)因为我走了Python来”嘲讽我”, 说Python能写修改器么. ??? 这世上恐怕没什么事情是不能做的, 只是该不该或是有没有必要罢了.
那么我就点到为止了 Just give a hint.
相关资料: Windows API文档: https://docs.microsoft.com/en-us/windows/win32/apiindex/windows-api-list ctypes文档: https://docs.python.org/zh-cn/3.7/library/ctypes.html pywin32: https://github.com/mhammond/pywin32 pywin32文档: 有兴趣的可以加交流群98354582, 文档也是在上面的库中提取的

辽公网安备21021302000353号