ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

工作自动化,替代手工操作,使用python操作MFC、windows程序

2022-01-21 16:32:11  阅读:207  来源: 互联网

标签:None MFC python WM windows wid 窗体 操作


目录

背景--为什么要自动化操作?

工作中总是遇到反复重复性的工作?怎么用程序把它变成自动化操作?将程序挂在一旁,执行自动化操作的同时,还能处理其他的任务?提高工作效率,让自己的时间变得可控?

只能运用于 MFC 和 windows 消息机制下
最近的工作中,遇到了需要比对c++程序的运行结果与matlab运行结果的事项。
目前需要校验的c++程序并没用引入软件测试这一步骤,需要手动去操作程序获取数据,由于数据量比较大,想考虑使用程序自动运行。
偶然间想到了可以给MFC发送消息,实现软件模拟手工操作来完成这项工作。

方法--怎么实现自动化操作?

操作C++程序(模拟手动点击输入等等)

操作 windows 程序主要是利用了 windows 的消息机制,用程序向程序发送消息的方式替代人工点击输入操作。那怎么去使用呢?

  1. 找到 windows 的窗体,需要利用 windows 的查找窗口 FindWindowEx 这个 api
  2. 点击按钮的操作,需要使用 PostMessage 这个 windows api
  3. 设置输入文本,需要使用 SendMessage 这个 windows api
  4. 关闭对话框,需要发送 WM_CLOSE 的消息

查找窗体

查找窗体是这个操作很重要的一步,对话框上的按钮、文本框等等都是窗体,都需要使用 FindWindowEx 去进行查找。
只有找到了需要控制的窗体,才能执行下面的控制操作。
参考资料:FindWindowEx

import win32gui
import time

def FindWindow(parent_wid,child_after_wid,class_name,window_name,try_cnt=100):
    openid = 0
    cnt = 0
    while not openid and cnt < try_cnt:
        openid = win32gui.FindWindowEx(parent_wid,child_after_wid,class_name,window_name)
        time.sleep(0.2)
        cnt+=1
    if cnt >= try_cnt:
        print('"%s->%s" not found!' % (class_name,window_name))
    else:
        print('"%s->%s" found!' % (class_name, window_name))
    return openid

操作方法
可以使用 visual studio 的 spy++ 工具来检索窗体的名称,如下为windows

openid = win32gui.FindWindowEx(None,None,None,'windows')

发送消息

发送消息主要涉及 PostMessageSendMessage 这两个发送消息的 api。
其中 PostMessage 为异步发送,发送消息立刻返回。
SendMessage 为同步发送,等到消息被处理才返回。
参考资料:
PostMessage
SendMessage

  1. 点击窗体
    鼠标的点击操作是我们最常用的一个操作,主要是向窗体发送 WM_LBUTTONDOWN 加上 WM_LBUTTONUP 这两个消息来模拟鼠标左键按下和松开的操作。
save_as_wid = FindWindow(None, None,None,'确认另存为',10)
btn_wid = FindWindow(save_as_wid, None,'Button','是(&Y)') if save_as_wid else 0
if btn_wid:
    win32gui.PostMessage(btn_wid, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON,0)
    time.sleep(0.02)
    win32gui.PostMessage(btn_wid, win32con.WM_LBUTTONUP, win32con.MK_LBUTTON,0)
  1. 菜单操作
    菜单操作也算一个鼠标的点击操作,但是却和鼠标操作不太一样。
    要进行菜单操作得知道我们要操作的菜单资源值是多少。

首先要找到窗体,假设窗体名字是 'windows'。
然后在C++源码中找到需要操作的菜单的资源值 45046。
最后向窗体发送 WM_COMMAND 消息,这时就完成了菜单的点击操作。

hid = FindWindow(None, None,None,'windows')
win32api.PostMessage(hid,win32con.WM_COMMAND,45046,0)
  1. 设置文本
    设置文本则是模拟我们往文本框中输入的操作,向文本框窗体发送 WM_SETTEXT 的消息
win32gui.SendMessage(wid, win32con.WM_SETTEXT, None, text)

获取文本

这一部分倒是找了很久才验证成功的,现在已经可以正确地读取文本内容。
主要是从一个窗体中,获取窗体的文本。

def GetWindowText(wid):
    text_length = win32gui.SendMessage(wid, win32con.WM_GETTEXTLENGTH, 0,0) + 1
    buffer = '\0'*text_length
    lpid = id(buffer)
    buf = win32gui.PyGetMemory(lpid,text_length)

    win32gui.SendMessage(wid, win32con.WM_GETTEXT,text_length,buf)
    address, text_length = win32gui.PyGetBufferAddressAndLen(buf)
    buffer = win32gui.PyGetString(address,text_length)

    return buffer

总结

  1. 收获
    有时候一些突发奇想的事情,做了,慢慢地就会发展成一个对自己有用地东西。坚决不忽略自己的想法,每一件事都会默默地成为自己的能力。
    这一次的开发中,让我对 windows 消息机制的理解更进一步了,同时也让我更加地爱上 python。
  2. 想法
    这其实是一个机缘巧合,让我使用python+windows消息的方式生成效率工具。但是这个程序也是有局限性,只能用于windows消息机制的程序,其他机制的程序也许会有其他的方式实现。
    python+windows消息机制的方式也只是临时使用的工具,主要的对象还是不能进行大变更的程序的控制。
    当然最好的方式是重构原程序,向外开放接口,引入软件测试来实现上面所说的功能。

语言只是一个工具,用 python 实现的上述功能其实完全也可以用 C++ 实现
欢迎大家一起交流代码呀

标签:None,MFC,python,WM,windows,wid,窗体,操作
来源: https://www.cnblogs.com/Kyle023/p/15803299.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有