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 BYTE gabDLGPmessages
[UAHOWP_MAX_SIZE
];
15 BOOL gbThemeHooksActive
= FALSE
;
17 PWND_CONTEXT
ThemeGetWndContext(HWND hWnd
)
19 PWND_CONTEXT pcontext
;
21 pcontext
= (PWND_CONTEXT
)GetPropW(hWnd
, (LPCWSTR
)MAKEINTATOM(atWndContext
));
24 pcontext
= HeapAlloc(GetProcessHeap(),
32 SetPropW( hWnd
, (LPCWSTR
)MAKEINTATOM(atWndContext
), pcontext
);
38 void ThemeDestroyWndContext(HWND hWnd
)
40 PWND_CONTEXT pContext
;
43 /*Do not destroy WND_CONTEXT of a window that belong to another process */
44 GetWindowThreadProcessId(hWnd
, &ProcessId
);
45 if(ProcessId
!= GetCurrentProcessId())
50 pContext
= (PWND_CONTEXT
)GetPropW(hWnd
, (LPCWSTR
)MAKEINTATOM(atWndContext
));
56 if(pContext
->HasThemeRgn
)
58 user32ApiHook
.SetWindowRgn(hWnd
, 0, TRUE
);
61 if (pContext
->hTabBackgroundBrush
!= NULL
)
63 CloseThemeData(GetWindowTheme(hWnd
));
65 DeleteObject(pContext
->hTabBackgroundBrush
);
66 pContext
->hTabBackgroundBrush
= NULL
;
69 if (pContext
->hTabBackgroundBmp
!= NULL
)
71 DeleteObject(pContext
->hTabBackgroundBmp
);
72 pContext
->hTabBackgroundBmp
= NULL
;
75 HeapFree(GetProcessHeap(), 0, pContext
);
77 SetPropW( hWnd
, (LPCWSTR
)MAKEINTATOM(atWndContext
), NULL
);
80 static BOOL CALLBACK
ThemeCleanupChildWndContext (HWND hWnd
, LPARAM msg
)
82 ThemeDestroyWndContext(hWnd
);
86 static BOOL CALLBACK
ThemeCleanupWndContext(HWND hWnd
, LPARAM msg
)
90 EnumWindows (ThemeCleanupWndContext
, 0);
94 ThemeDestroyWndContext(hWnd
);
95 EnumChildWindows (hWnd
, ThemeCleanupChildWndContext
, 0);
101 void SetThemeRegion(HWND hWnd
)
106 int CaptionHeight
, iPart
;
109 TRACE("SetThemeRegion %d\n", hWnd
);
111 wi
.cbSize
= sizeof(wi
);
112 GetWindowInfo(hWnd
, &wi
);
114 /* Get the caption part id */
115 if (wi
.dwStyle
& WS_MINIMIZE
)
116 iPart
= WP_MINCAPTION
;
117 else if (wi
.dwExStyle
& WS_EX_TOOLWINDOW
)
118 iPart
= WP_SMALLCAPTION
;
119 else if (wi
.dwStyle
& WS_MAXIMIZE
)
120 iPart
= WP_MAXCAPTION
;
124 CaptionHeight
= wi
.cyWindowBorders
;
125 CaptionHeight
+= GetSystemMetrics(wi
.dwExStyle
& WS_EX_TOOLWINDOW
? SM_CYSMCAPTION
: SM_CYCAPTION
);
127 GetWindowRect(hWnd
, &rcWindow
);
128 rcWindow
.right
-= rcWindow
.left
;
129 rcWindow
.bottom
= CaptionHeight
;
133 hTheme
= MSSTYLES_OpenThemeClass(ActiveThemeFile
, NULL
, L
"WINDOW");
134 GetThemeBackgroundRegion(hTheme
, 0, iPart
, FS_ACTIVE
, &rcWindow
, &hrgn
);
135 CloseThemeData(hTheme
);
137 GetWindowRect(hWnd
, &rcWindow
);
138 rcWindow
.right
-= rcWindow
.left
;
139 rcWindow
.bottom
-= rcWindow
.top
;
140 rcWindow
.top
= CaptionHeight
;
142 hrgn1
= CreateRectRgnIndirect(&rcWindow
);
144 CombineRgn(hrgn
, hrgn
, hrgn1
, RGN_OR
);
148 user32ApiHook
.SetWindowRgn(hWnd
, hrgn
, TRUE
);
151 int OnPostWinPosChanged(HWND hWnd
, WINDOWPOS
* pWinPos
)
153 PWND_CONTEXT pcontext
;
156 /* We only proceed to change the window shape if it has a caption */
157 style
= GetWindowLongW(hWnd
, GWL_STYLE
);
158 if((style
& WS_CAPTION
)!=WS_CAPTION
)
161 /* Get theme data for this window */
162 pcontext
= ThemeGetWndContext(hWnd
);
163 if (pcontext
== NULL
)
166 /* Do not change the region of the window if its size wasn't changed */
167 if ((pWinPos
->flags
& SWP_NOSIZE
) != 0 && pcontext
->DirtyThemeRegion
== FALSE
)
170 /* We don't touch the shape of the window if the application sets it on its own */
171 if (pcontext
->HasAppDefinedRgn
== TRUE
)
174 /* Calling SetWindowRgn will call SetWindowPos again so we need to avoid this recursion */
175 if (pcontext
->UpdatingRgn
== TRUE
)
180 if(pcontext
->HasThemeRgn
)
182 pcontext
->HasThemeRgn
= FALSE
;
183 user32ApiHook
.SetWindowRgn(hWnd
, 0, TRUE
);
188 pcontext
->DirtyThemeRegion
= FALSE
;
189 pcontext
->HasThemeRgn
= TRUE
;
190 pcontext
->UpdatingRgn
= TRUE
;
191 SetThemeRegion(hWnd
);
192 pcontext
->UpdatingRgn
= FALSE
;
197 /**********************************************************************
201 static LRESULT CALLBACK
202 ThemeDefWindowProcW(HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
206 return user32ApiHook
.DefWindowProcW(hWnd
,
212 return ThemeWndProc(hWnd
,
216 user32ApiHook
.DefWindowProcW
);
219 static LRESULT CALLBACK
220 ThemeDefWindowProcA(HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
224 return user32ApiHook
.DefWindowProcA(hWnd
,
230 return ThemeWndProc(hWnd
,
234 user32ApiHook
.DefWindowProcA
);
237 static LRESULT CALLBACK
238 ThemePreWindowProc(HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, ULONG_PTR ret
,PDWORD unknown
)
242 case WM_THEMECHANGED
:
244 PWND_CONTEXT pcontext
= ThemeGetWndContext(hWnd
);
246 if (GetAncestor(hWnd
, GA_PARENT
) == GetDesktopWindow())
247 UXTHEME_LoadTheme(TRUE
);
249 if (pcontext
== NULL
)
252 if (pcontext
->hTabBackgroundBrush
!= NULL
)
254 DeleteObject(pcontext
->hTabBackgroundBrush
);
255 pcontext
->hTabBackgroundBrush
= NULL
;
258 if (pcontext
->hTabBackgroundBmp
!= NULL
)
260 DeleteObject(pcontext
->hTabBackgroundBmp
);
261 pcontext
->hTabBackgroundBmp
= NULL
;
266 PWND_CONTEXT pcontext
= ThemeGetWndContext(hWnd
);
267 if (pcontext
== NULL
)
269 pcontext
->DirtyThemeRegion
= TRUE
;
277 static LRESULT CALLBACK
278 ThemePostWindowProc(HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, ULONG_PTR ret
,PDWORD unknown
)
282 case WM_WINDOWPOSCHANGED
:
284 return OnPostWinPosChanged(hWnd
, (WINDOWPOS
*)lParam
);
288 ThemeDestroyWndContext(hWnd
);
296 HRESULT
GetDiaogTextureBrush(HTHEME theme
, HWND hwnd
, HDC hdc
, HBRUSH
* result
, BOOL changeOrigin
)
298 PWND_CONTEXT pcontext
;
300 pcontext
= ThemeGetWndContext(hwnd
);
301 if (pcontext
== NULL
)
304 if (pcontext
->hTabBackgroundBrush
== NULL
)
310 UXTHEME_LoadImage(theme
, 0, TABP_BODY
, 0, &dummy
, FALSE
, &hbmp
, &bmpRect
, &hasImageAlpha
);
313 /* Unfortunately SetBrushOrgEx doesn't work at all */
314 RECT rcWindow
, rcParent
;
316 HDC hdcPattern
, hdcHackPattern
;
317 HBITMAP hbmpOld1
, hbmpold2
, hbmpHack
;
319 GetWindowRect(hwnd
, &rcWindow
);
320 GetWindowRect(GetParent(hwnd
), &rcParent
);
321 y
= (rcWindow
.top
- rcParent
.top
) % bmpRect
.bottom
;
323 hdcPattern
= CreateCompatibleDC(hdc
);
324 hbmpOld1
= (HBITMAP
)SelectObject(hdcPattern
, hbmp
);
326 hdcHackPattern
= CreateCompatibleDC(hdc
);
327 hbmpHack
= CreateCompatibleBitmap(hdc
, bmpRect
.right
, bmpRect
.bottom
);
328 hbmpold2
= (HBITMAP
)SelectObject(hdcHackPattern
, hbmpHack
);
330 BitBlt(hdcHackPattern
, 0, 0, bmpRect
.right
, bmpRect
.bottom
- y
, hdcPattern
, 0, y
, SRCCOPY
);
331 BitBlt(hdcHackPattern
, 0, bmpRect
.bottom
- y
, bmpRect
.right
, y
, hdcPattern
, 0, 0, SRCCOPY
);
333 hbmpold2
= (HBITMAP
)SelectObject(hdcHackPattern
, hbmpold2
);
334 hbmpOld1
= (HBITMAP
)SelectObject(hdcPattern
, hbmpOld1
);
336 DeleteDC(hdcPattern
);
337 DeleteDC(hdcHackPattern
);
339 /* Keep the handle of the bitmap we created so that it can be used later */
340 pcontext
->hTabBackgroundBmp
= hbmpHack
;
344 /* hbmp is cached so there is no need to free it */
345 pcontext
->hTabBackgroundBrush
= CreatePatternBrush(hbmp
);
348 if (!pcontext
->hTabBackgroundBrush
)
351 *result
= pcontext
->hTabBackgroundBrush
;
355 void HackFillStaticBg(HWND hwnd
, HDC hdc
, HBRUSH
* result
)
359 GetClientRect(hwnd
, &rcStatic
);
360 FillRect(hdc
, &rcStatic
, *result
);
362 SetBkMode (hdc
, TRANSPARENT
);
363 *result
= GetStockObject (NULL_BRUSH
);
366 static LRESULT CALLBACK
367 ThemeDlgPreWindowProc(HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, ULONG_PTR ret
,PDWORD unknown
)
372 static LRESULT CALLBACK
373 ThemeDlgPostWindowProc(HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, ULONG_PTR ret
,PDWORD unknown
)
379 case WM_CTLCOLORSTATIC
:
381 HWND hwndTarget
= (HWND
)lParam
;
382 HDC hdc
= (HDC
)wParam
;
383 HBRUSH
* phbrush
= (HBRUSH
*)ret
;
389 if (!IsThemeDialogTextureEnabled (hWnd
))
392 hTheme
= GetWindowTheme(hWnd
);
394 hTheme
= OpenThemeData(hWnd
, L
"TAB");
399 GetDiaogTextureBrush(hTheme
, hwndTarget
, hdc
, phbrush
, Msg
!= WM_CTLCOLORDLG
);
403 WCHAR controlClass
[32];
404 GetClassNameW (hwndTarget
, controlClass
, sizeof(controlClass
) / sizeof(controlClass
[0]));
406 /* This is a hack for the static class. Windows have a v6 static class just for this. */
407 if (lstrcmpiW (controlClass
, WC_STATICW
) == 0)
408 HackFillStaticBg(hwndTarget
, hdc
, phbrush
);
418 int WINAPI
ThemeSetWindowRgn(HWND hWnd
, HRGN hRgn
, BOOL bRedraw
)
420 PWND_CONTEXT pcontext
= ThemeGetWndContext(hWnd
);
423 pcontext
->HasAppDefinedRgn
= TRUE
;
424 pcontext
->HasThemeRgn
= FALSE
;
427 return user32ApiHook
.SetWindowRgn(hWnd
, hRgn
, bRedraw
);
430 BOOL WINAPI
ThemeGetScrollInfo(HWND hwnd
, int fnBar
, LPSCROLLINFO lpsi
)
432 PWND_CONTEXT pwndContext
;
436 /* Avoid creating a window context if it is not needed */
440 style
= GetWindowLongW(hwnd
, GWL_STYLE
);
441 if((style
& (WS_HSCROLL
|WS_VSCROLL
))==0)
444 pwndContext
= ThemeGetWndContext(hwnd
);
445 if (pwndContext
== NULL
)
449 * Uxtheme needs to handle the tracking of the scrollbar itself
450 * This means than if an application needs to get the track position
451 * with GetScrollInfo, it will get wrong data. So uxtheme needs to
452 * hook it and set the correct tracking position itself
454 ret
= user32ApiHook
.GetScrollInfo(hwnd
, fnBar
, lpsi
);
456 (lpsi
->fMask
& SIF_TRACKPOS
) &&
457 pwndContext
->SCROLL_TrackingWin
== hwnd
&&
458 pwndContext
->SCROLL_TrackingBar
== fnBar
)
460 lpsi
->nTrackPos
= pwndContext
->SCROLL_TrackingVal
;
465 return user32ApiHook
.GetScrollInfo(hwnd
, fnBar
, lpsi
);
468 /**********************************************************************
473 ThemeInitApiHook(UAPIHK State
, PUSERAPIHOOK puah
)
475 if (!puah
|| State
!= uahLoadInit
)
477 UXTHEME_LoadTheme(FALSE
);
478 ThemeCleanupWndContext(NULL
, 0);
479 gbThemeHooksActive
= FALSE
;
483 gbThemeHooksActive
= TRUE
;
485 /* Store the original functions from user32 */
486 user32ApiHook
= *puah
;
488 puah
->DefWindowProcA
= ThemeDefWindowProcA
;
489 puah
->DefWindowProcW
= ThemeDefWindowProcW
;
490 puah
->PreWndProc
= ThemePreWindowProc
;
491 puah
->PostWndProc
= ThemePostWindowProc
;
492 puah
->PreDefDlgProc
= ThemeDlgPreWindowProc
;
493 puah
->PostDefDlgProc
= ThemeDlgPostWindowProc
;
494 puah
->DefWndProcArray
.MsgBitArray
= gabDWPmessages
;
495 puah
->DefWndProcArray
.Size
= UAHOWP_MAX_SIZE
;
496 puah
->WndProcArray
.MsgBitArray
= gabMSGPmessages
;
497 puah
->WndProcArray
.Size
= UAHOWP_MAX_SIZE
;
498 puah
->DlgProcArray
.MsgBitArray
= gabDLGPmessages
;
499 puah
->DlgProcArray
.Size
= UAHOWP_MAX_SIZE
;
501 puah
->SetWindowRgn
= ThemeSetWindowRgn
;
502 puah
->GetScrollInfo
= ThemeGetScrollInfo
;
504 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCPAINT
);
505 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCACTIVATE
);
506 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCMOUSEMOVE
);
507 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCMOUSELEAVE
);
508 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCHITTEST
);
509 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCLBUTTONDOWN
);
510 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCUAHDRAWCAPTION
);
511 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCUAHDRAWFRAME
);
512 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_SETTEXT
);
513 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_WINDOWPOSCHANGED
);
514 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_CONTEXTMENU
);
515 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_STYLECHANGED
);
516 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_SETICON
);
517 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_NCDESTROY
);
518 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_SYSCOMMAND
);
519 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_CTLCOLORMSGBOX
);
520 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_CTLCOLORBTN
);
521 UAH_HOOK_MESSAGE(puah
->DefWndProcArray
, WM_CTLCOLORSTATIC
);
523 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_CREATE
);
524 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_SETTINGCHANGE
);
525 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_DRAWITEM
);
526 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_MEASUREITEM
);
527 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_WINDOWPOSCHANGING
);
528 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_WINDOWPOSCHANGED
);
529 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_STYLECHANGING
);
530 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_STYLECHANGED
);
531 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_NCCREATE
);
532 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_NCDESTROY
);
533 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_NCPAINT
);
534 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_MENUCHAR
);
535 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_MDISETMENU
);
536 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_THEMECHANGED
);
537 UAH_HOOK_MESSAGE(puah
->WndProcArray
, WM_UAHINIT
);
539 puah
->DlgProcArray
.MsgBitArray
= gabDLGPmessages
;
540 puah
->DlgProcArray
.Size
= UAHOWP_MAX_SIZE
;
542 UAH_HOOK_MESSAGE(puah
->DlgProcArray
, WM_INITDIALOG
);
543 UAH_HOOK_MESSAGE(puah
->DlgProcArray
, WM_CTLCOLORMSGBOX
);
544 UAH_HOOK_MESSAGE(puah
->DlgProcArray
, WM_CTLCOLORBTN
);
545 UAH_HOOK_MESSAGE(puah
->DlgProcArray
, WM_CTLCOLORDLG
);
546 UAH_HOOK_MESSAGE(puah
->DlgProcArray
, WM_CTLCOLORSTATIC
);
547 UAH_HOOK_MESSAGE(puah
->DlgProcArray
, WM_PRINTCLIENT
);
549 UXTHEME_LoadTheme(TRUE
);
554 typedef BOOL (WINAPI
* PREGISTER_UAH_WINXP
)(HINSTANCE hInstance
, USERAPIHOOKPROC CallbackFunc
);
555 typedef BOOL (WINAPI
* PREGISTER_UUAH_WIN2003
)(PUSERAPIHOOKINFO puah
);
564 lpFunc
= GetProcAddress(GetModuleHandle("user32.dll"), "RegisterUserApiHook");
566 ZeroMemory(&osvi
, sizeof(OSVERSIONINFO
));
567 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
570 if ( osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 1)
572 PREGISTER_UAH_WINXP lpfuncxp
= (PREGISTER_UAH_WINXP
)lpFunc
;
573 ret
= lpfuncxp(hDllInst
, ThemeInitApiHook
);
575 else if ( osvi
.dwMajorVersion
== 5 && osvi
.dwMinorVersion
== 2)
577 PREGISTER_UUAH_WIN2003 lpfunc2003
= (PREGISTER_UUAH_WIN2003
)lpFunc
;
580 uah
.m_size
= sizeof(uah
);
581 uah
.m_dllname1
= L
"uxtheme.dll";
582 uah
.m_funname1
= L
"ThemeInitApiHook";
583 uah
.m_dllname2
= NULL
;
584 uah
.m_funname2
= NULL
;
586 ret
= lpfunc2003(&uah
);
594 UXTHEME_broadcast_msg (NULL
, WM_THEMECHANGED
);
604 ret
= UnregisterUserApiHook();
606 UXTHEME_broadcast_msg (NULL
, WM_THEMECHANGED
);
611 INT WINAPI
ClassicSystemParametersInfoW(UINT uiAction
, UINT uiParam
, PVOID pvParam
, UINT fWinIni
)
613 if (gbThemeHooksActive
)
615 return user32ApiHook
.SystemParametersInfoW(uiAction
, uiParam
, pvParam
, fWinIni
);
618 return SystemParametersInfoW(uiAction
, uiParam
, pvParam
, fWinIni
);
621 INT WINAPI
ClassicSystemParametersInfoA(UINT uiAction
, UINT uiParam
, PVOID pvParam
, UINT fWinIni
)
623 if (gbThemeHooksActive
)
625 return user32ApiHook
.SystemParametersInfoA(uiAction
, uiParam
, pvParam
, fWinIni
);
628 return SystemParametersInfoA(uiAction
, uiParam
, pvParam
, fWinIni
);
631 INT WINAPI
ClassicGetSystemMetrics(int nIndex
)
633 if (gbThemeHooksActive
)
635 return user32ApiHook
.GetSystemMetrics(nIndex
);
638 return GetSystemMetrics(nIndex
);
641 BOOL WINAPI
ClassicAdjustWindowRectEx(LPRECT lpRect
, DWORD dwStyle
, BOOL bMenu
, DWORD dwExStyle
)
643 if (gbThemeHooksActive
)
645 return user32ApiHook
.AdjustWindowRectEx(lpRect
, dwStyle
, bMenu
, dwExStyle
);
648 return AdjustWindowRectEx(lpRect
, dwStyle
, bMenu
, dwExStyle
);