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
.dwStyle
& WS_MINIMIZE
)
101 iPart
= WP_MINCAPTION
;
102 else if (wi
.dwExStyle
& WS_EX_TOOLWINDOW
)
103 iPart
= WP_SMALLCAPTION
;
104 else if (wi
.dwStyle
& WS_MAXIMIZE
)
105 iPart
= WP_MAXCAPTION
;
109 CaptionHeight
= wi
.cyWindowBorders
;
110 CaptionHeight
+= GetSystemMetrics(wi
.dwExStyle
& WS_EX_TOOLWINDOW
? SM_CYSMCAPTION
: SM_CYCAPTION
);
112 GetWindowRect(hWnd
, &rcWindow
);
113 rcWindow
.right
-= rcWindow
.left
;
114 rcWindow
.bottom
= CaptionHeight
;
118 hTheme
= MSSTYLES_OpenThemeClass(ActiveThemeFile
, NULL
, L
"WINDOW");
119 GetThemeBackgroundRegion(hTheme
, 0, iPart
, FS_ACTIVE
, &rcWindow
, &hrgn
);
120 CloseThemeData(hTheme
);
122 GetWindowRect(hWnd
, &rcWindow
);
123 rcWindow
.right
-= rcWindow
.left
;
124 rcWindow
.bottom
-= rcWindow
.top
;
125 rcWindow
.top
= CaptionHeight
;
127 hrgn1
= CreateRectRgnIndirect(&rcWindow
);
129 CombineRgn(hrgn
, hrgn
, hrgn1
, RGN_OR
);
133 user32ApiHook
.SetWindowRgn(hWnd
, hrgn
, TRUE
);
136 int OnPostWinPosChanged(HWND hWnd
, WINDOWPOS
* pWinPos
)
138 PWND_CONTEXT pcontext
;
141 /* We only proceed to change the window shape if it has a caption */
142 style
= GetWindowLongW(hWnd
, GWL_STYLE
);
143 if((style
& WS_CAPTION
)!=WS_CAPTION
)
146 /* Get theme data for this window */
147 pcontext
= ThemeGetWndContext(hWnd
);
148 if (pcontext
== NULL
)
151 /* Do not change the region of the window if its size wasn't changed */
152 if ((pWinPos
->flags
& SWP_NOSIZE
) != 0 && pcontext
->DirtyThemeRegion
== FALSE
)
155 /* We don't touch the shape of the window if the application sets it on its own */
156 if (pcontext
->HasAppDefinedRgn
== TRUE
)
159 /* Calling SetWindowRgn will call SetWindowPos again so we need to avoid this recursion */
160 if (pcontext
->UpdatingRgn
== TRUE
)
165 if(pcontext
->HasThemeRgn
)
167 pcontext
->HasThemeRgn
= FALSE
;
168 user32ApiHook
.SetWindowRgn(hWnd
, 0, TRUE
);
173 pcontext
->DirtyThemeRegion
= FALSE
;
174 pcontext
->HasThemeRgn
= TRUE
;
175 pcontext
->UpdatingRgn
= TRUE
;
176 SetThemeRegion(hWnd
);
177 pcontext
->UpdatingRgn
= FALSE
;
182 /**********************************************************************
186 static LRESULT CALLBACK
187 ThemeDefWindowProcW(HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
191 return user32ApiHook
.DefWindowProcW(hWnd
,
197 return ThemeWndProc(hWnd
,
201 user32ApiHook
.DefWindowProcW
);
204 static LRESULT CALLBACK
205 ThemeDefWindowProcA(HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
209 return user32ApiHook
.DefWindowProcA(hWnd
,
215 return ThemeWndProc(hWnd
,
219 user32ApiHook
.DefWindowProcA
);
222 static LRESULT CALLBACK
223 ThemePreWindowProc(HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, ULONG_PTR ret
,PDWORD unknown
)
227 case WM_THEMECHANGED
:
228 if (GetAncestor(hWnd
, GA_PARENT
) == GetDesktopWindow())
229 UXTHEME_LoadTheme(TRUE
);
232 PWND_CONTEXT pcontext
= ThemeGetWndContext(hWnd
);
233 if (pcontext
== NULL
)
235 pcontext
->DirtyThemeRegion
= TRUE
;
243 static LRESULT CALLBACK
244 ThemePostWindowProc(HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, ULONG_PTR ret
,PDWORD unknown
)
248 case WM_WINDOWPOSCHANGED
:
250 return OnPostWinPosChanged(hWnd
, (WINDOWPOS
*)lParam
);
254 ThemeDestroyWndContext(hWnd
);
262 int WINAPI
ThemeSetWindowRgn(HWND hWnd
, HRGN hRgn
, BOOL bRedraw
)
264 PWND_CONTEXT pcontext
= ThemeGetWndContext(hWnd
);
267 pcontext
->HasAppDefinedRgn
= TRUE
;
268 pcontext
->HasThemeRgn
= FALSE
;
271 return user32ApiHook
.SetWindowRgn(hWnd
, hRgn
, bRedraw
);
274 BOOL WINAPI
ThemeGetScrollInfo(HWND hwnd
, int fnBar
, LPSCROLLINFO lpsi
)
276 PWND_CONTEXT pwndContext
;
280 /* Avoid creating a window context if it is not needed */
284 style
= GetWindowLongW(hwnd
, GWL_STYLE
);
285 if((style
& (WS_HSCROLL
|WS_VSCROLL
))==0)
288 pwndContext
= ThemeGetWndContext(hwnd
);
289 if (pwndContext
== NULL
)
293 * Uxtheme needs to handle the tracking of the scrollbar itself
294 * This means than if an application needs to get the track position
295 * with GetScrollInfo, it will get wrong data. So uxtheme needs to
296 * hook it and set the correct tracking position itself
298 ret
= user32ApiHook
.GetScrollInfo(hwnd
, fnBar
, lpsi
);
300 (lpsi
->fMask
& SIF_TRACKPOS
) &&
301 pwndContext
->SCROLL_TrackingWin
== hwnd
&&
302 pwndContext
->SCROLL_TrackingBar
== fnBar
)
304 lpsi
->nTrackPos
= pwndContext
->SCROLL_TrackingVal
;
309 return user32ApiHook
.GetScrollInfo(hwnd
, fnBar
, lpsi
);
312 /**********************************************************************
317 ThemeInitApiHook(UAPIHK State
, PUSERAPIHOOK puah
)
319 if (!puah
|| State
!= uahLoadInit
)
321 UXTHEME_LoadTheme(FALSE
);
322 ThemeCleanupWndContext(NULL
, 0);
323 gbThemeHooksActive
= FALSE
;
327 gbThemeHooksActive
= TRUE
;
329 /* Store the original functions from user32 */
330 user32ApiHook
= *puah
;
332 puah
->DefWindowProcA
= ThemeDefWindowProcA
;
333 puah
->DefWindowProcW
= ThemeDefWindowProcW
;
334 puah
->PreWndProc
= ThemePreWindowProc
;
335 puah
->PostWndProc
= ThemePostWindowProc
;
336 puah
->PreDefDlgProc
= ThemePreWindowProc
;
337 puah
->PostDefDlgProc
= ThemePostWindowProc
;
338 puah
->DefWndProcArray
.MsgBitArray
= gabDWPmessages
;
339 puah
->DefWndProcArray
.Size
= UAHOWP_MAX_SIZE
;
340 puah
->WndProcArray
.MsgBitArray
= gabMSGPmessages
;
341 puah
->WndProcArray
.Size
= UAHOWP_MAX_SIZE
;
342 puah
->DlgProcArray
.MsgBitArray
= gabMSGPmessages
;
343 puah
->DlgProcArray
.Size
= UAHOWP_MAX_SIZE
;
345 puah
->SetWindowRgn
= ThemeSetWindowRgn
;
346 puah
->GetScrollInfo
= ThemeGetScrollInfo
;
348 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCPAINT
);
349 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCACTIVATE
);
350 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCMOUSEMOVE
);
351 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCMOUSELEAVE
);
352 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCHITTEST
);
353 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCLBUTTONDOWN
);
354 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCUAHDRAWCAPTION
);
355 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCUAHDRAWFRAME
);
356 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_SETTEXT
);
357 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_WINDOWPOSCHANGED
);
358 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_CONTEXTMENU
);
359 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_STYLECHANGED
);
360 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_SETICON
);
361 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCDESTROY
);
362 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_SYSCOMMAND
);
363 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_CTLCOLORMSGBOX
);
364 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_CTLCOLORBTN
);
365 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_CTLCOLORSTATIC
);
367 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_CREATE
);
368 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_SETTINGCHANGE
);
369 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_DRAWITEM
);
370 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_MEASUREITEM
);
371 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_WINDOWPOSCHANGING
);
372 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_WINDOWPOSCHANGED
);
373 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_STYLECHANGING
);
374 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_STYLECHANGED
);
375 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_NCCREATE
);
376 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_NCDESTROY
);
377 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_NCPAINT
);
378 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_MENUCHAR
);
379 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_MDISETMENU
);
380 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_THEMECHANGED
);
381 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_UAHINIT
);
383 UXTHEME_LoadTheme(TRUE
);
388 typedef BOOL (WINAPI
* PREGISTER_UAH_WINXP
)(HINSTANCE hInstance
, USERAPIHOOKPROC CallbackFunc
);
389 typedef BOOL (WINAPI
* PREGISTER_UUAH_WIN2003
)(PUSERAPIHOOKINFO puah
);
398 lpFunc
= GetProcAddress(GetModuleHandle("user32.dll"), "RegisterUserApiHook");
400 ZeroMemory(&osvi
, sizeof(OSVERSIONINFO
));
401 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
404 if ( osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 1)
406 PREGISTER_UAH_WINXP lpfuncxp
= (PREGISTER_UAH_WINXP
)lpFunc
;
407 ret
= lpfuncxp(hDllInst
, ThemeInitApiHook
);
409 else if ( osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 2)
411 PREGISTER_UUAH_WIN2003 lpfunc2003
= (PREGISTER_UUAH_WIN2003
)lpFunc
;
414 uah
.m_size
= sizeof(uah
);
415 uah
.m_dllname1
= L
"uxtheme.dll";
416 uah
.m_funname1
= L
"ThemeInitApiHook";
417 uah
.m_dllname2
= NULL
;
418 uah
.m_funname2
= NULL
;
420 ret
= lpfunc2003(&uah
);
428 UXTHEME_broadcast_msg (NULL
, WM_THEMECHANGED
);
438 ret
= UnregisterUserApiHook();
440 UXTHEME_broadcast_msg (NULL
, WM_THEMECHANGED
);
445 INT WINAPI
ClassicSystemParametersInfoW(UINT uiAction
, UINT uiParam
, PVOID pvParam
, UINT fWinIni
)
447 if (gbThemeHooksActive
)
449 return user32ApiHook
.SystemParametersInfoW(uiAction
, uiParam
, pvParam
, fWinIni
);
452 return SystemParametersInfoW(uiAction
, uiParam
, pvParam
, fWinIni
);
455 INT WINAPI
ClassicSystemParametersInfoA(UINT uiAction
, UINT uiParam
, PVOID pvParam
, UINT fWinIni
)
457 if (gbThemeHooksActive
)
459 return user32ApiHook
.SystemParametersInfoA(uiAction
, uiParam
, pvParam
, fWinIni
);
462 return SystemParametersInfoA(uiAction
, uiParam
, pvParam
, fWinIni
);
465 INT WINAPI
ClassicGetSystemMetrics(int nIndex
)
467 if (gbThemeHooksActive
)
469 return user32ApiHook
.GetSystemMetrics(nIndex
);
472 return GetSystemMetrics(nIndex
);
475 BOOL WINAPI
ClassicAdjustWindowRectEx(LPRECT lpRect
, DWORD dwStyle
, BOOL bMenu
, DWORD dwExStyle
)
477 if (gbThemeHooksActive
)
479 return user32ApiHook
.AdjustWindowRectEx(lpRect
, dwStyle
, bMenu
, dwExStyle
);
482 return AdjustWindowRectEx(lpRect
, dwStyle
, bMenu
, dwExStyle
);