From 44d1e6891ce0072ac49d25cb61ee853f3d948a5b Mon Sep 17 00:00:00 2001 From: Bruno Marques Date: Mon, 24 Jun 2024 11:27:25 +0100 Subject: [PATCH] Customizing title bar via PyWinRT Also updated theme.py to pywin32 ahead of #2263, in order to minimize the merging mess --- EDMarketConnector.py | 12 +++++++++++- requirements-dev.txt | 2 -- requirements.txt | 4 ++++ theme.py | 34 ++++++++++++---------------------- 4 files changed, 27 insertions(+), 25 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 087322d34..da99dc31e 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1990,7 +1990,7 @@ def validate_providers(): # Run the app -if __name__ == "__main__": # noqa: C901 +def main(): logger.info(f'Startup v{appversion()} : Running on Python v{sys.version}') logger.debug(f'''Platform: {sys.platform} {sys.platform == "win32" and sys.getwindowsversion()} argv[0]: {sys.argv[0]} @@ -2245,3 +2245,13 @@ def messagebox_not_py3(): logger.info("Ctrl+C Detected, Attempting Clean Shutdown") app.onexit() logger.info('Exiting') + + +if __name__ == '__main__': + if sys.platform == 'win32': + from winrt.microsoft.windows.applicationmodel.dynamicdependency import bootstrap + + with bootstrap.initialize(options=bootstrap.InitializeOptions.ON_NO_MATCH_SHOW_UI): + main() + else: + main() diff --git a/requirements-dev.txt b/requirements-dev.txt index 05c5ad291..c79908e36 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -42,8 +42,6 @@ pytest==8.2.0 pytest-cov==5.0.0 # Pytest code coverage support coverage[toml]==7.5.0 # pytest-cov dep. This is here to ensure that it includes TOML support for pyproject.toml configs coverage-conditional-plugin==0.9.0 -# For manipulating folder permissions and the like. -pywin32==306; sys_platform == 'win32' # All of the normal requirements diff --git a/requirements.txt b/requirements.txt index 22f0a360f..e6dbc8735 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,8 @@ requests==2.32.3 pillow==10.3.0 watchdog==4.0.0 simplesystray==0.1.0; sys_platform == 'win32' +pywin32==306; sys_platform == 'win32' +winrt-Microsoft.UI.Interop==2.1.0; sys_platform == 'win32' +winrt-Microsoft.UI.Windowing==2.1.0; sys_platform == 'win32' +winrt-Microsoft.Windows.ApplicationModel.DynamicDependency.Bootstrap==2.1.0; sys_platform == 'win32' semantic-version==2.10.0 diff --git a/theme.py b/theme.py index 2087a499d..016d803c6 100644 --- a/theme.py +++ b/theme.py @@ -24,7 +24,11 @@ from traceback import print_exc if sys.platform == 'win32': - from ctypes import windll, byref, c_int + import win32con + import win32gui + from winrt.microsoft.ui.interop import get_window_id_from_window + from winrt.microsoft.ui.windowing import AppWindow + from ctypes import windll FR_PRIVATE = 0x10 fonts_loaded = windll.gdi32.AddFontResourceExW(str(config.respath_path / 'EUROCAPS.TTF'), FR_PRIVATE, 0) if fonts_loaded < 1: @@ -185,33 +189,19 @@ def apply(self) -> None: self.root.withdraw() self.root.update_idletasks() # Size gets recalculated here if sys.platform == 'win32': - GWL_STYLE = -16 # noqa: N806 # ctypes - WS_MAXIMIZEBOX = 0x00010000 # noqa: N806 # ctypes - # tk8.5.9/win/tkWinWm.c:342 - GWL_EXSTYLE = -20 # noqa: N806 # ctypes - WS_EX_APPWINDOW = 0x00040000 # noqa: N806 # ctypes - WS_EX_LAYERED = 0x00080000 # noqa: N806 # ctypes - DWMWA_USE_IMMERSIVE_DARK_MODE = 20 # noqa: N806 # ctypes - DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19 # noqa: N806 # ctypes - GetWindowLongW = windll.user32.GetWindowLongW # noqa: N806 # ctypes - SetWindowLongW = windll.user32.SetWindowLongW # noqa: N806 # ctypes - DwmSetWindowAttribute = windll.dwmapi.DwmSetWindowAttribute # noqa: N806 # ctypes + hwnd = win32gui.GetParent(self.root.winfo_id()) + window = AppWindow.get_from_window_id(get_window_id_from_window(hwnd)) if theme == self.THEME_DEFAULT: - dark = 0 + window.title_bar.reset_to_default() else: - dark = 1 - - hwnd = windll.user32.GetParent(self.root.winfo_id()) - SetWindowLongW(hwnd, GWL_STYLE, GetWindowLongW(hwnd, GWL_STYLE) & ~WS_MAXIMIZEBOX) # disable maximize + window.title_bar.extends_content_into_title_bar = True if theme == self.THEME_TRANSPARENT: - SetWindowLongW(hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW | WS_EX_LAYERED) # Add to taskbar + win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, + win32con.WS_EX_APPWINDOW | win32con.WS_EX_LAYERED) # Add to taskbar else: - SetWindowLongW(hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW) # Add to taskbar - - if DwmSetWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, byref(c_int(dark)), 4) != 0: - DwmSetWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1, byref(c_int(dark)), 4) + win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, win32con.WS_EX_APPWINDOW) # Add to taskbar else: if dpy: xroot = Window()