Author: gadamopoulos Date: Mon Aug 15 10:22:23 2011 New Revision: 53262
URL: http://svn.reactos.org/svn/reactos?rev=53262&view=rev Log: [uxtheme] - Properly disable themes when theme hooks are removed - Add WND_CONTEXT a per window struct that will hold several theme specific information. For now it contains only theme region related info. It will be stored as a window property - Implement destroying WND_CONTEXT for every window when theme hooks are removed or when the window is destroyed - Hook the messages that are sent to dialogs, like they are hooked for normal windows - Hook SetWindowRgn call from user32. When an application calls it, uxtheme will stop setting window region on its own region - Implement setting a custom window region for windows after receiving WM_WINDOWPOSCHANGED message using GetThemeBackgroundRegion
Modified: branches/GSoC_2011/ThemesSupport/dll/win32/uxtheme/ncthm.h branches/GSoC_2011/ThemesSupport/dll/win32/uxtheme/system.c branches/GSoC_2011/ThemesSupport/dll/win32/uxtheme/themehooks.c branches/GSoC_2011/ThemesSupport/dll/win32/uxtheme/uxthemedll.h
Modified: branches/GSoC_2011/ThemesSupport/dll/win32/uxtheme/ncthm.h URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/ThemesSupport/dll/win3... ============================================================================== --- branches/GSoC_2011/ThemesSupport/dll/win32/uxtheme/ncthm.h [iso-8859-1] (original) +++ branches/GSoC_2011/ThemesSupport/dll/win32/uxtheme/ncthm.h [iso-8859-1] Mon Aug 15 10:22:23 2011 @@ -1,3 +1,10 @@ + +typedef struct _WND_CONTEXT +{ + BOOL HasAppDefinedRgn; + BOOL HasThemeRgn; + BOOL UpdatingRgn; +} WND_CONTEXT, *PWND_CONTEXT;
typedef struct _DRAW_CONTEXT { @@ -91,5 +98,9 @@ void ThemeCleanupDrawContext(PDRAW_CONTEXT pcontext);
+PWND_CONTEXT +ThemeGetWndContext(HWND hWnd);
extern ATOM atWindowTheme; +extern ATOM atWndContrext; +
Modified: branches/GSoC_2011/ThemesSupport/dll/win32/uxtheme/system.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/ThemesSupport/dll/win3... ============================================================================== --- branches/GSoC_2011/ThemesSupport/dll/win32/uxtheme/system.c [iso-8859-1] (original) +++ branches/GSoC_2011/ThemesSupport/dll/win32/uxtheme/system.c [iso-8859-1] Mon Aug 15 10:22:23 2011 @@ -34,6 +34,7 @@
#include "uxthemedll.h" #include "msstyles.h" +#include "ncthm.h"
#include "wine/debug.h"
@@ -64,6 +65,7 @@ ATOM atWindowTheme; static ATOM atSubAppName; static ATOM atSubIdList; +ATOM atWndContrext;
static BOOL bThemeActive = FALSE; static WCHAR szCurrentTheme[MAX_PATH]; @@ -148,7 +150,7 @@ * * Set the current active theme from the registry */ -void UXTHEME_LoadTheme(void) +void UXTHEME_LoadTheme(BOOL bLoad) { HKEY hKey; DWORD buffsize; @@ -156,29 +158,36 @@ WCHAR tmp[10]; PTHEME_FILE pt;
- /* Get current theme configuration */ - if(!RegOpenKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) { - TRACE("Loading theme config\n"); - buffsize = sizeof(tmp)/sizeof(tmp[0]); - if(!RegQueryValueExW(hKey, szThemeActive, NULL, NULL, (LPBYTE)tmp, &buffsize)) { - bThemeActive = (tmp[0] != '0'); + if(bLoad == TRUE) + { + /* Get current theme configuration */ + if(!RegOpenKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) { + TRACE("Loading theme config\n"); + buffsize = sizeof(tmp)/sizeof(tmp[0]); + if(!RegQueryValueExW(hKey, szThemeActive, NULL, NULL, (LPBYTE)tmp, &buffsize)) { + bThemeActive = (tmp[0] != '0'); + } + else { + bThemeActive = FALSE; + TRACE("Failed to get ThemeActive: %d\n", GetLastError()); + } + buffsize = sizeof(szCurrentColor)/sizeof(szCurrentColor[0]); + if(RegQueryValueExW(hKey, szColorName, NULL, NULL, (LPBYTE)szCurrentColor, &buffsize)) + szCurrentColor[0] = '\0'; + buffsize = sizeof(szCurrentSize)/sizeof(szCurrentSize[0]); + if(RegQueryValueExW(hKey, szSizeName, NULL, NULL, (LPBYTE)szCurrentSize, &buffsize)) + szCurrentSize[0] = '\0'; + if (query_reg_path (hKey, szDllName, szCurrentTheme)) + szCurrentTheme[0] = '\0'; + RegCloseKey(hKey); } - else { - bThemeActive = FALSE; - TRACE("Failed to get ThemeActive: %d\n", GetLastError()); - } - buffsize = sizeof(szCurrentColor)/sizeof(szCurrentColor[0]); - if(RegQueryValueExW(hKey, szColorName, NULL, NULL, (LPBYTE)szCurrentColor, &buffsize)) - szCurrentColor[0] = '\0'; - buffsize = sizeof(szCurrentSize)/sizeof(szCurrentSize[0]); - if(RegQueryValueExW(hKey, szSizeName, NULL, NULL, (LPBYTE)szCurrentSize, &buffsize)) - szCurrentSize[0] = '\0'; - if (query_reg_path (hKey, szDllName, szCurrentTheme)) - szCurrentTheme[0] = '\0'; - RegCloseKey(hKey); + else + TRACE("Failed to open theme registry key\n"); } else - TRACE("Failed to open theme registry key\n"); + { + bThemeActive = FALSE; + }
if(bThemeActive) { /* Make sure the theme requested is actually valid */ @@ -542,6 +551,7 @@ atSubAppName = GlobalAddAtomW(szSubAppName); atSubIdList = GlobalAddAtomW(szSubIdList); atDialogThemeEnabled = GlobalAddAtomW(szDialogThemeEnabled); + atWndContrext = GlobalAddAtomW(L"ux_WndContext"); }
/***********************************************************************
Modified: branches/GSoC_2011/ThemesSupport/dll/win32/uxtheme/themehooks.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/ThemesSupport/dll/win3... ============================================================================== --- branches/GSoC_2011/ThemesSupport/dll/win32/uxtheme/themehooks.c [iso-8859-1] (original) +++ branches/GSoC_2011/ThemesSupport/dll/win32/uxtheme/themehooks.c [iso-8859-1] Mon Aug 15 10:22:23 2011 @@ -12,6 +12,9 @@ #include "vfwmsgs.h" #include "uxtheme.h" #include "uxthemedll.h" +#include "ncthm.h" +#include "tmschema.h" + #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(uxtheme); @@ -25,6 +28,163 @@ USERAPIHOOK user32ApiHook; BYTE gabDWPmessages[UAHOWP_MAX_SIZE]; BYTE gabMSGPmessages[UAHOWP_MAX_SIZE]; + + +PWND_CONTEXT ThemeGetWndContext(HWND hWnd) +{ + PWND_CONTEXT pcontext; + + pcontext = (PWND_CONTEXT)GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWndContrext)); + if(pcontext == NULL) + { + pcontext = HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(WND_CONTEXT)); + if(pcontext == NULL) + { + return NULL; + } + + SetPropW( hWnd, (LPCWSTR)MAKEINTATOM(atWndContrext), pcontext); + } + + return pcontext; +} + +void ThemeDetroyWndContext(HWND hWnd) +{ + PWND_CONTEXT pContext; + DWORD ProcessId; + + /*Do not destroy WND_CONTEXT of a window that belong to another process */ + GetWindowThreadProcessId(hWnd, &ProcessId); + if(ProcessId != GetCurrentProcessId()) + { + return; + } + + pContext = (PWND_CONTEXT)GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWndContrext)); + if(pContext == NULL) + { + return; + } + + if(pContext->HasThemeRgn) + { + user32ApiHook.SetWindowRgn(hWnd, 0, TRUE); + } + + HeapFree(GetProcessHeap(), 0, pContext); + + SetPropW( hWnd, (LPCWSTR)MAKEINTATOM(atWndContrext), NULL); +} + +static BOOL CALLBACK ThemeCleanupChildWndContext (HWND hWnd, LPARAM msg) +{ + ThemeDetroyWndContext(hWnd); + return TRUE; +} + +static BOOL CALLBACK ThemeCleanupWndContext(HWND hWnd, LPARAM msg) +{ + if (hWnd == NULL) + { + EnumWindows (ThemeCleanupWndContext, 0); + } + else + { + ThemeDetroyWndContext(hWnd); + EnumChildWindows (hWnd, ThemeCleanupChildWndContext, 0); + } + + return TRUE; +} + +void SetThemeRegion(HWND hWnd, PWND_CONTEXT pcontext) +{ + HTHEME hTheme; + RECT rcWindow; + HRGN hrgn, hrgn1; + int CaptionHeight, iPart; + WINDOWINFO wi; + + if(!IsAppThemed()) + { + if(pcontext->HasThemeRgn) + { + pcontext->HasThemeRgn = FALSE; + user32ApiHook.SetWindowRgn(hWnd, 0, TRUE); + } + return; + } + + wi.cbSize = sizeof(wi); + + GetWindowInfo(hWnd, &wi); + + if((wi.dwStyle & WS_CAPTION)!=WS_CAPTION) + { + return; + } + + /* Get the caption part id */ + if (wi.dwExStyle & WS_EX_TOOLWINDOW) + iPart = WP_SMALLCAPTION; + else if (wi.dwStyle & WS_MAXIMIZE) + iPart = WP_MAXCAPTION; + else + iPart = WP_CAPTION; + + pcontext->HasThemeRgn = TRUE; + + 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 = OpenThemeData (hWnd, L"WINDOW"); + + GetThemeBackgroundRegion(hTheme, 0, iPart, FS_ACTIVE, &rcWindow, &hrgn); + + CloseThemeData(hTheme); + + 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); + + user32ApiHook.SetWindowRgn(hWnd, hrgn, TRUE); +} + +int OnPostWinPosChanged(HWND hWnd) +{ + PWND_CONTEXT pcontext = ThemeGetWndContext(hWnd); + + if(pcontext && + pcontext->HasAppDefinedRgn == FALSE && + pcontext->UpdatingRgn == FALSE) + { + pcontext->UpdatingRgn = TRUE; + SetThemeRegion(hWnd, pcontext); + pcontext = ThemeGetWndContext(hWnd); + pcontext->UpdatingRgn = FALSE; + } + return 0; +} + +/********************************************************************** + * Hook Functions + */
static LRESULT CALLBACK ThemeDefWindowProcW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) @@ -75,12 +235,50 @@ 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); + } + case WM_DESTROY: + { + ThemeDetroyWndContext(hWnd); + return 0; + } + } + + return 0; +} + +int WINAPI ThemeSetWindowRgn(HWND hWnd, HRGN hRgn, BOOL bRedraw) +{ + PWND_CONTEXT pcontext = ThemeGetWndContext(hWnd); + if(pcontext) + { + pcontext->HasAppDefinedRgn = TRUE; + pcontext->HasThemeRgn = FALSE; + } + + return user32ApiHook.SetWindowRgn(hWnd, hRgn, bRedraw); +} + +/********************************************************************** + * Exports + */ + BOOL CALLBACK ThemeInitApiHook(UAPIHK State, PUSERAPIHOOK puah) { /* Sanity checks for the caller */ if (!puah || State != uahLoadInit) { + UXTHEME_LoadTheme(FALSE); + ThemeCleanupWndContext(NULL, 0); return TRUE; }
@@ -90,10 +288,17 @@ puah->DefWindowProcA = ThemeDefWindowProcA; puah->DefWindowProcW = ThemeDefWindowProcW; puah->PreWndProc = ThemePreWindowProc; + puah->PostWndProc = ThemePostWindowProc; + puah->PreDefDlgProc = ThemePreWindowProc; + puah->PostDefDlgProc = ThemePostWindowProc; 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.Size = UAHOWP_MAX_SIZE; + + puah->SetWindowRgn = ThemeSetWindowRgn;
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCPAINT); UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCACTIVATE); @@ -130,7 +335,7 @@ UAH_HOOK_MESSAGE(puah->WndProcArray, WM_THEMECHANGED); UAH_HOOK_MESSAGE(puah->WndProcArray, WM_UAHINIT);
- UXTHEME_LoadTheme(); + UXTHEME_LoadTheme(TRUE);
return TRUE; } @@ -187,8 +392,7 @@
ret = UnregisterUserApiHook();
- if(IsThemeActive()) - UXTHEME_broadcast_msg (NULL, WM_THEMECHANGED); + UXTHEME_broadcast_msg (NULL, WM_THEMECHANGED);
return ret; }
Modified: branches/GSoC_2011/ThemesSupport/dll/win32/uxtheme/uxthemedll.h URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2011/ThemesSupport/dll/win3... ============================================================================== --- branches/GSoC_2011/ThemesSupport/dll/win32/uxtheme/uxthemedll.h [iso-8859-1] (original) +++ branches/GSoC_2011/ThemesSupport/dll/win32/uxtheme/uxthemedll.h [iso-8859-1] Mon Aug 15 10:22:23 2011 @@ -95,7 +95,7 @@ ParseThemeIniFileProc callback, LPVOID lpData);
extern void UXTHEME_InitSystem(HINSTANCE hInst); -extern void UXTHEME_LoadTheme(void); +extern void UXTHEME_LoadTheme(BOOL bLoad); extern BOOL CALLBACK UXTHEME_broadcast_msg (HWND hWnd, LPARAM msg);
/* No alpha blending */