mirror of
https://github.com/reactos/reactos.git
synced 2024-08-18 09:28:36 +00:00
![Giannis Adamopoulos](/assets/img/avatar_default.png)
Only call it when needed. Also make it fail properly if the window theme could not be opened. CORE-15564
761 lines
22 KiB
C
761 lines
22 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS uxtheme.dll
|
|
* FILE: dll/win32/uxtheme/themehooks.c
|
|
* PURPOSE: uxtheme user api hook functions
|
|
* PROGRAMMER: Giannis Adamopoulos
|
|
*/
|
|
|
|
#include "uxthemep.h"
|
|
|
|
USERAPIHOOK g_user32ApiHook;
|
|
BYTE gabDWPmessages[UAHOWP_MAX_SIZE];
|
|
BYTE gabMSGPmessages[UAHOWP_MAX_SIZE];
|
|
BYTE gabDLGPmessages[UAHOWP_MAX_SIZE];
|
|
BOOL g_bThemeHooksActive = FALSE;
|
|
|
|
PWND_DATA ThemeGetWndData(HWND hWnd)
|
|
{
|
|
PWND_DATA pwndData;
|
|
|
|
pwndData = (PWND_DATA)GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWndContext));
|
|
if(pwndData == NULL)
|
|
{
|
|
pwndData = HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
sizeof(WND_DATA));
|
|
if(pwndData == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
SetPropW( hWnd, (LPCWSTR)MAKEINTATOM(atWndContext), pwndData);
|
|
}
|
|
|
|
return pwndData;
|
|
}
|
|
|
|
void ThemeDestroyWndData(HWND hWnd)
|
|
{
|
|
PWND_DATA pwndData;
|
|
DWORD ProcessId;
|
|
|
|
/*Do not destroy WND_DATA of a window that belong to another process */
|
|
GetWindowThreadProcessId(hWnd, &ProcessId);
|
|
if(ProcessId != GetCurrentProcessId())
|
|
{
|
|
return;
|
|
}
|
|
|
|
pwndData = (PWND_DATA)GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWndContext));
|
|
if(pwndData == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(pwndData->HasThemeRgn)
|
|
{
|
|
g_user32ApiHook.SetWindowRgn(hWnd, 0, TRUE);
|
|
}
|
|
|
|
if (pwndData->hTabBackgroundBrush != NULL)
|
|
{
|
|
CloseThemeData(GetWindowTheme(hWnd));
|
|
|
|
DeleteObject(pwndData->hTabBackgroundBrush);
|
|
}
|
|
|
|
if (pwndData->hTabBackgroundBmp != NULL)
|
|
{
|
|
DeleteObject(pwndData->hTabBackgroundBmp);
|
|
}
|
|
|
|
if (pwndData->hthemeWindow)
|
|
{
|
|
CloseThemeData(pwndData->hthemeWindow);
|
|
}
|
|
|
|
if (pwndData->hthemeScrollbar)
|
|
{
|
|
CloseThemeData(pwndData->hthemeScrollbar);
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(), 0, pwndData);
|
|
|
|
SetPropW( hWnd, (LPCWSTR)MAKEINTATOM(atWndContext), NULL);
|
|
}
|
|
|
|
HTHEME GetNCCaptionTheme(HWND hWnd, DWORD style)
|
|
{
|
|
PWND_DATA pwndData;
|
|
|
|
/* We only get the theme for the window class if the window has a caption */
|
|
if((style & WS_CAPTION) != WS_CAPTION)
|
|
return NULL;
|
|
|
|
/* Get theme data for this window */
|
|
pwndData = ThemeGetWndData(hWnd);
|
|
if (pwndData == NULL)
|
|
return NULL;
|
|
|
|
if (!(GetThemeAppProperties() & STAP_ALLOW_NONCLIENT))
|
|
{
|
|
if (pwndData->hthemeWindow)
|
|
{
|
|
CloseThemeData(pwndData->hthemeWindow);
|
|
pwndData->hthemeWindow = NULL;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/* If the theme data was not cached, open it now */
|
|
if (!pwndData->hthemeWindow)
|
|
pwndData->hthemeWindow = OpenThemeDataEx(hWnd, L"WINDOW", OTD_NONCLIENT);
|
|
|
|
return pwndData->hthemeWindow;
|
|
}
|
|
|
|
HTHEME GetNCScrollbarTheme(HWND hWnd, DWORD style)
|
|
{
|
|
PWND_DATA pwndData;
|
|
|
|
/* We only get the theme for the scrollbar class if the window has a scrollbar */
|
|
if((style & (WS_HSCROLL|WS_VSCROLL)) == 0)
|
|
return NULL;
|
|
|
|
/* Get theme data for this window */
|
|
pwndData = ThemeGetWndData(hWnd);
|
|
if (pwndData == NULL)
|
|
return NULL;
|
|
|
|
if (!(GetThemeAppProperties() & STAP_ALLOW_NONCLIENT))
|
|
{
|
|
if (pwndData->hthemeScrollbar)
|
|
{
|
|
CloseThemeData(pwndData->hthemeScrollbar);
|
|
pwndData->hthemeScrollbar = NULL;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/* If the theme data was not cached, open it now */
|
|
if (!pwndData->hthemeScrollbar)
|
|
pwndData->hthemeScrollbar = OpenThemeDataEx(hWnd, L"SCROLLBAR", OTD_NONCLIENT);
|
|
|
|
return pwndData->hthemeScrollbar;
|
|
}
|
|
|
|
static BOOL CALLBACK ThemeCleanupChildWndContext (HWND hWnd, LPARAM msg)
|
|
{
|
|
ThemeDestroyWndData(hWnd);
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL CALLBACK ThemeCleanupWndContext(HWND hWnd, LPARAM msg)
|
|
{
|
|
if (hWnd == NULL)
|
|
{
|
|
EnumWindows (ThemeCleanupWndContext, 0);
|
|
}
|
|
else
|
|
{
|
|
ThemeDestroyWndData(hWnd);
|
|
EnumChildWindows (hWnd, ThemeCleanupChildWndContext, 0);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void SetThemeRegion(HWND hWnd)
|
|
{
|
|
HTHEME hTheme;
|
|
RECT rcWindow;
|
|
HRGN hrgn, hrgn1;
|
|
int CaptionHeight, iPart;
|
|
WINDOWINFO wi;
|
|
|
|
TRACE("SetThemeRegion %d\n", hWnd);
|
|
|
|
wi.cbSize = sizeof(wi);
|
|
GetWindowInfo(hWnd, &wi);
|
|
|
|
/* Get the caption part id */
|
|
if (wi.dwStyle & WS_MINIMIZE)
|
|
iPart = WP_MINCAPTION;
|
|
else if (wi.dwExStyle & WS_EX_TOOLWINDOW)
|
|
iPart = WP_SMALLCAPTION;
|
|
else if (wi.dwStyle & WS_MAXIMIZE)
|
|
iPart = WP_MAXCAPTION;
|
|
else
|
|
iPart = WP_CAPTION;
|
|
|
|
CaptionHeight = wi.cyWindowBorders;
|
|
CaptionHeight += GetSystemMetrics(wi.dwExStyle & WS_EX_TOOLWINDOW ? SM_CYSMCAPTION : SM_CYCAPTION );
|
|
|
|
GetWindowRect(hWnd, &rcWindow);
|
|
rcWindow.right -= rcWindow.left;
|
|
rcWindow.bottom = CaptionHeight;
|
|
rcWindow.top = 0;
|
|
rcWindow.left = 0;
|
|
|
|
hTheme = GetNCCaptionTheme(hWnd, wi.dwStyle);
|
|
GetThemeBackgroundRegion(hTheme, 0, iPart, FS_ACTIVE, &rcWindow, &hrgn);
|
|
|
|
GetWindowRect(hWnd, &rcWindow);
|
|
rcWindow.right -= rcWindow.left;
|
|
rcWindow.bottom -= rcWindow.top;
|
|
rcWindow.top = CaptionHeight;
|
|
rcWindow.left = 0;
|
|
hrgn1 = CreateRectRgnIndirect(&rcWindow);
|
|
|
|
CombineRgn(hrgn, hrgn, hrgn1, RGN_OR );
|
|
|
|
DeleteObject(hrgn1);
|
|
|
|
g_user32ApiHook.SetWindowRgn(hWnd, hrgn, TRUE);
|
|
}
|
|
|
|
int OnPostWinPosChanged(HWND hWnd, WINDOWPOS* pWinPos)
|
|
{
|
|
PWND_DATA pwndData;
|
|
DWORD style;
|
|
|
|
/* We only proceed to change the window shape if it has a caption */
|
|
style = GetWindowLongW(hWnd, GWL_STYLE);
|
|
if((style & WS_CAPTION)!=WS_CAPTION)
|
|
return 0;
|
|
|
|
/* Get theme data for this window */
|
|
pwndData = ThemeGetWndData(hWnd);
|
|
if (pwndData == NULL)
|
|
return 0;
|
|
|
|
/* Do not change the region of the window if its size wasn't changed */
|
|
if ((pWinPos->flags & SWP_NOSIZE) != 0 && pwndData->DirtyThemeRegion == FALSE)
|
|
return 0;
|
|
|
|
/* We don't touch the shape of the window if the application sets it on its own */
|
|
if (pwndData->HasAppDefinedRgn != FALSE)
|
|
return 0;
|
|
|
|
/* Calling SetWindowRgn will call SetWindowPos again so we need to avoid this recursion */
|
|
if (pwndData->UpdatingRgn != FALSE)
|
|
return 0;
|
|
|
|
if(!IsAppThemed() || !(GetThemeAppProperties() & STAP_ALLOW_NONCLIENT))
|
|
{
|
|
if(pwndData->HasThemeRgn)
|
|
{
|
|
pwndData->HasThemeRgn = FALSE;
|
|
g_user32ApiHook.SetWindowRgn(hWnd, 0, TRUE);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
pwndData->DirtyThemeRegion = FALSE;
|
|
pwndData->HasThemeRgn = TRUE;
|
|
pwndData->UpdatingRgn = TRUE;
|
|
SetThemeRegion(hWnd);
|
|
pwndData->UpdatingRgn = FALSE;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**********************************************************************
|
|
* Hook Functions
|
|
*/
|
|
|
|
static LRESULT CALLBACK
|
|
ThemeDefWindowProcW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
PWND_DATA pwndData;
|
|
|
|
pwndData = (PWND_DATA)GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWndContext));
|
|
|
|
if(!IsAppThemed() ||
|
|
!(GetThemeAppProperties() & STAP_ALLOW_NONCLIENT) ||
|
|
(pwndData && pwndData->HasAppDefinedRgn))
|
|
{
|
|
return g_user32ApiHook.DefWindowProcW(hWnd,
|
|
Msg,
|
|
wParam,
|
|
lParam);
|
|
}
|
|
|
|
return ThemeWndProc(hWnd,
|
|
Msg,
|
|
wParam,
|
|
lParam,
|
|
g_user32ApiHook.DefWindowProcW);
|
|
}
|
|
|
|
static LRESULT CALLBACK
|
|
ThemeDefWindowProcA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
PWND_DATA pwndData;
|
|
|
|
pwndData = (PWND_DATA)GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWndContext));
|
|
|
|
if(!IsAppThemed() ||
|
|
!(GetThemeAppProperties() & STAP_ALLOW_NONCLIENT) ||
|
|
(pwndData && pwndData->HasAppDefinedRgn))
|
|
{
|
|
return g_user32ApiHook.DefWindowProcA(hWnd,
|
|
Msg,
|
|
wParam,
|
|
lParam);
|
|
}
|
|
|
|
return ThemeWndProc(hWnd,
|
|
Msg,
|
|
wParam,
|
|
lParam,
|
|
g_user32ApiHook.DefWindowProcA);
|
|
}
|
|
|
|
static LRESULT CALLBACK
|
|
ThemePreWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, ULONG_PTR ret,PDWORD unknown)
|
|
{
|
|
switch(Msg)
|
|
{
|
|
case WM_CREATE:
|
|
case WM_STYLECHANGED:
|
|
case WM_SIZE:
|
|
case WM_WINDOWPOSCHANGED:
|
|
{
|
|
if(IsAppThemed() && (GetThemeAppProperties() & STAP_ALLOW_NONCLIENT))
|
|
ThemeCalculateCaptionButtonsPos(hWnd, NULL);
|
|
break;
|
|
}
|
|
case WM_THEMECHANGED:
|
|
{
|
|
PWND_DATA pwndData = ThemeGetWndData(hWnd);
|
|
|
|
if (GetAncestor(hWnd, GA_PARENT) == GetDesktopWindow())
|
|
UXTHEME_LoadTheme(TRUE);
|
|
|
|
if (pwndData == NULL)
|
|
return 0;
|
|
|
|
if (pwndData->hTabBackgroundBrush != NULL)
|
|
{
|
|
DeleteObject(pwndData->hTabBackgroundBrush);
|
|
pwndData->hTabBackgroundBrush = NULL;
|
|
}
|
|
|
|
if (pwndData->hTabBackgroundBmp != NULL)
|
|
{
|
|
DeleteObject(pwndData->hTabBackgroundBmp);
|
|
pwndData->hTabBackgroundBmp = NULL;
|
|
}
|
|
|
|
if (pwndData->hthemeWindow)
|
|
{
|
|
CloseThemeData(pwndData->hthemeWindow);
|
|
pwndData->hthemeWindow = NULL;
|
|
}
|
|
|
|
if (pwndData->hthemeScrollbar)
|
|
{
|
|
CloseThemeData(pwndData->hthemeScrollbar);
|
|
pwndData->hthemeScrollbar = NULL;
|
|
}
|
|
|
|
if(IsAppThemed() && (GetThemeAppProperties() & STAP_ALLOW_NONCLIENT))
|
|
ThemeCalculateCaptionButtonsPos(hWnd, NULL);
|
|
|
|
pwndData->DirtyThemeRegion = TRUE;
|
|
break;
|
|
}
|
|
case WM_NCCREATE:
|
|
{
|
|
PWND_DATA pwndData = ThemeGetWndData(hWnd);
|
|
if (pwndData == NULL)
|
|
return 0;
|
|
pwndData->DirtyThemeRegion = TRUE;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static LRESULT CALLBACK
|
|
ThemePostWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, ULONG_PTR ret,PDWORD unknown)
|
|
{
|
|
switch(Msg)
|
|
{
|
|
case WM_WINDOWPOSCHANGED:
|
|
{
|
|
return OnPostWinPosChanged(hWnd, (WINDOWPOS*)lParam);
|
|
}
|
|
case WM_NCDESTROY:
|
|
{
|
|
ThemeDestroyWndData(hWnd);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
HRESULT GetDiaogTextureBrush(HTHEME theme, HWND hwnd, HDC hdc, HBRUSH* result, BOOL changeOrigin)
|
|
{
|
|
PWND_DATA pwndData;
|
|
|
|
pwndData = ThemeGetWndData(hwnd);
|
|
if (pwndData == NULL)
|
|
return E_FAIL;
|
|
|
|
if (pwndData->hTabBackgroundBrush == NULL)
|
|
{
|
|
HBITMAP hbmp;
|
|
RECT dummy, bmpRect;
|
|
BOOL hasImageAlpha;
|
|
HRESULT hr;
|
|
|
|
hr = UXTHEME_LoadImage(theme, 0, TABP_BODY, 0, &dummy, FALSE, &hbmp, &bmpRect, &hasImageAlpha);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
if (changeOrigin)
|
|
{
|
|
/* Unfortunately SetBrushOrgEx doesn't work at all */
|
|
RECT rcWindow, rcParent;
|
|
UINT y;
|
|
HDC hdcPattern, hdcHackPattern;
|
|
HBITMAP hbmpOld1, hbmpold2, hbmpHack;
|
|
|
|
GetWindowRect(hwnd, &rcWindow);
|
|
GetWindowRect(GetParent(hwnd), &rcParent);
|
|
y = (rcWindow.top - rcParent.top) % bmpRect.bottom;
|
|
|
|
hdcPattern = CreateCompatibleDC(hdc);
|
|
hbmpOld1 = (HBITMAP)SelectObject(hdcPattern, hbmp);
|
|
|
|
hdcHackPattern = CreateCompatibleDC(hdc);
|
|
hbmpHack = CreateCompatibleBitmap(hdc, bmpRect.right, bmpRect.bottom);
|
|
hbmpold2 = (HBITMAP)SelectObject(hdcHackPattern, hbmpHack);
|
|
|
|
BitBlt(hdcHackPattern, 0, 0, bmpRect.right, bmpRect.bottom - y, hdcPattern, 0, y, SRCCOPY);
|
|
BitBlt(hdcHackPattern, 0, bmpRect.bottom - y, bmpRect.right, y, hdcPattern, 0, 0, SRCCOPY);
|
|
|
|
hbmpold2 = (HBITMAP)SelectObject(hdcHackPattern, hbmpold2);
|
|
hbmpOld1 = (HBITMAP)SelectObject(hdcPattern, hbmpOld1);
|
|
|
|
DeleteDC(hdcPattern);
|
|
DeleteDC(hdcHackPattern);
|
|
|
|
/* Keep the handle of the bitmap we created so that it can be used later */
|
|
pwndData->hTabBackgroundBmp = hbmpHack;
|
|
hbmp = hbmpHack;
|
|
}
|
|
|
|
/* hbmp is cached so there is no need to free it */
|
|
pwndData->hTabBackgroundBrush = CreatePatternBrush(hbmp);
|
|
}
|
|
|
|
if (!pwndData->hTabBackgroundBrush)
|
|
return E_FAIL;
|
|
|
|
*result = pwndData->hTabBackgroundBrush;
|
|
return S_OK;
|
|
}
|
|
|
|
void HackFillStaticBg(HWND hwnd, HDC hdc, HBRUSH* result)
|
|
{
|
|
RECT rcStatic;
|
|
|
|
GetClientRect(hwnd, &rcStatic);
|
|
FillRect(hdc, &rcStatic, *result);
|
|
|
|
SetBkMode (hdc, TRANSPARENT);
|
|
*result = GetStockObject (NULL_BRUSH);
|
|
}
|
|
|
|
static LRESULT CALLBACK
|
|
ThemeDlgPreWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, ULONG_PTR ret,PDWORD unknown)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static LRESULT CALLBACK
|
|
ThemeDlgPostWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, ULONG_PTR ret,PDWORD unknown)
|
|
{
|
|
switch(Msg)
|
|
{
|
|
case WM_CTLCOLORDLG:
|
|
case WM_CTLCOLORBTN:
|
|
case WM_CTLCOLORSTATIC:
|
|
{
|
|
HWND hwndTarget = (HWND)lParam;
|
|
HDC hdc = (HDC)wParam;
|
|
HBRUSH* phbrush = (HBRUSH*)ret;
|
|
HTHEME hTheme;
|
|
|
|
if(!IsAppThemed() || !(GetThemeAppProperties() & STAP_ALLOW_NONCLIENT))
|
|
break;
|
|
|
|
if (!IsThemeDialogTextureEnabled (hWnd))
|
|
break;
|
|
|
|
hTheme = GetWindowTheme(hWnd);
|
|
if (!hTheme)
|
|
hTheme = OpenThemeData(hWnd, L"TAB");
|
|
|
|
if (!hTheme)
|
|
break;
|
|
|
|
GetDiaogTextureBrush(hTheme, hwndTarget, hdc, phbrush, Msg != WM_CTLCOLORDLG);
|
|
|
|
#if 1
|
|
{
|
|
WCHAR controlClass[32];
|
|
GetClassNameW (hwndTarget, controlClass, sizeof(controlClass) / sizeof(controlClass[0]));
|
|
|
|
/* This is a hack for the static class. Windows have a v6 static class just for this. */
|
|
if (lstrcmpiW (controlClass, WC_STATICW) == 0)
|
|
HackFillStaticBg(hwndTarget, hdc, phbrush);
|
|
}
|
|
#endif
|
|
SetBkMode( hdc, TRANSPARENT );
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int WINAPI ThemeSetWindowRgn(HWND hWnd, HRGN hRgn, BOOL bRedraw)
|
|
{
|
|
PWND_DATA pwndData = ThemeGetWndData(hWnd);
|
|
if(pwndData)
|
|
{
|
|
pwndData->HasAppDefinedRgn = TRUE;
|
|
pwndData->HasThemeRgn = FALSE;
|
|
}
|
|
|
|
return g_user32ApiHook.SetWindowRgn(hWnd, hRgn, bRedraw);
|
|
}
|
|
|
|
BOOL WINAPI ThemeGetScrollInfo(HWND hwnd, int fnBar, LPSCROLLINFO lpsi)
|
|
{
|
|
PWND_DATA pwndData;
|
|
DWORD style;
|
|
BOOL ret;
|
|
|
|
/* Avoid creating a window context if it is not needed */
|
|
if(!IsAppThemed() || !(GetThemeAppProperties() & STAP_ALLOW_NONCLIENT))
|
|
goto dodefault;
|
|
|
|
style = GetWindowLongW(hwnd, GWL_STYLE);
|
|
if((style & (WS_HSCROLL|WS_VSCROLL))==0)
|
|
goto dodefault;
|
|
|
|
pwndData = ThemeGetWndData(hwnd);
|
|
if (pwndData == NULL)
|
|
goto dodefault;
|
|
|
|
/*
|
|
* Uxtheme needs to handle the tracking of the scrollbar itself
|
|
* This means than if an application needs to get the track position
|
|
* with GetScrollInfo, it will get wrong data. So uxtheme needs to
|
|
* hook it and set the correct tracking position itself
|
|
*/
|
|
ret = g_user32ApiHook.GetScrollInfo(hwnd, fnBar, lpsi);
|
|
if ( lpsi &&
|
|
(lpsi->fMask & SIF_TRACKPOS) &&
|
|
pwndData->SCROLL_TrackingWin == hwnd &&
|
|
pwndData->SCROLL_TrackingBar == fnBar)
|
|
{
|
|
lpsi->nTrackPos = pwndData->SCROLL_TrackingVal;
|
|
}
|
|
return ret;
|
|
|
|
dodefault:
|
|
return g_user32ApiHook.GetScrollInfo(hwnd, fnBar, lpsi);
|
|
}
|
|
|
|
/**********************************************************************
|
|
* Exports
|
|
*/
|
|
|
|
BOOL CALLBACK
|
|
ThemeInitApiHook(UAPIHK State, PUSERAPIHOOK puah)
|
|
{
|
|
if (!puah || State != uahLoadInit)
|
|
{
|
|
UXTHEME_LoadTheme(FALSE);
|
|
ThemeCleanupWndContext(NULL, 0);
|
|
g_bThemeHooksActive = FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
g_bThemeHooksActive = TRUE;
|
|
|
|
/* Store the original functions from user32 */
|
|
g_user32ApiHook = *puah;
|
|
|
|
puah->DefWindowProcA = ThemeDefWindowProcA;
|
|
puah->DefWindowProcW = ThemeDefWindowProcW;
|
|
puah->PreWndProc = ThemePreWindowProc;
|
|
puah->PostWndProc = ThemePostWindowProc;
|
|
puah->PreDefDlgProc = ThemeDlgPreWindowProc;
|
|
puah->PostDefDlgProc = ThemeDlgPostWindowProc;
|
|
puah->DefWndProcArray.MsgBitArray = gabDWPmessages;
|
|
puah->DefWndProcArray.Size = UAHOWP_MAX_SIZE;
|
|
puah->WndProcArray.MsgBitArray = gabMSGPmessages;
|
|
puah->WndProcArray.Size = UAHOWP_MAX_SIZE;
|
|
puah->DlgProcArray.MsgBitArray = gabDLGPmessages;
|
|
puah->DlgProcArray.Size = UAHOWP_MAX_SIZE;
|
|
|
|
puah->SetWindowRgn = ThemeSetWindowRgn;
|
|
puah->GetScrollInfo = ThemeGetScrollInfo;
|
|
|
|
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCPAINT);
|
|
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCACTIVATE);
|
|
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCMOUSEMOVE);
|
|
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCMOUSELEAVE);
|
|
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCHITTEST);
|
|
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCLBUTTONDOWN);
|
|
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCUAHDRAWCAPTION);
|
|
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCUAHDRAWFRAME);
|
|
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_SETTEXT);
|
|
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_WINDOWPOSCHANGED);
|
|
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_CONTEXTMENU);
|
|
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_STYLECHANGED);
|
|
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_SETICON);
|
|
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCDESTROY);
|
|
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_SYSCOMMAND);
|
|
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_CTLCOLORMSGBOX);
|
|
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_CTLCOLORBTN);
|
|
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_CTLCOLORSTATIC);
|
|
|
|
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_CREATE);
|
|
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_SETTINGCHANGE);
|
|
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_DRAWITEM);
|
|
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_MEASUREITEM);
|
|
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_WINDOWPOSCHANGING);
|
|
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_WINDOWPOSCHANGED);
|
|
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_STYLECHANGING);
|
|
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_STYLECHANGED);
|
|
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_NCCREATE);
|
|
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_NCDESTROY);
|
|
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_NCPAINT);
|
|
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_MENUCHAR);
|
|
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_MDISETMENU);
|
|
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_THEMECHANGED);
|
|
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_UAHINIT);
|
|
|
|
puah->DlgProcArray.MsgBitArray = gabDLGPmessages;
|
|
puah->DlgProcArray.Size = UAHOWP_MAX_SIZE;
|
|
|
|
UAH_HOOK_MESSAGE(puah->DlgProcArray, WM_INITDIALOG);
|
|
UAH_HOOK_MESSAGE(puah->DlgProcArray, WM_CTLCOLORMSGBOX);
|
|
UAH_HOOK_MESSAGE(puah->DlgProcArray, WM_CTLCOLORBTN);
|
|
UAH_HOOK_MESSAGE(puah->DlgProcArray, WM_CTLCOLORDLG);
|
|
UAH_HOOK_MESSAGE(puah->DlgProcArray, WM_CTLCOLORSTATIC);
|
|
UAH_HOOK_MESSAGE(puah->DlgProcArray, WM_PRINTCLIENT);
|
|
|
|
UXTHEME_LoadTheme(TRUE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
typedef BOOL (WINAPI * PREGISTER_UAH_WINXP)(HINSTANCE hInstance, USERAPIHOOKPROC CallbackFunc);
|
|
typedef BOOL (WINAPI * PREGISTER_UUAH_WIN2003)(PUSERAPIHOOKINFO puah);
|
|
|
|
BOOL WINAPI
|
|
ThemeHooksInstall()
|
|
{
|
|
PVOID lpFunc;
|
|
OSVERSIONINFO osvi;
|
|
BOOL ret;
|
|
|
|
lpFunc = GetProcAddress(GetModuleHandle("user32.dll"), "RegisterUserApiHook");
|
|
|
|
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
|
|
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
GetVersionEx(&osvi);
|
|
|
|
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
|
|
{
|
|
PREGISTER_UAH_WINXP lpfuncxp = (PREGISTER_UAH_WINXP)lpFunc;
|
|
ret = lpfuncxp(hDllInst, ThemeInitApiHook);
|
|
}
|
|
else if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
|
|
{
|
|
PREGISTER_UUAH_WIN2003 lpfunc2003 = (PREGISTER_UUAH_WIN2003)lpFunc;
|
|
USERAPIHOOKINFO uah;
|
|
|
|
uah.m_size = sizeof(uah);
|
|
uah.m_dllname1 = L"uxtheme.dll";
|
|
uah.m_funname1 = L"ThemeInitApiHook";
|
|
uah.m_dllname2 = NULL;
|
|
uah.m_funname2 = NULL;
|
|
|
|
ret = lpfunc2003(&uah);
|
|
}
|
|
else
|
|
{
|
|
UNIMPLEMENTED;
|
|
ret = FALSE;
|
|
}
|
|
|
|
UXTHEME_broadcast_theme_changed (NULL, TRUE);
|
|
|
|
return ret;
|
|
}
|
|
|
|
BOOL WINAPI
|
|
ThemeHooksRemove()
|
|
{
|
|
BOOL ret;
|
|
|
|
ret = UnregisterUserApiHook();
|
|
|
|
UXTHEME_broadcast_theme_changed (NULL, FALSE);
|
|
|
|
return ret;
|
|
}
|
|
|
|
INT WINAPI ClassicSystemParametersInfoW(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni)
|
|
{
|
|
if (g_bThemeHooksActive)
|
|
{
|
|
return g_user32ApiHook.SystemParametersInfoW(uiAction, uiParam, pvParam, fWinIni);
|
|
}
|
|
|
|
return SystemParametersInfoW(uiAction, uiParam, pvParam, fWinIni);
|
|
}
|
|
|
|
INT WINAPI ClassicSystemParametersInfoA(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni)
|
|
{
|
|
if (g_bThemeHooksActive)
|
|
{
|
|
return g_user32ApiHook.SystemParametersInfoA(uiAction, uiParam, pvParam, fWinIni);
|
|
}
|
|
|
|
return SystemParametersInfoA(uiAction, uiParam, pvParam, fWinIni);
|
|
}
|
|
|
|
INT WINAPI ClassicGetSystemMetrics(int nIndex)
|
|
{
|
|
if (g_bThemeHooksActive)
|
|
{
|
|
return g_user32ApiHook.GetSystemMetrics(nIndex);
|
|
}
|
|
|
|
return GetSystemMetrics(nIndex);
|
|
}
|
|
|
|
BOOL WINAPI ClassicAdjustWindowRectEx(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle)
|
|
{
|
|
if (g_bThemeHooksActive)
|
|
{
|
|
return g_user32ApiHook.AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle);
|
|
}
|
|
|
|
return AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle);
|
|
}
|