USERAPIHOOK user32ApiHook;
BYTE gabDWPmessages[UAHOWP_MAX_SIZE];
BYTE gabMSGPmessages[UAHOWP_MAX_SIZE];
+BYTE gabDLGPmessages[UAHOWP_MAX_SIZE];
BOOL gbThemeHooksActive = FALSE;
-PWND_CONTEXT ThemeGetWndContext(HWND hWnd)
+PWND_DATA ThemeGetWndData(HWND hWnd)
{
- PWND_CONTEXT pcontext;
+ PWND_DATA pwndData;
- pcontext = (PWND_CONTEXT)GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWndContext));
- if(pcontext == NULL)
+ pwndData = (PWND_DATA)GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWndContext));
+ if(pwndData == NULL)
{
- pcontext = HeapAlloc(GetProcessHeap(),
+ pwndData = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
- sizeof(WND_CONTEXT));
- if(pcontext == NULL)
+ sizeof(WND_DATA));
+ if(pwndData == NULL)
{
return NULL;
}
- SetPropW( hWnd, (LPCWSTR)MAKEINTATOM(atWndContext), pcontext);
+ SetPropW( hWnd, (LPCWSTR)MAKEINTATOM(atWndContext), pwndData);
}
- return pcontext;
+ return pwndData;
}
-void ThemeDestroyWndContext(HWND hWnd)
+void ThemeDestroyWndData(HWND hWnd)
{
- PWND_CONTEXT pContext;
+ PWND_DATA pwndData;
DWORD ProcessId;
- /*Do not destroy WND_CONTEXT of a window that belong to another process */
+ /*Do not destroy WND_DATA of a window that belong to another process */
GetWindowThreadProcessId(hWnd, &ProcessId);
if(ProcessId != GetCurrentProcessId())
{
return;
}
- pContext = (PWND_CONTEXT)GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWndContext));
- if(pContext == NULL)
+ pwndData = (PWND_DATA)GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWndContext));
+ if(pwndData == NULL)
{
return;
}
- if(pContext->HasThemeRgn)
+ if(pwndData->HasThemeRgn)
{
user32ApiHook.SetWindowRgn(hWnd, 0, TRUE);
}
-
- HeapFree(GetProcessHeap(), 0, pContext);
+
+ if (pwndData->hTabBackgroundBrush != NULL)
+ {
+ CloseThemeData(GetWindowTheme(hWnd));
+
+ DeleteObject(pwndData->hTabBackgroundBrush);
+ pwndData->hTabBackgroundBrush = NULL;
+ }
+
+ if (pwndData->hTabBackgroundBmp != NULL)
+ {
+ DeleteObject(pwndData->hTabBackgroundBmp);
+ pwndData->hTabBackgroundBmp = NULL;
+ }
+
+ HeapFree(GetProcessHeap(), 0, pwndData);
SetPropW( hWnd, (LPCWSTR)MAKEINTATOM(atWndContext), NULL);
}
static BOOL CALLBACK ThemeCleanupChildWndContext (HWND hWnd, LPARAM msg)
{
- ThemeDestroyWndContext(hWnd);
+ ThemeDestroyWndData(hWnd);
return TRUE;
}
}
else
{
- ThemeDestroyWndContext(hWnd);
+ ThemeDestroyWndData(hWnd);
EnumChildWindows (hWnd, ThemeCleanupChildWndContext, 0);
}
GetWindowInfo(hWnd, &wi);
/* Get the caption part id */
- if (wi.dwExStyle & WS_EX_TOOLWINDOW)
+ 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;
int OnPostWinPosChanged(HWND hWnd, WINDOWPOS* pWinPos)
{
- PWND_CONTEXT pcontext;
+ PWND_DATA pwndData;
DWORD style;
/* We only proceed to change the window shape if it has a caption */
return 0;
/* Get theme data for this window */
- pcontext = ThemeGetWndContext(hWnd);
- if (pcontext == NULL)
+ 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 && pcontext->DirtyThemeRegion == FALSE)
+ 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 (pcontext->HasAppDefinedRgn == TRUE)
+ if (pwndData->HasAppDefinedRgn == TRUE)
return 0;
/* Calling SetWindowRgn will call SetWindowPos again so we need to avoid this recursion */
- if (pcontext->UpdatingRgn == TRUE)
+ if (pwndData->UpdatingRgn == TRUE)
return 0;
if(!IsAppThemed())
{
- if(pcontext->HasThemeRgn)
+ if(pwndData->HasThemeRgn)
{
- pcontext->HasThemeRgn = FALSE;
+ pwndData->HasThemeRgn = FALSE;
user32ApiHook.SetWindowRgn(hWnd, 0, TRUE);
}
return 0;
}
- pcontext->DirtyThemeRegion = FALSE;
- pcontext->HasThemeRgn = TRUE;
- pcontext->UpdatingRgn = TRUE;
+ pwndData->DirtyThemeRegion = FALSE;
+ pwndData->HasThemeRgn = TRUE;
+ pwndData->UpdatingRgn = TRUE;
SetThemeRegion(hWnd);
- pcontext->UpdatingRgn = FALSE;
+ pwndData->UpdatingRgn = FALSE;
return 0;
}
{
if(!IsAppThemed())
{
- if (Msg == WM_NCUAHDRAWCAPTION)
- {
- user32ApiHook.DrawCaption(hWnd, NULL, NULL, 0);
- return 0;
- }
-
return user32ApiHook.DefWindowProcW(hWnd,
Msg,
wParam,
{
if(!IsAppThemed())
{
- if (Msg == WM_NCUAHDRAWCAPTION)
- {
- user32ApiHook.DrawCaption(hWnd, NULL, NULL, 0);
- return 0;
- }
-
return user32ApiHook.DefWindowProcA(hWnd,
Msg,
wParam,
switch(Msg)
{
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;
+ }
+ }
case WM_NCCREATE:
{
- PWND_CONTEXT pcontext = ThemeGetWndContext(hWnd);
- if (pcontext == NULL)
+ PWND_DATA pwndData = ThemeGetWndData(hWnd);
+ if (pwndData == NULL)
return 0;
- pcontext->DirtyThemeRegion = TRUE;
+ pwndData->DirtyThemeRegion = TRUE;
}
}
{
return OnPostWinPosChanged(hWnd, (WINDOWPOS*)lParam);
}
- case WM_DESTROY:
+ case WM_NCDESTROY:
{
- ThemeDestroyWndContext(hWnd);
+ 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;
+
+ UXTHEME_LoadImage(theme, 0, TABP_BODY, 0, &dummy, FALSE, &hbmp, &bmpRect, &hasImageAlpha);
+ 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())
+ 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
+ break;
+ }
+ }
+
+ return 0;
+}
+
int WINAPI ThemeSetWindowRgn(HWND hWnd, HRGN hRgn, BOOL bRedraw)
{
- PWND_CONTEXT pcontext = ThemeGetWndContext(hWnd);
- if(pcontext)
+ PWND_DATA pwndData = ThemeGetWndData(hWnd);
+ if(pwndData)
{
- pcontext->HasAppDefinedRgn = TRUE;
- pcontext->HasThemeRgn = FALSE;
+ pwndData->HasAppDefinedRgn = TRUE;
+ pwndData->HasThemeRgn = FALSE;
}
return 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())
+ 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 = 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 user32ApiHook.GetScrollInfo(hwnd, fnBar, lpsi);
+}
+
/**********************************************************************
* Exports
*/
puah->DefWindowProcW = ThemeDefWindowProcW;
puah->PreWndProc = ThemePreWindowProc;
puah->PostWndProc = ThemePostWindowProc;
- puah->PreDefDlgProc = ThemePreWindowProc;
- puah->PostDefDlgProc = 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 = gabMSGPmessages;
+ 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->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;