如何利用Python和win32编程避免重复性体力劳动(四)——下拉列表操作:CB_SETCURSEL、CBN_SELENDOK和CBN_SELCHANGE

来源:互联网 发布:淘宝店铺联盟怎么弄 编辑:程序博客网 时间:2024/06/07 02:10

Part 4:控件操作B

至于另存为图片,情况要稍微复杂一点,因为另存为图片的默认选项是BMP,特别不巧,我使用的FaceGen版本保存为BMP有BUG,不能成功保存,所以我们除了定位保存文件的路径以外,还需要对文件类型的下拉组合框(ComboBox进)行操作:

我们假设我们找到了组合框的句柄为CB_handle,我们可以用CB_SETCURSEL消息来更改当前的选项:

  • CB_SETCURSEL 消息
    • 描述:
    • 参数:
      • wParam:以0起始的待选选项的索引;如果该值为-1,将从组合框列表中删除当前选项,并使当前选项为空
      • lParam:未使用。
    • 返回值:
      • 更改选择成功将返回所设置选项的索引号。

只要给组合框发一个CB_SETCURSEL消息,你就会发现下拉列表的选项已经改变了。

这时,只要你点保存,你就会发现,这保存的跟之前的一样啊!根本没有变!

问题在哪里?

我们用鼠标或者键盘操作一下,是没有问题的,一旦更保存类型,保存窗口里的预览也会随之变化。所以,除了CB_SETCURSEL以外,一定还缺了点儿什么。

于是,我们可以调用Spy++的消息机制查看一下手动操作时,我们的下拉组合框发生的事情,好像除了渲染和点击,没有什么特别值得注意的。

那再看看父窗体呢?好像有点儿不太一样的东西:

  • CBN_SELENDOK 通知(notification code)
    • 描述:当用户选择了有效的列表项时发送,提示父窗体处理用户的选择。父窗体通过WM_COMMAND消息接收这个通知。
    • 参数:(作为WM_COMMAND的参数)
      • wParam:LOWORD为组合框的ID. HIWORD为CBN_SELENDOK的值。
      • lParam:组合框的句柄。
  • CBN_SELCHANGE 通知(notification code)
    • 描述:当用户更改了列表项的选择时发送,不论用户是通过鼠标选择或是通过方向键选择都会发送此通知。父窗体通过WM_COMMAND消息接收这个通知。
    • 参数:(作为WM_COMMAND的参数)
      • wParam:LOWORD为组合框的ID. HIWORD为CBN_SELCHANGE的值。
      • lParam:组合框的句柄。
  • 说明:他们是WM_COMMAND消息wParam的high word(wParam的16-31位,详情参见Part 2)的常数之一,在Python中可以用位移操作将其移动到高位上(a<<16),再用加法加上低位的内容。

继续查MSDN的资料,我们发现,对于一个有效的选择,一定会发送这两个通知,发送完CBNSELENDOK以后马上发送CBNSELCHANGE。而且,使用CBSETCURSEL消息时,CBNSELCHANGE通知是不会被送达的!

问题就在这里,加上这两个消息之后,就能正常操作下拉菜单了。完整函数如下

[python] view plain copy
  1.     def save_to_image(self, filePath, format="jpg"):  
  2.         format_dict = {  
  3.             "bmp"0,  # Facegen的Bug导致无法保存bmp  
  4.             "jpg"1,  
  5.             "tga"2,  
  6.             "tif"3,  
  7.         }  
  8.         Mhandle, confirmBTN_handle = self.menu_command('save_to_image')  
  9.         mhandle = find_subHandle(Mhandle, [("DUIViewWndClassName"0), ("DirectUIHWND"0)])  
  10.         EDIT_handle = find_subHandle(mhandle, [("FloatNotifySink"0), ("ComboBox"0), ("Edit"0)])  # 定位保存地址句柄  
  11.         PCB_handle = find_subHandle(mhandle, [("FloatNotifySink"1)])  # 定位下拉菜单父窗体句柄  
  12.         CB_handle = find_subHandle(PCB_handle, [("ComboBox"0)])  # 定位下拉菜单窗体句柄  
  13.         wait_and_assert(EDIT_handle, find_subHandle(mhandle, [("FloatNotifySink"0), ("ComboBox"0), ("Edit"0)]))  
  14.         # 以下3行皆为ComboBox的list中选择格式必要的Message操作  
  15.         if win32api.SendMessage(CB_handle, win32con.CB_SETCURSEL, format_dict[format], 0) == format_dict[format]:  
  16.             win32api.SendMessage(PCB_handle, win32con.WM_COMMAND, 0x90000, CB_handle)  
  17.             win32api.SendMessage(PCB_handle, win32con.WM_COMMAND, 0x10000, CB_handle)  
  18.         else:  
  19.             raise Exception("Change saving type failed")  
  20.         # 填入保存地址,确认  
  21.         if win32api.SendMessage(EDIT_handle, win32con.WM_SETTEXT, 0, os.path.abspath(filePath).encode('gbk')) == 1:  
  22.             return win32api.SendMessage(Mhandle, win32con.WM_COMMAND, 1, confirmBTN_handle)  
  23.         raise Exception("Set file opening path failed")  
阅读全文
0 0
原创粉丝点击