*/
#include "uxthemep.h"
-#include <wine/debug.h>
-WINE_DEFAULT_DEBUG_CHANNEL(uxtheme);
+#include <stdio.h>
+#include <winreg.h>
+#include <uxundoc.h>
/***********************************************************************
* Defines and global variables
ATOM atWindowTheme;
static ATOM atSubAppName;
static ATOM atSubIdList;
-ATOM atWndContrext;
+ATOM atWndContext;
-static BOOL bThemeActive = FALSE;
-static WCHAR szCurrentTheme[MAX_PATH];
-static WCHAR szCurrentColor[64];
-static WCHAR szCurrentSize[64];
+PTHEME_FILE ActiveThemeFile;
/***********************************************************************/
static DWORD query_reg_path (HKEY hKey, LPCWSTR lpszValue,
LPVOID pvData)
{
- DWORD dwRet, dwType, dwUnExpDataLen = MAX_PATH, dwExpDataLen;
+ DWORD dwRet, dwType, dwUnExpDataLen = MAX_PATH * sizeof(WCHAR), dwExpDataLen;
TRACE("(hkey=%p,%s,%p)\n", hKey, debugstr_w(lpszValue),
pvData);
return dwRet;
}
+static HRESULT UXTHEME_SetActiveTheme(PTHEME_FILE tf)
+{
+ if(ActiveThemeFile)
+ MSSTYLES_CloseThemeFile(ActiveThemeFile);
+ ActiveThemeFile = tf;
+ if (ActiveThemeFile)
+ {
+ MSSTYLES_ReferenceTheme(ActiveThemeFile);
+ MSSTYLES_ParseThemeIni(ActiveThemeFile);
+ }
+ return S_OK;
+}
+
+static BOOL bIsThemeActive(LPCWSTR pszTheme, LPCWSTR pszColor, LPCWSTR pszSize)
+{
+ if (ActiveThemeFile == NULL)
+ return FALSE;
+
+ if (wcscmp(pszTheme, ActiveThemeFile->szThemeFile) != 0)
+ return FALSE;
+
+ if (!pszColor[0])
+ {
+ if (ActiveThemeFile->pszAvailColors != ActiveThemeFile->pszSelectedColor)
+ return FALSE;
+ }
+ else
+ {
+ if (wcscmp(pszColor, ActiveThemeFile->pszSelectedColor) != 0)
+ return FALSE;
+ }
+
+ if (!pszSize[0])
+ {
+ if (ActiveThemeFile->pszAvailSizes != ActiveThemeFile->pszSelectedSize)
+ return FALSE;
+ }
+ else
+ {
+ if (wcscmp(pszSize, ActiveThemeFile->pszSelectedSize) != 0)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/***********************************************************************
* UXTHEME_LoadTheme
*
HRESULT hr;
WCHAR tmp[10];
PTHEME_FILE pt;
+ WCHAR szCurrentTheme[MAX_PATH];
+ WCHAR szCurrentColor[64];
+ WCHAR szCurrentSize[64];
+ BOOL bThemeActive = FALSE;
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]);
+ buffsize = sizeof(tmp);
if(!RegQueryValueExW(hKey, szThemeActive, NULL, NULL, (LPBYTE)tmp, &buffsize)) {
bThemeActive = (tmp[0] != '0');
}
bThemeActive = FALSE;
TRACE("Failed to get ThemeActive: %d\n", GetLastError());
}
- buffsize = sizeof(szCurrentColor)/sizeof(szCurrentColor[0]);
+ buffsize = sizeof(szCurrentColor);
if(RegQueryValueExW(hKey, szColorName, NULL, NULL, (LPBYTE)szCurrentColor, &buffsize))
szCurrentColor[0] = '\0';
- buffsize = sizeof(szCurrentSize)/sizeof(szCurrentSize[0]);
+ buffsize = sizeof(szCurrentSize);
if(RegQueryValueExW(hKey, szSizeName, NULL, NULL, (LPBYTE)szCurrentSize, &buffsize))
szCurrentSize[0] = '\0';
if (query_reg_path (hKey, szDllName, szCurrentTheme))
bThemeActive = FALSE;
}
- if(bThemeActive) {
+ if(bThemeActive)
+ {
+ if( bIsThemeActive(szCurrentTheme, szCurrentColor, szCurrentSize) )
+ {
+ TRACE("Tried to load active theme again\n");
+ return;
+ }
+
/* Make sure the theme requested is actually valid */
hr = MSSTYLES_OpenThemeFile(szCurrentTheme,
szCurrentColor[0]?szCurrentColor:NULL,
&pt);
if(FAILED(hr)) {
bThemeActive = FALSE;
- szCurrentTheme[0] = '\0';
- szCurrentColor[0] = '\0';
- szCurrentSize[0] = '\0';
}
else {
- /* Make sure the global color & size match the theme */
- lstrcpynW(szCurrentColor, pt->pszSelectedColor, sizeof(szCurrentColor)/sizeof(szCurrentColor[0]));
- lstrcpynW(szCurrentSize, pt->pszSelectedSize, sizeof(szCurrentSize)/sizeof(szCurrentSize[0]));
-
- MSSTYLES_SetActiveTheme(pt, FALSE);
TRACE("Theme active: %s %s %s\n", debugstr_w(szCurrentTheme),
debugstr_w(szCurrentColor), debugstr_w(szCurrentSize));
+
+ UXTHEME_SetActiveTheme(pt);
MSSTYLES_CloseThemeFile(pt);
}
}
if(!bThemeActive) {
- MSSTYLES_SetActiveTheme(NULL, FALSE);
+ UXTHEME_SetActiveTheme(NULL);
TRACE("Theming not active\n");
}
}
}
/***********************************************************************
- * UXTHEME_SetActiveTheme
+ * UXTHEME_ApplyTheme
*
* Change the current active theme
*/
-static HRESULT UXTHEME_SetActiveTheme(PTHEME_FILE tf)
+static HRESULT UXTHEME_ApplyTheme(PTHEME_FILE tf)
{
HKEY hKey;
WCHAR tmp[2];
HRESULT hr;
- if(tf && !bThemeActive) UXTHEME_BackupSystemMetrics();
- hr = MSSTYLES_SetActiveTheme(tf, TRUE);
- if(FAILED(hr))
- return hr;
- if(tf) {
- bThemeActive = TRUE;
- lstrcpynW(szCurrentTheme, tf->szThemeFile, sizeof(szCurrentTheme)/sizeof(szCurrentTheme[0]));
- lstrcpynW(szCurrentColor, tf->pszSelectedColor, sizeof(szCurrentColor)/sizeof(szCurrentColor[0]));
- lstrcpynW(szCurrentSize, tf->pszSelectedSize, sizeof(szCurrentSize)/sizeof(szCurrentSize[0]));
+ TRACE("UXTHEME_ApplyTheme\n");
+
+ if (tf && !ActiveThemeFile)
+ {
+ UXTHEME_BackupSystemMetrics();
}
- else {
+
+ hr = UXTHEME_SetActiveTheme(tf);
+ if (FAILED(hr))
+ return hr;
+
+ if (!tf)
+ {
UXTHEME_RestoreSystemMetrics();
- bThemeActive = FALSE;
- szCurrentTheme[0] = '\0';
- szCurrentColor[0] = '\0';
- szCurrentSize[0] = '\0';
}
TRACE("Writing theme config to registry\n");
if(!RegCreateKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) {
- tmp[0] = bThemeActive?'1':'0';
+ tmp[0] = ActiveThemeFile?'1':'0';
tmp[1] = '\0';
RegSetValueExW(hKey, szThemeActive, 0, REG_SZ, (const BYTE*)tmp, sizeof(WCHAR)*2);
- if(bThemeActive) {
- RegSetValueExW(hKey, szColorName, 0, REG_SZ, (const BYTE*)szCurrentColor,
- (lstrlenW(szCurrentColor)+1)*sizeof(WCHAR));
- RegSetValueExW(hKey, szSizeName, 0, REG_SZ, (const BYTE*)szCurrentSize,
- (lstrlenW(szCurrentSize)+1)*sizeof(WCHAR));
- RegSetValueExW(hKey, szDllName, 0, REG_SZ, (const BYTE*)szCurrentTheme,
- (lstrlenW(szCurrentTheme)+1)*sizeof(WCHAR));
+ if (ActiveThemeFile) {
+ RegSetValueExW(hKey, szColorName, 0, REG_SZ, (const BYTE*)tf->pszSelectedColor,
+ (lstrlenW(tf->pszSelectedColor)+1)*sizeof(WCHAR));
+ RegSetValueExW(hKey, szSizeName, 0, REG_SZ, (const BYTE*)tf->pszSelectedSize,
+ (lstrlenW(tf->pszSelectedSize)+1)*sizeof(WCHAR));
+ RegSetValueExW(hKey, szDllName, 0, REG_SZ, (const BYTE*)tf->szThemeFile,
+ (lstrlenW(tf->szThemeFile)+1)*sizeof(WCHAR));
}
else {
RegDeleteValueW(hKey, szColorName);
atSubAppName = GlobalAddAtomW(szSubAppName);
atSubIdList = GlobalAddAtomW(szSubIdList);
atDialogThemeEnabled = GlobalAddAtomW(szDialogThemeEnabled);
- atWndContrext = GlobalAddAtomW(L"ux_WndContext");
+ atWndContext = GlobalAddAtomW(L"ux_WndContext");
}
/***********************************************************************
*/
BOOL WINAPI IsAppThemed(void)
{
- return IsThemeActive();
+ TRACE("\n");
+ SetLastError(ERROR_SUCCESS);
+ return (ActiveThemeFile != NULL);
}
/***********************************************************************
*/
BOOL WINAPI IsThemeActive(void)
{
- TRACE("\n");
+ BOOL bActive;
+ LRESULT Result;
+ HKEY hKey;
+ WCHAR tmp[10];
+ DWORD buffsize;
+
+ TRACE("IsThemeActive\n");
SetLastError(ERROR_SUCCESS);
- return bThemeActive;
+
+ if (ActiveThemeFile)
+ return TRUE;
+
+ if (gbThemeHooksActive)
+ return FALSE;
+
+ bActive = FALSE;
+ Result = RegOpenKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey);
+ if (Result == ERROR_SUCCESS)
+ {
+ buffsize = sizeof(tmp);
+ if (!RegQueryValueExW(hKey, szThemeActive, NULL, NULL, (LPBYTE)tmp, &buffsize))
+ bActive = (tmp[0] != '0');
+ RegCloseKey(hKey);
+ }
+
+ return bActive;
}
/***********************************************************************
TRACE("(%d)\n", fEnable);
- if(fEnable != bThemeActive) {
+ if (fEnable != (ActiveThemeFile != NULL)) {
if(fEnable)
UXTHEME_BackupSystemMetrics();
else
UXTHEME_RestoreSystemMetrics();
UXTHEME_SaveSystemMetrics ();
- bThemeActive = fEnable;
- if(bThemeActive) szEnabled[0] = '1';
+
+ if (fEnable) szEnabled[0] = '1';
if(!RegOpenKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) {
RegSetValueExW(hKey, szThemeActive, 0, REG_SZ, (LPBYTE)szEnabled, sizeof(WCHAR));
RegCloseKey(hKey);
{
ATOM oldValue = (ATOM)(size_t)RemovePropW(hwnd, (LPCWSTR)MAKEINTATOM(aProp));
if(oldValue)
+ {
DeleteAtom(oldValue);
- if(pszValue) {
- ATOM atValue = AddAtomW(pszValue);
- if(!atValue
- || !SetPropW(hwnd, (LPCWSTR)MAKEINTATOM(aProp), (LPWSTR)MAKEINTATOM(atValue))) {
- HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ if(pszValue)
+ {
+ ATOM atValue;
+
+ /* A string with zero lenght is not acceptatble in AddAtomW but we want to support
+ users passing an empty string meaning they want no theme for the specified window */
+ if(!pszValue[0])
+ pszValue = L"0";
+
+ atValue = AddAtomW(pszValue);
+ if (!atValue)
+ {
+ ERR("AddAtomW for %S failed with last error %d!\n", pszValue, GetLastError());
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ if (!SetPropW(hwnd, (LPCWSTR)MAKEINTATOM(aProp), (LPWSTR)MAKEINTATOM(atValue)))
+ {
+ ERR("SetPropW for atom %d failed with last error %d\n", aProp, GetLastError());
if(atValue) DeleteAtom(atValue);
- return hr;
+ return HRESULT_FROM_WIN32(GetLastError());
}
}
return S_OK;
return NULL;
}
-/***********************************************************************
- * OpenThemeDataEx (UXTHEME.61)
- */
-HTHEME WINAPI OpenThemeDataEx(HWND hwnd, LPCWSTR pszClassList, DWORD flags)
+static HTHEME WINAPI
+OpenThemeDataInternal(PTHEME_FILE ThemeFile, HWND hwnd, LPCWSTR pszClassList, DWORD flags)
{
WCHAR szAppBuff[256];
WCHAR szClassBuff[256];
LPCWSTR pszAppName;
LPCWSTR pszUseClassList;
HTHEME hTheme = NULL;
- TRACE("(%p,%s)\n", hwnd, debugstr_w(pszClassList));
-
+ TRACE("(%p,%s, %x)\n", hwnd, debugstr_w(pszClassList), flags);
+
if(!pszClassList)
{
SetLastError(E_POINTER);
if(flags)
FIXME("unhandled flags: %x\n", flags);
- if(bThemeActive)
+ if (ThemeFile)
{
pszAppName = UXTHEME_GetWindowProperty(hwnd, atSubAppName, szAppBuff, sizeof(szAppBuff)/sizeof(szAppBuff[0]));
/* If SetWindowTheme was used on the window, that overrides the class list passed to this function */
pszUseClassList = pszClassList;
if (pszUseClassList)
- hTheme = MSSTYLES_OpenThemeClass(pszAppName, pszUseClassList);
+ {
+ if (!ThemeFile->classes)
+ MSSTYLES_ParseThemeIni(ThemeFile);
+ hTheme = MSSTYLES_OpenThemeClass(ThemeFile, pszAppName, pszUseClassList);
+ }
}
+
if(IsWindow(hwnd))
+ {
SetPropW(hwnd, (LPCWSTR)MAKEINTATOM(atWindowTheme), hTheme);
+ }
+ else
+ {
+ SetLastError(E_PROP_ID_UNSUPPORTED);
+ }
+
+ SetLastError(hTheme ? ERROR_SUCCESS : E_PROP_ID_UNSUPPORTED);
+
TRACE(" = %p\n", hTheme);
return hTheme;
}
+/***********************************************************************
+ * OpenThemeDataEx (UXTHEME.61)
+ */
+HTHEME WINAPI OpenThemeDataEx(HWND hwnd, LPCWSTR pszClassList, DWORD flags)
+{
+ return OpenThemeDataInternal(ActiveThemeFile, hwnd, pszClassList, flags);
+}
+
+/***********************************************************************
+ * OpenThemeDataFromFile (UXTHEME.16)
+ */
HTHEME WINAPI OpenThemeDataFromFile(HTHEMEFILE hThemeFile, HWND hwnd, LPCWSTR pszClassList, DWORD flags)
{
- return S_OK;
+ return OpenThemeDataInternal((PTHEME_FILE)hThemeFile, hwnd, pszClassList, flags);
}
/***********************************************************************
*/
HTHEME WINAPI OpenThemeData(HWND hwnd, LPCWSTR classlist)
{
- return OpenThemeDataEx(hwnd, classlist, 0);
+ return OpenThemeDataInternal(ActiveThemeFile, hwnd, classlist, 0);
}
/***********************************************************************
HTHEME WINAPI GetWindowTheme(HWND hwnd)
{
TRACE("(%p)\n", hwnd);
+
if(!IsWindow(hwnd))
+ {
SetLastError(E_HANDLE);
+ return NULL;
+ }
return GetPropW(hwnd, (LPCWSTR)MAKEINTATOM(atWindowTheme));
}
HRESULT WINAPI SetWindowTheme(HWND hwnd, LPCWSTR pszSubAppName,
LPCWSTR pszSubIdList)
{
- HRESULT hr;
+ HRESULT hr;
TRACE("(%p,%s,%s)\n", hwnd, debugstr_w(pszSubAppName),
debugstr_w(pszSubIdList));
if(!IsWindow(hwnd))
- return E_HANDLE;
+ return E_HANDLE;
hr = UXTHEME_SetWindowProperty(hwnd, atSubAppName, pszSubAppName);
- if(SUCCEEDED(hr))
- hr = UXTHEME_SetWindowProperty(hwnd, atSubIdList, pszSubIdList);
- if(SUCCEEDED(hr))
- UXTHEME_broadcast_msg (hwnd, WM_THEMECHANGED);
+ if (!SUCCEEDED(hr))
+ return hr;
+
+ hr = UXTHEME_SetWindowProperty(hwnd, atSubIdList, pszSubIdList);
+ if (!SUCCEEDED(hr))
+ return hr;
+
+ UXTHEME_broadcast_msg (hwnd, WM_THEMECHANGED);
return hr;
}
LPWSTR pszColorBuff, int cchMaxColorChars,
LPWSTR pszSizeBuff, int cchMaxSizeChars)
{
- if(!bThemeActive)
- return E_PROP_ID_UNSUPPORTED;
- if(pszThemeFileName) lstrcpynW(pszThemeFileName, szCurrentTheme, dwMaxNameChars);
- if(pszColorBuff) lstrcpynW(pszColorBuff, szCurrentColor, cchMaxColorChars);
- if(pszSizeBuff) lstrcpynW(pszSizeBuff, szCurrentSize, cchMaxSizeChars);
+ int cchar;
+
+ if(ActiveThemeFile == NULL)
+ return E_PROP_ID_UNSUPPORTED;
+
+ if (pszThemeFileName && dwMaxNameChars)
+ {
+ cchar = lstrlenW(ActiveThemeFile->szThemeFile) + 1;
+ if(cchar > dwMaxNameChars)
+ return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ lstrcpynW(pszThemeFileName, ActiveThemeFile->szThemeFile, cchar);
+ }
+
+ if (pszColorBuff && cchMaxColorChars)
+ {
+ cchar = lstrlenW(ActiveThemeFile->pszSelectedColor) + 1;
+ if(cchar > cchMaxColorChars)
+ return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ lstrcpynW(pszColorBuff, ActiveThemeFile->pszSelectedColor, cchar);
+ }
+
+ if (pszSizeBuff && cchMaxSizeChars)
+ {
+ cchar = lstrlenW(ActiveThemeFile->pszSelectedSize) + 1;
+ if(cchar > cchMaxSizeChars)
+ return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ lstrcpynW(pszSizeBuff, ActiveThemeFile->pszSelectedSize, cchar);
+ }
+
return S_OK;
}
HRESULT WINAPI CloseThemeData(HTHEME hTheme)
{
TRACE("(%p)\n", hTheme);
- if(!hTheme)
+ if(!hTheme || hTheme == INVALID_HANDLE_VALUE)
return E_HANDLE;
return MSSTYLES_CloseThemeClass(hTheme);
}
FIXME("%d %d 0x%08x: stub\n", iPartId, iStateId, dwOptions);
if(!hTheme)
return E_HANDLE;
- return ERROR_CALL_NOT_IMPLEMENTED;
+ return E_NOTIMPL;
}
/***********************************************************************
{
HRESULT hr;
TRACE("(%p,%s,%p)\n", hThemeFile, unknown, hWnd);
- hr = UXTHEME_SetActiveTheme(hThemeFile);
+ hr = UXTHEME_ApplyTheme(hThemeFile);
UXTHEME_broadcast_msg (NULL, WM_THEMECHANGED);
return hr;
}
PARSETHEMEINIFILEPROC callback, LPVOID lpData)
{
FIXME("%s %s: stub\n", debugstr_w(pszIniFileName), debugstr_w(pszUnknown));
- return ERROR_CALL_NOT_IMPLEMENTED;
+ return E_NOTIMPL;
}
/**********************************************************************
MSSTYLES_CloseThemeFile(pt);
return S_OK;
}
-
-HRESULT WINAPI DrawNCPreview(HDC hDC,
- DWORD DNCP_Flag,
- LPRECT prcPreview,
- LPCWSTR pszThemeFileName,
- LPCWSTR pszColorName,
- LPCWSTR pszSizeName,
- PNONCLIENTMETRICSW pncMetrics,
- COLORREF* lpaRgbValues)
-{
- return S_OK;
-}
-