Last active
November 24, 2021 18:18
-
-
Save vednig/11e90db2eac5f57ac2769a2502173ee2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ctypes | |
from struct import Struct | |
from tkinter.constants import BOTTOM, NONE | |
import win32 | |
import winxptheme | |
import winnt | |
import win32ui | |
import win32service | |
import winshell | |
import win32api, win32con, win32gui | |
handle=0 | |
size_rect = (0,0,0,0) | |
class MyWindow: | |
def __init__(self): | |
win32gui.InitCommonControls() | |
self.hinst = win32gui.GetModuleHandle(None) | |
className = 'MyWndClass' | |
message_map = { | |
win32con.WM_DESTROY: self.OnDestroy, | |
} | |
wc = win32gui.WNDCLASS() | |
global handle | |
handle=wc | |
wc.style = win32con.CS_HREDRAW | win32con.CS_VREDRAW | |
wc.lpfnWndProc = win32_custom_title_bar_example_window_callback | |
wc.lpszClassName = className | |
win32gui.RegisterClass(wc) | |
style = win32con.WS_THICKFRAME | win32con.WS_SYSMENU | win32con.WS_MAXIMIZEBOX | win32con.WS_MINIMIZEBOX | win32con.WS_VISIBLE | win32con.WS_CAPTION | win32con.WS_EX_COMPOSITED | |
self.hwnd = win32gui.CreateWindow( | |
className, | |
'My win32api app', | |
style, | |
win32con.CW_USEDEFAULT, | |
win32con.CW_USEDEFAULT, | |
300, | |
300, | |
0, | |
0, | |
0, | |
None | |
) | |
#win32gui.UpdateWindow(self.hwnd) | |
#win32gui.ShowWindow(self.hwnd, win32con.SW_SHOW) | |
def OnDestroy(self, hwnd, message, wparam, lparam): | |
win32gui.PostQuitMessage(0) | |
return True | |
def win32_custom_title_bar_example_window_callback(handle,message,w_param,l_param): | |
title_bar_hovered_button = win32api.GetWindowLong(handle,-21) | |
if message==win32con.WM_NCCALCSIZE: | |
print(message) | |
if w_param: | |
print('W_PARAM ',w_param) | |
else: | |
print('Else: W_PARAM ',w_param) | |
return win32gui.DefWindowProc(handle,message,w_param,l_param) | |
dpi=user32.GetDpiForWindow(handle) | |
frame_x= user32.GetSystemMetricsForDpi(win32con.SM_CXFRAME, dpi) | |
frame_Y= user32.GetSystemMetricsForDpi(win32con.SM_CYFRAME, dpi) | |
padding= user32.GetSystemMetricsForDpi(win32con.SM_CXBORDER, dpi) | |
params= l_param | |
print(frame_x,frame_Y,padding) | |
'''#Just a Try Out Test to know no. of args | |
k=win32gui.Rectangle(l_param) | |
print(k)''' | |
lst = ctypes.cast(l_param, ctypes.POINTER(ctypes.c_int)) | |
print((lst[0]),3) | |
f=win32gui.RectInRegion((lst[0]),3) | |
print(f) | |
requested_client_rect= dict() | |
return 0 | |
elif message==win32con.WM_CREATE: | |
global size_rect | |
win32gui.GetWindowRect(handle,size_rect) | |
win32gui.SetWindowPos(handle,None,size_rect.left, size_rect.top,size_rect.right - size_rect.left, size_rect.bottom - size_rect.top,win32con.SWP_FRAMECHANGED | win32con.SWP_NOMOVE | win32con.SWP_NOSIZE) | |
return | |
print('Create:',message) | |
elif message==win32con.WM_ACTIVATE: | |
title_bar_rect = win32_titlebar_rect(handle) | |
win32gui.InvalidateRect(handle,title_bar_rect,False) | |
return win32gui.DefWindowProc(handle,message,w_param,l_param) | |
print('Activate:',message) | |
elif message==win32con.WM_NCHITTEST: | |
hit = win32gui.DefWindowProc(handle, message, w_param, l_param) | |
if hit==win32con.HTBOTTOMLEFT: | |
return hit | |
dpi = user32.GetDpiForWindow(handle) | |
frame_y = user32.GetSystemMetricsForDpi(win32con.SM_CYFRAME, dpi) | |
padding = user32.GetSystemMetricsForDpi(win32con.SM_CXBORDER, dpi) | |
cursor_point =[0,0] | |
cursor_point[0]=win32api.LOWORD(l_param) | |
cursor_point[1]=win32api.HIWORD(l_param) | |
cursor_point=tuple(cursor_point) | |
win32gui.ScreenToClient(handle, cursor_point) | |
if cursor_point[0] > 0 and cursor_point[1] < frame_y + padding: | |
return win32con.HTTOP | |
return win32con.HTCLIENT | |
elif message==win32con.WM_PAINT: | |
hasfocus= win32gui.GetFocus() | |
hdc, ps = win32gui.BeginPaint(handle) | |
print('Paint:',ps[2]) | |
#Paint Background | |
bg_color=win32api.RGB(200,250,230) | |
bg_brush=win32gui.CreateSolidBrush(bg_color) | |
win32gui.FillRect(hdc,ps[2],bg_brush) | |
win32gui.DeleteObject(bg_brush) | |
#Paint Title Bar | |
theme = uxtheme.OpenThemeData(handle,"Window") | |
title_bar_color=win32api.RGB(150,200,180) | |
title_bar_brush = win32gui.CreateSolidBrush(title_bar_color) | |
title_bar_hover_color = win32api.RGB(130,180,160) | |
title_bar_hover_brush = win32gui.CreateSolidBrush(title_bar_hover_color) | |
title_bar_rect = win32_titlebar_rect(handle) | |
print('title_bar_rect:',title_bar_rect) | |
#Titlebar Background | |
win32gui.FillRect(hdc,title_bar_rect,title_bar_brush) | |
win32gui.DeleteObject(title_bar_brush) | |
if hasfocus: | |
title_bar_item_color = win32api.RGB(33, 33, 33) | |
else: | |
title_bar_item_color = win32api.RGB(127, 127, 127) | |
button_icon_brush = win32gui.CreateSolidBrush(title_bar_item_color) | |
button_icon_pen = win32gui.CreatePen(win32con.PS_SOLID, 1, title_bar_item_color) | |
button_rects = win32_get_title_bar_button_rects(handle, title_bar_rect) | |
dpi = user32.GetDpiForWindow(handle) | |
icon_dimension = win32_dpi_scale(10,dpi) | |
# Minimize button | |
if title_bar_hovered_button == 1: | |
win32gui.FillRect(hdc, button_rects["minimize"], title_bar_hover_brush) | |
icon_rect = [0,0,0,0] | |
icon_rect[right] = int(icon_dimension) | |
icon_rect[bottom] = 1 | |
icon_rect=tuple(icon_rect) | |
win32_center_rect_in_rect(icon_rect, button_rects["minimize"]) | |
print(icon_rect, button_icon_brush) | |
win32gui.FillRect(hdc, icon_rect, button_icon_brush) | |
if title_bar_hovered_button == 2: | |
win32gui.FillRect(hdc, button_rects["minimize"], title_bar_hover_brush) | |
icon_rect = [0,0,0,0] | |
icon_rect[right] = int(icon_dimension) | |
icon_rect[bottom] = int(icon_dimension) | |
icon_rect = tuple(icon_rect) | |
win32_center_rect_in_rect(icon_rect, button_rects["minimize"]) | |
win32gui.SelectObject(hdc, button_icon_pen) | |
win32gui.SelectObject(hdc, win32gui.GetStockObject(win32con.HOLLOW_BRUSH)) | |
win32gui.Rectangle(hdc, icon_rect[left], icon_rect[top], icon_rect[right], icon_rect[bottom]) | |
custom_pen = 0 | |
if title_bar_hovered_button == 3: | |
fill_brush = win32gui.CreateSolidBrush(win32api.RGB(0xCC, 0, 0)) | |
win32gui.FillRect(hdc, button_rects['close'], fill_brush) | |
win32gui.DeleteObject(fill_brush) | |
custom_pen = win32gui.CreatePen(win32con.PS_SOLID, 1, win32api.RGB(0xFF, 0xFF, 0xFF)) | |
win32gui.SelectObject(hdc, custom_pen) | |
icon_rect = [0,0,0,0] | |
icon_rect[right] = int(icon_dimension) | |
icon_rect[bottom] = int(icon_dimension) | |
icon_rect=tuple(icon_rect) | |
win32_center_rect_in_rect(icon_rect, button_rects['close']) | |
win32gui.MoveToEx(hdc, icon_rect[left], icon_rect[top]) | |
win32gui.LineTo(hdc, icon_rect[right] + 1, icon_rect[bottom] + 1) | |
win32gui.MoveToEx(hdc, icon_rect[left], icon_rect[bottom]) | |
win32gui.LineTo(hdc, icon_rect[right] + 1, icon_rect[top] - 1) | |
if custom_pen: | |
win32gui.DeleteObject(custom_pen) | |
win32gui.DeleteObject(title_bar_hover_brush) | |
win32gui.DeleteObject(button_icon_brush) | |
win32gui.DeleteObject(button_icon_pen) | |
# Draw window title | |
old_font = NONE | |
#get system font theme | |
old_font='Arial' | |
title_text_buffer = '' | |
buffer_length = 1 | |
user32.GetWindowTextW(handle, title_text_buffer, buffer_length) | |
title_bar_text_rect = title_bar_rect | |
text_padding = 10 | |
title_bar_text_rect=list(title_bar_text_rect) | |
title_bar_text_rect[left] += int(text_padding) | |
title_bar_text_rect[right] = int(button_rects['minimize'][left] - text_padding) | |
title_bar_text_rect = tuple(title_bar_text_rect) | |
draw_theme_options={} | |
print( win32con.DM_TTOPTION) | |
draw_theme_options['dwFlags']= win32con.DM_TTOPTION | |
draw_theme_options['crText'] = title_bar_item_color | |
print(theme,hdc,title_text_buffer,-1,title_bar_text_rect,win32con.DT_VCENTER | win32con.DT_SINGLELINE | win32con.DT_WORD_ELLIPSIS) | |
win32gui.DrawText(theme,title_text_buffer,-1,title_bar_text_rect,win32con.DT_VCENTER | win32con.DT_SINGLELINE | win32con.DT_WORD_ELLIPSIS) | |
shadow_color = win32api.RGB(100, 100, 100) | |
if hasfocus: | |
fake_top_shadow_color = shadow_color | |
else: | |
print(int(win32con.GetRValue(title_bar_color) + win32con.GetRValue(shadow_color)) / 2,int(win32con.GetGValue(title_bar_color) + win32con.GetGValue(shadow_color)) / 2,int(win32con.GetBValue(title_bar_color) + win32con.GetBValue(shadow_color)) / 2) | |
fake_top_shadow_color = win32api.RGB(int((win32con.GetRValue(title_bar_color) + win32con.GetRValue(shadow_color)) / 2),int((win32con.GetGValue(title_bar_color) + win32con.GetGValue(shadow_color)) / 2),int((win32con.GetBValue(title_bar_color) + win32con.GetBValue(shadow_color)) / 2)) | |
fake_top_shadow_brush = win32gui.CreateSolidBrush(fake_top_shadow_color) | |
fake_top_shadow_rect = win32_fake_shadow_rect(handle) | |
win32gui.FillRect(hdc, fake_top_shadow_rect, fake_top_shadow_brush) | |
win32gui.DeleteObject(fake_top_shadow_brush) | |
win32gui.EndPaint(handle,ps) | |
return 2 | |
elif message==win32con.WM_DESTROY: | |
win32api.PostQuitMessage(0) | |
return 0 | |
elif message==win32con.WM_NCMOUSEMOVE: | |
return win32gui.DefWindowProc(handle, message, w_param, l_param); | |
elif message==win32con.WM_MOUSEMOVE: | |
return win32gui.DefWindowProc(handle, message, w_param, l_param); | |
elif message==win32con.WM_NCLBUTTONDOWN: | |
return win32gui.DefWindowProc(handle, message, w_param, l_param); | |
elif message==win32con.WM_NCLBUTTONUP: | |
return win32gui.DefWindowProc(handle, message, w_param, l_param) | |
elif message==win32con.WM_SETCURSOR: | |
return 0 | |
else: | |
print('Else: ',message) | |
return win32gui.DefWindowProc(handle,message,w_param,l_param) | |
left=0 | |
top=1 | |
right=2 | |
bottom=3 | |
def win32_titlebar_rect(handle): | |
title_bar_size ={0} | |
top_and_bottom_borders = 2 | |
theme = uxtheme.OpenThemeData(handle,'Window') | |
dpi = user32.GetDpiForWindow(handle) | |
print(title_bar_size) | |
uxtheme.GetThemePartSize(theme,NONE, 1, 1, None, 1, 0) | |
uxtheme.CloseThemeData(theme) | |
height = win32_dpi_scale(1,dpi) | |
rect = win32gui.GetClientRect(handle) | |
print('RECT: ',rect) | |
y=list(rect) | |
y[bottom] = int(y[top]+height) | |
rect = tuple(y) | |
print('RECT: ',rect) | |
return rect | |
def win32_dpi_scale(value,dpi): | |
return ((value*dpi)/96) | |
def win32_get_title_bar_button_rects(handle,title_bar_rects): | |
dpi = user32.GetDpiForWindow(handle) | |
button_width = win32_dpi_scale(47,dpi) | |
button_rects={} | |
button_rects['close'] = title_bar_rects | |
x=(0,0) | |
x=list(x) | |
x[0]+=1 | |
x=tuple(x) | |
print(x) | |
print('Close.Top',button_rects['close']) | |
k=list(button_rects['close']) | |
k[top] += 1 | |
k[left] = k[right] - button_width | |
button_rects['close']=tuple(k) | |
button_rects['maximize'] = button_rects['close'] | |
p = list(button_rects['maximize']) | |
p[left] -= button_width | |
p[right] -= button_width | |
button_rects['maximize'] = tuple(p) | |
button_rects['minimize'] = button_rects['maximize'] | |
l=list(button_rects['minimize']) | |
l[left] -= button_width | |
l[right] -= button_width | |
button_rects['minimize']=tuple(l) | |
return button_rects | |
def win32_fake_shadow_rect(handle): | |
rect=[0,0,0,0] | |
rect=list( win32gui.GetClientRect(handle)) | |
rect[bottom] = rect[top] | |
return tuple(rect) | |
def win32_center_rect_in_rect(to_center,outer_rect): | |
to_width = to_center[right] - to_center[left] | |
to_height = to_center[bottom] - to_center[top] | |
outer_width = outer_rect[right] - outer_rect[left] | |
outer_height = outer_rect[bottom] - outer_rect[top] | |
padding_x = (outer_width-to_width)/2 | |
padding_y = (outer_height-to_height)/2 | |
to_center = list(to_center) | |
to_center[left] = outer_rect[left]+ padding_x | |
to_center[top] = outer_rect[top] + padding_y | |
to_center[right] = to_center[left]+ to_width | |
to_center[bottom] = to_center[top] + to_height | |
to_center = tuple(to_center) | |
import ctypes | |
user32 = ctypes.windll.user32 | |
uxtheme = ctypes.windll.uxtheme | |
gdi32 =ctypes.windll.gdi32 | |
screensize = user32.GetSystemMetrics(78), user32.GetSystemMetrics(79) | |
n=user32.GetDpiForWindow(handle) | |
print(screensize,n) | |
w = MyWindow() | |
win32gui.PumpMessages() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment