📄 msstyles.c
字号:
if (setMetrics)
{
parse_apply_color (&colorState);
parse_apply_nonclient (&nonClientState);
}
continue;
}
if(MSSTYLES_ParseIniSectionName(lpName, dwLen, szAppName, szClassName, &iPartId, &iStateId)) {
BOOL isGlobal = FALSE;
if(!lstrcmpiW(szClassName, szGlobals)) {
isGlobal = TRUE;
}
cls = MSSTYLES_AddClass(tf, szAppName, szClassName);
ps = MSSTYLES_AddPartState(cls, iPartId, iStateId);
while((lpName=UXINI_GetNextValue(ini, &dwLen, &lpValue, &dwValueLen))) {
lstrcpynW(szPropertyName, lpName, min(dwLen+1, sizeof(szPropertyName)/sizeof(szPropertyName[0])));
if(MSSTYLES_LookupProperty(szPropertyName, &iPropertyPrimitive, &iPropertyId)) {
MSSTYLES_AddProperty(ps, iPropertyPrimitive, iPropertyId, lpValue, dwValueLen, isGlobal);
}
else {
TRACE("Unknown property %s\n", debugstr_w(szPropertyName));
}
}
}
}
/* App/Class combos override values defined by the base class, map these overrides */
globals = MSSTYLES_FindClass(tf, NULL, szGlobals);
cls = tf->classes;
while(cls) {
if(*cls->szAppName) {
cls->overrides = MSSTYLES_FindClass(tf, NULL, cls->szClassName);
if(!cls->overrides) {
TRACE("No overrides found for app %s class %s\n", debugstr_w(cls->szAppName), debugstr_w(cls->szClassName));
}
else {
cls->overrides = globals;
}
}
else {
/* Everything overrides globals..except globals */
if(cls != globals) cls->overrides = globals;
}
cls = cls->next;
}
UXINI_CloseINI(ini);
if(!tf->classes) {
ERR("Failed to parse theme ini\n");
}
}
/***********************************************************************
* MSSTYLES_OpenThemeClass
*
* Open a theme class, uses the current active theme
*
* PARAMS
* pszAppName Application name, for theme styles specific
* to a particular application
* pszClassList List of requested classes, semicolon delimited
*/
PTHEME_CLASS MSSTYLES_OpenThemeClass(LPCWSTR pszAppName, LPCWSTR pszClassList)
{
PTHEME_CLASS cls = NULL;
WCHAR szClassName[MAX_THEME_CLASS_NAME];
LPCWSTR start;
LPCWSTR end;
DWORD len;
if(!tfActiveTheme) {
TRACE("there is no active theme\n");
return NULL;
}
if(!tfActiveTheme->classes) {
return NULL;
}
start = pszClassList;
while((end = strchrW(start, ';'))) {
len = end-start;
lstrcpynW(szClassName, start, min(len+1, sizeof(szClassName)/sizeof(szClassName[0])));
start = end+1;
cls = MSSTYLES_FindClass(tfActiveTheme, pszAppName, szClassName);
if(cls) break;
}
if(!cls && *start) {
lstrcpynW(szClassName, start, sizeof(szClassName)/sizeof(szClassName[0]));
cls = MSSTYLES_FindClass(tfActiveTheme, pszAppName, szClassName);
}
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;
}
/***********************************************************************
* MSSTYLES_CloseThemeClass
*
* Close a theme class
*
* PARAMS
* tc Theme class to close
*
* NOTES
* 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;
}
/***********************************************************************
* MSSTYLES_FindProperty
*
* Locate a property in a class. Part and state IDs will be used as a
* preference, but may be ignored in the attempt to locate the property.
* Will scan the entire chain of overrides for this class.
*/
PTHEME_PROPERTY MSSTYLES_FindProperty(PTHEME_CLASS tc, int iPartId, int iStateId, int iPropertyPrimitive, int iPropertyId)
{
PTHEME_CLASS next = tc;
PTHEME_PARTSTATE ps;
PTHEME_PROPERTY tp;
TRACE("(%p, %d, %d, %d)\n", tc, iPartId, iStateId, iPropertyId);
/* Try and find an exact match on part & state */
while(next && (ps = MSSTYLES_FindPartState(next, iPartId, iStateId, &next))) {
if((tp = MSSTYLES_PSFindProperty(ps, iPropertyPrimitive, iPropertyId))) {
return tp;
}
}
/* If that fails, and we didn't already try it, search for just part */
if(iStateId != 0)
iStateId = 0;
/* As a last ditch attempt..go for just class */
else if(iPartId != 0)
iPartId = 0;
else
return NULL;
if((tp = MSSTYLES_FindProperty(tc, iPartId, iStateId, iPropertyPrimitive, iPropertyId)))
return tp;
return NULL;
}
/* Prepare a bitmap to be used for alpha blending */
static BOOL prepare_alpha (HBITMAP bmp, BOOL* hasAlpha)
{
DIBSECTION dib;
int n;
BYTE* p;
*hasAlpha = FALSE;
if (!bmp || GetObjectW( bmp, sizeof(dib), &dib ) != sizeof(dib))
return FALSE;
if(dib.dsBm.bmBitsPixel != 32)
/* nothing to do */
return TRUE;
*hasAlpha = TRUE;
p = (BYTE*)dib.dsBm.bmBits;
n = abs(dib.dsBmih.biHeight) * dib.dsBmih.biWidth;
/* AlphaBlend() wants premultiplied alpha, so do that now */
while (n-- > 0)
{
int a = p[3]+1;
p[0] = (p[0] * a) >> 8;
p[1] = (p[1] * a) >> 8;
p[2] = (p[2] * a) >> 8;
p += 4;
}
return TRUE;
}
HBITMAP MSSTYLES_LoadBitmap (PTHEME_CLASS tc, LPCWSTR lpFilename, BOOL* hasAlpha)
{
WCHAR szFile[MAX_PATH];
LPWSTR tmp;
PTHEME_IMAGE img;
lstrcpynW(szFile, lpFilename, sizeof(szFile)/sizeof(szFile[0]));
tmp = szFile;
do {
if(*tmp == '\\') *tmp = '_';
if(*tmp == '/') *tmp = '_';
if(*tmp == '.') *tmp = '_';
} while(*tmp++);
/* Try to locate in list of loaded images */
img = tc->tf->images;
while (img)
{
if (lstrcmpiW (szFile, img->name) == 0)
{
TRACE ("found %p %s: %p\n", img, debugstr_w (img->name), img->image);
*hasAlpha = img->hasAlpha;
return img->image;
}
img = img->next;
}
/* Not found? Load from resources */
img = HeapAlloc (GetProcessHeap(), 0, sizeof (THEME_IMAGE));
img->image = LoadImageW(tc->hTheme, szFile, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
prepare_alpha (img->image, hasAlpha);
img->hasAlpha = *hasAlpha;
/* ...and stow away for later reuse. */
lstrcpyW (img->name, szFile);
img->next = tc->tf->images;
tc->tf->images = img;
TRACE ("new %p %s: %p\n", img, debugstr_w (img->name), img->image);
return img->image;
}
BOOL MSSTYLES_GetNextInteger(LPCWSTR lpStringStart, LPCWSTR lpStringEnd, LPCWSTR *lpValEnd, int *value)
{
LPCWSTR cur = lpStringStart;
int total = 0;
BOOL gotNeg = FALSE;
while(cur < lpStringEnd && (*cur < '0' || *cur > '9' || *cur == '-')) cur++;
if(cur >= lpStringEnd) {
return FALSE;
}
if(*cur == '-') {
cur++;
gotNeg = TRUE;
}
while(cur < lpStringEnd && (*cur >= '0' && *cur <= '9')) {
total = total * 10 + (*cur - '0');
cur++;
}
if(gotNeg) total = -total;
*value = total;
if(lpValEnd) *lpValEnd = cur;
return TRUE;
}
BOOL MSSTYLES_GetNextToken(LPCWSTR lpStringStart, LPCWSTR lpStringEnd, LPCWSTR *lpValEnd, LPWSTR lpBuff, DWORD buffSize) {
LPCWSTR cur = lpStringStart;
LPCWSTR start;
LPCWSTR end;
while(cur < lpStringEnd && (isspace(*cur) || *cur == ',')) cur++;
if(cur >= lpStringEnd) {
return FALSE;
}
start = cur;
while(cur < lpStringEnd && *cur != ',') cur++;
end = cur;
while(isspace(*end)) end--;
lstrcpynW(lpBuff, start, min(buffSize, end-start+1));
if(lpValEnd) *lpValEnd = cur;
return TRUE;
}
/***********************************************************************
* MSSTYLES_GetPropertyBool
*
* Retrieve a color value for a property
*/
HRESULT MSSTYLES_GetPropertyBool(PTHEME_PROPERTY tp, BOOL *pfVal)
{
*pfVal = FALSE;
if(*tp->lpValue == 't' || *tp->lpValue == 'T')
*pfVal = TRUE;
return S_OK;
}
/***********************************************************************
* MSSTYLES_GetPropertyColor
*
* Retrieve a color value for a property
*/
HRESULT MSSTYLES_GetPropertyColor(PTHEME_PROPERTY tp, COLORREF *pColor)
{
LPCWSTR lpEnd;
LPCWSTR lpCur;
int red, green, blue;
lpCur = tp->lpValue;
lpEnd = tp->lpValue + tp->dwValueLen;
MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &red);
MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &green);
if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &blue)) {
TRACE("Could not parse color property\n");
return E_PROP_ID_UNSUPPORTED;
}
*pColor = RGB(red,green,blue);
return S_OK;
}
/***********************************************************************
* MSSTYLES_GetPropertyColor
*
* Retrieve a color value for a property
*/
static HRESULT MSSTYLES_GetFont (LPCWSTR lpCur, LPCWSTR lpEnd,
LPCWSTR *lpValEnd, LOGFONTW* pFont)
{
static const WCHAR szBold[] = {'b','o','l','d','\0'};
static const WCHAR szItalic[] = {'i','t','a','l','i','c','\0'};
static const WCHAR szUnderline[] = {'u','n','d','e','r','l','i','n','e','\0'};
static const WCHAR szStrikeOut[] = {'s','t','r','i','k','e','o','u','t','\0'};
int pointSize;
WCHAR attr[32];
if(!MSSTYLES_GetNextToken(lpCur, lpEnd, &lpCur, pFont->lfFaceName, LF_FACESIZE)) {
TRACE("Property is there, but failed to get face name\n");
*lpValEnd = lpCur;
return E_PROP_ID_UNSUPPORTED;
}
if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pointSize)) {
TRACE("Property is there, but failed to get point size\n");
*lpValEnd = lpCur;
return E_PROP_ID_UNSUPPORTED;
}
pFont->lfHeight = pointSize;
pFont->lfWeight = FW_REGULAR;
pFont->lfCharSet = DEFAULT_CHARSET;
while(MSSTYLES_GetNextToken(lpCur, lpEnd, &lpCur, attr, sizeof(attr)/sizeof(attr[0]))) {
if(!lstrcmpiW(szBold, attr)) pFont->lfWeight = FW_BOLD;
else if(!!lstrcmpiW(szItalic, attr)) pFont->lfItalic = TRUE;
else if(!!lstrcmpiW(szUnderline, attr)) pFont->lfUnderline = TRUE;
else if(!!lstrcmpiW(szStrikeOut, attr)) pFont->lfStrikeOut = TRUE;
}
*lpValEnd = lpCur;
return S_OK;
}
HRESULT MSSTYLES_GetPropertyFont(PTHEME_PROPERTY tp, HDC hdc, LOGFONTW *pFont)
{
LPCWSTR lpCur = tp->lpValue;
LPCWSTR lpEnd = tp->lpValue + tp->dwValueLen;
HRESULT hr;
ZeroMemory(pFont, sizeof(LOGFONTW));
hr = MSSTYLES_GetFont (lpCur, lpEnd, &lpCur, pFont);
if (SUCCEEDED (hr))
pFont->lfHeight = -MulDiv(pFont->lfHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72);
return hr;
}
/***********************************************************************
* MSSTYLES_GetPropertyInt
*
* Retrieve an int value for a property
*/
HRESULT MSSTYLES_GetPropertyInt(PTHEME_PROPERTY tp, int *piVal)
{
if(!MSSTYLES_GetNextInteger(tp->lpValue, (tp->lpValue + tp->dwValueLen), NULL, piVal)) {
TRACE("Could not parse int property\n");
return E_PROP_ID_UNSUPPORTED;
}
return S_OK;
}
/***********************************************************************
* MSSTYLES_GetPropertyIntList
*
* Retrieve an int list value for a property
*/
HRESULT MSSTYLES_GetPropertyIntList(PTHEME_PROPERTY tp, INTLIST *pIntList)
{
int i;
LPCWSTR lpCur = tp->lpValue;
LPCWSTR lpEnd = tp->lpValue + tp->dwValueLen;
for(i=0; i < MAX_INTLIST_COUNT; i++) {
if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pIntList->iValues[i]))
break;
}
pIntList->iValueCount = i;
return S_OK;
}
/***********************************************************************
* MSSTYLES_GetPropertyPosition
*
* Retrieve a position value for a property
*/
HRESULT MSSTYLES_GetPropertyPosition(PTHEME_PROPERTY tp, POINT *pPoint)
{
int x,y;
LPCWSTR lpCur = tp->lpValue;
LPCWSTR lpEnd = tp->lpValue + tp->dwValueLen;
MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &x);
if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &y)) {
TRACE("Could not parse position property\n");
return E_PROP_ID_UNSUPPORTED;
}
pPoint->x = x;
pPoint->y = y;
return S_OK;
}
/***********************************************************************
* MSSTYLES_GetPropertyString
*
* Retrieve a string value for a property
*/
HRESULT MSSTYLES_GetPropertyString(PTHEME_PROPERTY tp, LPWSTR pszBuff, int cchMaxBuffChars)
{
lstrcpynW(pszBuff, tp->lpValue, min(tp->dwValueLen+1, cchMaxBuffChars));
return S_OK;
}
/***********************************************************************
* MSSTYLES_GetPropertyRect
*
* Retrieve a rect value for a property
*/
HRESULT MSSTYLES_GetPropertyRect(PTHEME_PROPERTY tp, RECT *pRect)
{
LPCWSTR lpCur = tp->lpValue;
LPCWSTR lpEnd = tp->lpValue + tp->dwValueLen;
MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, (int*)&pRect->left);
MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, (int*)&pRect->top);
MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, (int*)&pRect->right);
if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, (int*)&pRect->bottom)) {
TRACE("Could not parse rect property\n");
return E_PROP_ID_UNSUPPORTED;
}
return S_OK;
}
/***********************************************************************
* MSSTYLES_GetPropertyMargins
*
* Retrieve a margins value for a property
*/
HRESULT MSSTYLES_GetPropertyMargins(PTHEME_PROPERTY tp, RECT *prc, MARGINS *pMargins)
{
LPCWSTR lpCur = tp->lpValue;
LPCWSTR lpEnd = tp->lpValue + tp->dwValueLen;
MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pMargins->cxLeftWidth);
MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pMargins->cxRightWidth);
MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pMargins->cyTopHeight);
if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pMargins->cyBottomHeight)) {
TRACE("Could not parse margins property\n");
return E_PROP_ID_UNSUPPORTED;
}
return S_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -