A package for manipulating windows and titlebar of GUI applications made using Python. Supports Windows 7, 8.x, 10, and 11.
hPyT-Preview-1.2.0.mp4
π Table of Contents
- hPyT - Hack Python Titlebar
- π Supported Libraries
- π¦ Installing
- π§© Running the preview app
- π₯ Importing
- NEW Features in
v1.4.0
π - Hide/Unhide TitleBar - Understanding Window Geometry
- π Rainbow TitleBar
- π Rainbow Border
- Hide/Unhide both Maximize and Minimize Buttons (Completely Hides both buttons)
- Hide/Unhide All Buttons or Stuffs
- Enable/Disable Maximize Button
- Enable/Disable Minimize Button
- π¨ Custom TitleBar Color
- ποΈ Custom TitleBar Text Color
- ποΈ Custom Border Color
- Window Corner Radius
- Window DWM Manipulation
- Opacity
- β‘ Flashing Window
- π» Window Management
- β¨ Window Animations
- βοΈ Stylize text
- Workaround for other libraries
- Miscellaneous
- π hPyT Changelog
- Tkinter & CustomTkinter
- PyQt
- PySide
- WxPython
- Kivy
- Almost all other UI libraries
Important
Follow this section to see how to use hPyT with other libraries.
pip install hPyT==1.4.0
After installing the module, you can run the following command to open the preview/demo app:
python -m hPyT
...or try this even simpler command (if it doesn't work, check if your Python installation's Scripts
folder exists in your PATH
environment variable):
hPyT-preview
It looks like this:
This app allows you to play with hPyT's features and see them in action.
from hPyT import *
from customtkinter import * # you can use any other library from the above mentioned list
window = CTk() # creating a window using CustomTkinter
- Function to change
corner radius
of the window with thehPyT.corner_radius
module - Functions to manipulate
DWM
window attributes with thehPyT.window_dwm
module- Enable RTL layout
- Disable DWM transitions
- Cloak the window
title_bar.hide(window, no_span = False) # hides full titlebar
# optional parameter : no_span, more details in the note below
# title_bar.unhide(window)
Parameter | Type | Default | Description |
---|---|---|---|
no_span |
bool |
False |
If True , the content area height will not be adjusted to accommodate the title bar. |
When hiding a title bar, the application window's total geometry and its content area geometry behave differently, which may introduce ambiguities. Here's a detailed explanation of the issue:
-
Full Window Dimensions:
- Includes the content area, title bar, and borders.
- When the user specifies dimensions (e.g.,
400x400
), it usually represents the content area dimensions. The total window height becomescontent height + title bar height + border width
. - The color of the
top border
andtitle bar
is usually the same in Windows 11 & 10, making it appear as a single entity. So when hiding the title bar, we also need to hide the top border. - However, in Windows 7 & 8, the top border is a different color from the title bar, so we don't need to hide the top border when hiding the title bar. Moreover removing the top border will make the window behave abnormally in these versions.
-
Content Area Dimensions:
- Represents only the usable area inside the window, excluding the title bar and borders.
When the title bar is hidden:
- The content area height expands to occupy the height previously used by the title bar. For example, a
400x400
content area might expand to400x438
(assuming the visual title bar height is 38px).
Better illustrated in the following example:
...
def show_window_dimensions():
hwnd: int = ctypes.windll.user32.GetForegroundWindow()
x_with_decorations: int = root.winfo_rootx() # X position of the full window
y_with_decorations: int = root.winfo_rooty() # Y position of the full window
x_without_decorations: int = root.winfo_x() # X position of the content area
y_without_decorations: int = root.winfo_y() # Y position of the content area
titlebar_height: int = y_with_decorations - y_without_decorations
border_width: int = x_with_decorations - x_without_decorations
window_rect: RECT = get_window_rect(hwnd)
width: int = window_rect.right - window_rect.left
height: int = window_rect.bottom - window_rect.top
print(f"Title bar height: {titlebar_height}")
print(f"Border width: {border_width}")
print(f"Main window dimensions: {width}x{height}")
print(
f"Content window dimensions: {root.winfo_geometry()}"
) # This will return the dimensions of the content area only
...
def click(e=None):
root.update_idletasks()
print("------ Before hiding title bar ------")
show_window_dimensions()
title_bar.hide(root)
is_hidden = True
print("------ After hiding title bar ------")
show_window_dimensions()
button = CTkButton(root, text="Click Me", command=click)
button.place(relx=0.5, rely=0.5, anchor="center")
root.mainloop()
Output:
------ Before hiding title bar ------
Title bar height: 38
Border width: 9
Main window dimensions: 468x497
Content window dimensions: 450x450
------ After hiding title bar ------
Title bar height: 0
Border width: 9
Main window dimensions: 468x497
Content window dimensions: 450x488
By the above example, you can see that the content area height has increased from 450px
to 488px
after hiding the title bar.
This automatic resizing may cause layout problems or unintended behavior in some applications. For instance:
- UI elements might overlap or stretch.
- Custom layouts may require recalibration.
To address this, a no_span
parameter is introduced in the hide
method. This parameter allows users to control whether the content area height should be adjusted dynamically to maintain its original size.
- Default Behavior (
no_span=False
): The content area height will expand to occupy the title bar's space. - With
no_span=True
: The content area will be resized dynamically to maintain its original dimensions.
title_bar.hide(root, no_span=True)
- Content window dimensions: 450x488
+ Content window dimensions: 450x450
- Main window dimensions: 468x497
+ Main window dimensions: 468x459
This feature is only supported on Windows 11.
rainbow_title_bar.start(window, interval=5) # starts the rainbow titlebar
# rainbow_title_bar.stop(window) # stops the rainbow titlebar
Parameter | Type | Default | Description |
---|---|---|---|
interval |
int |
5 |
The time in milliseconds in which the color would change. |
color_stops |
int |
5 |
The number of color stops between each RGB value. |
This feature is only supported on Windows 11.
rainbow_border.start(window, interval=4) # starts the rainbow border
# rainbow_border.stop(window) # stops the rainbow border
Parameter | Type | Default | Description |
---|---|---|---|
interval |
int |
5 |
The time in milliseconds in which the color would change. |
color_stops |
int |
5 |
The number of color stops between each RGB value. |