我正在为使用python的Windows编写简单的托盘。
我成功地创build了一个托盘图标,菜单,子菜单。 我stucked添加特定托盘项目的图像。
这里是我使用的代码。 ( 链接 )即使这个代码没有工作。 Windows文档不清楚。
def addMenuItem(self, wID, title, menu): path = os.path.dirname(os.path.abspath(__file__)) path += "\print_pref.ico" option_icon = self.prep_menu_icon(path) item, extras = win32gui_struct.PackMENUITEMINFO(text=title, hbmpItem=option_icon, wID=wID) win32gui.InsertMenuItem(menu, 0, 1, item) def prep_menu_icon(self, icon): # First load the icon. ico_x = win32api.GetSystemMetrics(win32con.SM_CXSMICON) ico_y = win32api.GetSystemMetrics(win32con.SM_CYSMICON) hicon = win32gui.LoadImage(0, icon, win32con.IMAGE_ICON, ico_x, ico_y, win32con.LR_LOADFROMFILE) hdcBitmap = win32gui.CreateCompatibleDC(0) hdcScreen = win32gui.GetDC(0) hbm = win32gui.CreateCompatibleBitmap(hdcScreen, ico_x, ico_y) hbmOld = win32gui.SelectObject(hdcBitmap, hbm) # Fill the background. brush = win32gui.GetSysColorBrush(win32con.COLOR_MENU) win32gui.FillRect(hdcBitmap, (0, 0, 16, 16), brush) # unclear if brush needs to be feed. Best clue I can find is: # "GetSysColorBrush returns a cached brush instead of allocating a new # one." - implies no DeleteObject # draw the icon win32gui.DrawIconEx(hdcBitmap, 0, 0, hicon, ico_x, ico_y, 0, 0, win32con.DI_NORMAL) win32gui.SelectObject(hdcBitmap, hbmOld) win32gui.DeleteDC(hdcBitmap) return hbm
有人能帮我吗。
编辑
self.tray = win32gui.CreatePopupMenu() self.addMenuItem(1, "Open", self.tray)
附上图像。 在“打开”旁边的小方框里,我想要图像来。
对可能不会导致错误的类型的句柄存在问题。
我通过使用像PyCDC
和PyCBitMap
的win32ui
类而不是句柄来得到这个工作。
尝试将prep_menu_icon
更改为:
def prep_menu_icon(self, icon): # First load the icon. ico_x = win32api.GetSystemMetrics(win32con.SM_CXSMICON) ico_y = win32api.GetSystemMetrics(win32con.SM_CYSMICON) hIcon = win32gui.LoadImage(0, icon, win32con.IMAGE_ICON, ico_x, ico_y, win32con.LR_LOADFROMFILE) hwndDC = win32gui.GetWindowDC(self.hwnd) dc = win32ui.CreateDCFromHandle(hwndDC) memDC = dc.CreateCompatibleDC() iconBitmap = win32ui.CreateBitmap() iconBitmap.CreateCompatibleBitmap(dc, ico_x, ico_y) oldBmp = memDC.SelectObject(iconBitmap) brush = win32gui.GetSysColorBrush(win32con.COLOR_MENU) win32gui.FillRect(memDC.GetSafeHdc(), (0, 0, ico_x, ico_y), brush) win32gui.DrawIconEx(memDC.GetSafeHdc(), 0, 0, hIcon, ico_x, ico_y, 0, 0, win32con.DI_NORMAL) memDC.SelectObject(oldBmp) memDC.DeleteDC() win32gui.ReleaseDC(self.hwnd, hwndDC) return iconBitmap.GetHandle()
我得到菜单项图标:
我似乎无法得到在我的电脑上设置的软件包,所以不能真正测试这个,但这一行
option_icon = self.prep_menu_icon("\print_pref.ico")
给我一些关心。 我不确定你是否正在阅读你认为是你的文件。
这\
将表明一个转义序列。 在Windows上,您需要将这些反斜杠加倍以防止它们像"\\print_pref.ico"
一样被转义。 如果您正在尝试在当前目录中加载文件,则可能完全不需要,只需提供文件名"print_pref.ico"
。 如果您试图在驱动器的根目录中找到文件,则需要提供驱动器盘符"C:\\print_pref.ico"
。
将代码行167更改为item, extras = win32gui_struct.PackMENUITEMINFO(text=title,hbmpItem=5,wID=wID)
,然后您将找到一个关闭图标。 但是由5
和option_icon
构造的MENUITEMINFO
没有区别。
类型不匹配是我可以成像的唯一原因。option_icon的类型是hgdiObjdect
,而MENUITEMINFO.hbmpItem
需要一个HBITMAP
。应该有一个转换。
这很奇怪,我不认为hbmpitem
是一个句柄,它可以被分配到5,所以它更像是内核中的某个表的索引。如果这样的话,类型应该不重要。
handle
问题: 您可以尝试MENUITEMINFO
预定义的所有数字,然后打印该item
,您会发现该数字只是传递给struct.and一个句柄是某种指针,这个数字不是内存地址。所以它是某种索引。
prep_menu_icon
是一个正常的C ++函数的python版本, hcion
hbitmap
转换为hbitmap
。 python版本缺少一些类型GetHandle
,它不起作用,但是GetHandle
做了一些魔术。