Получить HMENU меню tk в WindowsPython

Программы на Python
Ответить
Anonymous
 Получить HMENU меню tk в Windows

Сообщение Anonymous »

Я хотел бы получить HMENU меню tk для установки цвета его фона с помощью функции SetMenuInfo из Windows API (установка с помощью configure() влияет только на фон элементов меню, но не на фон самого меню), но я не могу найти способ получить HMENU меню, чтобы иметь возможность вызывать эту функцию, не показывая сначала меню, а затем получая его HMENU. Функция winfo_id() виджета меню возвращает не HMENU меню, а HWND невидимого окна, которое создается вместе с меню. Я также пытался поискать в Интернете и документации tk что-нибудь, что могло бы мне помочь, но ничего не нашел. Единственный способ найти HMENU, который я могу придумать, — это найти окно меню с помощью функции FindWindowW, а затем получить связанное с ним меню, отправив ему MN_GETHMENU при возникновении события . Примерно так:
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)

Но это приведет к небольшой задержке при установке цвета фона, а я не хочу, чтобы это произошло.
Действительно ли tk отображает HMENU меню? Если да, то как я могу его получить?
Изменить: я знаю, что вы можете использовать GetMenu, но это работает только в том случае, если меню установлено как строка меню определенного окна. Я не думаю, что смогу использовать эту функцию, потому что, согласно документации tk Menu, когда меню устанавливается в качестве строки меню для окна верхнего уровня, создается клон меню. Поэтому, временно установив меню, я хочу получить его HMENU в виде строки меню, получить его HMENU с помощью GetMenu, а затем восстановить исходное меню строки меню/удалить его, это вернет только HMENU для клонированного меню.
Хотя GetMenu работает для меню строки меню, мне нужен способ каким-то образом получить HMENU меню, которое я, например, опубликую вручную или использую для виджета Menubutton, без сначала отобразив его, найдите его всплывающее окно, а затем отправьте ему сообщение, чтобы получить HMENU связанного с ним меню.
Минимальный воспроизводимый пример:
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()

В качестве примера этот код печатает следующее:
3933734
0
Menu bar menu's HMENU: 15730469
Actual menu's HMENU: 24970897


Подробнее здесь: https://stackoverflow.com/questions/798 ... on-windows
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»