设为首页 收藏本站
查看: 1915|回复: 0

[经验分享] Python and Menu[编程点滴1]

[复制链接]

尚未签到

发表于 2015-4-20 12:18:02 | 显示全部楼层 |阅读模式
  拿这篇文章除除草...
  问题:写程序模拟人操作电脑,在桌面新建text文件.
  求解过程:
  大概思路就是鼠标在桌面进行右键点击,通过弹出的PopupMenu来新建text文件,写入数据并保存.
  1,首先,要保证鼠标在桌面上,而不是被其他窗口遮挡,这样邮件点击才会弹出正确的菜单,那么如果我们原意的话可以让程序把其他窗口的进程都kill掉,
  但还是不要了,因为这没太大意义,也不能展现什么技术点.由我们来保证现在鼠标已经在桌面上,而且不是在某个图标上.
  2,让鼠标进行右键点击,弹出Popup菜单.
  对于Windows相关对象的操作,基本可以由pywin32中的库来实现.
  调用mouse_event可以在某个点出发鼠标点击,即按下右键,然后弹起
  但是必须要正确的设置dwFlags,才能将dx,dy当做cursor的绝对位置来使用.
  3,在弹出的菜单中单击[新建(&W)]菜单项,然后会弹出一个二级的PopupMenu,点击[文本文档]菜单项.
  菜单窗口的类名是"#32768",其他的用数字标识类名的还有"#32769"(桌面窗口), "#32770"(对话框窗口)等.
  调用FindWindow就可以获得当前处于焦点的菜单窗口的句柄,
  但是通过窗口句柄是不能操作菜单的,我们需要的是一个菜单的句柄,那么首先被考虑的就是GetMenu,
  参考msdn中对GetMenu的Remarks我们就会发现GetMenu对于Popup菜单是不起作用的,
  一个有效的方法是发送一个要求获取菜单句柄的消息MN_GETHMENU,
  获得hmenu之后, 就可以获得第i个菜单项的坐标,剩下的就是点击了.
  如果想让程序兼容性更好一点的话,我们会考虑通过菜单项内容中的文字来找到某个菜单项(比如[文本文档]),而不是通过index,
  因为随着某些软件(比如git)的安装,桌面的PopupMenu会被修改(会增加一些新项目),原来确定的index就可能变得无效.调用GetMenuItemInfo可以获得菜单项的全部信息,
  然后拿相应菜单的text来比对,就可以确定哪一个是需要点击的菜单项.
  但这又会引入另一个问题,GetMenuItemInfo的参数中LPMENUITEMINFO要求一个结构体的指针.
  在python目前的库中的GetMenuItemInfo实现的也是,而python内建的机制中不支持指针,所以必须通过C的方法来实现.
  可以通过ctypes库中的函数来自行实现这个结构体并生成指针,或者是调用一个现成的库win32gui_struct(helpers for working with various win32gui structures).
  4,随着3中第二次鼠标点击,桌面出现一个新建的text文件,可以立即编辑文件的名字,keybd_event可以来发送按键消息,编辑完名字之后,回车,现在我们已经让程序自动新建了一个text文件.
  5当然我们还可以编辑一下这个文件,刚刚好,文件目前还处于选中状态,回车一下,text文件就会打开,写入我们想要的内容,然后Save一下,关闭文件,就这么简单.
  下面是一段不负责任的代码,不保证兼容性,但相信对你会有帮助:
  



  1 # coding = utf-8
  2 import win32gui
  3 import win32api
  4 import os, win32process
  5 import win32com.client
  6 import win32con
  7 import winnt
  8 import time
  9 import shutil
10 from time import sleep
11 import os
12 import os.path
13 import random
14 import subprocess
15 import win32clipboard
16 import platform
17 import win32gui_struct
18 import struct
19 import array
20
21 ########################################################################################
22 #函数功能:在x,y(屏幕坐标)处点击鼠标,button控制是左键还是邮件
23 #参数:x,y--屏幕坐标,button--鼠标的左键或右键
24 #备注:其中,cx,cy是我的屏幕的长和宽,按(0-65536)的比例在映射一下x,y的虚拟位置
25 ########################################################################################
26 def MouseClick(x, y, button = "LEFT"):
27     SCREENRANGE = 65536
28     cx = 1366
29     cy = 768
30     x = x * SCREENRANGE / cx
31     y = y * SCREENRANGE / cy
32
33     if "RIGHT" == button:
34         win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTDOWN + win32con.MOUSEEVENTF_ABSOLUTE + win32con.MOUSEEVENTF_MOVE, x, y)
35         win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTUP + win32con.MOUSEEVENTF_ABSOLUTE + win32con.MOUSEEVENTF_MOVE, x, y)
36     else:
37         win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN + win32con.MOUSEEVENTF_ABSOLUTE + win32con.MOUSEEVENTF_MOVE, x, y)
38         win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP + win32con.MOUSEEVENTF_ABSOLUTE + win32con.MOUSEEVENTF_MOVE, x, y)
39
40 ########################################################################################
41 #函数功能:模拟鼠标移动到当前处于焦点的Popup菜单的某一项
42 #参数:idx--菜单项的序号
43 #备注:MN_GETHMENU = 0x01E1 这个消息在win32con中没有,自己定义了一下,见msdn
44 #备注2:菜单中有separator,不要漏数
45 ########################################################################################
46 def MouseHoverMenuItem(idx):
47     hwnd = win32gui.FindWindow("#32768", None)
48     MN_GETHMENU = 0x01E1
49     hmenu = win32gui.SendMessage(hwnd, MN_GETHMENU, 0, 0)
50     icount = win32gui.GetMenuItemCount(hmenu)
51     if idx < 0:
52         idx += icount
53     rect = win32gui.GetMenuItemRect(hwnd, hmenu, idx)[1]
54     x = (rect[2] - rect[0]) / 2 + rect[0]
55     y = (rect[3] - rect[1]) / 2 + rect[1]
56     DesktopCommon.MouseTo(x, y)
57
58 ########################################################################################
59 #函数功能:模拟鼠标点击当前处于焦点的Popup菜单的某一项
60 #参数:idx--菜单项的序号,button -- "LEFT", "RIGHT" 点击鼠标的左键或是右键
61 #备注:MN_GETHMENU = 0x01E1 这个消息在win32con中没有,自己定义了一下,见msdn
62 ########################################################################################
63 def ClickOnMenuItem(idx, button = "LEFT"):
64     hwnd = win32gui.FindWindow("#32768", None)
65     MN_GETHMENU = 0x01E1
66     hmenu = win32gui.SendMessage(hwnd, MN_GETHMENU, 0, 0)
67     icount = win32gui.GetMenuItemCount(hmenu)
68     if idx < 0:
69         idx += icount
70     rect = win32gui.GetMenuItemRect(hwnd, hmenu, idx)[1]
71     x = (rect[2] - rect[0]) / 2 + rect[0]
72     y = (rect[3] - rect[1]) / 2 + rect[1]
73
74     MouseClick(x, y, button)
75 ########################################################################################
76 #函数功能:点击菜单中文字内容为text的菜单项
77 #参数:text--要点击的菜单的内容, button -- 点击左键还是右键
78 #返回值:如果成功点击,则返回True,否则False
79 ########################################################################################
80 def ClickOnMenuItemByText(text, button = "LEFT"):
81     hwnd = win32gui.FindWindow("#32768", None)
82     MN_GETHMENU = 0x01E1
83     hmenu = win32gui.SendMessage(hwnd, MN_GETHMENU, 0, 0)
84     icount = win32gui.GetMenuItemCount(hmenu)
85     for i in xrange(icount):
86         t = GetMenuItemString(i).decode("gbk").encode("UTF-8")
87         #        print text, t
88         if text == t:
89             rect = rect = win32gui.GetMenuItemRect(hwnd, hmenu, i)[1]
90             x = (rect[2] - rect[0]) / 2 + rect[0]
91             y = (rect[3] - rect[1]) / 2 + rect[1]
92             MouseClick(x, y, button)
93             return True
94
95     return False
96 ########################################################################################
97 #函数功能:通过下标获得某个菜单项的内容文本
98 #参数:idx要操作的菜单项的index
99 #返回值:获得的菜单项的内容的文本
100 ########################################################################################
101 def GetMenuItemString(idx):
102     hwnd = win32gui.FindWindow("#32768", None)
103     MN_GETHMENU = 0x01E1
104     hmenu = win32gui.SendMessage(hwnd, MN_GETHMENU, 0, 0)
105     mii, extra = win32gui_struct.EmptyMENUITEMINFO()
106     win32gui.GetMenuItemInfo(hmenu, idx, True, mii)
107     fType, fState, wID, hSubMenu, hbmpChecked, hbmpUnchecked,\
108     dwItemData, text, hbmpItem = win32gui_struct.UnpackMENUITEMINFO(mii)
109     print text
110     return text
111
112 ########################################################################################
113 #函数功能:获得菜单中的菜单项的个数
114 #函数返回:菜单项的个数
115 ########################################################################################
116 def GetMenuItemCount():
117     hwnd = win32gui.FindWindow("#32768", None)
118     MN_GETHMENU = 0x01E1
119     hmenu = win32gui.SendMessage(hwnd, MN_GETHMENU, 0, 0)
120     icount = win32gui.GetMenuItemCount(hmenu)
121     return icount
122
123 if __name__ == '__main__':
124     #sleep几秒,可以有反应时间
125     sleep(6)
126     hwnd = win32gui.GetDesktopWindow()
127     rect = win32gui.GetWindowRect(hwnd)
128     x = rect[0] + (rect[2] - rect[0]) * 2 / 3
129     y = rect[1] + (rect[3] - rect[1]) * 2 / 3
130     MouseClick(x, y, "RIGHT")
131     sleep(2)
132     ClickOnMenuItemByText("新建(&W)")
133     sleep(2)
134     ClickOnMenuItemByText("文本文档")
135     sleep(2)
136     keymap = {'j': 0x4A, 'a': 0x41, 'c': 0x43, 'k': 0x4B, 'i': 0x49, 'e': 0x45, '\n': win32con.VK_RETURN}
137     for key in 'jackie\n':
138         win32api.keybd_event(keymap[key], 0, 0, 0)
139         win32api.keybd_event(keymap[key], 0, win32con.KEYEVENTF_KEYUP, 0)
140         sleep(1)
141         #end

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-58853-1-1.html 上篇帖子: 朴素贝叶斯算法的python实现 下篇帖子: python 模拟登录博客园并且自动发布一篇文章
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表