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 return user32ApiHook
.DefWindowProcW(hWnd
,
195 return ThemeWndProc(hWnd
,
199 user32ApiHook
.DefWindowProcW
);
202 static LRESULT CALLBACK
203 ThemeDefWindowProcA(HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
207 return user32ApiHook
.DefWindowProcA(hWnd
,
213 return ThemeWndProc(hWnd
,
217 user32ApiHook
.DefWindowProcA
);
220 static LRESULT CALLBACK
221 ThemePreWindowProc(HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, ULONG_PTR ret
,PDWORD unknown
)
225 case WM_THEMECHANGED
:
226 if (GetAncestor(hWnd
, GA_PARENT
) == GetDesktopWindow())
227 UXTHEME_LoadTheme(TRUE
);
230 PWND_CONTEXT pcontext
= ThemeGetWndContext(hWnd
);
231 if (pcontext
== NULL
)
233 pcontext
->DirtyThemeRegion
= TRUE
;
241 static LRESULT CALLBACK
242 ThemePostWindowProc(HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, ULONG_PTR ret
,PDWORD unknown
)
246 case WM_WINDOWPOSCHANGED
:
248 return OnPostWinPosChanged(hWnd
, (WINDOWPOS
*)lParam
);
252 ThemeDestroyWndContext(hWnd
);
260 int WINAPI
ThemeSetWindowRgn(HWND hWnd
, HRGN hRgn
, BOOL bRedraw
)
262 PWND_CONTEXT pcontext
= ThemeGetWndContext(hWnd
);
265 pcontext
->HasAppDefinedRgn
= TRUE
;
266 pcontext
->HasThemeRgn
= FALSE
;
269 return user32ApiHook
.SetWindowRgn(hWnd
, hRgn
, bRedraw
);
272 BOOL WINAPI
ThemeGetScrollInfo(HWND hwnd
, int fnBar
, LPSCROLLINFO lpsi
)
274 PWND_CONTEXT pwndContext
;
278 /* Avoid creating a window context if it is not needed */
282 style
= GetWindowLongW(hwnd
, GWL_STYLE
);
283 if((style
& (WS_HSCROLL
|WS_VSCROLL
))==0)
286 pwndContext
= ThemeGetWndContext(hwnd
);
287 if (pwndContext
== NULL
)
291 * Uxtheme needs to handle the tracking of the scrollbar itself
292 * This means than if an application needs to get the track position
293 * with GetScrollInfo, it will get wrong data. So uxtheme needs to
294 * hook it and set the correct tracking position itself
296 ret
= user32ApiHook
.GetScrollInfo(hwnd
, fnBar
, lpsi
);
298 (lpsi
->fMask
& SIF_TRACKPOS
) &&
299 pwndContext
->SCROLL_TrackingWin
== hwnd
&&
300 pwndContext
->SCROLL_TrackingBar
== fnBar
)
302 lpsi
->nTrackPos
= pwndContext
->SCROLL_TrackingVal
;
307 return user32ApiHook
.GetScrollInfo(hwnd
, fnBar
, lpsi
);
310 /**********************************************************************
315 ThemeInitApiHook(UAPIHK State
, PUSERAPIHOOK puah
)
317 if (!puah
|| State
!= uahLoadInit
)
319 UXTHEME_LoadTheme(FALSE
);
320 ThemeCleanupWndContext(NULL
, 0);
321 gbThemeHooksActive
= FALSE
;
325 gbThemeHooksActive
= TRUE
;
327 /* Store the original functions from user32 */
328 user32ApiHook
= *puah
;
330 puah
->DefWindowProcA
= ThemeDefWindowProcA
;
331 puah
->DefWindowProcW
= ThemeDefWindowProcW
;
332 puah
->PreWndProc
= ThemePreWindowProc
;
333 puah
->PostWndProc
= ThemePostWindowProc
;
334 puah
->PreDefDlgProc
= ThemePreWindowProc
;
335 puah
->PostDefDlgProc
= ThemePostWindowProc
;
336 puah
->DefWndProcArray
.MsgBitArray
= gabDWPmessages
;
337 puah
->DefWndProcArray
.Size
= UAHOWP_MAX_SIZE
;
338 puah
->WndProcArray
.MsgBitArray
= gabMSGPmessages
;
339 puah
->WndProcArray
.Size
= UAHOWP_MAX_SIZE
;
340 puah
->DlgProcArray
.MsgBitArray
= gabMSGPmessages
;
341 puah
->DlgProcArray
.Size
= UAHOWP_MAX_SIZE
;
343 puah
->SetWindowRgn
= ThemeSetWindowRgn
;
344 puah
->GetScrollInfo
= ThemeGetScrollInfo
;
346 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCPAINT
);
347 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCACTIVATE
);
348 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCMOUSEMOVE
);
349 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCMOUSELEAVE
);
350 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCHITTEST
);
351 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCLBUTTONDOWN
);
352 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCUAHDRAWCAPTION
);
353 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCUAHDRAWFRAME
);
354 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_SETTEXT
);
355 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_WINDOWPOSCHANGED
);
356 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_CONTEXTMENU
);
357 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_STYLECHANGED
);
358 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_SETICON
);
359 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCDESTROY
);
360 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_SYSCOMMAND
);
361 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_CTLCOLORMSGBOX
);
362 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_CTLCOLORBTN
);
363 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_CTLCOLORSTATIC
);
365 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_CREATE
);
366 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_SETTINGCHANGE
);
367 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_DRAWITEM
);
368 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_MEASUREITEM
);
369 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_WINDOWPOSCHANGING
);
370 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_WINDOWPOSCHANGED
);
371 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_STYLECHANGING
);
372 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_STYLECHANGED
);
373 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_NCCREATE
);
374 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_NCDESTROY
);
375 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_NCPAINT
);
376 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_MENUCHAR
);
377 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_MDISETMENU
);
378 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_THEMECHANGED
);
379 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_UAHINIT
);
381 UXTHEME_LoadTheme(TRUE
);
386 typedef BOOL (WINAPI
* PREGISTER_UAH_WINXP
)(HINSTANCE hInstance
, USERAPIHOOKPROC CallbackFunc
);
387 typedef BOOL (WINAPI
* PREGISTER_UUAH_WIN2003
)(PUSERAPIHOOKINFO puah
);
396 lpFunc
= GetProcAddress(GetModuleHandle("user32.dll"), "RegisterUserApiHook");
398 ZeroMemory(&osvi
, sizeof(OSVERSIONINFO
));
399 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
402 if ( osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 1)
404 PREGISTER_UAH_WINXP lpfuncxp
= (PREGISTER_UAH_WINXP
)lpFunc
;
405 ret
= lpfuncxp(hDllInst
, ThemeInitApiHook
);
407 else if ( osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 2)
409 PREGISTER_UUAH_WIN2003 lpfunc2003
= (PREGISTER_UUAH_WIN2003
)lpFunc
;
412 uah
.m_size
= sizeof(uah
);
413 uah
.m_dllname1
= L
"uxtheme.dll";
414 uah
.m_funname1
= L
"ThemeInitApiHook";
415 uah
.m_dllname2
= NULL
;
416 uah
.m_funname2
= NULL
;
418 ret
= lpfunc2003(&uah
);
426 UXTHEME_broadcast_msg (NULL
, WM_THEMECHANGED
);
436 ret
= UnregisterUserApiHook();
438 UXTHEME_broadcast_msg (NULL
, WM_THEMECHANGED
);
443 INT WINAPI
ClassicSystemParametersInfoW(UINT uiAction
, UINT uiParam
, PVOID pvParam
, UINT fWinIni
)
445 if (gbThemeHooksActive
)
447 return user32ApiHook
.SystemParametersInfoW(uiAction
, uiParam
, pvParam
, fWinIni
);
450 return SystemParametersInfoW(uiAction
, uiParam
, pvParam
, fWinIni
);
453 INT WINAPI
ClassicSystemParametersInfoA(UINT uiAction
, UINT uiParam
, PVOID pvParam
, UINT fWinIni
)
455 if (gbThemeHooksActive
)
457 return user32ApiHook
.SystemParametersInfoA(uiAction
, uiParam
, pvParam
, fWinIni
);
460 return SystemParametersInfoA(uiAction
, uiParam
, pvParam
, fWinIni
);
463 INT WINAPI
ClassicGetSystemMetrics(int nIndex
)
465 if (gbThemeHooksActive
)
467 return user32ApiHook
.GetSystemMetrics(nIndex
);
470 return GetSystemMetrics(nIndex
);
473 BOOL WINAPI
ClassicAdjustWindowRectEx(LPRECT lpRect
, DWORD dwStyle
, BOOL bMenu
, DWORD dwExStyle
)
475 if (gbThemeHooksActive
)
477 return user32ApiHook
.AdjustWindowRectEx(lpRect
, dwStyle
, bMenu
, dwExStyle
);
480 return AdjustWindowRectEx(lpRect
, dwStyle
, bMenu
, dwExStyle
);