在窗口托盘菜单中添加图像

时间:2017-08-16 14:46:43

标签: python windows win32gui systray

我正在使用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"旁边的小盒子里。我想要图像来。 enter image description here

3 个答案:

答案 0 :(得分:9)

针对可能不会导致错误的类型的句柄存在问题。

我使用win32ui类({1}}和PyCDC代替句柄来完成此工作。

尝试将PyCBitMap更改为:

prep_menu_icon

我得到菜单项图标:

Popup menu with icons

答案 1 :(得分:3)

我似乎无法在我的计算机上设置软件包,所以无法真正测试这一点,但这一行

option_icon = self.prep_menu_icon("\print_pref.ico")

给了我一些担忧。我不确定你是否正在阅读你认为自己的文件。

\表示转义序列。在Windows上,您需要将这些反斜杠加倍,以防止它们像"\\print_pref.ico"一样进行转义。如果您尝试在当前目录中加载文件,则可能根本不需要它,只能提供文件名 - "print_pref.ico"。如果您尝试在驱动器的根目录中找到文件,则需要提供驱动器号"C:\\print_pref.ico"

答案 2 :(得分:2)

将代码行167更改为item, extras = win32gui_struct.PackMENUITEMINFO(text=title,hbmpItem=5,wID=wID),然后您会找到一个关闭图标。 但MENUITEMINFO5构建的option_icon之间没有区别。

类型不匹配是我可以成像的唯一原因。option_icon的类型是hgdiObjdect,而MENUITEMINFO.hbmpItem需要HBITMAP。应该有一个演员。

这很奇怪,我不认为hbmpitem是一个句柄,它可以分配给5,所以它更像是kernel.if中某个表的索引,因此类型无关紧要。

讨论handle问题:

你可以尝试MENUITEMINFO中预定义的所有数字,然后打印item,你会发现数字只是传入struct.and一个句柄是某种指针,这个数字是不是记忆地址。所以它是某种索引。

prep_menu_icon是普通C ++函数的python版本,它将hcion转换为hbitmap。 python版本缺少一些类型转换,但它不起作用。但是GetHandle做了一些魔术。