Sync to Wine-20050725:
Thomas Weidenmueller <wine-patches(a)reactsoft.com>
- IsThemeDialogTextureEnabled should have one parameter to match the
prototype in the official headers.
Mike McCormack <mike(a)codeweavers.com>
- gcc 4.0 -Wpointer-sign fixes (Reg* functions).
Stefan Huehner <stefan(a)huehner.org>
- Make some function static.
- Fix -Wmissing-declarations warnings.
Frank Richter <frank.richter(a)gmail.com>
- Enable/disable "flat menus" based on the setting from the active
theme.
- Have the theme INI file parsed upon theme activation and not just when
the first theme data is requested; that way, the themed system colors
are set correctly from the start, and not just after some theme data
was requested.
- GetThemeBackgroundContentRect() does not use the content margins
alone, it also falls back to the border size or sizing margins, and if
it can't find any possible margins at all, it returns the original
rectangle.
- Make dialog theme texture setting non-global (ie a per-window
setting).
- Better viewport origin in DrawThemeParentBackground().
- OpenThemeData() now always sets the window theme to the handle
returned (even if that is NULL) - previously, it could happen that
when no theme was active or the theme data could not be opened that
the window theme remained became then-dangling (and hence subsequent
calls to GetWindowTheme() would return that bogus theme).
- Correct border rectangle drawing.
- Don't crash if NULL is passed as the class list to OpenThemeData().
- UXTHEME_LoadImage(): Set default image count to 1 to avoid division by
zero in case image count property is not given. Properly support 0
state IDs.
- Every window needs to receive WM_THEMECHANGED (esp. controls), so also
send it to child windows.
- Changed the default transparent color in case none was explicitly
specified from the upper left pixel color to magenta. Empirically
gives better results.
- Write WCHAR strings to registry with correct size.
- Opening some theme class data now also increases the reference count
of the theme file, so as long as theme class data is still opened
somewhere, the theme file won't get freed. Otherwise, it could happen
that invalid class data was used, which could lead to problems.
Modified: trunk/reactos/lib/uxtheme/draw.c
Modified: trunk/reactos/lib/uxtheme/msstyles.c
Modified: trunk/reactos/lib/uxtheme/msstyles.h
Modified: trunk/reactos/lib/uxtheme/system.c
_____
Modified: trunk/reactos/lib/uxtheme/draw.c
--- trunk/reactos/lib/uxtheme/draw.c 2005-08-12 18:17:37 UTC (rev
17341)
+++ trunk/reactos/lib/uxtheme/draw.c 2005-08-12 18:22:47 UTC (rev
17342)
@@ -41,7 +41,7 @@
* Defines and global variables
*/
-DWORD dwDialogTextureFlags;
+extern ATOM atDialogThemeEnabled;
/***********************************************************************
/
@@ -50,8 +50,19 @@
*/
HRESULT WINAPI EnableThemeDialogTexture(HWND hwnd, DWORD dwFlags)
{
+ static const WCHAR szTab[] = { 'T','a','b',0 };
+ HRESULT hr;
+
TRACE("(%p,0x%08lx\n", hwnd, dwFlags);
- dwDialogTextureFlags = dwFlags;
+ hr = SetPropW (hwnd, MAKEINTATOMW (atDialogThemeEnabled),
+ (HANDLE)(dwFlags|0x80000000));
+ /* 0x80000000 serves as a "flags set" flag */
+ if (FAILED(hr))
+ return hr;
+ if (dwFlags & ETDT_USETABTEXTURE)
+ return SetWindowTheme (hwnd, NULL, szTab);
+ else
+ return SetWindowTheme (hwnd, NULL, NULL);
return S_OK;
}
@@ -60,7 +71,15 @@
*/
BOOL WINAPI IsThemeDialogTextureEnabled(HWND hwnd)
{
+ DWORD dwDialogTextureFlags;
TRACE("(%p)\n", hwnd);
+
+ dwDialogTextureFlags = (DWORD)GetPropW (hwnd,
+ MAKEINTATOMW (atDialogThemeEnabled));
+ if (dwDialogTextureFlags == 0)
+ /* Means EnableThemeDialogTexture wasn't called for this dialog
*/
+ return TRUE;
+
return (dwDialogTextureFlags & ETDT_ENABLE) &&
!(dwDialogTextureFlags & ETDT_DISABLE);
}
@@ -95,7 +114,7 @@
MapWindowPoints(hParent, NULL, (LPPOINT)&rt, 2);
}
- SetViewportOrgEx(hdc, rt.left, rt.top, &org);
+ OffsetViewportOrgEx(hdc, -rt.left, -rt.top, &org);
SendMessageW(hParent, WM_ERASEBKGND, (WPARAM)hdc, 0);
SendMessageW(hParent, WM_PRINTCLIENT, (WPARAM)hdc, PRF_CLIENT);
@@ -190,7 +209,7 @@
HBITMAP *hBmp, RECT *bmpRect)
{
int imagelayout = IL_VERTICAL;
- int imagecount = 0;
+ int imagecount = 1;
BITMAP bmp;
WCHAR szPath[MAX_PATH];
PTHEME_PROPERTY tp = UXTHEME_SelectImage(hTheme, hdc, iPartId,
iStateId, pRect, glyph);
@@ -213,12 +232,12 @@
int height = bmp.bmHeight/imagecount;
bmpRect->left = 0;
bmpRect->right = bmp.bmWidth;
- bmpRect->top = (min(imagecount, iStateId)-1) * height;
+ bmpRect->top = (max(min(imagecount, iStateId), 1)-1) * height;
bmpRect->bottom = bmpRect->top + height;
}
else {
int width = bmp.bmWidth/imagecount;
- bmpRect->left = (min(imagecount, iStateId)-1) * width;
+ bmpRect->left = (max(min(imagecount, iStateId), 1)-1) * width;
bmpRect->right = bmpRect->left + width;
bmpRect->top = 0;
bmpRect->bottom = bmp.bmHeight;
@@ -302,8 +321,8 @@
GetThemeBool(hTheme, iPartId, iStateId, TMT_GLYPHTRANSPARENT,
&transparent);
if(transparent) {
if(FAILED(GetThemeColor(hTheme, iPartId, iStateId,
TMT_GLYPHTRANSPARENTCOLOR, &transparentcolor))) {
- /* If image is transparent, but no color was specified, get
the color of the upper left corner */
- transparentcolor = GetPixel(hdcSrc, 0, 0);
+ /* If image is transparent, but no color was specified, use
magenta */
+ transparentcolor = RGB(255, 0, 255);
}
}
GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_VALIGN, &valign);
@@ -588,15 +607,17 @@
GetThemeInt(hTheme, iPartId, iStateId, TMT_BORDERSIZE,
&bordersize);
if(bordersize > 0) {
- POINT ptCorners[4];
+ POINT ptCorners[5];
ptCorners[0].x = pRect->left;
ptCorners[0].y = pRect->top;
- ptCorners[1].x = pRect->right;
+ ptCorners[1].x = pRect->right-1;
ptCorners[1].y = pRect->top;
- ptCorners[2].x = pRect->right;
- ptCorners[2].y = pRect->bottom;
+ ptCorners[2].x = pRect->right-1;
+ ptCorners[2].y = pRect->bottom-1;
ptCorners[3].x = pRect->left;
- ptCorners[3].y = pRect->bottom;
+ ptCorners[3].y = pRect->bottom-1;
+ ptCorners[4].x = pRect->left;
+ ptCorners[4].y = pRect->top;
InflateRect(pRect, -bordersize, -bordersize);
if(pOptions->dwFlags & DTBG_OMITBORDER)
@@ -607,7 +628,7 @@
return HRESULT_FROM_WIN32(GetLastError());
oldPen = SelectObject(hdc, hPen);
- if(!Polyline(hdc, ptCorners, 4))
+ if(!Polyline(hdc, ptCorners, 5))
hr = HRESULT_FROM_WIN32(GetLastError());
SelectObject(hdc, oldPen);
@@ -855,15 +876,34 @@
if(!hTheme)
return E_HANDLE;
+ /* try content margins property... */
hr = GetThemeMargins(hTheme, hdc, iPartId, iStateId,
TMT_CONTENTMARGINS, NULL, &margin);
- if(FAILED(hr)) {
- TRACE("Margins not found\n");
- return hr;
+ if(SUCCEEDED(hr)) {
+ pContentRect->left = pBoundingRect->left + margin.cxLeftWidth;
+ pContentRect->top = pBoundingRect->top + margin.cyTopHeight;
+ pContentRect->right = pBoundingRect->right -
margin.cxRightWidth;
+ pContentRect->bottom = pBoundingRect->bottom -
margin.cyBottomHeight;
+ } else {
+ /* otherwise, try to determine content rect from the background
type and props */
+ int bgtype = BT_BORDERFILL;
+ memcpy(pContentRect, pBoundingRect, sizeof(RECT));
+
+ GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_BGTYPE,
&bgtype);
+ if(bgtype == BT_BORDERFILL) {
+ int bordersize = 1;
+
+ GetThemeInt(hTheme, iPartId, iStateId, TMT_BORDERSIZE,
&bordersize);
+ InflateRect(pContentRect, -bordersize, -bordersize);
+ } else if ((bgtype == BT_IMAGEFILE)
+ && (SUCCEEDED(hr = GetThemeMargins(hTheme, hdc,
iPartId, iStateId,
+ TMT_SIZINGMARGINS, NULL, &margin)))) {
+ pContentRect->left = pBoundingRect->left +
margin.cxLeftWidth;
+ pContentRect->top = pBoundingRect->top +
margin.cyTopHeight;
+ pContentRect->right = pBoundingRect->right -
margin.cxRightWidth;
+ pContentRect->bottom = pBoundingRect->bottom -
margin.cyBottomHeight;
+ }
+ /* If nothing was found, leave unchanged */
}
- pContentRect->left = pBoundingRect->left + margin.cxLeftWidth;
- pContentRect->top = pBoundingRect->top + margin.cyTopHeight;
- pContentRect->right = pBoundingRect->right - margin.cxRightWidth;
- pContentRect->bottom = pBoundingRect->bottom -
margin.cyBottomHeight;
TRACE("left:%ld,top:%ld,right:%ld,bottom:%ld\n",
pContentRect->left, pContentRect->top, pContentRect->right,
pContentRect->bottom);
_____
Modified: trunk/reactos/lib/uxtheme/msstyles.c
--- trunk/reactos/lib/uxtheme/msstyles.c 2005-08-12 18:17:37 UTC
(rev 17341)
+++ trunk/reactos/lib/uxtheme/msstyles.c 2005-08-12 18:22:47 UTC
(rev 17342)
@@ -253,7 +253,7 @@
*
* Retrieve the ini file for the selected color/style
*/
-PUXINI_FILE MSSTYLES_GetActiveThemeIni(PTHEME_FILE tf)
+static PUXINI_FILE MSSTYLES_GetActiveThemeIni(PTHEME_FILE tf)
{
static const WCHAR szFileResNamesResource[] = {
'F','I','L','E','R','E','S','N','A','M','E','S','\0'
@@ -320,7 +320,7 @@
* iPartId Location to store part id
* iStateId Location to store state id
*/
-BOOL MSSTYLES_ParseIniSectionName(LPCWSTR lpSection, DWORD dwLen,
LPWSTR szAppName, LPWSTR szClassName, int *iPartId, int *iStateId)
+static BOOL MSSTYLES_ParseIniSectionName(LPCWSTR lpSection, DWORD
dwLen, LPWSTR szAppName, LPWSTR szClassName, int *iPartId, int
*iStateId)
{
WCHAR sec[255];
WCHAR part[60] = {'\0'};
@@ -423,7 +423,7 @@
* RETURNS
* The class added, or a class previously added with the same name
*/
-PTHEME_CLASS MSSTYLES_AddClass(PTHEME_FILE tf, LPCWSTR pszAppName,
LPCWSTR pszClassName)
+static PTHEME_CLASS MSSTYLES_AddClass(PTHEME_FILE tf, LPCWSTR
pszAppName, LPCWSTR pszClassName)
{
PTHEME_CLASS cur = MSSTYLES_FindClass(tf, pszAppName,
pszClassName);
if(cur) return cur;
@@ -480,7 +480,7 @@
* RETURNS
* The part/state added, or a part/state previously added with the
same IDs
*/
-PTHEME_PARTSTATE MSSTYLES_AddPartState(PTHEME_CLASS tc, int iPartId,
int iStateId)
+static PTHEME_PARTSTATE MSSTYLES_AddPartState(PTHEME_CLASS tc, int
iPartId, int iStateId)
{
PTHEME_PARTSTATE cur = MSSTYLES_FindPartState(tc, iPartId,
iStateId, NULL);
if(cur) return cur;
@@ -507,7 +507,7 @@
* RETURNS
* The property found, or NULL
*/
-PTHEME_PROPERTY MSSTYLES_LFindProperty(PTHEME_PROPERTY tp, int
iPropertyPrimitive, int iPropertyId)
+static PTHEME_PROPERTY MSSTYLES_LFindProperty(PTHEME_PROPERTY tp, int
iPropertyPrimitive, int iPropertyId)
{
PTHEME_PROPERTY cur = tp;
while(cur) {
@@ -596,7 +596,7 @@
* RETURNS
* The property added, or a property previously added with the same
IDs
*/
-PTHEME_PROPERTY MSSTYLES_AddProperty(PTHEME_PARTSTATE ps, int
iPropertyPrimitive, int iPropertyId, LPCWSTR lpValue, DWORD dwValueLen,
BOOL isGlobal)
+static PTHEME_PROPERTY MSSTYLES_AddProperty(PTHEME_PARTSTATE ps, int
iPropertyPrimitive, int iPropertyId, LPCWSTR lpValue, DWORD dwValueLen,
BOOL isGlobal)
{
PTHEME_PROPERTY cur = MSSTYLES_PSFindProperty(ps,
iPropertyPrimitive, iPropertyId);
/* Should duplicate properties overwrite the original, or be
ignored? */
@@ -637,7 +637,7 @@
* RETURNS
* The property added, or a property previously added with the same
IDs
*/
-PTHEME_PROPERTY MSSTYLES_AddMetric(PTHEME_FILE tf, int
iPropertyPrimitive, int iPropertyId, LPCWSTR lpValue, DWORD dwValueLen)
+static PTHEME_PROPERTY MSSTYLES_AddMetric(PTHEME_FILE tf, int
iPropertyPrimitive, int iPropertyId, LPCWSTR lpValue, DWORD dwValueLen)
{
PTHEME_PROPERTY cur = MSSTYLES_FFindMetric(tf, iPropertyPrimitive,
iPropertyId);
/* Should duplicate properties overwrite the original, or be
ignored? */
@@ -709,6 +709,10 @@
FIXME("Invalid color value for %s\n",
debugstr_w(szPropertyName));
}
}
+ else if (iPropertyId == TMT_FLATMENUS) {
+ BOOL flatMenus = (*lpValue == 'T') || (*lpValue
== 't');
+ SystemParametersInfoW (SPI_SETFLATMENU, 0,
(PVOID)flatMenus, 0);
+ }
/* Catch all metrics, including colors */
MSSTYLES_AddMetric(tf, iPropertyPrimitive,
iPropertyId, lpValue, dwValueLen);
}
@@ -806,6 +810,8 @@
}
if(cls) {
TRACE("Opened app %s, class %s from list %s\n",
debugstr_w(cls->szAppName), debugstr_w(cls->szClassName),
debugstr_w(pszClassList));
+ cls->tf = tfActiveTheme;
+ cls->tf->dwRefCount++;
}
return cls;
}
@@ -819,11 +825,12 @@
* tc Theme class to close
*
* NOTES
- * There is currently no need clean anything up for theme classes,
- * so do nothing for now
+ * The MSSTYLES_CloseThemeFile decreases the refcount of the owning
+ * theme file and cleans it up, if needed.
*/
HRESULT MSSTYLES_CloseThemeClass(PTHEME_CLASS tc)
{
+ MSSTYLES_CloseThemeFile (tc->tf);
return S_OK;
}
_____
Modified: trunk/reactos/lib/uxtheme/msstyles.h
--- trunk/reactos/lib/uxtheme/msstyles.h 2005-08-12 18:17:37 UTC
(rev 17341)
+++ trunk/reactos/lib/uxtheme/msstyles.h 2005-08-12 18:22:47 UTC
(rev 17342)
@@ -46,8 +46,11 @@
struct _THEME_PARTSTATE *next;
} THEME_PARTSTATE, *PTHEME_PARTSTATE;
+struct _THEME_FILE;
+
typedef struct _THEME_CLASS {
HMODULE hTheme;
+ struct _THEME_FILE* tf;
WCHAR szAppName[MAX_THEME_APP_NAME];
WCHAR szClassName[MAX_THEME_CLASS_NAME];
PTHEME_PARTSTATE partstate;
_____
Modified: trunk/reactos/lib/uxtheme/system.c
--- trunk/reactos/lib/uxtheme/system.c 2005-08-12 18:17:37 UTC (rev
17341)
+++ trunk/reactos/lib/uxtheme/system.c 2005-08-12 18:22:47 UTC (rev
17342)
@@ -62,6 +62,7 @@
ATOM atWindowTheme;
ATOM atSubAppName;
ATOM atSubIdList;
+ATOM atDialogThemeEnabled;
BOOL bThemeActive = FALSE;
WCHAR szCurrentTheme[MAX_PATH];
@@ -70,6 +71,27 @@
/***********************************************************************
/
+static BOOL CALLBACK UXTHEME_broadcast_msg_enumchild (HWND hWnd, LPARAM
msg)
+{
+ PostMessageW(hWnd, msg, 0, 0);
+ return TRUE;
+}
+
+/* Broadcast a message to *all* windows, including children */
+static BOOL CALLBACK UXTHEME_broadcast_msg (HWND hWnd, LPARAM msg)
+{
+ if (hWnd == NULL)
+ {
+ EnumWindows (UXTHEME_broadcast_msg, msg);
+ }
+ else
+ {
+ PostMessageW(hWnd, msg, 0, 0);
+ EnumChildWindows (hWnd, UXTHEME_broadcast_msg_enumchild, msg);
+ }
+ return TRUE;
+}
+
/***********************************************************************
* UXTHEME_LoadTheme
*
@@ -78,7 +100,7 @@
static void UXTHEME_LoadTheme(void)
{
HKEY hKey;
- LONG buffsize;
+ DWORD buffsize;
HRESULT hr;
WCHAR tmp[10];
PTHEME_FILE pt;
@@ -169,9 +191,12 @@
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);
- RegSetValueExW(hKey, szSizeName, 0, REG_SZ, (const
BYTE*)szCurrentSize, lstrlenW(szCurrentSize)+1);
- RegSetValueExW(hKey, szDllName, 0, REG_SZ, (const
BYTE*)szCurrentTheme, lstrlenW(szCurrentTheme)+1);
+ 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));
}
else {
RegDeleteValueW(hKey, szColorName);
@@ -200,12 +225,16 @@
static const WCHAR szSubIdList[] = {
'u','x','_','s','u','b','i','d','l','s','t','\0'
};
+ static const WCHAR szDialogThemeEnabled[] = {
+
'u','x','_','d','i','a','l','o','g','t','h','e','m','e','\0'
+ };
hDllInst = hInst;
- atWindowTheme = GlobalAddAtomW(szWindowTheme);
- atSubAppName = GlobalAddAtomW(szSubAppName);
- atSubIdList = GlobalAddAtomW(szSubIdList);
+ atWindowTheme = GlobalAddAtomW(szWindowTheme);
+ atSubAppName = GlobalAddAtomW(szSubAppName);
+ atSubIdList = GlobalAddAtomW(szSubIdList);
+ atDialogThemeEnabled = GlobalAddAtomW(szDialogThemeEnabled);
UXTHEME_LoadTheme();
}
@@ -247,7 +276,7 @@
RegSetValueExW(hKey, szThemeActive, 0, REG_SZ,
(LPBYTE)szEnabled, sizeof(WCHAR));
RegCloseKey(hKey);
}
- PostMessageW(HWND_BROADCAST, WM_THEMECHANGED, 0, 0);
+ UXTHEME_broadcast_msg (NULL, WM_THEMECHANGED);
}
return S_OK;
}
@@ -295,20 +324,23 @@
WCHAR szClassBuff[256];
LPCWSTR pszAppName;
LPCWSTR pszUseClassList;
- HTHEME hTheme;
- TRACE("(%p,%s)\n", hwnd, debugstr_w(pszClassList));
- if(!bThemeActive)
- return NULL;
+ HTHEME hTheme = NULL;
+ TRACE("(%p,%s)", hwnd, debugstr_w(pszClassList));
- 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 = UXTHEME_GetWindowProperty(hwnd, atSubIdList,
szClassBuff, sizeof(szClassBuff)/sizeof(szClassBuff[0]));
- if(!pszUseClassList)
- pszUseClassList = pszClassList;
+ if(bThemeActive)
+ {
+ 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 = UXTHEME_GetWindowProperty(hwnd, atSubIdList,
szClassBuff, sizeof(szClassBuff)/sizeof(szClassBuff[0]));
+ if(!pszUseClassList)
+ pszUseClassList = pszClassList;
- hTheme = MSSTYLES_OpenThemeClass(pszAppName, pszUseClassList);
+ if (pszUseClassList)
+ hTheme = MSSTYLES_OpenThemeClass(pszAppName,
pszUseClassList);
+ }
if(IsWindow(hwnd))
SetPropW(hwnd, MAKEINTATOMW(atWindowTheme), hTheme);
+ TRACE(" = %p\n", hTheme);
return hTheme;
}
@@ -338,7 +370,7 @@
if(SUCCEEDED(hr))
hr = UXTHEME_SetWindowProperty(hwnd, atSubIdList,
pszSubIdList);
if(SUCCEEDED(hr))
- PostMessageW(hwnd, WM_THEMECHANGED, 0, 0);
+ UXTHEME_broadcast_msg (hwnd, WM_THEMECHANGED);
return hr;
}
@@ -554,7 +586,7 @@
HRESULT hr;
TRACE("(%p,%s,%p)\n", hThemeFile, unknown, hWnd);
hr = UXTHEME_SetActiveTheme(hThemeFile);
- PostMessageW(HWND_BROADCAST, WM_THEMECHANGED, 0, 0);
+ UXTHEME_broadcast_msg (NULL, WM_THEMECHANGED);
return hr;
}