Skip to content

Instantly share code, notes, and snippets.

@vednig
Last active November 24, 2021 18:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vednig/11e90db2eac5f57ac2769a2502173ee2 to your computer and use it in GitHub Desktop.
Save vednig/11e90db2eac5f57ac2769a2502173ee2 to your computer and use it in GitHub Desktop.
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