首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在窗口托盘菜单中添加图像

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

Stack Overflow用户
提问于 2017-08-16 22:46:43
回答 3查看 757关注 0票数 19

我正在使用python为windows编写简单的托盘。

我成功地创建了一个托盘图标,菜单,子菜单。我很努力地为特定的托盘项目添加图像。

下面是我使用的代码。(Link)即使是这段代码也不能工作。Windows文档不清楚。

代码语言:javascript
复制
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

谁能帮帮我。

编辑

代码语言:javascript
复制
self.tray = win32gui.CreatePopupMenu()
self.addMenuItem(1, "Open", self.tray)

附加图像。在“打开”旁边的小盒子里,我想要图像来。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-08-26 08:20:19

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

我通过使用PyCDCPyCBitMapwin32ui类而不是handles来实现这一点。

尝试将prep_menu_icon更改为:

代码语言:javascript
复制
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()

我得到了菜单项图标:

票数 9
EN

Stack Overflow用户

发布于 2017-08-21 14:16:23

我似乎不能在我的电脑上设置这个包,所以我不能真正测试它,但是这行

代码语言:javascript
复制
option_icon = self.prep_menu_icon("\print_pref.ico")

这让我有点担心。我不确定您是否正在读取您认为自己正在读取的文件。

\将指示一个转义序列。在Windows上,您需要将这些反斜杠加倍,以防止它们像"\\print_pref.ico"那样被转义。如果您正在尝试加载当前目录中的文件,则可能根本不需要该文件,只需给出文件名- "print_pref.ico"即可。如果您尝试在驱动器的根目录中查找文件,则需要指定驱动器号"C:\\print_pref.ico"

票数 3
EN

Stack Overflow用户

发布于 2017-08-26 00:36:33

将代码行167更改为item, extras = win32gui_struct.PackMENUITEMINFO(text=title,hbmpItem=5,wID=wID),然后您将看到一个关闭图标。

5option_icon构造的MENUITEMINFO没有什么不同。

类型不匹配是我能想到的唯一原因。option_icon的类型是hgdiObjdectMENUITEMINFO.hbmpItem需要一个HBITMAP。应该有一个演员阵容。

奇怪的是,我不认为hbmpitem是一个句柄,它可以被赋值为5,所以它更像是内核中某个表的索引。如果是这样的话,类型应该无关紧要。

讨论handle问题:

你可以尝试所有在MENUITEMINFO中预定义的数字,然后打印item,你会发现数字只是传递到结构中。句柄是某种指针,这个数字不是内存地址,所以它是某种索引。

prep_menu_icon是一个普通C++函数的python版本,它将hcion转换为hbitmap

python版本缺少一些类型转换,因此无法工作。但是GetHandle施展了一些魔法。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45716730

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档