removed scaling with ctypes shcore for Windows < 8.1

This commit is contained in:
Tom Schimansky 2022-05-26 19:16:01 +02:00
parent 34da9505e9
commit a1afc3056b
6 changed files with 45 additions and 32 deletions

View File

@ -22,6 +22,9 @@ if sys.platform == "darwin":
else: else:
DrawEngine.preferred_drawing_method = "font_shapes" DrawEngine.preferred_drawing_method = "font_shapes"
if sys.platform.startswith("win") and sys.getwindowsversion().build < 9000: # No automatic scaling on Windows < 8.1
ScalingTracker.deactivate_automatic_dpi_awareness = True
# load Roboto fonts (used on Windows/Linux) # load Roboto fonts (used on Windows/Linux)
script_directory = os.path.dirname(os.path.abspath(__file__)) script_directory = os.path.dirname(os.path.abspath(__file__))
FontManager.load_font(os.path.join(script_directory, "assets", "fonts", "Roboto", "Roboto-Regular.ttf")) FontManager.load_font(os.path.join(script_directory, "assets", "fonts", "Roboto", "Roboto-Regular.ttf"))

View File

@ -124,7 +124,7 @@ class ScalingTracker:
@classmethod @classmethod
def activate_high_dpi_awareness(cls): def activate_high_dpi_awareness(cls):
""" make process DPI aware, customtkinter elemets will get scaled automatically, """ make process DPI aware, customtkinter elements will get scaled automatically,
only gets activated when CTk object is created """ only gets activated when CTk object is created """
if not cls.deactivate_automatic_dpi_awareness: if not cls.deactivate_automatic_dpi_awareness:
@ -135,28 +135,30 @@ class ScalingTracker:
from ctypes import windll from ctypes import windll
windll.shcore.SetProcessDpiAwareness(2) windll.shcore.SetProcessDpiAwareness(2)
# Microsoft Docs: https://docs.microsoft.com/en-us/windows/win32/api/shellscalingapi/ne-shellscalingapi-process_dpi_awareness # Microsoft Docs: https://docs.microsoft.com/en-us/windows/win32/api/shellscalingapi/ne-shellscalingapi-process_dpi_awareness
else: else:
pass # DPI awareness on Linux not implemented pass # DPI awareness on Linux not implemented
@classmethod @classmethod
def get_window_dpi_scaling(cls, window) -> float: def get_window_dpi_scaling(cls, window) -> float:
if sys.platform == "darwin": if not cls.deactivate_automatic_dpi_awareness:
return 1 # scaling works automatically on macOS if sys.platform == "darwin":
return 1 # scaling works automatically on macOS
elif sys.platform.startswith("win"): elif sys.platform.startswith("win"):
from ctypes import windll, pointer, wintypes from ctypes import windll, pointer, wintypes
DPI100pc = 96 # DPI 96 is 100% scaling DPI100pc = 96 # DPI 96 is 100% scaling
DPI_type = 0 # MDT_EFFECTIVE_DPI = 0, MDT_ANGULAR_DPI = 1, MDT_RAW_DPI = 2 DPI_type = 0 # MDT_EFFECTIVE_DPI = 0, MDT_ANGULAR_DPI = 1, MDT_RAW_DPI = 2
window_hwnd = wintypes.HWND(window.winfo_id()) window_hwnd = wintypes.HWND(window.winfo_id())
monitor_handle = windll.user32.MonitorFromWindow(window_hwnd, wintypes.DWORD(2)) # MONITOR_DEFAULTTONEAREST = 2 monitor_handle = windll.user32.MonitorFromWindow(window_hwnd, wintypes.DWORD(2)) # MONITOR_DEFAULTTONEAREST = 2
x_dpi, y_dpi = wintypes.UINT(), wintypes.UINT() x_dpi, y_dpi = wintypes.UINT(), wintypes.UINT()
windll.shcore.GetDpiForMonitor(monitor_handle, DPI_type, pointer(x_dpi), pointer(y_dpi)) windll.shcore.GetDpiForMonitor(monitor_handle, DPI_type, pointer(x_dpi), pointer(y_dpi))
return (x_dpi.value + y_dpi.value) / (2 * DPI100pc) return (x_dpi.value + y_dpi.value) / (2 * DPI100pc)
else:
return 1 # DPI awareness on Linux not implemented
else: else:
return 1 # DPI awareness on Linux not implemented return 1
@classmethod @classmethod
def check_dpi_scaling(cls): def check_dpi_scaling(cls):

View File

@ -93,7 +93,7 @@ class CTkOptionMenu(CTkBaseClass):
height=self.apply_widget_scaling(self.desired_height)) height=self.apply_widget_scaling(self.desired_height))
self.draw() self.draw()
def set_dimensions(self, width=None, height=None): def set_dimensions(self, width: int = None, height: int = None):
super().set_dimensions(width, height) super().set_dimensions(width, height)
self.canvas.configure(width=self.apply_widget_scaling(self.desired_width), self.canvas.configure(width=self.apply_widget_scaling(self.desired_width),
@ -148,10 +148,9 @@ class CTkOptionMenu(CTkBaseClass):
y_position=self.winfo_rooty() + self.current_height + 4, y_position=self.winfo_rooty() + self.current_height + 4,
width=self.current_width, width=self.current_width,
values=self.values, values=self.values,
command=self.set_value) command=self.set)
def set_value(self, value): def set(self, value: str):
print("set value", value)
self.current_value = value self.current_value = value
if self.text_label is not None: if self.text_label is not None:
@ -159,6 +158,9 @@ class CTkOptionMenu(CTkBaseClass):
else: else:
self.draw() self.draw()
def get(self) -> str:
return self.current_value
def configure(self, *args, **kwargs): def configure(self, *args, **kwargs):
require_redraw = False # some attribute changes require a call of self.draw() at the end require_redraw = False # some attribute changes require a call of self.draw() at the end
@ -181,10 +183,15 @@ class CTkOptionMenu(CTkBaseClass):
require_redraw = True require_redraw = True
del kwargs["bg_color"] del kwargs["bg_color"]
if "hover_color" in kwargs: if "button_color" in kwargs:
self.hover_color = kwargs["hover_color"] self.button_color = kwargs["button_color"]
require_redraw = True require_redraw = True
del kwargs["hover_color"] del kwargs["button_color"]
if "button_hover_color" in kwargs:
self.button_hover_color = kwargs["button_hover_color"]
require_redraw = True
del kwargs["button_hover_color"]
if "text_color" in kwargs: if "text_color" in kwargs:
self.text_color = kwargs["text_color"] self.text_color = kwargs["text_color"]
@ -252,10 +259,10 @@ class CTkOptionMenu(CTkBaseClass):
if self.state is not tkinter.DISABLED: if self.state is not tkinter.DISABLED:
self.open_dropdown_menu() self.open_dropdown_menu()
if self.function is not None: # click animation: change color with .on_leave() and back to normal after 100ms with click_animation()
# click animation: change color with .on_leave() and back to normal after 100ms with click_animation() self.on_leave()
self.on_leave() self.click_animation_running = True
self.click_animation_running = True self.after(100, self.click_animation)
self.after(100, self.click_animation)
if self.function is not None:
self.function() self.function()

View File

@ -58,7 +58,4 @@ s_var = tkinter.StringVar(value="on")
switch_1 = customtkinter.CTkSwitch(master=frame_1) switch_1 = customtkinter.CTkSwitch(master=frame_1)
switch_1.pack(pady=y_padding, padx=10) switch_1.pack(pady=y_padding, padx=10)
optionmenu_1 = customtkinter.CTkOptionMenu(master=frame_1, values=["option 1", "option 2", "number 42"])
optionmenu_1.pack(pady=y_padding, padx=10)
app.mainloop() app.mainloop()

View File

@ -2,7 +2,7 @@
name = customtkinter name = customtkinter
version = 4.1.0 version = 4.1.0
description = Create modern looking GUIs with Python description = Create modern looking GUIs with Python
long_description = file: README.md long_description = file: Readme.md
long_description_content_type = text/markdown long_description_content_type = text/markdown
url = https://github.com/TomSchimansky/CustomTkinter url = https://github.com/TomSchimansky/CustomTkinter
author = Tom Schimansky author = Tom Schimansky

View File

@ -1,4 +1,5 @@
from tkinter import * from tkinter import *
import customtkinter
ws = Tk() ws = Tk()
ws.title('PythonGuides') ws.title('PythonGuides')
@ -13,7 +14,7 @@ countries = ['Bahamas','Canada', 'Cuba','United States']
# setting variable for Integers # setting variable for Integers
variable = StringVar() variable = StringVar()
variable.set(countries[3]) variable.set("test")
# creating widget # creating widget
dropdown = OptionMenu( dropdown = OptionMenu(
@ -24,7 +25,10 @@ dropdown = OptionMenu(
) )
# positioning widget # positioning widget
dropdown.pack(expand=True) dropdown.pack(pady=10, padx=10)
optionmenu_1 = customtkinter.CTkOptionMenu(master=ws, values=["option 1", "option 2", "number 42"])
optionmenu_1.pack(pady=10, padx=10)
# infinite loop # infinite loop
ws.mainloop() ws.mainloop()