我创建了一个窗口:
root = Tk()
并删除了标题栏:
root.overrideredirect(True)
现在窗口不在Windows的任务栏上。如何在任务栏中显示它? (如果其他窗户在我的上面,我只想把窗户拉到前面)
答案 0 :(得分:6)
Tk没有提供一种方法来设置一个顶层窗口,其中 overrideredirect 设置为显示在任务栏上。要执行此操作,窗口需要应用WS_EX_APPWINDOW扩展样式,并且此类型的Tk窗口设置为WS_EX_TOOLWINDOW。我们可以使用python ctypes扩展来重置它,但是我们需要注意Windows上的Tk顶层窗口不是由窗口管理器直接管理的。因此,我们必须将此新样式应用于winfo_id
方法返回的窗口的父级。
以下示例显示了这样一个窗口。
import tkinter as tk
import tkinter.ttk as ttk
from ctypes import windll
GWL_EXSTYLE=-20
WS_EX_APPWINDOW=0x00040000
WS_EX_TOOLWINDOW=0x00000080
def set_appwindow(root):
hwnd = windll.user32.GetParent(root.winfo_id())
style = windll.user32.GetWindowLongPtrW(hwnd, GWL_EXSTYLE)
style = style & ~WS_EX_TOOLWINDOW
style = style | WS_EX_APPWINDOW
res = windll.user32.SetWindowLongPtrW(hwnd, GWL_EXSTYLE, style)
# re-assert the new window style
root.wm_withdraw()
root.after(10, lambda: root.wm_deiconify())
def main():
root = tk.Tk()
root.wm_title("AppWindow Test")
button = ttk.Button(root, text='Exit', command=lambda: root.destroy())
button.place(x=10,y=10)
root.overrideredirect(True)
root.after(10, lambda: set_appwindow(root))
root.mainloop()
if __name__ == '__main__':
main()
答案 1 :(得分:0)
这是@patthoyts 在同样实现的类中的回答:.toggle_fullscreen
和 .iconify
import tkinter as tk
import ctypes
from ctypes.wintypes import BOOL, HWND, LONG
INT = ctypes.c_int
UINT = ctypes.c_uint
LONG_PTR = ctypes.c_uint
def _errcheck_not_zero(value, func, args):
if value == 0:
raise ctypes.WinError()
return args
GetParent = ctypes.windll.user32.GetParent
GetParent.argtypes = (HWND, )
GetParent.restype = HWND
GetParent.errcheck = _errcheck_not_zero
GetWindowLongPtrW = ctypes.windll.user32.GetWindowLongPtrW
GetWindowLongPtrW.argtypes = (HWND, INT)
GetWindowLongPtrW.restype = LONG_PTR
GetWindowLongPtrW.errcheck = _errcheck_not_zero
SetWindowLongPtrW = ctypes.windll.user32.SetWindowLongPtrW
SetWindowLongPtrW.argtypes = (HWND, INT, LONG_PTR)
SetWindowLongPtrW.restype = LONG_PTR
SetWindowLongPtrW.errcheck = _errcheck_not_zero
GWL_EXSTYLE = -20
WS_EX_APPWINDOW = 0x00040000
WS_EX_TOOLWINDOW = 0x00000080
class NoTitlebarTk(tk.Tk):
def __init__(self):
super().__init__()
self.locked = False
self._fullscreen = False
self.map_binding = super().bind("<Map>", self._overrideredirect)
def _overrideredirect(self, event:tk.Event=None) -> None:
if self.locked:
return None
self.locked = True
if self.map_binding is not None:
super().unbind("<Map>", self.map_binding)
self.map_binding = None
super().overrideredirect(True)
super().update_idletasks()
self.hwnd = GetParent(super().winfo_id())
style = GetWindowLongPtrW(self.hwnd, GWL_EXSTYLE)
style = (style & ~WS_EX_TOOLWINDOW) | WS_EX_APPWINDOW
res = SetWindowLongPtrW(self.hwnd, GWL_EXSTYLE, style)
# re-assert the new window style
super().withdraw()
super().after(10, self.deiconify)
super().after(20, self.focus_force)
self.locked = False
def overrideredirect(self, boolean:bool=None) -> None:
raise RuntimeError("This window must stay as `overrideredirect`")
wm_overrideredirect = overrideredirect
def attributes(self, *args) -> None:
if (len(args) == 2) and (args[0] == "-fullscreen"):
value = args[1]
if isinstance(value, str):
value = value.lower() in ("1", "true")
if bool(value):
return self.fullscreen()
return self.notfullscreen()
return super().attributes(*args)
wm_attributes = attributes
def iconify(self) -> None:
super().overrideredirect(False)
super().iconify()
super().update()
self.map_binding = super().bind("<Map>", self._overrideredirect)
def fullscreen(self) -> None:
if self._fullscreen:
return None
self._fullscreen = True
super().overrideredirect(False)
super().attributes("-fullscreen", True)
def notfullscreen(self) -> None:
if not self._fullscreen:
return None
self._fullscreen = False
super().attributes("-fullscreen", False)
self._overrideredirect()
self.map_binding = super().bind("<Map>", self._overrideredirect)
def toggle_fullscreen(self) -> None:
if self._fullscreen:
self.notfullscreen()
else:
self.fullscreen()
if __name__ == "__main__":
root = NoTitlebarTk()
root.title("AppWindow Test")
root.geometry("400x400")
button = tk.Button(root, text="Exit", command=root.destroy)
button.pack()
button = tk.Button(root, text="Minimise", command=root.iconify)
button.pack()
button = tk.Button(root, text="Fullscreen", command=root.toggle_fullscreen)
button.pack()
root.mainloop()