Добавить изображение в меню лотка окна
Я пишу простой лоток для Windows, используя python.
Мне удалось создать иконку в трее, меню, подменю. Я добавил, что добавляю изображение для определенного элемента лотка.
вот код, который я использовал. (Ссылка) Даже этот код не работал. Документация 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
Может кто-то мне помочь.
Edit
self.tray = win32gui.CreatePopupMenu()
self.addMenuItem(1, "Open", self.tray)
Присоединение изображения. В маленькой коробке рядом с "Open" я хочу, чтобы изображение пришло.
![введите описание изображения здесь]()
Ответы
Ответ 1
Существуют проблемы с ручками против типов, которые могут не приводить к ошибкам.
Я получил эту работу, используя классы 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()
И я получаю иконки пунктов меню:
![Всплывающее меню с значками]()
Ответ 2
Я не могу получить пакет, настроенный на моем компьютере, поэтому не могу проверить это, но эта строка
option_icon = self.prep_menu_icon("\print_pref.ico")
вызывает некоторую озабоченность. Я не уверен, читаете ли вы файл, который, по вашему мнению, вы есть.
То, что \
будет указывать escape-последовательность. В Windows вам нужно удвоить эти обратные косые черты, чтобы предотвратить их экранирование как "\\print_pref.ico"
. Если вы пытаетесь загрузить файл в текущем каталоге, вам может и не понадобиться это, и он может просто указать имя файла - "print_pref.ico"
. Если вы пытаетесь найти файл в корневом каталоге диска, вам нужно указать букву диска "C:\\print_pref.ico"
.
Ответ 3
Измените строку кода 167 на item, extras = win32gui_struct.PackMENUITEMINFO(text=title,hbmpItem=5,wID=wID)
, после чего вы найдете значок закрытия.
Но между MENUITEMINFO
, построенным с помощью 5
и option_icon
, нет никакого различия.
Несоответствие типов - единственная причина, по которой я могу сделать изображение. Тип option_icon
равен hgdiObjdect
, а MENUITEMINFO.hbmpItem
требуется HBITMAP
. Там должны быть литые.
Это странно, я не думаю, что hbmpitem
- это дескриптор, его можно назначить на 5, поэтому он больше похож на индекс некоторой таблицы в kernel.if, так что тип не имеет значения.
Обсудите проблему handle
:
вы можете попробовать все число, предварительно заданное в MENUITEMINFO
, затем распечатать item
, вы увидите, что номер просто перейдет в struct.and дескриптор - это своего рода указатель, этот номер не является адресом памяти. Так что это какой-то индекс.
prep_menu_icon
представляет собой версию на языке python нормальной функции С++, которая переводит hcion
в HBITMAP
.
в версии python отсутствует некоторый тип приведения, и он не работает. Но тогда GetHandle
выполните некоторую магию.