如何利用Python和win32编程避免重复性体力劳动(二)——菜单操作:GetMenu,GetSubMenu,GetMenuItemID以及wParam的HIWORD&LOWORD

来源:互联网 发布:阿里通网络短信 编辑:程序博客网 时间:2024/06/06 09:58

Part 2:菜单操作

有了句柄,我们就可以操作FaceGen了!嗯,要先打开文件,File→Open,然后再File→Save Image(很悲剧,Save Image没有快捷键,所以不得不进行菜单操作)。现在我们有了FindWindow和FindWindowEx,要怎么操作菜单呢?

哦,抱歉,靠他俩还做不到。

窗口的菜单就像窗口的标题栏一样,是窗口自身的一部分,不是其他窗体控件,也就没有办法用FindWindow和FindWindowEx返回句柄。所以要对菜单进行操作的话,我们需要新的函数,也就是GetMenu,GetSubMenu和GetMenuItemID,它们也都属于win32gui模块。怎么用呢,结合下图来说:


  • GetMenu(hwnd)
    • 描述:获取窗口的菜单句柄。
    • 参数:
      • hwnd:整型,需要获取菜单的窗口的句柄。
    • 说明:获取的是插图中黄色的部分。
  • GetSubMenu(hMenu, nPos)
    • 描述:获取菜单的下拉菜单或者子菜单。
    • 参数:
      • hMenu:整型,菜单的句柄,从GetMenu获得。
      • nPos:整型,下拉菜单或子菜单的的索引,从0算起。
    • 说明:这个可以获取插图中蓝色的部分z;如描述所述,这个不仅可以获取本例中的下拉菜单,还可以获取子菜单。
  • GetMenuItemID(hMenu, nPos)
    • 描述:获取菜单中特定项目的标识符。
    • 参数:
      • hMenu:整型,包含所需菜单项的菜单句柄,从GetSubMenu获得。
      • nPos:整型,菜单项的索引,从0算起。
    • 说明:这个获取的就是红色区域中的项目啦,注意,分隔符是被编入索引的,所以Open的索引是2而非1,而Exit的索引是9而非6。

找到这个菜单项的标识符有什么用呢?找到以后我们就可以告诉应用程序:我们要执行这个菜单项的命令!怎么告诉呢?这就要涉及消息机制了,我们要给应用程序发个消息,让它执行所需菜单项的命令。假设之前获取的Open的标识符是open_ID,那么只需要这样:

[python] view plain copy
  1. win32gui.PostMessage(self.Mhandle, win32con.WM_COMMAND, open_ID, 0)  

就会有一个打开文件的对话框出现啦。

解释一下:

  • PostMessage(hWnd, Msg, wParam, lParam)
    • 描述:在消息队列中加入为指定的窗体加入一条消息,并马上返回,不等待线程对消息的处理。
    • 参数:
      • hWnd:整型,接收消息的窗体句柄
      • Msg:整型,要发送的消息,这些消息都是windows预先定义好的,可以参见系统定义消息(System-Defined Messages))
      • wParam:整型,消息的wParam参数
      • lParam:整型,消息的lParam参数
    • 说明:简单说,就是给指定程序发一个消息,这些消息都用整型编好号,作为windows的常量可以查询的。在这里,我们用的就是win32con这个库里定义的WM_COMMAND这个消息,具体的wParam和lParam是根据消息的不同而不同的。具体请根据MSDN查阅。

关于wParam的low word和high word:

    

查阅MSDN的消息时,会发现有的wParam定义了low word和high word,这是什么呢?wParam的定义是32位整型,high word就是他的31至16位,low word是它的15至0位,如图。当参数超过两个,wParam和lParam不够用时,可以将wParam就给拆成两个int16来使用。这种时候在python里记得用把HIWORD的常数向左移16位,再加LOWORD,即wParam = HIWORD<<16+LOWORD。

更新一下我们定义的类,把菜单添加进去:

[python] view plain copy
  1. class FaceGenWindow(object):  
  2.     def __init__(self, fgFilePath=None):  
  3.         self.Mhandle = win32gui.FindWindow("FaceGenMainWinClass"None)  
  4.         self.menu = win32gui.GetMenu(self.Mhandle)  
  5.         self.menu = win32gui.GetSubMenu(self.menu, 0)  
  6.         print "FaceGen initialization compeleted"  
  7.   
  8.   
  9.     # 然后定义一个菜单操作的方法:  
  10.   
  11.   
  12.     def menu_command(self, command):  
  13.         """ 
  14.         菜单操作 
  15.         返回弹出的打开或保存的对话框的句柄 dig_handle 
  16.         返回确定按钮的句柄 confBTN_handle 
  17.         """  
  18.         command_dict = {  # [目录的编号, 打开的窗口名]  
  19.             "open": [2, u"打开"],  
  20.             "save_to_image": [5, u"另存为"],  
  21.         }  
  22.         cmd_ID = win32gui.GetMenuItemID(self.menu, command_dict[command][0])  
  23.         win32gui.PostMessage(self.Mhandle, win32con.WM_COMMAND, cmd_ID, 0)  
  24.         for i in range(10):  
  25.             if win32gui.FindWindow(None, command_dict[command][1]):   
  26.                 break  # 如果找到了打开或者另存为的对话框,就跳出循环  
  27.             else:  
  28.                 win32api.Sleep(200)  # 利用这个函数等待200ms,就不需要再额外导入time模块了  
  29.         dig_handle = win32gui.FindWindow(None, command_dict[command][1])  
  30.         confBTN_handle = win32gui.FindWindowEx(dig_handle, 0"Button"None)  
  31.         return dig_handle, confBTN_handle  

在这里顺便返回了弹出来的对话框的句柄和确定按钮的句柄,后面操作会用到。

阅读全文
0 0