Holen Sie sich das HMENU eines tk-Menüs unter WindowsPython

Python-Programme
Anonymous
 Holen Sie sich das HMENU eines tk-Menüs unter Windows

Post by Anonymous »

Ich möchte das HMENU eines tk-Menüs erhalten, um seine Hintergrundfarbe mithilfe der SetMenuInfo-Funktion von der Windows-API festzulegen (das Festlegen mit configure() wirkt sich nur auf den Hintergrund der Menüelemente aus, nicht jedoch auf den Hintergrund des Menüs selbst), aber ich kann keine Möglichkeit finden, das HMENU eines Menüs abzurufen, um diese Funktion aufrufen zu können, ohne zuerst das Menü anzuzeigen und dann sein HMENU abzurufen. Die Funktion wininfo_id() eines Menü-Widgets gibt nicht das HMENU des Menüs zurück, sondern das HWND eines unsichtbaren Fensters, das mit dem Menü erstellt wird. Ich habe auch versucht, im Internet und in der TK-Dokumentation nach etwas zu suchen, das mir helfen könnte, aber ich habe nichts gefunden. Die einzige Möglichkeit, die ich mir vorstellen kann, um das HMENU zu finden, besteht darin, das Fenster des Menüs mithilfe der Funktion FindWindowW zu finden und dann das zugehörige Menü abzurufen, indem MN_GETHMENU an das Fenster gesendet wird, wenn das Ereignis ausgelöst wird. Etwa so:

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)
Aber dies führt zu einer kurzen Verzögerung beim Festlegen der Hintergrundfarbe und ich möchte nicht, dass das passiert.
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()
Dieser Code gibt Folgendes als Beispiel aus:

Code: Select all

3933734
0
Menu bar menu's HMENU: 15730469
Actual menu's HMENU: 24970897

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post