Code: Select all
MN_GETHMENU = 0x01E1
def set_menu_background_color(event):
hwnd = ctypes.windll.user32.FindWindowW("#32768", None)
hmenu = ctypes.windll.user32.SendMessageW(hwnd, MN_GETHMENU, 0, 0)
# Set the menu background color using SetMenuInfo()
menu.bind("", set_menu_background_color)
Stellt tk tatsächlich das HMENU eines Menüs zur Verfügung? Wenn ja, wie kann ich es bekommen?
Bearbeiten: Ich weiß, dass Sie GetMenu verwenden können, aber das funktioniert nur, wenn das Menü als Menüleiste eines bestimmten Fensters festgelegt ist. Ich glaube nicht, dass ich diese Funktion verwenden kann, da laut der tk-Menüdokumentation ein Klon des Menüs erstellt wird, wenn ein Menü als Menüleiste für ein Fenster der obersten Ebene festgelegt wird. Wenn ich also vorübergehend das HMENU des Menüs, dessen HMENU ich erhalten möchte, als Menüleiste festlege, sein HMENU mit GetMenu erhalte und dann das Menü der ursprünglichen Menüleiste wiederherstelle/entferne, wird nur das HMENU für das geklonte Menü zurückgegeben.
Während GetMenu für das Menü der Menüleiste funktioniert, benötige ich eine Möglichkeit, irgendwie an das HMENU eines Menüs zu gelangen, das ich beispielsweise manuell posten oder für ein Menubutton-Widget verwenden werde, ohne es anzuzeigen Suchen Sie zuerst das Popup-Fenster und senden Sie ihm dann eine Nachricht, um das HMENU des zugehörigen Menüs abzurufen.
Minimales, reproduzierbares Beispiel:
Code: Select all
import tkinter as tk, ctypes
root = tk.Tk()
menu = tk.Menu(tearoff = False)
menu.add_command(label = "Item 1")
menu.add_command(label = "Item 2")
menu.add_command(label = "Item 3")
root.bind("", lambda event: menu.post(root.winfo_pointerx(), root.winfo_pointery()))
# I want to get the HMENU of the 'menu' tk Menu.
root.update()
print(menu.winfo_id()) # Prints the HWND of an invisible window created with the menu
print(ctypes.windll.user32.GetParent(menu.winfo_id())) # Prints 0
# GetMenu() can only be used to get the HMENU of the menu bar's menu
# If we try this:
root.configure(menu = menu)
hwnd = ctypes.windll.user32.GetParent(root.winfo_id())
hmenu = ctypes.windll.user32.GetMenu(hwnd)
print("Menu bar menu's HMENU:", hmenu)
# We will obtain the HMENU of the menu bar's menu which is NOT the same
# as the original menu's HMENU
# The menu bar's menu is a cloned version of our `menu`, which will update
# every time we update our `menu`, as stated in the tk docs:
# https://www.tcl-lang.org/man/tcl8.6/TkCmd/menu.htm#M22
# However, we can get the HMENU of a menu if the menu is displayed, try to find
# the popup window of the menu and only then get its HMENU by sending a message
# to its popup window
MN_GETHMENU = 0x01E1
def print_visible_menu_hmenu(event):
hwnd = ctypes.windll.user32.FindWindowW("#32768", None)
hmenu = ctypes.windll.user32.SendMessageW(hwnd, MN_GETHMENU, 0, 0)
print("Actual menu's HMENU:", hmenu)
menu.bind("", print_visible_menu_hmenu) # `set_menu_background_color` will be called every time the menu is displayed (and when the selected item changes)
# But there will be a short delay when changing the menu's background color
# using SetMenuInfo(), since we need to find the menu's popup window and only
# then we will have the menu's HMENU, after the menu was displayed
# I need to find a way to get the actual menu's HMENU (the last printed result) without
# showing the menu, but I don't see a way tk somehow exposes it (or if tk even exposes it)
root.mainloop()
Code: Select all
3933734
0
Menu bar menu's HMENU: 15730469
Actual menu's HMENU: 24970897
Mobile version