2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS uxtheme.dll
4 * FILE: dll/win32/uxtheme/themehooks.c
5 * PURPOSE: uxtheme user api hook functions
6 * PROGRAMMER: Giannis Adamopoulos
11 USERAPIHOOK user32ApiHook
;
12 BYTE gabDWPmessages
[UAHOWP_MAX_SIZE
];
13 BYTE gabMSGPmessages
[UAHOWP_MAX_SIZE
];
14 BOOL gbThemeHooksActive
= FALSE
;
16 PWND_CONTEXT
ThemeGetWndContext(HWND hWnd
)
18 PWND_CONTEXT pcontext
;
20 pcontext
= (PWND_CONTEXT
)GetPropW(hWnd
, (LPCWSTR
)MAKEINTATOM(atWndContext
));
23 pcontext
= HeapAlloc(GetProcessHeap(),
31 SetPropW( hWnd
, (LPCWSTR
)MAKEINTATOM(atWndContext
), pcontext
);
37 void ThemeDestroyWndContext(HWND hWnd
)
39 PWND_CONTEXT pContext
;
42 /*Do not destroy WND_CONTEXT of a window that belong to another process */
43 GetWindowThreadProcessId(hWnd
, &ProcessId
);
44 if(ProcessId
!= GetCurrentProcessId())
49 pContext
= (PWND_CONTEXT
)GetPropW(hWnd
, (LPCWSTR
)MAKEINTATOM(atWndContext
));
55 if(pContext
->HasThemeRgn
)
57 user32ApiHook
.SetWindowRgn(hWnd
, 0, TRUE
);
60 HeapFree(GetProcessHeap(), 0, pContext
);
62 SetPropW( hWnd
, (LPCWSTR
)MAKEINTATOM(atWndContext
), NULL
);
65 static BOOL CALLBACK
ThemeCleanupChildWndContext (HWND hWnd
, LPARAM msg
)
67 ThemeDestroyWndContext(hWnd
);
71 static BOOL CALLBACK
ThemeCleanupWndContext(HWND hWnd
, LPARAM msg
)
75 EnumWindows (ThemeCleanupWndContext
, 0);
79 ThemeDestroyWndContext(hWnd
);
80 EnumChildWindows (hWnd
, ThemeCleanupChildWndContext
, 0);
86 void SetThemeRegion(HWND hWnd
)
91 int CaptionHeight
, iPart
;
94 TRACE("SetThemeRegion %d\n", hWnd
);
96 wi
.cbSize
= sizeof(wi
);
97 GetWindowInfo(hWnd
, &wi
);
99 /* Get the caption part id */
100 if (wi
.dwExStyle
& WS_EX_TOOLWINDOW
)
101 iPart
= WP_SMALLCAPTION
;
102 else if (wi
.dwStyle
& WS_MAXIMIZE
)
103 iPart
= WP_MAXCAPTION
;
107 CaptionHeight
= wi
.cyWindowBorders
;
108 CaptionHeight
+= GetSystemMetrics(wi
.dwExStyle
& WS_EX_TOOLWINDOW
? SM_CYSMCAPTION
: SM_CYCAPTION
);
110 GetWindowRect(hWnd
, &rcWindow
);
111 rcWindow
.right
-= rcWindow
.left
;
112 rcWindow
.bottom
= CaptionHeight
;
116 hTheme
= MSSTYLES_OpenThemeClass(ActiveThemeFile
, NULL
, L
"WINDOW");
117 GetThemeBackgroundRegion(hTheme
, 0, iPart
, FS_ACTIVE
, &rcWindow
, &hrgn
);
118 CloseThemeData(hTheme
);
120 GetWindowRect(hWnd
, &rcWindow
);
121 rcWindow
.right
-= rcWindow
.left
;
122 rcWindow
.bottom
-= rcWindow
.top
;
123 rcWindow
.top
= CaptionHeight
;
125 hrgn1
= CreateRectRgnIndirect(&rcWindow
);
127 CombineRgn(hrgn
, hrgn
, hrgn1
, RGN_OR
);
131 user32ApiHook
.SetWindowRgn(hWnd
, hrgn
, TRUE
);
134 int OnPostWinPosChanged(HWND hWnd
, WINDOWPOS
* pWinPos
)
136 PWND_CONTEXT pcontext
;
139 /* We only proceed to change the window shape if it has a caption */
140 style
= GetWindowLongW(hWnd
, GWL_STYLE
);
141 if((style
& WS_CAPTION
)!=WS_CAPTION
)
144 /* Get theme data for this window */
145 pcontext
= ThemeGetWndContext(hWnd
);
146 if (pcontext
== NULL
)
149 /* Do not change the region of the window if its size wasn't changed */
150 if ((pWinPos
->flags
& SWP_NOSIZE
) != 0 && pcontext
->DirtyThemeRegion
== FALSE
)
153 /* We don't touch the shape of the window if the application sets it on its own */
154 if (pcontext
->HasAppDefinedRgn
== TRUE
)
157 /* Calling SetWindowRgn will call SetWindowPos again so we need to avoid this recursion */
158 if (pcontext
->UpdatingRgn
== TRUE
)
163 if(pcontext
->HasThemeRgn
)
165 pcontext
->HasThemeRgn
= FALSE
;
166 user32ApiHook
.SetWindowRgn(hWnd
, 0, TRUE
);
171 pcontext
->DirtyThemeRegion
= FALSE
;
172 pcontext
->HasThemeRgn
= TRUE
;
173 pcontext
->UpdatingRgn
= TRUE
;
174 SetThemeRegion(hWnd
);
175 pcontext
->UpdatingRgn
= FALSE
;
180 /**********************************************************************
184 static LRESULT CALLBACK
185 ThemeDefWindowProcW(HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
189 if (Msg
== WM_NCUAHDRAWCAPTION
)
191 user32ApiHook
.DrawCaption(hWnd
, NULL
, NULL
, 0);
195 return user32ApiHook
.DefWindowProcW(hWnd
,
201 return ThemeWndProc(hWnd
,
205 user32ApiHook
.DefWindowProcW
);
208 static LRESULT CALLBACK
209 ThemeDefWindowProcA(HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
213 if (Msg
== WM_NCUAHDRAWCAPTION
)
215 user32ApiHook
.DrawCaption(hWnd
, NULL
, NULL
, 0);
219 return user32ApiHook
.DefWindowProcA(hWnd
,
225 return ThemeWndProc(hWnd
,
229 user32ApiHook
.DefWindowProcA
);
232 static LRESULT CALLBACK
233 ThemePreWindowProc(HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, ULONG_PTR ret
,PDWORD unknown
)
237 case WM_THEMECHANGED
:
238 if (GetAncestor(hWnd
, GA_PARENT
) == GetDesktopWindow())
239 UXTHEME_LoadTheme(TRUE
);
242 PWND_CONTEXT pcontext
= ThemeGetWndContext(hWnd
);
243 if (pcontext
== NULL
)
245 pcontext
->DirtyThemeRegion
= TRUE
;
253 static LRESULT CALLBACK
254 ThemePostWindowProc(HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, ULONG_PTR ret
,PDWORD unknown
)
258 case WM_WINDOWPOSCHANGED
:
260 return OnPostWinPosChanged(hWnd
, (WINDOWPOS
*)lParam
);
264 ThemeDestroyWndContext(hWnd
);
272 int WINAPI
ThemeSetWindowRgn(HWND hWnd
, HRGN hRgn
, BOOL bRedraw
)
274 PWND_CONTEXT pcontext
= ThemeGetWndContext(hWnd
);
277 pcontext
->HasAppDefinedRgn
= TRUE
;
278 pcontext
->HasThemeRgn
= FALSE
;
281 return user32ApiHook
.SetWindowRgn(hWnd
, hRgn
, bRedraw
);
284 /**********************************************************************
289 ThemeInitApiHook(UAPIHK State
, PUSERAPIHOOK puah
)
291 if (!puah
|| State
!= uahLoadInit
)
293 UXTHEME_LoadTheme(FALSE
);
294 ThemeCleanupWndContext(NULL
, 0);
295 gbThemeHooksActive
= FALSE
;
299 gbThemeHooksActive
= TRUE
;
301 /* Store the original functions from user32 */
302 user32ApiHook
= *puah
;
304 puah
->DefWindowProcA
= ThemeDefWindowProcA
;
305 puah
->DefWindowProcW
= ThemeDefWindowProcW
;
306 puah
->PreWndProc
= ThemePreWindowProc
;
307 puah
->PostWndProc
= ThemePostWindowProc
;
308 puah
->PreDefDlgProc
= ThemePreWindowProc
;
309 puah
->PostDefDlgProc
= ThemePostWindowProc
;
310 puah
->DefWndProcArray
.MsgBitArray
= gabDWPmessages
;
311 puah
->DefWndProcArray
.Size
= UAHOWP_MAX_SIZE
;
312 puah
->WndProcArray
.MsgBitArray
= gabMSGPmessages
;
313 puah
->WndProcArray
.Size
= UAHOWP_MAX_SIZE
;
314 puah
->DlgProcArray
.MsgBitArray
= gabMSGPmessages
;
315 puah
->DlgProcArray
.Size
= UAHOWP_MAX_SIZE
;
317 puah
->SetWindowRgn
= ThemeSetWindowRgn
;
319 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCPAINT
);
320 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCACTIVATE
);
321 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCMOUSEMOVE
);
322 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCMOUSELEAVE
);
323 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCHITTEST
);
324 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCLBUTTONDOWN
);
325 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCUAHDRAWCAPTION
);
326 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCUAHDRAWFRAME
);
327 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_SETTEXT
);
328 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_WINDOWPOSCHANGED
);
329 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_CONTEXTMENU
);
330 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_STYLECHANGED
);
331 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_SETICON
);
332 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCDESTROY
);
333 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_SYSCOMMAND
);
334 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_CTLCOLORMSGBOX
);
335 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_CTLCOLORBTN
);
336 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_CTLCOLORSTATIC
);
338 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_CREATE
);
339 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_SETTINGCHANGE
);
340 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_DRAWITEM
);
341 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_MEASUREITEM
);
342 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_WINDOWPOSCHANGING
);
343 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_WINDOWPOSCHANGED
);
344 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_STYLECHANGING
);
345 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_STYLECHANGED
);
346 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_NCCREATE
);
347 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_NCDESTROY
);
348 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_NCPAINT
);
349 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_MENUCHAR
);
350 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_MDISETMENU
);
351 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_THEMECHANGED
);
352 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_UAHINIT
);
354 UXTHEME_LoadTheme(TRUE
);
359 typedef BOOL (WINAPI
* PREGISTER_UAH_WINXP
)(HINSTANCE hInstance
, USERAPIHOOKPROC CallbackFunc
);
360 typedef BOOL (WINAPI
* PREGISTER_UUAH_WIN2003
)(PUSERAPIHOOKINFO puah
);
369 lpFunc
= GetProcAddress(GetModuleHandle("user32.dll"), "RegisterUserApiHook");
371 ZeroMemory(&osvi
, sizeof(OSVERSIONINFO
));
372 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
375 if ( osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 1)
377 PREGISTER_UAH_WINXP lpfuncxp
= (PREGISTER_UAH_WINXP
)lpFunc
;
378 ret
= lpfuncxp(hDllInst
, ThemeInitApiHook
);
380 else if ( osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 2)
382 PREGISTER_UUAH_WIN2003 lpfunc2003
= (PREGISTER_UUAH_WIN2003
)lpFunc
;
385 uah
.m_size
= sizeof(uah
);
386 uah
.m_dllname1
= L
"uxtheme.dll";
387 uah
.m_funname1
= L
"ThemeInitApiHook";
388 uah
.m_dllname2
= NULL
;
389 uah
.m_funname2
= NULL
;
391 ret
= lpfunc2003(&uah
);
399 UXTHEME_broadcast_msg (NULL
, WM_THEMECHANGED
);
409 ret
= UnregisterUserApiHook();
411 UXTHEME_broadcast_msg (NULL
, WM_THEMECHANGED
);
416 INT WINAPI
ClassicSystemParametersInfoW(UINT uiAction
, UINT uiParam
, PVOID pvParam
, UINT fWinIni
)
418 if (gbThemeHooksActive
)
420 return user32ApiHook
.SystemParametersInfoW(uiAction
, uiParam
, pvParam
, fWinIni
);
423 return SystemParametersInfoW(uiAction
, uiParam
, pvParam
, fWinIni
);
426 INT WINAPI
ClassicSystemParametersInfoA(UINT uiAction
, UINT uiParam
, PVOID pvParam
, UINT fWinIni
)
428 if (gbThemeHooksActive
)
430 return user32ApiHook
.SystemParametersInfoA(uiAction
, uiParam
, pvParam
, fWinIni
);
433 return SystemParametersInfoA(uiAction
, uiParam
, pvParam
, fWinIni
);
436 INT WINAPI
ClassicGetSystemMetrics(int nIndex
)
438 if (gbThemeHooksActive
)
440 return user32ApiHook
.GetSystemMetrics(nIndex
);
443 return GetSystemMetrics(nIndex
);
446 BOOL WINAPI
ClassicAdjustWindowRectEx(LPRECT lpRect
, DWORD dwStyle
, BOOL bMenu
, DWORD dwExStyle
)
448 if (gbThemeHooksActive
)
450 return user32ApiHook
.AdjustWindowRectEx(lpRect
, dwStyle
, bMenu
, dwExStyle
);
453 return AdjustWindowRectEx(lpRect
, dwStyle
, bMenu
, dwExStyle
);