It's impossible with tkinter
alone.
Sure, tkinter
provides some options like an icon, a title, a child-toplevel, a tool window, etc, but don't be fooled by these options!
While he has an interface to communicate with window manager, he's mainly a tool for the client area of the window, and window managment/decoration isn't his purpose.
Operating with the Aero
stuff is more complicated thing, than a trivial window styling, and it handled by the DWM
, which can be controlled via the DWM composition API(1, 2).
For all that interaction we need the ctypes
library (comes with python
) and a set of the WinAPI functions:
- DwmIsCompositionEnabled - to check if the Aero is enabled (system-wide).
- DwmSetWindowAttribute - to specify (enable/disable) the non-client area rendering policy (and therefore revert to the Basic/Aero frame).
- GetParent - to get a hwnd of the owner window, because we're trying to make changes in the non-client area.
Try to run this piece of code:
import ctypes as ct
import tkinter as tk
class App(tk.Tk):
is_composition_enabled = ct.windll.dwmapi.DwmIsCompositionEnabled
set_window_attribute = ct.windll.dwmapi.DwmSetWindowAttribute
get_parent = ct.windll.user32.GetParent
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.state = True
self.minsize(width=250, height=100)
self.frame = tk.Frame(self)
self.frame.pack(expand=True, fill='both')
self.status_label = tk.Label(self.frame)
self.status_label.pack(expand=True, fill='both')
self.populate_status_label()
self.toggle_button = tk.Button(self.frame, text='Toggle glass', command=self.toggle_glass)
self.toggle_button.pack(fill='x')
def populate_status_label(self):
status = 'en' if self.state else 'dis'
self.status_label.configure(text='Glass border %sabled!' % status)
def toggle_glass(self):
response = self.handle_glass()
if response:
self.state = not self.state
self.populate_status_label()
else:
print('Something bad happened!')
def handle_glass(self):
try:
composition_enabled = ct.c_bool()
response = not bool(self.is_composition_enabled(ct.byref(composition_enabled)))
if response and composition_enabled.value:
hwnd = self.get_parent(self.winfo_id())
switch_to_disable, switch_to_enable, rendering_policy = 1, 2, 2
dwma_ncrendering_switch = ct.c_int(switch_to_disable if self.state else switch_to_enable)
return not bool(self.set_window_attribute(hwnd, rendering_policy, ct.byref(dwma_ncrendering_switch),
ct.sizeof(dwma_ncrendering_switch)))
except AttributeError:
return False
app = App()
app.mainloop()
As a result, you should get something similar to this:

However, if your goal is to only disable a border transparency, while maintaining a same aero-like style, there's not much you can do about it.