如何利用Python和win32编程避免重复性体力劳动(一)——开始、FindWindow和FindWindowEx

如何利用Python和win32编程避免重复性体力劳动(一)——开始、FindWindow和FindWindowEx本系列文章假设各位看官对python是足够熟悉的,但却不太了解win32编程。嘛。。其实我也没学过win32编程,脸请各位看官随意招呼。需求:最近因为做课题,要把800个FaceGen软件生成的三维面孔保存成图片,以后不排除每一张面孔还要生成某个特质上连续变化的图片。FaceGen以抽取面孔的特征向量来构建面孔,所以保存的文件相当精简,只需要300字节就能无损保存面孔的全部信息。一般的三维

大家好,又见面了,我是你们的朋友全栈君。

本博客正逐步迁移至OrangeCube四次元

请移步至这里以获得更加的排版和阅读体验,谢谢您

本系列文章假设各位看官对python是足够熟悉的,但却不太了解win32编程。

嘛。。其实我也没学过win32编程,脸请各位看官随意招呼。

需求:最近因为做课题,要把800个FaceGen软件生成的三维面孔保存成图片,以后不排除每一张面孔还要生成某个特质上连续变化的图片。FaceGen以抽取面孔的特征向量来构建面孔,所以保存的文件相当精简,只需要300字节就能无损保存面孔的全部信息。一般的三维工具包是没有办法解析FaceGen软件的fg格式的,而他们自己的SDK又死贵死贵的,3K刀貌似。。嘛,自己动手,丰衣足食。

分析:要做的事情其实很简单,fg文件已经都准备好,我只需要用FaceGen打开它的fg文件,然后直接Save to Image就好了。鉴于一系列原因,不是很想用按键精灵之类的东西。何况利用pywin32可以很方便的利用win32的一些接口,何必再去模拟操作。

Part 0: 开始之前?

首先,来这里安装一个Pywin32吧,Pywin32是一个Python库,为python提供访问Windows API的扩展,提供了齐全的windows常量、接口、线程以及COM机制等等。安装后自带一个pythonwin的IDE。或者也可以来这边下载一个ActivePython,整合了pywin32和一些其他的库以及一大堆的支持文档,他们的文档查起来是非常方便的。当然了,WIN32的一些相关函数在MSDN上也能直接找到。

其次,为了方面查找目标窗口的句柄,可以下载一个微软自家的Spy++,这玩意儿满大街都是。有了它,还能很方便的查看窗体的消息。

句柄是一个32位整数,在windows中标记对象用,类似一个dict中的key,详情参看这篇文章

消息是windows应用的重要部分,用来告诉窗体“发生了什么”,比如给一个按钮发送BN_CLICKED这么个消息,按钮就知道“哦,我被点了”,才能执行相应的下一步操作。本文将大量使用消息机制。详情参看这篇文章

Part 1: 查找窗体句柄

貌似在win32编程的世界里,包括窗口到文本框的所有控件就是窗体,所有的窗体都有独立的句柄。要操作任意一个窗体,你都需要找到这个窗体的句柄,这里,我们就可以用到FindWindow函数和FindWindowEx函数。在pywin32中,他们都属于win32gui的模块。

  • FindWindow(lpClassName=None, lpWindowName=None):
    • 描述:自顶层窗口(也就是桌面)开始搜索条件匹配的窗体,并返回这个窗体的句柄。不搜索子窗口、不区分大小写。找不到就返回0
    • 参数:
      • lpClassName:字符型,是窗体的类名,这个可以在Spy++里找到。
      • lpWindowName:字符型,是窗口名,也就是标题栏上你能看见的那个标题。
    • 说明:这个函数我们仅能用来找主窗口。
  • FindWindowEx(hwndParent=0, hwndChildAfter=0, lpszClass=None, lpszWindow=None);
    • 描述:搜索类名和窗体名匹配的窗体,并返回这个窗体的句柄。不区分大小写,找不到就返回0。
    • 参数:
      • hwndParent:若不为0,则搜索句柄为hwndParent窗体的子窗体。
      • hwndChildAfter:若不为0,则按照z-index的顺序从hwndChildAfter向后开始搜索子窗体,否则从第一个子窗体开始搜索。
      • lpClassName:字符型,是窗体的类名,这个可以在Spy++里找到。
      • lpWindowName:字符型,是窗口名,也就是标题栏上你能看见的那个标题。
    • 说明:找到了主窗口以后就靠它来定位子窗体啦。

有了这两个函数,我们就可以写出可以定义到任意一个窗体句柄的函数啦:

def find_idxSubHandle(pHandle, winClass, index=0):
    """
    已知子窗口的窗体类名
    寻找第index号个同类型的兄弟窗口
    """
    assert type(index) == int and index >= 0
    handle = win32gui.FindWindowEx(pHandle, 0, winClass, None)
    while index > 0:
        handle = win32gui.FindWindowEx(pHandle, handle, winClass, None)
        index -= 1
    return handle


def find_subHandle(pHandle, winClassList):
    """
    递归寻找子窗口的句柄
    pHandle是祖父窗口的句柄
    winClassList是各个子窗口的class列表,父辈的list-index小于子辈
    """
    assert type(winClassList) == list
    if len(winClassList) == 1:
        return find_idxSubHandle(pHandle, winClassList[0][0], winClassList[0][1])
    else:
        pHandle = find_idxSubHandle(pHandle, winClassList[0][0], winClassList[0][1])
        return find_subHandle(pHandle, winClassList[1:])

这样在后续的调用中,我们就能使用我们定义的finde_subHandle来方便地找到某个特定的Edit窗体控件。

比如我们定义一个FaceGenWindow的类:

class FaceGenWindow(object):
    def __init__(self, fgFilePath=None):
        self.Mhandle = win32gui.FindWindow("FaceGenMainWinClass", None)
        print "FaceGen initialization compeleted"

实体化以后就可以很方便地在类的方法中调用find_subHandle函数来找到FaceGenWindow的子窗体了,比如某个Edit控件:

handle = find_subHandle(self.Mhandle, [("ComboBoxEx32", 1), ("ComboBox", 0), ("Edit", 0)])

另外,python中找回来的句柄都是十进制整型,Spy++里显示的都是十六进制整型,这个要注意下,调试的时候用十六进制输出句柄,如下:

print "%x" % (handle)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/138400.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 字符串正则匹配leetcode_动态规划100题

    字符串正则匹配leetcode_动态规划100题原题链接给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。‘.’ 匹配任意单个字符‘*’ 匹配零个或多个前面的那一个元素所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。示例 1:输入:s = “aa” p = “a”输出:false解释:”a” 无法匹配 “aa” 整个字符串。示例 2:输入:s = “aa” p = “a*”输出:true解释:因为 ‘*’ 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是

    2022年8月9日
    3
  • iPhone的屏幕尺寸和分辨率

    iPhone的屏幕尺寸和分辨率设计原型时,使用低分辨率的就可以。最终用户界面才使用高分辨率的,以适应苹果Retina屏的显示。iPhone4做原型时,可以用320*480,iPhone5做原型时,可以用320*568,iPhone6做原型时,可以用375*667,iPhone6Plus原型,可以用414×736, 参考链接:http://www.zhihu.com/question/2

    2022年5月14日
    41
  • centos7中firewall防火墙详解和配置_centos8 防火墙

    centos7中firewall防火墙详解和配置_centos8 防火墙一、ipset概述ipset与iptableiptables是在Linux内核中配置防火墙规则的用户空间工具。在内核版本更新到2.4以来,iptable一直作为系统中主要的防火墙解决方案。CentOS7将原来的iptable替换为firewall,而firewall提供了对ipset的支持。ipset相当于iptable的扩展,它和iptable处理方式,iptable通过链表…

    2022年9月27日
    0
  • 详解Element.scrollIntoView()

    详解Element.scrollIntoView()Element.scrollIntoView()方法让当前的元素滚动到浏览器窗口的可视区域内。语法element.scrollIntoView();//等同于element.scrollIntoView(true)element.scrollIntoView(alignToTop);//Boolean型参数element.scrollIntoView(scrollIntoViewOptions);//Object型参数参数alignToTop可选一个Boolean值

    2022年6月18日
    33
  • 微机原理与接口技术重要的知识点总结_微机原理与接口技术戴胜华

    微机原理与接口技术重要的知识点总结_微机原理与接口技术戴胜华概述8086有16位寄存器和16位外部数据总线,具有20位地址总线,可寻址1MB地址空间80286提供了24位基地址Intel80386处理器是IA-32结构系列中的第一个32位处理器。该处理器有32位地址总线,能支持多至4GB的物理存储器,把分页引进了IA-32结构,并行操作,分页就是一种保护模式80486在IA-32处理器的芯片中引入了缓存,也是第一次把x87FPU(浮点处理…

    2022年10月2日
    0
  • apache 负载均衡_apache部署

    apache 负载均衡_apache部署[1]Apache负载均衡设置方法mod_proxy使用介绍一般来说,负载均衡就是将客户端的请求分流给后端的各个真实服务器,达到负载均衡的目的。还有一种方式是用两台服务器,一台作为主服务器(Master),另一台作为热备份(HotStandby),请求全部分给主服务器,在主服务器当机时,立即切换到备份服务器,以提高系统的整体可 第一次看到这个标题时我也很惊讶,Apache居然还能做负载

    2022年9月9日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号