在 window 托盘菜单中添加图像
Add image in window tray menu
我正在使用 python 为 windows 编写简单托盘。
我成功创建了托盘图标、菜单、子菜单。我坚持为特定托盘项目添加图像。
这是我使用的代码。 (Link) 即使这段代码也不起作用。 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)
附上图片。在 "Open" 旁边的小方框里,我想要图像。
我似乎无法在我的计算机上设置程序包,所以无法真正测试它,但是这一行
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,所以更像是内核中某个table的索引。如果是这样的话,类型应该无关紧要。
讨论 handle
问题:
你可以尝试在MENUITEMINFO
中预定义的所有数字,然后打印item
,你会发现数字只是传递给结构。而句柄是某种指针,这个数字不是内存地址,所以它是某种索引。
prep_menu_icon
是普通 C++ 函数的 python 版本,它将 hcion
转换为 hbitmap
。
python 版本缺少一些类型转换,因此不起作用。但是 GetHandle
做了一些魔术。
针对可能不会导致错误的类型的句柄存在问题。
我通过使用 win32ui
类 之类的 PyCDC
和 PyCBitMap
而不是句柄来完成这项工作。
尝试将 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()
我得到了菜单项图标:
我正在使用 python 为 windows 编写简单托盘。
我成功创建了托盘图标、菜单、子菜单。我坚持为特定托盘项目添加图像。
这是我使用的代码。 (Link) 即使这段代码也不起作用。 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)
附上图片。在 "Open" 旁边的小方框里,我想要图像。
我似乎无法在我的计算机上设置程序包,所以无法真正测试它,但是这一行
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,所以更像是内核中某个table的索引。如果是这样的话,类型应该无关紧要。
讨论 handle
问题:
你可以尝试在MENUITEMINFO
中预定义的所有数字,然后打印item
,你会发现数字只是传递给结构。而句柄是某种指针,这个数字不是内存地址,所以它是某种索引。
prep_menu_icon
是普通 C++ 函数的 python 版本,它将 hcion
转换为 hbitmap
。
python 版本缺少一些类型转换,因此不起作用。但是 GetHandle
做了一些魔术。
针对可能不会导致错误的类型的句柄存在问题。
我通过使用 win32ui
类 之类的 PyCDC
和 PyCBitMap
而不是句柄来完成这项工作。
尝试将 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()
我得到了菜单项图标: