ventana - insertar imagen en python
Añadir imagen en el menú de la bandeja de la ventana (3)
Estoy escribiendo una bandeja simple para windows usando python.
Logré crear un icono de bandeja, menú, submenú. Me quedé atascado al agregar la imagen para un elemento de la bandeja en particular.
Aquí está el código que utilicé. ( Link ) Incluso este código no funcionó. La documentación de Windows no está clara.
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
Alguien me puede ayudar.
Editar
self.tray = win32gui.CreatePopupMenu()
self.addMenuItem(1, "Open", self.tray)
Adjuntando imagen. En una pequeña casilla junto a "Abrir" quiero que venga la imagen.
Cambie la línea de código 167 a item, extras = win32gui_struct.PackMENUITEMINFO(text=title,hbmpItem=5,wID=wID)
, luego encontrará un icono de cierre. Pero no hay diferencia entre los MENUITEMINFO
s construidos por 5
y option_icon
.
La falta de coincidencia de tipos es la única razón por la que puedo crear una imagen. El tipo de option_icon
es hgdiObjdect
, y el MENUITEMINFO.hbmpItem
requiere un HBITMAP
. Deben haber una conversión.
Es raro, no creo que hbmpitem
sea un manejador, puede asignarse a 5, por lo que es más como un índice de alguna tabla en el kernel.if que el tipo no debería importar.
Discuta sobre el problema de la handle
:
puede probar todos los números predefinidos en el MENUITEMINFO
, luego imprimir el item
, encontrará el número que acaba de pasar a la estructura y un identificador es algún tipo de puntero, este número no es una dirección de Memoria. Así que es un tipo de índice .
prep_menu_icon
es una versión de python de una función normal de C ++ que traduce el hcion
a hbitmap
. la versión de Python carece de algún tipo de cast, y no funciona. Pero GetHandle
hace algo de magia.
Hay problemas con los controladores de tipos que pueden no producir errores.
Conseguí este trabajo utilizando las clases de PyCDC
como PyCDC
y PyCBitMap
lugar de manejadores.
Intenta cambiar prep_menu_icon
a esto:
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()
Y obtengo los íconos del menú:
Parece que no puedo configurar el paquete en mi computadora, así que realmente no puedo probar esto, pero esta línea
option_icon = self.prep_menu_icon("/print_pref.ico")
me da alguna preocupacion No estoy seguro si estás leyendo el archivo que crees que eres.
Eso va a indicar una secuencia de escape. En Windows, necesita doblar esas barras invertidas para evitar que se escapen como "//print_pref.ico"
. Si está intentando cargar un archivo en el directorio actual, es posible que no lo necesite en absoluto y solo puede dar el nombre del archivo "print_pref.ico"
. Si está intentando localizar un archivo en el directorio raíz de la unidad, debe indicar la letra de la unidad "C://print_pref.ico"
.