├── upload_requirements.txt
├── pyproject.toml
├── translucenttb
├── __init__.py
├── blur.py
└── main.py
├── example
├── example.py
└── colorful.py
├── setup.py
├── .github
└── workflows
│ └── pypi.yml
├── README.md
└── .gitignore
/upload_requirements.txt:
--------------------------------------------------------------------------------
1 | setuptools
2 | twine
3 | wheel
4 | build
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.black]
2 | line-length = 79
3 |
4 | [tool.isort]
5 | line_length = 79
6 | profile = "black"
7 | multi_line_output = 3
8 |
9 | [tool.ruff]
10 | line-length = 79
11 |
--------------------------------------------------------------------------------
/translucenttb/__init__.py:
--------------------------------------------------------------------------------
1 | from platform import system
2 |
3 | if system() != "Windows":
4 | raise OSError("Platform not Windows!")
5 |
6 |
7 | from .main import Settings, blur # noqa: F401
8 |
--------------------------------------------------------------------------------
/example/example.py:
--------------------------------------------------------------------------------
1 | from translucenttb import Settings # import the blur function
2 |
3 | # blur(blurtype, hexColor)
4 | # blurtype:
5 | # clear
6 | # noeffect
7 | # blur
8 | # acrylic
9 |
10 | # for example
11 | Settings().mainloop()
12 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | """Setup"""
2 | from distutils.core import setup
3 |
4 | with open("README.md", "r", encoding="utf-8") as file:
5 | long_description = file.read()
6 |
7 | setup(
8 | name="translucenttb",
9 | version="0.0.4",
10 | description="A python version TranslucentTB",
11 | long_description=long_description,
12 | long_description_content_type="text/markdown",
13 | author="littlewhitecloud",
14 | url="https://github.com/littlewhitecloud/TranslucentTB/",
15 | )
16 |
--------------------------------------------------------------------------------
/.github/workflows/pypi.yml:
--------------------------------------------------------------------------------
1 | name: Upload translucenttb to Pypi
2 |
3 | on:
4 | release:
5 | types: [published]
6 |
7 | jobs:
8 | deploy:
9 |
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | - uses: actions/checkout@v2
14 | - name: Set up Python
15 | uses: actions/setup-python@v2
16 | with:
17 | python-version: 3.9
18 | - name: Install dependencies
19 | run: |
20 | python -m pip install --upgrade pip
21 | pip install -r upload_requirements.txt
22 | - name: Build and publish to Pypi
23 | env:
24 | TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
25 | TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
26 | run: |
27 | python3 -m build
28 | twine upload dist/*
29 |
--------------------------------------------------------------------------------
/example/colorful.py:
--------------------------------------------------------------------------------
1 | from time import sleep
2 |
3 | from translucenttb import blur
4 |
5 |
6 | def colorful():
7 | hexdict = [
8 | "#FF0000",
9 | "#FF3030",
10 | "#FF5656",
11 | "#FF7456",
12 | "#FFA500",
13 | "#FF7438",
14 | "#FF8956",
15 | "#FFAB56",
16 | "#FFB871",
17 | "#FFFF00",
18 | "#FFCD71",
19 | "#FFE071",
20 | "#FFF571",
21 | "#F4FF71",
22 | "#D8FF71",
23 | "#C8FF71",
24 | "#008000",
25 | "#9FF65B",
26 | "#00FFFF",
27 | "#79F65B",
28 | "#5FF65B",
29 | "#5BF67D",
30 | "#5BF69C",
31 | "#5BF67D",
32 | "#5BF6C5",
33 | "#5BF6DC",
34 | "#2AFFDC",
35 | "#2AFCFF",
36 | "#2AC5FF",
37 | "#2AADFF",
38 | "#2A87FF",
39 | "#2A6BFF",
40 | "#2A49FF",
41 | "#0000FF",
42 | "#2A35FF",
43 | "#3A2AFF",
44 | "#502AFF",
45 | "#602AFF",
46 | "#800080",
47 | ]
48 |
49 | for hexcolor in hexdict:
50 | blur("noeffect", hexcolor)
51 | sleep(0.1)
52 |
53 |
54 | colorful()
55 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### TranslucentTB
2 | #### This is a python version TranslucentTB maybe with tkinter and ctypes
3 |
4 | A lightweight utility that makes the Windows taskbar translucent/transparent on Windows 10 and Windows11.
5 |
6 | ### Screenshots
7 | 
8 | 
9 | 
10 | 
11 |
12 | ### Usage
13 | ```python
14 | from translucenttb import blur # import the blur function
15 | blur(blurtype="Acrylic") # for example: We use Acrylic
16 | # choose one type from ("Clear", "Opaque", "Aero", "Acrylic")
17 | ```
18 |
19 | ### UI
20 | 
21 |
22 | ```python
23 | from translucenttb import Settings
24 | example = Settings()
25 | example.mainloop()
26 | ```
27 | ### Example:
28 |
29 |
30 | ```python
31 | from time import sleep
32 |
33 | from translucenttb import blur
34 |
35 |
36 | def colorful():
37 | hexdict = [
38 | "#FF0000",
39 | "#FF3030",
40 | "#FF5656",
41 | "#FF7456",
42 | "#FFA500",
43 | "#FF7438",
44 | "#FF8956",
45 | "#FFAB56",
46 | "#FFB871",
47 | "#FFFF00",
48 | "#FFCD71",
49 | "#FFE071",
50 | "#FFF571",
51 | "#F4FF71",
52 | "#D8FF71",
53 | "#C8FF71",
54 | "#008000",
55 | "#9FF65B",
56 | "#00FFFF",
57 | "#79F65B",
58 | "#5FF65B",
59 | "#5BF67D",
60 | "#5BF69C",
61 | "#5BF67D",
62 | "#5BF6C5",
63 | "#5BF6DC",
64 | "#2AFFDC",
65 | "#2AFCFF",
66 | "#2AC5FF",
67 | "#2AADFF",
68 | "#2A87FF",
69 | "#2A6BFF",
70 | "#2A49FF",
71 | "#0000FF",
72 | "#2A35FF",
73 | "#3A2AFF",
74 | "#502AFF",
75 | "#602AFF",
76 | "#800080",
77 | ]
78 |
79 | for hexcolor in hexdict:
80 | blur("noeffect", hexcolor)
81 | sleep(0.1)
82 |
83 |
84 | colorful()
85 | ```
86 | https://github.com/littlewhitecloud/TranslucentTB/assets/71159641/a2d0b4cc-0698-46c0-b050-e3d89c788964
87 |
88 |
89 |
--------------------------------------------------------------------------------
/translucenttb/blur.py:
--------------------------------------------------------------------------------
1 | from ctypes import (
2 | POINTER,
3 | Structure,
4 | byref,
5 | c_int,
6 | c_size_t,
7 | c_uint,
8 | cast,
9 | pointer,
10 | sizeof,
11 | windll,
12 | )
13 | from ctypes.wintypes import BOOL, DWORD, HRGN, HWND
14 |
15 |
16 | class ACCENTPOLICY(Structure):
17 | _fields_ = [
18 | ("AccentState", c_uint),
19 | ("AccentFlags", c_uint),
20 | ("GradientColor", c_uint),
21 | ("AnimationId", c_uint),
22 | ]
23 |
24 |
25 | class WINDOWCOMPOSITIONATTRIBDATA(Structure):
26 | _fields_ = [
27 | ("Attribute", c_int),
28 | ("Data", POINTER(c_int)),
29 | ("SizeOfData", c_size_t),
30 | ]
31 |
32 |
33 | class DWM_BLURBEHIND(Structure):
34 | _fields_ = [
35 | ("dwFlags", DWORD),
36 | ("fEnable", BOOL),
37 | ("hRgnBlur", HRGN),
38 | ("fTransitionOnMaximized", BOOL),
39 | ]
40 |
41 |
42 | class MARGINS(Structure):
43 | _fields_ = [
44 | ("cxLeftWidth", c_int),
45 | ("cxRightWidth", c_int),
46 | ("cyTopHeight", c_int),
47 | ("cyBottomHeight", c_int),
48 | ]
49 |
50 |
51 | SetWindowCompositionAttribute = windll.user32.SetWindowCompositionAttribute
52 | SetWindowCompositionAttribute.argtypes = (HWND, WINDOWCOMPOSITIONATTRIBDATA)
53 | SetWindowCompositionAttribute.restype = c_int
54 |
55 |
56 | def HEXtoRGBAint(HEX: str):
57 | alpha = HEX[7:]
58 | blue = HEX[5:7]
59 | green = HEX[3:5]
60 | red = HEX[1:3]
61 | gradientColor = alpha + blue + green + red
62 | return int(gradientColor, base=16)
63 |
64 |
65 | def blur(blurtype: str = "Acrylic", hexColor: str = "", spechwnd: int = None):
66 | hwnd = spechwnd if spechwnd else windll.user32.FindWindowW("Shell_TrayWnd", None)
67 |
68 | accent = ACCENTPOLICY()
69 | accent.AccentState = 3
70 | gradientColor = 0
71 |
72 | if hexColor:
73 | accent.AccentFlags = 2
74 | gradientColor = HEXtoRGBAint(hexColor)
75 |
76 | if blurtype == "Clear":
77 | accent.AccentState = 2
78 | elif blurtype == "Opaque":
79 | accent.AccentState = 1
80 | elif blurtype == "Aero":
81 | DWM_BB_ENABLE = 0x01
82 | bb = DWM_BLURBEHIND()
83 | bb.dwFlags = DWM_BB_ENABLE
84 | bb.fEnable = 1
85 | bb.hRgnBlur = 1
86 | windll.dwmapi.DwmEnableBlurBehindWindow(hwnd, byref(bb))
87 | elif blurtype == "Acrylic":
88 | accent.AccentState = 4
89 | accent.GradientColor = gradientColor
90 |
91 | data = WINDOWCOMPOSITIONATTRIBDATA()
92 | data.Attribute = 19
93 | data.SizeOfData = sizeof(accent)
94 | data.Data = cast(pointer(accent), POINTER(c_int))
95 |
96 | SetWindowCompositionAttribute(int(hwnd), data)
97 |
--------------------------------------------------------------------------------
/translucenttb/main.py:
--------------------------------------------------------------------------------
1 | from re import match
2 | from tkinter import Event, Tk
3 | from tkinter.colorchooser import askcolor
4 | from tkinter.ttk import Button, Combobox, Entry, Frame, Label, Separator
5 |
6 | from darkdetect import isDark
7 | from sv_ttk import set_theme
8 |
9 | from .blur import blur, byref, c_int, sizeof, windll
10 |
11 |
12 | class Settings(Tk):
13 | """Window to choose effect for taskbar"""
14 |
15 | def __init__(self):
16 | super().__init__()
17 |
18 | self.option_add("*font", ("Cascadia Mono", 9))
19 | set_theme("dark" if isDark() else "light")
20 | self.title("TranslucentTb")
21 | self.geometry("570x120")
22 | self.resizable(False, False)
23 | self.iconbitmap("")
24 |
25 | if isDark():
26 | windll.dwmapi.DwmSetWindowAttribute(
27 | windll.user32.GetParent(self.winfo_id()),
28 | 20,
29 | byref(c_int(2)),
30 | sizeof(c_int(2)),
31 | )
32 | self.withdraw()
33 | self.deiconify()
34 |
35 | selectframe = Frame(self)
36 |
37 | chooseframe = Frame(selectframe)
38 | choose = Label(
39 | chooseframe,
40 | text="Choose a effect you'd like to apply to the taskbar:",
41 | )
42 | effectchooser = Combobox(
43 | chooseframe, value=("Clear", "Opaque", "Aero", "Acrylic")
44 | )
45 |
46 | colorframe = Frame(selectframe)
47 | color = Label(
48 | colorframe, text="Choose or input a hexcolor you'd like to use:"
49 | )
50 | colorentry = Entry(colorframe)
51 | colorbutton = Button(
52 | colorframe, text="🎨", command=lambda: self.choose(colorentry)
53 | )
54 |
55 | bottomframe = Frame(self)
56 | exittcl = Button(bottomframe, text="Exit", command=self.quit)
57 | applytb = Button(
58 | bottomframe,
59 | text="Apply",
60 | style="Accent.TButton",
61 | command=lambda: self.apply(effectchooser.get(), colorentry.get()),
62 | )
63 | sep = Separator(bottomframe, orient="horizontal")
64 |
65 | bottomframe.pack(side="bottom", fill="x")
66 | sep.pack(side="top", fill="x")
67 | for widget in (exittcl, applytb):
68 | widget.pack(side="right", fill="y", padx=1, pady=1)
69 |
70 | choose.pack(side="left", padx=7)
71 | effectchooser.pack(side="left")
72 | chooseframe.grid(row=1, column=0, sticky="nw")
73 |
74 | color.pack(side="left", padx=7)
75 | colorentry.pack(side="left")
76 | colorbutton.pack(side="left", padx=3)
77 | colorframe.grid(row=2, column=0, sticky="nw")
78 |
79 | selectframe.pack(side="top")
80 |
81 | colorentry.bind("", self.check)
82 |
83 | def apply(self, effect: str, hexColor: str = None):
84 | """Apply effect to the window"""
85 | blur(blurtype=effect, hexColor=hexColor)
86 |
87 | def choose(self, entry: Entry):
88 | """Choose a color for blur"""
89 | entry.delete(0, "end")
90 | entry.insert("insert", askcolor()[-1])
91 |
92 | def check(self, event: Event) -> None:
93 | if match(r"^#(?:[0-9a-fA-F]{3}){1,2}$", event.widget.get()):
94 | event.widget.state(["invalid"])
95 | else:
96 | event.widget.state(["!invalid"])
97 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | share/python-wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 | MANIFEST
28 |
29 | # PyInstaller
30 | # Usually these files are written by a python script from a template
31 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
32 | *.manifest
33 | *.spec
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | .tox/
42 | .nox/
43 | .coverage
44 | .coverage.*
45 | .cache
46 | nosetests.xml
47 | coverage.xml
48 | *.cover
49 | *.py,cover
50 | .hypothesis/
51 | .pytest_cache/
52 | cover/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | .pybuilder/
76 | target/
77 |
78 | # Jupyter Notebook
79 | .ipynb_checkpoints
80 |
81 | # IPython
82 | profile_default/
83 | ipython_config.py
84 |
85 | # pyenv
86 | # For a library or package, you might want to ignore these files since the code is
87 | # intended to run in multiple environments; otherwise, check them in:
88 | # .python-version
89 |
90 | # pipenv
91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
94 | # install all needed dependencies.
95 | #Pipfile.lock
96 |
97 | # poetry
98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
99 | # This is especially recommended for binary packages to ensure reproducibility, and is more
100 | # commonly ignored for libraries.
101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
102 | #poetry.lock
103 |
104 | # pdm
105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
106 | #pdm.lock
107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
108 | # in version control.
109 | # https://pdm.fming.dev/#use-with-ide
110 | .pdm.toml
111 |
112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
113 | __pypackages__/
114 |
115 | # Celery stuff
116 | celerybeat-schedule
117 | celerybeat.pid
118 |
119 | # SageMath parsed files
120 | *.sage.py
121 |
122 | # Environments
123 | .env
124 | .venv
125 | env/
126 | venv/
127 | ENV/
128 | env.bak/
129 | venv.bak/
130 |
131 | # Spyder project settings
132 | .spyderproject
133 | .spyproject
134 |
135 | # Rope project settings
136 | .ropeproject
137 |
138 | # mkdocs documentation
139 | /site
140 |
141 | # mypy
142 | .mypy_cache/
143 | .dmypy.json
144 | dmypy.json
145 |
146 | # Pyre type checker
147 | .pyre/
148 |
149 | # pytype static type analyzer
150 | .pytype/
151 |
152 | # Cython debug symbols
153 | cython_debug/
154 |
155 | # PyCharm
156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
158 | # and can be added to the global gitignore or merged into this file. For a more nuclear
159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder.
160 | #.idea/
161 |
--------------------------------------------------------------------------------