Skip to content

Commit

Permalink
Add a new simple dialog (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
littlewhitecloud authored May 4, 2024
1 parent 25c0d5f commit 7892532
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 25 deletions.
4 changes: 2 additions & 2 deletions customtitlebar/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
# By Littlewhitecloud
# ------------------------

__version__ = "1.0.8.2"
__version__ = "1.0.8.3"
__author__ = "littlewhitecloud"

from sys import platform

if platform != "win32":
raise OSError("Platform isn't win32 (Windows)")

from .titlebar import CTT
from .titlebar import CTT, Dialog
6 changes: 6 additions & 0 deletions customtitlebar/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
from ctypes.wintypes import HWND, RECT, UINT

WM_NCCALCSIZE = 0x0083
WM_NCHITTEST = 0x0084

WS_CAPTION = 0x00C00000
WS_VISIBLE = 0x10000000
WS_THICKFRAME = 0x00040000

SWP_NOSIZE = 0x0001
SWP_NOREDRAW = 0x0008
Expand All @@ -10,6 +15,7 @@
SW_MAXIMIZE = 3
SW_NORMAL = 1

GWL_STYLE = -16
GWL_WNDPROC = -4


Expand Down
81 changes: 62 additions & 19 deletions customtitlebar/titlebar.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@

from ctypes import WINFUNCTYPE, c_char_p, c_uint64, windll
from pathlib import Path
from tkinter import Button, Event, Frame, Label, Tk
from tkinter import Button, Event, Frame, Label, Tk, Toplevel
from typing import Any, Mapping

from darkdetect import isDark
from PIL import Image, ImageTk

from .data import *

env = Path(__file__).parent


Expand Down Expand Up @@ -49,11 +48,17 @@ def __init__(self, theme: str = "auto") -> None:
self.max_hov_img = ImageTk.PhotoImage(Image.open(self.path / "togglefull_100.png"))

self.titlebar = Frame(self, bg=self.bg, height=30)
self.icon = Label(self.titlebar, bg=self.bg)
self.text = Label(self.titlebar, bg=self.bg, fg=self.colors[self.fg])
self.min = Button(self.titlebar, bg=self.bg, bd=0, width=44, relief="flat")
self.max = Button(self.titlebar, bg=self.bg, bd=0, width=44, relief="flat")
self.exit = Button(self.titlebar, bg=self.bg, bd=0, width=44, relief="flat")
self.buttongroup = Frame(self.titlebar, bg=self.bg)
self.infogroup = Frame(self.titlebar, bg=self.bg)
self.icon = Label(self.infogroup, bg=self.bg)
self.text = Label(self.infogroup, bg=self.bg, fg=self.colors[self.fg])

self.min = Button(self.buttongroup)
self.max = Button(self.buttongroup)
self.exit = Button(self.buttongroup)

for widget in (self.min, self.max, self.exit):
widget.config(bg=self.bg, bd=0, width=44, height=30, relief="flat")

self.exit.config(
activebackground=self.colors[f"{self.theme}exit_bg"],
Expand Down Expand Up @@ -92,12 +97,14 @@ def __init__(self, theme: str = "auto") -> None:

self.setup()

self.icon.pack(fill="y", side="left", padx=5, pady=5)
self.text.pack(fill="y", side="left", pady=5, padx=5)
self.icon.pack(fill="x", side="left")
self.text.pack(fill="x", side="left")
self.exit.pack(fill="y", side="right")
self.max.pack(fill="y", side="right")
self.min.pack(fill="y", side="right")
self.titlebar.pack(fill="x", side="top")
self.infogroup.pack(fill = "x", side = "left", padx=5, pady=5)
self.buttongroup.pack(fill = "y", side="right")
self.titlebar.pack(fill="x", side="top", expand=False)
self.titlebar.pack_propagate(False)

# Window
Expand All @@ -119,13 +126,13 @@ def handle(hwnd: int, msg: int, wp: int, lp: int) -> int:

old, new = "old", "new"
prototype = WINFUNCTYPE(c_uint64, c_uint64, c_uint64, c_uint64, c_uint64)

globals()[old] = None
globals()[new] = prototype(handle)
globals()[old] = windll.user32.GetWindowLongPtrA(self.hwnd, GWL_WNDPROC)
windll.user32.SetWindowLongPtrA(self.hwnd, GWL_WNDPROC, globals()[new])

self.update()
self.focus_force()

def dragging(self, event: Event) -> None:
"""Drag the window"""
Expand Down Expand Up @@ -155,7 +162,6 @@ def maximize(self, _: Event | None = None) -> None:
self.titlebar.bind("<Double-Button-1>", self.resize)

windll.user32.ShowWindow(self.hwnd, SW_MAXIMIZE)
# TODO: leave a place for the taskbar

def resize(self, _: Event | None = None) -> None:
"""Resize window"""
Expand Down Expand Up @@ -230,6 +236,7 @@ def titlebarconfig(
def title(self, text: str) -> None:
"""Rebuild tkinter's title"""
# TODO: show "..." if title is too long

self.text.config(text=text)
self.wm_title(text)

Expand All @@ -251,7 +258,9 @@ def iconbitmap(self, image: str) -> None:
# TODO: parse %sx%s+%s+%s
def geometry(self, size: str) -> None:
"""Rebuild tkinter's geometry"""
self.width, self.height = size.split("x")[0], size.split("x")[1]
tmp = size.split('+')[0].split('x')
self.width, self.height = tmp[0], tmp[1]

self.wm_geometry(size)

def settheme(self, theme: str) -> None:
Expand All @@ -260,14 +269,16 @@ def settheme(self, theme: str) -> None:
def autotheme() -> str:
return "dark" if isDark() else "light"

self.theme = theme
if theme not in ("dark", "light", "auto"): # Check the theme
print(
f"Warning: Now the theme is `{theme}`, not matching `D(d)ark` `L(l)ight` `A(a)uto`, using auto mode instead"
)
self.theme = autotheme()
elif theme == "auto":

if theme == "auto":
self.theme = autotheme()
else:
self.theme = theme

self.bg = self.colors[self.theme]
self.nf = self.colors[f"{self.theme}_nf"]
Expand All @@ -292,8 +303,40 @@ def setcolor(self, focus: bool) -> None:
if self.theme == "light" and self.onfocus:
self.text.config(foreground=self.colors[self.fg])

def focusout(self, _: Event | None = None) -> None:
self.setcolor(False)
def focusout(self, _: Event | None = None) -> None: self.setcolor(False)
def focusin(self, _: Event | None = None) -> None: self.setcolor(True)

def focusin(self, _: Event | None = None) -> None:
self.setcolor(True)
class Dialog(Toplevel):

def __init__(self) -> None:
super().__init__()

self.overrideredirect(True)
self.setup()

def setup(self) -> None:

def handle(hwnd: int, msg: int, wp: int, lp: int) -> int:
if msg == WM_NCCALCSIZE and wp:
lpncsp = NCCALCSIZE_PARAMS.from_address(lp)
lpncsp.rgrc[0].top -= 6

return windll.user32.CallWindowProcW(*map(c_uint64, (globals()[old], hwnd, msg, wp, lp)))

self.title("Tk")
self.geometry("300x400")
self.iconbitmap("")

self.hwnd = windll.user32.FindWindowW(c_char_p(None), "Tk")

windll.user32.SetWindowLongA(self.hwnd, GWL_STYLE, WS_VISIBLE | WS_THICKFRAME)

old, new = "old", "new"
prototype = WINFUNCTYPE(c_uint64, c_uint64, c_uint64, c_uint64, c_uint64)
globals()[old] = None
globals()[new] = prototype(handle)
globals()[old] = windll.user32.GetWindowLongPtrA(self.hwnd, GWL_WNDPROC)
windll.user32.SetWindowLongPtrA(self.hwnd, GWL_WNDPROC, globals()[new])

self.update()
self.focus_force()
6 changes: 2 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
with open("README.md", "r", encoding="utf-8") as readme:
long_description = readme.read()

requires = ["Pillow>=9.0.0", "darkdetect>=0.8.0"]
requires = ["Pillow>=10.2.0", "darkdetect>=0.8.0"]

setup(
name="CustomTkinterTitlebar",
version="1.0.8.2",
version="1.0.8.3",
author="littlewhitecloud",
author_email="[email protected]",
description="This is a 📚project can help you to have a custom titlebar! 这是一个可以创建自定义标题栏的📚项目",
Expand All @@ -21,8 +21,6 @@
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
Expand Down

0 comments on commit 7892532

Please sign in to comment.