// XTPSkinManagerSchema.cpp: implementation of the CXTPSkinManagerSchema class. // // This file is a part of the XTREME SKINFRAMEWORK MFC class library. // (c)1998-2012 Codejock Software, All Rights Reserved. // // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN // CONSENT OF CODEJOCK SOFTWARE. // // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A // SINGLE COMPUTER. // // CONTACT INFORMATION: // support@codejock.com // http://www.codejock.com // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "Common/Tmschema.h" #include "Common/XTPSystemHelpers.h" #include "Common/XTPColorManager.h" #include "Common/XTPVC80Helpers.h" #include "Common/XTPDrawHelpers.h" #include "XTPSkinManager.h" #include "XTPSkinManagerSchema.h" #include "XTPSkinManagerResource.h" #include "XTPSkinImage.h" #include "XTPSkinObject.h" #include "XTPSkinObjectFrame.h" #include "XTPSkinDrawTools.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif #ifndef OIC_WINLOGO #define OIC_WINLOGO 32517 #endif #ifndef LAYOUT_BITMAPORIENTATIONPRESERVED #define LAYOUT_BITMAPORIENTATIONPRESERVED 0x00000008 #endif void InflateBorders(CRect& rcBorders, int cxFrame, int cyFrame) { rcBorders.left += cxFrame; rcBorders.right += cxFrame; rcBorders.top += cyFrame; rcBorders.bottom += cyFrame; } CXTPSkinManagerSchemaProperty::CXTPSkinManagerSchemaProperty() { propType = XTP_SKINPROPERTY_UNKNOWN; nPropertyCode = 0; ZeroMemory(&rcVal, sizeof(RECT)); } CXTPSkinManagerSchemaProperty::~CXTPSkinManagerSchemaProperty() { ClearProperty(); } void CXTPSkinManagerSchemaProperty::ClearProperty() { if (propType == XTP_SKINPROPERTY_STRING) delete[] lpszVal; if (propType == XTP_SKINPROPERTY_FONT) delete lfVal; propType = XTP_SKINPROPERTY_UNKNOWN; } void CXTPSkinManagerSchemaProperty::SetPropertyColor(LPCTSTR lpszValue) { ClearProperty(); int r = 0, g = 0, b = 0; SCANF_S(lpszValue, _T("%i %i %i"), &r, &g, &b); clrVal = RGB(r, g, b); } void CXTPSkinManagerSchemaProperty::SetPropertyString(LPCTSTR lpszValue) { ClearProperty(); int nLen = (int)_tcslen(lpszValue); lpszVal = new TCHAR[nLen + 1]; STRCPY_S(lpszVal, nLen + 1, lpszValue); propType = XTP_SKINPROPERTY_STRING; } void CXTPSkinManagerSchemaProperty::SetPropertyBool(LPCTSTR lpszValue) { ClearProperty(); bVal = _tcsicmp(lpszValue, _T("TRUE")) == 0; } void CXTPSkinManagerSchemaProperty::SetPropertyInt(LPCTSTR lpszValue) { ClearProperty(); iVal = _ttoi(lpszValue); } void CXTPSkinManagerSchemaProperty::SetPropertyEnum(int nEnumValue) { ClearProperty(); iVal = nEnumValue; } void CXTPSkinManagerSchemaProperty::SetPropertySize(LPCTSTR lpszValue) { ClearProperty(); SCANF_S(lpszValue, _T("%i,%i"), &szVal.cx, &szVal.cy); } void CXTPSkinManagerSchemaProperty::SetPropertyRect(LPCTSTR lpszValue) { ClearProperty(); SCANF_S(lpszValue, _T("%ld,%ld,%ld,%ld"), &rcVal.left, &rcVal.right, &rcVal.top, &rcVal.bottom); } void CXTPSkinManagerSchemaProperty::SetPropertyFont(LPCTSTR lpszValue) { ClearProperty(); lfVal = new LOGFONT; ZeroMemory(lfVal, sizeof(LOGFONT)); CWindowDC dc (NULL); lfVal->lfCharSet = (BYTE)::GetTextCharsetInfo (dc, NULL, 0); TCHAR chBold[50]; chBold[0] = 0; SCANF_S(lpszValue, _T("%[^,], %ld, %s"), SCANF_PARAM_S(lfVal->lfFaceName, LF_FACESIZE), &lfVal->lfHeight, SCANF_PARAM_S(chBold, 50)); lfVal->lfWeight = _tcsicmp(chBold, _T("BOLD")) != 0? FW_NORMAL: FW_BOLD; int ppi = dc.GetDeviceCaps(LOGPIXELSY); lfVal->lfHeight = - MulDiv(lfVal->lfHeight, ppi, 72); } BOOL CXTPSkinManagerSchemaProperty::operator==(const CXTPSkinManagerSchemaProperty& prop) const { if (&prop == this) return TRUE; if (prop.propType != propType) return FALSE; switch (propType) { case XTP_SKINPROPERTY_COLOR: return clrVal == prop.clrVal; case XTP_SKINPROPERTY_STRING: return _tcsicmp(lpszVal, prop.lpszVal) == 0; case XTP_SKINPROPERTY_BOOL: return bVal == prop.bVal; case XTP_SKINPROPERTY_RECT: return ::EqualRect(&prop.rcVal, &rcVal); case XTP_SKINPROPERTY_INT: return iVal == prop.iVal; case XTP_SKINPROPERTY_POSITION: return (szVal.cx == prop.szVal.cx) && (szVal.cy == prop.szVal.cy); case XTP_SKINPROPERTY_ENUM: return iVal == prop.iVal; case XTP_SKINPROPERTY_FONT: return memcmp(lfVal, prop.lfVal, sizeof(LOGFONT)) == 0; } return FALSE; } ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CXTPSkinManagerSchema::CXTPSkinManagerSchema(CXTPSkinManagerResourceFile* pResourceFile) { ::InitializeCriticalSection(&m_csDraw); m_pResourceFile = pResourceFile; CMDTARGET_ADDREF(m_pResourceFile); m_pManager = pResourceFile->GetSkinManager(); m_bPreMultiplyImages = TRUE; m_nGlobalClassId = GetClassCode(_T("GLOBALS")); m_nWindowClassId = GetClassCode(_T("WINDOW")); m_mapProperties.InitHashTable(199, FALSE); m_pMetrics = new CXTPSkinManagerMetrics(this); } CXTPSkinManagerSchema::~CXTPSkinManagerSchema() { RemoveAllProperties(); FreeFrameRegions(); POSITION pos = m_mapClasses.GetStartPosition(); CString strClassName; CXTPSkinManagerClass* pClass; while (pos != NULL) { m_mapClasses.GetNextAssoc( pos, strClassName, (void*&)pClass); delete pClass; } m_mapClasses.RemoveAll(); SAFE_DELETE(m_pMetrics); CMDTARGET_RELEASE(m_pResourceFile); ::DeleteCriticalSection(&m_csDraw); } void CXTPSkinManagerSchema::RemoveAllProperties() { POSITION pos = m_mapProperties.GetStartPosition(); UINT nProperty; CXTPSkinManagerSchemaProperty* pProperty; while (pos != NULL) { m_mapProperties.GetNextAssoc( pos, nProperty, pProperty); delete pProperty; } m_mapProperties.RemoveAll(); } UINT CXTPSkinManagerSchema::GetClassCode(LPCTSTR lpszClass) { if (_tcsicmp(_T("Globals"), lpszClass) == 0) return 1; if (_tcsicmp(_T("Documentation"), lpszClass) == 0) return 2; if (_tcsicmp(_T("SysMetrics"), lpszClass) == 0) return 3; if (_tcsicmp(_T("ListBox"), lpszClass) == 0) return 4; if (_tcsicmp(_T("Dialog"), lpszClass) == 0) return 5; UINT nClass = 5; #include "XTPSkinManagerSchema.inc" #undef BEGIN_TM_CLASS_PARTS #define BEGIN_TM_CLASS_PARTS(name) nClass++; if (_tcsicmp(_T(#name), lpszClass) == 0) return nClass; #include "Common/Tmschema.h" TRACE(_T("Warning: %s class not supported"), lpszClass); return 0; // Not supported } int CXTPSkinManagerSchema::GetEnumCode(LPCTSTR lpszProperty, LPCTSTR lpszValue) { #include "XTPSkinManagerSchema.inc" #undef BEGIN_TM_ENUM #undef TM_ENUM #undef END_TM_ENUM #define BEGIN_TM_ENUM(name) if (_tcsicmp(_T(#name), lpszProperty) == 0) { #define TM_ENUM(val, prefix, name) if (_tcsicmp(_T(#name), lpszValue) == 0) return val; #define END_TM_ENUM() } #include "Common/Tmschema.h" return -1; } UINT CXTPSkinManagerSchema::GetClassPartCode(LPCTSTR lpszClass, LPCTSTR lpszClassPart) { #include "XTPSkinManagerSchema.inc" #undef BEGIN_TM_CLASS_PARTS #undef TM_PART #undef END_TM_CLASS_PARTS #define BEGIN_TM_CLASS_PARTS(name) if (_tcsicmp(_T(#name), lpszClass) == 0) { #define TM_PART(val, prefix, name) if (_tcsicmp(_T(#name), lpszClassPart) == 0) return val; #define END_TM_CLASS_PARTS() } #include "Common/Tmschema.h" return 0; } UINT CXTPSkinManagerSchema::GetStateCode(LPCTSTR lpszClassPart, LPCTSTR lpszState) { #include "XTPSkinManagerSchema.inc" #undef BEGIN_TM_PART_STATES #undef TM_STATE #undef END_TM_PART_STATES #define BEGIN_TM_PART_STATES(name) if (_tcsicmp(_T(#name), lpszClassPart) == 0) { #define TM_STATE(val, prefix, name) if (_tcsicmp(_T(#name), lpszState) == 0) return val; #define END_TM_PART_STATES() } #include "Common/Tmschema.h" return 0; } UINT CXTPSkinManagerSchema::GetPropertyCode(LPCTSTR lpszProperty, XTPSkinManagerProperty& nPropertyType) { #include "XTPSkinManagerSchema.inc" #undef TM_PROP #define TM_PROP(val, prefix, name, primval) if (_tcsicmp(_T(#name), lpszProperty) == 0) { nPropertyType = XTP_SKINPROPERTY_##primval; return val; } #include "Common/Tmschema.h" return 0; } UINT CXTPSkinManagerSchema::CalculatePropertyCode(UINT iClassId, int iPartId, int iStateId, int iPropId) { return iPropId + ((iClassId + ((iPartId + (iStateId << 6 )) << 6)) << 14); } UINT CXTPSkinManagerSchema::GetSchemaPartCode(CString strSchemaPart) { if (strSchemaPart.Find(_T(':')) != -1) return 0; // Not Supported; strSchemaPart.Remove(_T(' ')); CString strClass, strClassPart, strState; int nStateIndex = strSchemaPart.Find(_T('(')); if (nStateIndex != -1) { strState = strSchemaPart.Mid(nStateIndex + 1, strSchemaPart.GetLength() - nStateIndex - 2); strSchemaPart = strSchemaPart.Left(nStateIndex); } int nClassPartIndex = strSchemaPart.Find(_T('.')); if (nClassPartIndex != -1) { strClass = strSchemaPart.Left(nClassPartIndex); strClassPart = strSchemaPart.Mid(nClassPartIndex + 1); } else { strClass = strSchemaPart; } int nClassPartCode = 0; if (!strClassPart.IsEmpty()) { nClassPartCode = GetClassPartCode(strClass, strClassPart); if (nClassPartCode == 0) { ASSERT(FALSE); return 0; } } int nStateCode = 0; if (!strState.IsEmpty()) { nStateCode = GetStateCode(strClassPart.IsEmpty()? strClass: strClassPart, strState); if (nStateCode == 0) { ASSERT(FALSE); return 0; } } int nClassCode = GetClassCode(strClass); if (nClassCode == 0) return 0; return CalculatePropertyCode(nClassCode, nClassPartCode, nStateCode, 0); } CXTPSkinManagerSchemaProperty* CXTPSkinManagerSchema::CreateProperty(LPCTSTR lpszProperty, XTPSkinManagerProperty nPropertyType, LPCTSTR lpszValue) { CXTPSkinManagerSchemaProperty* pProperty = new CXTPSkinManagerSchemaProperty(); switch (nPropertyType) { case XTP_SKINPROPERTY_COLOR: pProperty->SetPropertyColor(lpszValue); break; case XTP_SKINPROPERTY_STRING: pProperty->SetPropertyString(lpszValue); break; case XTP_SKINPROPERTY_BOOL: pProperty->SetPropertyBool(lpszValue); break; case XTP_SKINPROPERTY_RECT: pProperty->SetPropertyRect(lpszValue); break; case XTP_SKINPROPERTY_INT: pProperty->SetPropertyInt(lpszValue); break; case XTP_SKINPROPERTY_POSITION: pProperty->SetPropertySize(lpszValue); break; case XTP_SKINPROPERTY_ENUM: pProperty->SetPropertyEnum(GetEnumCode(lpszProperty, lpszValue)); break; case XTP_SKINPROPERTY_FONT: pProperty->SetPropertyFont(lpszValue); break; default: delete pProperty; return NULL; } pProperty->propType = nPropertyType; return pProperty; } HRESULT CXTPSkinManagerSchema::ReadProperties() { CXTPSkinManagerResourceFile* pResourceFile = GetResourceFile(); RemoveAllProperties(); CString str, strSchemaPart; UINT nSchemaPart = 0; while (pResourceFile->ReadString(str)) { str.TrimLeft(); int nCommentIndex = str.Find(_T(';')); if (nCommentIndex == 0) continue; if (nCommentIndex > 0) { str = str.Left(nCommentIndex); } if (str.IsEmpty()) continue; str.MakeUpper(); if (str[0] == _T('[')) { strSchemaPart = str.Mid(1, str.GetLength() - 2); nSchemaPart = GetSchemaPartCode(strSchemaPart); } else if (nSchemaPart) { int nPos = str.Find(_T('=')); if (nPos <= 0) continue; CString strProperty = str.Left(nPos); strProperty.TrimRight(); strProperty.MakeUpper(); XTPSkinManagerProperty nPropertyType = XTP_SKINPROPERTY_UNKNOWN; UINT nPropertyCode = GetPropertyCode(strProperty, nPropertyType); if (nPropertyCode == 0 || nPropertyType == XTP_SKINPROPERTY_UNKNOWN) { continue; } CString strValue = str.Mid(nPos + 1); strValue.TrimLeft(); strValue.TrimRight(); strValue.MakeUpper(); CXTPSkinManagerSchemaProperty* pProperty = 0; if (m_mapProperties.Lookup(nSchemaPart + nPropertyCode, pProperty)) { m_mapProperties.RemoveKey(nSchemaPart + nPropertyCode); delete pProperty; } pProperty = CreateProperty(strProperty, nPropertyType, strValue); if (pProperty == 0) { continue; } pProperty->nPropertyCode = nPropertyCode; m_mapProperties.SetAt(nSchemaPart + nPropertyCode, pProperty); } } int nAlpha = 0; if (SUCCEEDED(GetIntProperty(GetClassCode(_T("DOCUMENTATION")), 0, 0, TMT_ALPHALEVEL, nAlpha)) && nAlpha == 255) { m_bPreMultiplyImages = FALSE; } return S_OK; } CXTPSkinManagerSchemaProperty* CXTPSkinManagerSchema::GetProperty(UINT iClassId, int iPartId, int iStateId, int iPropId) { CXTPSkinManagerSchemaProperty* pProperty; if (iStateId && m_mapProperties.Lookup(CalculatePropertyCode(iClassId, iPartId, iStateId, iPropId), pProperty)) return pProperty; if (m_mapProperties.Lookup(CalculatePropertyCode(iClassId, iPartId, 0, iPropId), pProperty)) return pProperty; if (iPartId && iStateId && m_mapProperties.Lookup(CalculatePropertyCode(iClassId, 0, iStateId, iPropId), pProperty)) return pProperty; if (iPartId && m_mapProperties.Lookup(CalculatePropertyCode(iClassId, 0, 0, iPropId), pProperty)) return pProperty; if (m_mapProperties.Lookup(CalculatePropertyCode(m_nGlobalClassId, 0, 0, iPropId), pProperty)) return pProperty; return NULL; } HRESULT CXTPSkinManagerSchema::GetStringProperty(UINT iClassId, int iPartId, int iStateId, int iPropId, CString& str) { CXTPSkinManagerSchemaProperty* pProperty = GetProperty(iClassId, iPartId, iStateId, iPropId); if (!pProperty) return E_FAIL; if (pProperty->propType != XTP_SKINPROPERTY_STRING) return E_INVALIDARG; str = pProperty->lpszVal; return S_OK; } HRESULT CXTPSkinManagerSchema::GetRectProperty(UINT iClassId, int iPartId, int iStateId, int iPropId, CRect& rc) { CXTPSkinManagerSchemaProperty* pProperty = GetProperty(iClassId, iPartId, iStateId, iPropId); if (!pProperty) return E_FAIL; if (pProperty->propType != XTP_SKINPROPERTY_RECT) return E_INVALIDARG; rc = pProperty->rcVal; return S_OK; } HRESULT CXTPSkinManagerSchema::GetIntProperty(UINT iClassId, int iPartId, int iStateId, int iPropId, int& iVal) { CXTPSkinManagerSchemaProperty* pProperty = GetProperty(iClassId, iPartId, iStateId, iPropId); if (!pProperty) return E_FAIL; if (pProperty->propType != XTP_SKINPROPERTY_INT) return E_INVALIDARG; iVal = pProperty->iVal; return S_OK; } HRESULT CXTPSkinManagerSchema::GetBoolProperty(UINT iClassId, int iPartId, int iStateId, int iPropId, BOOL& bVal) { CXTPSkinManagerSchemaProperty* pProperty = GetProperty(iClassId, iPartId, iStateId, iPropId); if (!pProperty) return E_FAIL; if (pProperty->propType != XTP_SKINPROPERTY_BOOL) return E_INVALIDARG; bVal = pProperty->bVal; return S_OK; } HRESULT CXTPSkinManagerSchema::GetColorProperty(UINT iClassId, int iPartId, int iStateId, int iPropId, COLORREF& clrVal) { CXTPSkinManagerSchemaProperty* pProperty = GetProperty(iClassId, iPartId, iStateId, iPropId); if (!pProperty) return E_FAIL; if (pProperty->propType != XTP_SKINPROPERTY_COLOR) return E_INVALIDARG; clrVal = pProperty->clrVal; GetSkinManager()->ApplyColorFilter(clrVal); return S_OK; } HRESULT CXTPSkinManagerSchema::GetEnumProperty(UINT iClassId, int iPartId, int iStateId, int iPropId, int& nVal) { CXTPSkinManagerSchemaProperty* pProperty = GetProperty(iClassId, iPartId, iStateId, iPropId); if (!pProperty) return E_FAIL; if (pProperty->propType != XTP_SKINPROPERTY_ENUM) return E_INVALIDARG; nVal = pProperty->iVal; return S_OK; } HRESULT CXTPSkinManagerSchema::GetFontProperty(UINT iClassId, int iPartId, int iStateId, int iPropId, LOGFONT& lfVal) { CXTPSkinManagerSchemaProperty* pProperty = GetProperty(iClassId, iPartId, iStateId, iPropId); if (!pProperty) return E_FAIL; if (pProperty->propType != XTP_SKINPROPERTY_FONT) return E_INVALIDARG; lfVal = *pProperty->lfVal; return S_OK; } HRESULT CXTPSkinManagerSchema::GetSizeProperty(UINT iClassId, int iPartId, int iStateId, int iPropId, CSize& szVal) { CXTPSkinManagerSchemaProperty* pProperty = GetProperty(iClassId, iPartId, iStateId, iPropId); if (!pProperty) return E_FAIL; if (pProperty->propType != XTP_SKINPROPERTY_POSITION) return E_INVALIDARG; szVal = pProperty->szVal; return S_OK; } ////////////////////////////////////////////////////////////////////////// // CXTPSkinManagerSchema int CXTPSkinManagerSchema::FindBestImageGlyphSize(CXTPSkinManagerClass* pClass, int iPartId, int iStateId, const CRect& rcDest, int nImageCount, BOOL bHorizontalImageLayout) { int nImageFile = TMT_IMAGEFILE5; CString strImageFile; while (nImageFile >= TMT_IMAGEFILE1) { strImageFile = pClass->GetThemeString(iPartId, iStateId, nImageFile); if (!strImageFile.IsEmpty()) { CSize sz = pClass->GetImages()->GetExtent(GetResourceFile(), strImageFile); if (sz == CSize(0)) return -1; if (bHorizontalImageLayout) sz.cx /= nImageCount; else sz.cy /= nImageCount; if ((nImageFile == TMT_IMAGEFILE1) || (rcDest.Height() >= sz.cy && rcDest.Width() >= sz.cx)) return nImageFile; } nImageFile--; } return nImageFile; } BOOL CXTPSkinManagerSchema::DrawThemeBackgroundGlyph(CDC* pDC, CXTPSkinManagerClass* pClass, int iPartId, int iStateId, const RECT *pRect) { int nImageFile = TMT_GLYPHIMAGEFILE; int nImageCount = pClass->GetThemeInt(iPartId, iStateId, TMT_IMAGECOUNT, 1); if (nImageCount < 1) nImageCount = 1; BOOL bHorizontalImageLayout = pClass->GetThemeEnumValue(iPartId, iStateId, TMT_IMAGELAYOUT, IL_HORIZONTAL) == IL_HORIZONTAL; CRect rcDest(pRect); CRect rcContentMargins = pClass->GetThemeRect(iPartId, iStateId, TMT_CONTENTMARGINS); rcDest.DeflateRect(rcContentMargins); if (pClass->GetThemeEnumValue(iPartId, iStateId, TMT_IMAGESELECTTYPE) == IST_SIZE) { nImageFile = FindBestImageGlyphSize(pClass, iPartId, iStateId, rcDest, nImageCount, bHorizontalImageLayout); if (nImageFile == -1) return FALSE; } CString strImageFile = pClass->GetThemeString(iPartId, iStateId, nImageFile); if (strImageFile.IsEmpty()) return FALSE; CXTPSkinImage* pImage = pClass->GetImages()->LoadFile(GetResourceFile(), strImageFile); if (!pImage) { return FALSE; } CSize sz(pImage->GetWidth(), pImage->GetHeight()); if (bHorizontalImageLayout) sz.cx /= nImageCount; else sz.cy /= nImageCount; BOOL bTransparent = pImage->IsAlphaImage()? FALSE: pClass->GetThemeBool(iPartId, iStateId, TMT_GLYPHTRANSPARENT); CPoint ptTopLeft((rcDest.left + rcDest.right - sz.cx)/2, (rcDest.top + rcDest.bottom - sz.cy)/2); if (ptTopLeft.y < rcDest.top) ptTopLeft.y = rcDest.top; CRect rcGlyph(ptTopLeft, sz); CRect rcSrcImage = bHorizontalImageLayout? CRect((iStateId - 1) * sz.cx, 0, iStateId * sz.cx, sz.cy): CRect(0, (iStateId - 1) * sz.cy, sz.cx, iStateId * sz.cy); if (nImageCount <= iStateId - 1) rcSrcImage = CRect(0, 0, sz.cx, sz.cy); COLORREF clrTransparent = COLORREF_NULL; if (bTransparent) { clrTransparent = pClass->GetThemeColor(iPartId, iStateId, TMT_TRANSPARENTCOLOR, RGB(0xFF, 0, 0xFF)); } pImage->DrawImage(pDC, rcGlyph, rcSrcImage, CRect(0, 0, 0, 0), clrTransparent, ST_TRUESIZE, FALSE); return TRUE; } BOOL CXTPSkinManagerSchema::DrawThemeBackgroundBorder(CDC* pDC, CXTPSkinManagerClass* pClass, int iPartId, int iStateId, const RECT *pRect) { int nBorderSize = pClass->GetThemeInt(iPartId, iStateId, TMT_BORDERSIZE, 1); COLORREF clrBorderColor = pClass->GetThemeColor(iPartId, iStateId, TMT_BORDERCOLOR); COLORREF clrFillColor = pClass->GetThemeColor(iPartId, iStateId, TMT_FILLCOLOR); BOOL bBorderOnly = pClass->GetThemeBool(iPartId, iStateId, TMT_BORDERONLY, FALSE); CRect rc(pRect); if ((nBorderSize > 0) && (clrBorderColor != COLORREF_NULL)) { pDC->FillSolidRect(rc.left, rc.top, rc.Width(), nBorderSize, clrBorderColor); pDC->FillSolidRect(rc.left, rc.bottom - nBorderSize, rc.Width(), nBorderSize, clrBorderColor); pDC->FillSolidRect(rc.left, rc.top + nBorderSize, nBorderSize, rc.Height() - nBorderSize * 2, clrBorderColor); pDC->FillSolidRect(rc.right - nBorderSize, rc.top + nBorderSize, nBorderSize, rc.Height() - nBorderSize * 2, clrBorderColor); rc.DeflateRect(nBorderSize, nBorderSize); } if ((clrFillColor != COLORREF_NULL) && (!bBorderOnly)) { pDC->FillSolidRect(rc, clrFillColor); } return TRUE; } BOOL CXTPSkinManagerSchema::DrawThemeBackground(CDC* pDC, CXTPSkinManagerClass* pClass, int iPartId, int iStateId, const RECT *pRect) { int nBackgroundType = pClass->GetThemeEnumValue(iPartId, iStateId, TMT_BGTYPE, BT_IMAGEFILE); if (nBackgroundType == BT_BORDERFILL) { return DrawThemeBackgroundBorder(pDC, pClass, iPartId, iStateId, pRect); } if (nBackgroundType != BT_IMAGEFILE) return TRUE; int nImageFile = (pClass->GetThemeEnumValue(iPartId, iStateId, TMT_IMAGESELECTTYPE) != IST_NONE) && (pClass->GetThemeEnumValue(iPartId, iStateId, TMT_GLYPHTYPE, GT_NONE) == GT_NONE) ? TMT_IMAGEFILE1: TMT_IMAGEFILE; CString strImageFile = pClass->GetThemeString(iPartId, iStateId, nImageFile); if (strImageFile.IsEmpty()) { if (nImageFile != TMT_IMAGEFILE1) return FALSE; strImageFile = pClass->GetThemeString(iPartId, iStateId, TMT_IMAGEFILE); if (strImageFile.IsEmpty()) return FALSE; } CRect rcSizingMargins = pClass->GetThemeRect(iPartId, iStateId, TMT_SIZINGMARGINS); CXTPSkinImage* pImage = pClass->GetImages()->LoadFile(GetResourceFile(), strImageFile); if (!pImage) { return FALSE; } int nImageCount = pClass->GetThemeInt(iPartId, iStateId, TMT_IMAGECOUNT, 1); if (nImageCount < 1) nImageCount = 1; BOOL bHorizontalImageLayout = pClass->GetThemeEnumValue(iPartId, iStateId, TMT_IMAGELAYOUT, IL_HORIZONTAL) == IL_HORIZONTAL; CSize sz(pImage->GetWidth(), pImage->GetHeight()); if (bHorizontalImageLayout) sz.cx /= nImageCount; else sz.cy /= nImageCount; BOOL bTransparent = pImage->IsAlphaImage()? FALSE: pClass->GetThemeBool(iPartId, iStateId, TMT_TRANSPARENT); CRect rcImage(*pRect); int nSizingType = pClass->GetThemeEnumValue(iPartId, iStateId, TMT_SIZINGTYPE, ST_STRETCH); if (nSizingType == ST_TRUESIZE) { CSize szDest(sz); if (pClass->GetThemeInt(iPartId, iStateId, TMT_TRUESIZESTRETCHMARK) > 0) { if (szDest.cx > rcImage.Width()) { szDest.cx = rcImage.Width(); } if (szDest.cy > rcImage.Height()) { szDest.cy = rcImage.Height(); } } CPoint ptTopLeft((rcImage.left + rcImage.right - szDest.cx)/2, (rcImage.top + rcImage.bottom - szDest.cy)/2); if (ptTopLeft.y < rcImage.top) ptTopLeft.y = rcImage.top; if (ptTopLeft.x < rcImage.left) ptTopLeft.x = rcImage.left; if (pClass->GetThemeEnumValue(iPartId, iStateId, TMT_VALIGN) == VA_BOTTOM) rcImage = CRect(CPoint(ptTopLeft.x, rcImage.bottom - szDest.cy), szDest); else rcImage = CRect(ptTopLeft, szDest); rcSizingMargins = CRect(0, 0, 0, 0); } CRect rcSrcImage = bHorizontalImageLayout? CRect((iStateId - 1) * sz.cx, 0, iStateId * sz.cx, sz.cy): CRect(0, (iStateId - 1) * sz.cy, sz.cx, iStateId * sz.cy); if ((nImageCount <= iStateId - 1) || (iStateId == 0)) rcSrcImage = CRect(0, 0, sz.cx, sz.cy); COLORREF clrTransparent = COLORREF_NULL; if (bTransparent) { clrTransparent = pClass->GetThemeColor(iPartId, iStateId, TMT_TRANSPARENTCOLOR, RGB(0xFF, 0, 0xFF)); } BOOL bBorderOnly = pClass->GetThemeBool(iPartId, iStateId, TMT_BORDERONLY); if (pClass->GetClassCode() == m_nWindowClassId && (iPartId >= WP_FRAMELEFT && iPartId <= WP_SMALLFRAMEBOTTOM)) bBorderOnly = FALSE; pImage->m_bMirrorImage = pClass->GetThemeBool(iPartId, iStateId, TMT_MIRRORIMAGE, TRUE); pImage->CreateSolidRectArray(nImageCount, bHorizontalImageLayout, rcSizingMargins); pImage->DrawImage(pDC, rcImage, rcSrcImage, rcSizingMargins, clrTransparent, nSizingType, bBorderOnly); if (pClass->GetThemeEnumValue(iPartId, iStateId, TMT_GLYPHTYPE) == GT_IMAGEGLYPH) { DrawThemeBackgroundGlyph(pDC, pClass, iPartId, iStateId, pRect); } return TRUE; } CSize CXTPSkinManagerSchema::GetCaptionButtonSize(CXTPSkinManagerClass* pClass, int yButton) { int iPartId = WP_CLOSEBUTTON, iStateId = 1; if (pClass->GetThemeEnumValue(iPartId, iStateId, TMT_BGTYPE) != BT_IMAGEFILE) return CSize(yButton, yButton); int nImageFile = (pClass->GetThemeEnumValue(iPartId, iStateId, TMT_IMAGESELECTTYPE) != IST_NONE) && (pClass->GetThemeEnumValue(iPartId, iStateId, TMT_GLYPHTYPE, GT_NONE) == GT_NONE) ? TMT_IMAGEFILE1: TMT_IMAGEFILE; CString strImageFile = pClass->GetThemeString(iPartId, iStateId, nImageFile); if (strImageFile.IsEmpty()) { if (nImageFile != TMT_IMAGEFILE1) return CSize(yButton, yButton); strImageFile = pClass->GetThemeString(iPartId, iStateId, TMT_IMAGEFILE); if (strImageFile.IsEmpty()) return CSize(yButton, yButton); } CXTPSkinImage* pImage = pClass->GetImages()->LoadFile(GetResourceFile(), strImageFile); if (!pImage) { return CSize(yButton, yButton); } int nImageCount = pClass->GetThemeInt(iPartId, iStateId, TMT_IMAGECOUNT, 1); if (nImageCount < 1) nImageCount = 1; BOOL bHorizontalImageLayout = pClass->GetThemeEnumValue(iPartId, iStateId, TMT_IMAGELAYOUT, IL_HORIZONTAL) == IL_HORIZONTAL; CSize sz(pImage->GetWidth(), pImage->GetHeight()); if (bHorizontalImageLayout) sz.cx /= nImageCount; else sz.cy /= nImageCount; int xButton = MulDiv(sz.cx, yButton, sz.cy) + MulDiv(sz.cx - sz.cy, 4, sz.cy); return CSize(xButton, yButton); } int CXTPSkinManagerSchema::DrawThemeFrameButtons(CDC* pDC, CXTPSkinObjectFrame* pFrame) { CXTPWindowRect rc(pFrame); rc.OffsetRect(-rc.TopLeft()); CRect rcBorders = pFrame->GetBorders(); LONG lStyle = pFrame->GetStyle(); DWORD dwExStyle = pFrame->GetExStyle(); int cBorders = GetWindowBorders(lStyle, dwExStyle, TRUE, FALSE); int cxFrame = cBorders * GetMetrics()->m_cxBorder; if ((lStyle & WS_MAXIMIZE) && rcBorders.left > 6) // Special fix for Windows Windows 7/Vista large borders { int nOffset = rcBorders.left - (cxFrame + (dwExStyle & WS_EX_CLIENTEDGE ? GetMetrics()->m_cxEdge : 0)); rc.DeflateRect(nOffset, nOffset); } int nCaptionHeight = rcBorders.top - rc.top; int nTop = 0; if (dwExStyle & WS_EX_WINDOWEDGE) nTop++; else if (dwExStyle & WS_EX_STATICEDGE) nTop++; if (lStyle & WS_SIZEBOX) nTop += (1 + GetMetrics()->m_nBorderSize) / 2; int yButton = nCaptionHeight - 5 - cxFrame; if (dwExStyle & WS_EX_CLIENTEDGE) { yButton -= 2; nTop -= 1; } CXTPSkinManagerClass* pClass = m_pManager->GetSkinClass(pFrame, _T("WINDOW")); CSize szButton = dwExStyle & WS_EX_TOOLWINDOW ? CSize(yButton, yButton) : GetCaptionButtonSize(pClass, yButton); CRect rcButton = CRect(CPoint(rc.right - szButton.cx - cBorders - 2, rc.top + nTop + (nCaptionHeight - szButton.cy)/2), szButton); CXTPSkinObjectFrame::CCaptionButtons* pButtons = pFrame->GetCaptionButtons(); for (int i = 0; i < (int)pButtons->GetSize(); i++) { CXTPSkinObjectFrame::CCaptionButton* pButton = pButtons->GetAt(i); pButton->m_rcButton = rcButton; pButton->Draw(pDC, pFrame->IsActive()); rcButton.OffsetRect(-rcButton.Width() - 2, 0); } return rcButton.right + 2; } void CXTPSkinManagerSchema::DrawNonClientRect(CDC* pDC, CRect rcFrame, CXTPSkinObjectFrame* pFrame) { DWORD dwExStyle = pFrame->GetExStyle(); DWORD dwStyle = pFrame->GetStyle(); if (dwExStyle & WS_EX_WINDOWEDGE) { DrawEdge(pDC->GetSafeHdc(), &rcFrame, EDGE_RAISED, BF_RECT | BF_ADJUST); } else if (dwExStyle & WS_EX_STATICEDGE) { DrawEdge(pDC->GetSafeHdc(), &rcFrame, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST); } if ((dwStyle & WS_CAPTION) || (dwExStyle & WS_EX_DLGMODALFRAME)) { COLORREF clr = GetColor((dwExStyle & (WS_EX_CLIENTEDGE | WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_STATICEDGE)) || (dwStyle & WS_DLGFRAME) ? COLOR_3DFACE : COLOR_WINDOWFRAME); pDC->Draw3dRect(rcFrame, clr, clr); rcFrame.DeflateRect(1, 1); } if (dwStyle & WS_SIZEBOX) { int nSize = GetMetrics()->m_nBorderSize; XTPSkinFrameworkDrawFrame(pDC->GetSafeHdc(), rcFrame, nSize, GetColor(COLOR_3DFACE)); rcFrame.DeflateRect(nSize, nSize); } if (dwExStyle & WS_EX_CLIENTEDGE) { DrawClientEdge(pDC, rcFrame, pFrame); } } void CXTPSkinManagerSchema::DrawClientEdge(CDC* pDC, const CRect& rcFrame, CXTPSkinObjectFrame* pFrame) { CRect rc = rcFrame; CXTPSkinManagerClass* pClass = m_pManager->GetSkinClass(pFrame, pFrame->GetClassName()); if (pClass->GetThemeEnumValue(0, 0, TMT_BGTYPE) == BT_BORDERFILL) { COLORREF clrBorderColor = pClass->GetThemeColor(0, 0, TMT_BORDERCOLOR); pDC->Draw3dRect(rc, clrBorderColor, clrBorderColor); rc.DeflateRect(1, 1); HBRUSH hBrush = pFrame->GetClientBrush(pDC); XTPSkinFrameworkDrawFrame(pDC->GetSafeHdc(), &rc, 1, hBrush); } else { pDC->Draw3dRect(rc, GetMetrics()->m_clrEdgeShadow, GetMetrics()->m_clrEdgeHighLight); rc.DeflateRect(1, 1); pDC->Draw3dRect(rc, GetMetrics()->m_clrEdgeDkShadow, GetMetrics()->m_clrEdgeLight); rc.DeflateRect(1, 1); } } HICON CXTPSkinManagerSchema::GetFrameSmIcon(HWND hWnd, BOOL bCheckStyle) const { DWORD dwStyle = GetWindowLong(hWnd, GWL_STYLE); DWORD dwExStyle = GetWindowLong(hWnd, GWL_EXSTYLE); if (bCheckStyle) { if (dwExStyle & WS_EX_TOOLWINDOW) return NULL; if ((dwStyle & WS_SYSMENU) == 0) return NULL; } HICON hIcon = (HICON)(DWORD_PTR)::SendMessage(hWnd, WM_GETICON, ICON_SMALL, 0); if (hIcon) return hIcon; hIcon = (HICON)(DWORD_PTR)::SendMessage(hWnd, WM_GETICON, ICON_BIG, 0); if (hIcon) return hIcon; hIcon = (HICON)(DWORD_PTR)::GetClassLongPtr(hWnd, GCLP_HICONSM); if (hIcon) return hIcon; if (((dwStyle & (WS_BORDER | WS_DLGFRAME)) != WS_DLGFRAME) && ((dwExStyle & WS_EX_DLGMODALFRAME) == 0)) { ULONG_PTR dwResult; if (SendMessageTimeout(hWnd, WM_QUERYDRAGICON, 0, 0, SMTO_NORMAL, 100, &dwResult)) { hIcon = (HICON)dwResult; } if (hIcon == NULL) { hIcon = AfxGetApp()->LoadOEMIcon(OIC_WINLOGO); } } return hIcon; } void CXTPSkinManagerSchema::DrawThemeFrame(CDC* pDC, CXTPSkinObjectFrame* pFrame) { CXTPWindowRect rc(pFrame); rc.OffsetRect(-rc.TopLeft()); const DWORD dwStyle = pFrame->GetStyle(); const DWORD dwExStyle = pFrame->GetExStyle(); const BOOL bToolWindow = (WS_EX_TOOLWINDOW == (WS_EX_TOOLWINDOW & dwExStyle)); const BOOL bMaximize = (WS_MAXIMIZE == (WS_MAXIMIZE & dwStyle)); const BOOL bMinimize = (WS_MINIMIZE == (WS_MINIMIZE & dwStyle)); if ((dwStyle & WS_CAPTION) != WS_CAPTION) { DrawNonClientRect(pDC, rc, pFrame); return; } CRect rcBorders = pFrame->GetBorders(); if (dwExStyle & WS_EX_CLIENTEDGE) { DrawClientEdge(pDC, CRect(rcBorders.left - 2, rcBorders.top - 2, rc.Width() - rcBorders.right + 2, rc.Height() - rcBorders.bottom + 2), pFrame); InflateBorders(rcBorders, -2, -2); } CRect rcCaption(0, 0, rc.right, rcBorders.top); CRect rcFrame(0, rcBorders.top, rc.Width(), rc.Height()); CXTPSkinManagerClass* pClassWindow = m_pManager->GetSkinClass(pFrame, _T("WINDOW")); int nFrameState = pFrame->IsActive()? FS_ACTIVE: FS_INACTIVE; pClassWindow->DrawThemeBackground(pDC, bToolWindow? WP_SMALLFRAMELEFT: WP_FRAMELEFT, nFrameState, CRect(rcFrame.left, rcFrame.top, rcFrame.left + rcBorders.left, rcFrame.bottom - rcBorders.bottom)); pClassWindow->DrawThemeBackground(pDC, bToolWindow? WP_SMALLFRAMERIGHT: WP_FRAMERIGHT, nFrameState, CRect(rcFrame.right - rcBorders.right, rcFrame.top, rcFrame.right , rcFrame.bottom - rcBorders.bottom)); pClassWindow->DrawThemeBackground(pDC, bToolWindow? WP_SMALLFRAMEBOTTOM: WP_FRAMEBOTTOM, nFrameState, CRect(rcFrame.left, rcFrame.bottom - rcBorders.bottom, rcFrame.right , rcFrame.bottom)); { CXTPLockGuard lock(m_csDraw); CXTPBufferDC dc(*pDC, rcCaption); int nStateId = WP_CAPTION; if (bToolWindow) nStateId = WP_SMALLCAPTION; if (bMaximize) nStateId = WP_MAXCAPTION; if (bMinimize) nStateId = WP_MINCAPTION; pClassWindow->DrawThemeBackground(&dc, nStateId, nFrameState, rcCaption); CSize szIcon(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)); int nTextLeft = rcBorders.left; HICON hIcon = GetFrameSmIcon(pFrame->GetSafeHwnd()); int cBorders = GetWindowBorders(dwStyle, dwExStyle, TRUE, FALSE) - GetMetrics()->m_cyBorder; if (hIcon) { int cxySlot = rcBorders.top - cBorders; int nTop = cBorders + (cxySlot - szIcon.cy)/2; CRect rcButn(rcBorders.left + 2, nTop, rcBorders.left + 2 + szIcon.cx, nTop + szIcon.cy); DWORD dwLayout = XTPDrawHelpers()->IsContextRTL(&dc); if (dwLayout & LAYOUT_RTL) XTPDrawHelpers()->SetContextRTL(&dc, dwLayout | LAYOUT_BITMAPORIENTATIONPRESERVED); DrawIconEx(dc.m_hDC, rcButn.left, rcButn.top,hIcon, rcButn.Width(), rcButn.Height(), 0, NULL, DI_NORMAL); if (dwLayout & LAYOUT_RTL) XTPDrawHelpers()->SetContextRTL(&dc, dwLayout); nTextLeft = 2 + szIcon.cx + rcBorders.left; } int nTextRight = DrawThemeFrameButtons(&dc, pFrame); dc.SetTextColor(GetColor(pFrame->IsActive() ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT)); CFont* pOldFont = dc.SelectObject(bToolWindow ? &GetMetrics()->m_fntSmCaption : &GetMetrics()->m_fntCaption); CString strCaption; CXTPDrawHelpers::GetWindowCaption(pFrame->GetSafeHwnd(), strCaption); CRect rcText(nTextLeft, 1 + cBorders, nTextRight, rcBorders.top); pClassWindow->DrawThemeText(&dc, bToolWindow ? WP_SMALLCAPTION : WP_CAPTION, pFrame->IsActive() ? CS_ACTIVE : CS_INACTIVE, strCaption, DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS | DT_NOPREFIX | (dwExStyle & WS_EX_RTLREADING ? DT_RTLREADING : 0) | (dwExStyle & WS_EX_RIGHT ? DT_RIGHT : 0), rcText); dc.SelectObject(pOldFont); } } int CXTPSkinManagerSchema::GetWindowBorders(LONG lStyle, DWORD dwExStyle, BOOL fWindow, BOOL fClient) { int cBorders = 0; if (fWindow) { if (dwExStyle & WS_EX_WINDOWEDGE) cBorders += 2; else if (dwExStyle & WS_EX_STATICEDGE) cBorders++; if ((lStyle & WS_CAPTION) || (dwExStyle & WS_EX_DLGMODALFRAME)) cBorders++; if (lStyle & WS_SIZEBOX) cBorders += GetMetrics()->m_nBorderSize; } if (fClient) { if (dwExStyle & WS_EX_CLIENTEDGE) cBorders += 2; } return(cBorders); } CRect CXTPSkinManagerSchema::CalcFrameBorders(CXTPSkinObjectFrame* pFrame) { DWORD dwExStyle = pFrame->GetExStyle(); DWORD dwStyle = pFrame->GetStyle(); return CalcFrameBorders(dwStyle, dwExStyle); } CRect CXTPSkinManagerSchema::CalcFrameBorders(DWORD dwStyle, DWORD dwExStyle) { BOOL bToolWindow = (dwExStyle & WS_EX_TOOLWINDOW) == WS_EX_TOOLWINDOW; CXTPSkinManagerMetrics* pMetrics = GetMetrics(); if (((dwStyle & (WS_CAPTION | WS_MAXIMIZE)) == (WS_CAPTION | WS_MAXIMIZE) && ((dwStyle & WS_CHILD) == 0))) { int nCaptionHeight = bToolWindow ? pMetrics->m_cySmallCaption: pMetrics->m_cyCaption; CRect rc(0, 0, 100, 100); AdjustWindowRectEx(rc, dwStyle, FALSE, dwExStyle); int nBorder = -rc.left; return CRect(nBorder, nBorder + nCaptionHeight, nBorder, nBorder); } CRect rcBorders(0, 0, 0, 0); if ((dwStyle & WS_CAPTION) == WS_CAPTION) { int nCaptionHeight = bToolWindow ? pMetrics->m_cySmallCaption: pMetrics->m_cyCaption; rcBorders.top += nCaptionHeight; } int cBorders = GetWindowBorders(dwStyle, dwExStyle, TRUE, FALSE); InflateBorders(rcBorders, cBorders * pMetrics->m_cxBorder, cBorders * pMetrics->m_cyBorder); if ((dwExStyle & WS_EX_CLIENTEDGE) == WS_EX_CLIENTEDGE) { InflateBorders(rcBorders, pMetrics->m_cxEdge, pMetrics->m_cyEdge); } return rcBorders; } AFX_INLINE void IncludeRgnPart(CRgn* pRgn, int x1, int y1, int x2, int y2) { if (x1 < x2 && y1 < y2) { if (pRgn->GetSafeHandle() == NULL) { pRgn->CreateRectRgn(0, 0, 0, 0); } CRgn rgnExclude; rgnExclude.CreateRectRgn(x1, y1, x2, y2); pRgn->CombineRgn(pRgn, &rgnExclude, RGN_OR); } } void CXTPSkinManagerSchema::RegionFromBitmap(CBitmap* pBitmap, FRAMEPART nAlign, FRAMEREGIONPART* pPart, const CRect& rc, COLORREF clrTransparent) { CXTPCompatibleDC dc(NULL, pBitmap); CSize sz = rc.Size(); pPart->nCenter = 0; BOOL bCheckCenter = TRUE; if (nAlign == frameTop || nAlign == frameBottom) { for (int y = 0; y < sz.cy; y++) { int x = 0; while ( x < pPart->rcSizingMargins.left && dc.GetPixel(x, y) == clrTransparent) { x++; } if (x > 0) { IncludeRgnPart(&pPart->rgnLeft, 0, y, x, y + 1); } x = sz.cx - 1; int nOffset = sz.cx - pPart->rcSizingMargins.right; while (x >= nOffset) { int x0 = x; while (x >= nOffset && dc.GetPixel(x, y) == clrTransparent) { x--; } if (x != x0) { IncludeRgnPart(&pPart->rgnRight, x - nOffset + 1, y, x0 - nOffset + 1, y + 1); } while (x >= nOffset && dc.GetPixel(x, y) != clrTransparent) { x--; } if (x == x0) break; } if (bCheckCenter) { x = pPart->rcSizingMargins.left; int y0 = nAlign == frameTop ? y : sz.cy - 1 - y; while (x < sz.cx - pPart->rcSizingMargins.right && dc.GetPixel(x, y0) == clrTransparent) { x++; } if (x == sz.cx - pPart->rcSizingMargins.right) { pPart->nCenter++; } else { bCheckCenter = FALSE; } } } } else { for (int x = 0; x < sz.cx; x++) { int y = 0; while (y < pPart->rcSizingMargins.top && dc.GetPixel(x, y) == clrTransparent) { y++; } if (y > 0) { IncludeRgnPart(&pPart->rgnLeft, x, 0, x + 1, y); } y = sz.cy - 1; int nOffset = sz.cy - pPart->rcSizingMargins.bottom; while (y >= nOffset) { int y0 = y; while (y >= nOffset && dc.GetPixel(x, y) == clrTransparent) { y--; } if (y != y0) { IncludeRgnPart(&pPart->rgnRight, x, y - nOffset + 1, x + 1, y0 - nOffset + 1); } while (y >= nOffset && dc.GetPixel(x, y) != clrTransparent) { y--; } if (y == y0) break; } if (bCheckCenter) { y = pPart->rcSizingMargins.top; int x0 = nAlign == frameLeft ? x : sz.cx - 1 - x; while (y < sz.cy - pPart->rcSizingMargins.bottom && dc.GetPixel(x0, y) == clrTransparent) { y++; } if (y == sz.cy - pPart->rcSizingMargins.bottom) { pPart->nCenter++; } else { bCheckCenter = FALSE; } } } } } BOOL CXTPSkinManagerSchema::DrawWindowPart(CXTPSkinObjectFrame* pFrame, CBitmap& bmp, int iPartId, BOOL bVertical, int nBorderHeight, CRect& rcDest, CRect& rcSizingMargins, COLORREF& clrTransparent) { bmp.DeleteObject(); CXTPSkinManagerClass* pClass = m_pManager->GetSkinClass(pFrame, _T("WINDOW")); CString strImageFile = pClass->GetThemeString(iPartId, FS_ACTIVE, TMT_IMAGEFILE); if (strImageFile.IsEmpty()) return FALSE; CSize sz = pClass->GetImages()->GetExtent(GetResourceFile(), strImageFile); if (sz == CSize(0)) return FALSE; CXTPSkinImage* pImage = pClass->GetImages()->LoadFile(GetResourceFile(), strImageFile); if (!pImage) return FALSE; int nImageCount = pClass->GetThemeInt(iPartId, FS_ACTIVE, TMT_IMAGECOUNT, 1); ASSERT(nImageCount >= 1); if (nImageCount < 1) return FALSE; CWindowDC dcWindow(pFrame); CDC dc; dc.CreateCompatibleDC(&dcWindow); CRect rcSrc(0, 0, sz.cx, sz.cy / nImageCount); rcDest = bVertical ? CRect(0, 0, nBorderHeight, rcSrc.Height()) : CRect(0, 0, sz.cx, nBorderHeight); bmp.CreateCompatibleBitmap(&dcWindow, rcDest.Width(), rcDest.Height()); CBitmap* pOldBitmap = dc.SelectObject(&bmp); BOOL bTransparent = pImage->IsAlphaImage()? FALSE : pClass->GetThemeBool(iPartId, FS_ACTIVE, TMT_TRANSPARENT); clrTransparent = COLORREF_NULL; if (bTransparent) { clrTransparent = pClass->GetThemeColor(iPartId, FS_ACTIVE, TMT_TRANSPARENTCOLOR, RGB(0xFF, 0, 0xFF)); } dc.FillSolidRect(rcDest, clrTransparent != COLORREF_NULL ? clrTransparent : RGB(0xFF, 0, 0xFF)); rcSizingMargins = pClass->GetThemeRect(iPartId, FS_ACTIVE, TMT_SIZINGMARGINS); if (rcSizingMargins.top + rcSizingMargins.bottom > rcDest.Height()) { rcSizingMargins.bottom = max(0, rcDest.Height() - rcSizingMargins.top); } pImage->DrawImage(&dc, rcDest, rcSrc, rcSizingMargins, clrTransparent, ST_STRETCH, FALSE); dc.SelectObject(pOldBitmap); clrTransparent = clrTransparent != COLORREF_NULL ? clrTransparent : RGB(0xFF, 0, 0xFF); return TRUE; }; CXTPSkinManagerSchema::FRAMEREGION* CXTPSkinManagerSchema::CreateFrameRegion(CXTPSkinObjectFrame* pFrame, CSize szDest) { int nCaptionHeight = pFrame->GetBorders().top; int nBorderHeight = pFrame->GetBorders().left; BOOL bToolWindow = pFrame->GetExStyle() & WS_EX_TOOLWINDOW; for (int i = 0; i < m_arrFrameRegions.GetSize(); i++) { FRAMEREGION* pRegion = m_arrFrameRegions[i]; if (nCaptionHeight == pRegion->nCaptionHeight && bToolWindow == pRegion->bToolWindow && nBorderHeight == pRegion->nBorderHeight) { if (szDest.cx < pRegion->Part[frameTop].rcSizingMargins.left + pRegion->Part[frameTop].rcSizingMargins.right) break; return pRegion; } } CBitmap bmp; CRect rcDest, rcSizingMargins; COLORREF clrTransparent; if (!DrawWindowPart(pFrame, bmp, bToolWindow ? WP_SMALLCAPTION : WP_CAPTION, FALSE, nCaptionHeight, rcDest, rcSizingMargins, clrTransparent)) return NULL; FRAMEREGION* pRegion = new FRAMEREGION(); pRegion->bAutoDelete = FALSE; pRegion->bToolWindow = bToolWindow; pRegion->nCaptionHeight = nCaptionHeight; pRegion->nBorderHeight = nBorderHeight; if (szDest.cx < rcSizingMargins.left + rcSizingMargins.right) { CRect rcDestSizingMargins = rcSizingMargins; rcDest.right = szDest.cx; pRegion->bAutoDelete = TRUE; rcSizingMargins.left = MulDiv(rcDest.Width(), rcDestSizingMargins.left, (rcDestSizingMargins.left + rcDestSizingMargins.right)); rcSizingMargins.right = rcDest.Width() - rcDestSizingMargins.left; } pRegion->Part[frameTop].rcSizingMargins = rcSizingMargins; RegionFromBitmap(&bmp, frameTop, &pRegion->Part[frameTop], rcDest, clrTransparent); if (DrawWindowPart(pFrame, bmp, bToolWindow ? WP_SMALLFRAMELEFT : WP_FRAMELEFT, TRUE, nBorderHeight, rcDest, rcSizingMargins, clrTransparent)) { pRegion->Part[frameLeft].rcSizingMargins = rcSizingMargins; RegionFromBitmap(&bmp, frameLeft, &pRegion->Part[frameLeft], rcDest, clrTransparent); } if (DrawWindowPart(pFrame, bmp, bToolWindow ? WP_SMALLFRAMERIGHT : WP_FRAMERIGHT, TRUE, nBorderHeight, rcDest, rcSizingMargins, clrTransparent)) { pRegion->Part[frameRight].rcSizingMargins = rcSizingMargins; RegionFromBitmap(&bmp, frameRight, &pRegion->Part[frameRight], rcDest, clrTransparent); } if (DrawWindowPart(pFrame, bmp, bToolWindow ? WP_SMALLFRAMEBOTTOM : WP_FRAMEBOTTOM, FALSE, nBorderHeight, rcDest, rcSizingMargins, clrTransparent)) { pRegion->Part[frameBottom].rcSizingMargins = rcSizingMargins; RegionFromBitmap(&bmp, frameBottom, &pRegion->Part[frameBottom], rcDest, clrTransparent); } if (!pRegion->bAutoDelete) m_arrFrameRegions.Add(pRegion); return pRegion; } void CXTPSkinManagerSchema::FreeFrameRegions() { for (int i = 0; i < m_arrFrameRegions.GetSize(); i++) { delete m_arrFrameRegions[i]; } m_arrFrameRegions.RemoveAll(); } void CXTPSkinManagerSchema::RefreshMetrcis() { FreeFrameRegions(); m_pMetrics->RefreshMetrics(); } HRGN CXTPSkinManagerSchema::CalcFrameRegion(CXTPSkinObjectFrame* pFrame, CSize sz) { CRgn rgnResult; if ((pFrame->GetStyle() & WS_MAXIMIZE) && ((pFrame->GetStyle() & WS_CHILD) == 0)) { int nBorder = pFrame->GetBorders().left; if (pFrame->GetExStyle() & WS_EX_CLIENTEDGE) nBorder -= 2; CRect rc = XTPMultiMonitor()->GetWorkArea(pFrame); if (rc.Width() == sz.cx) rgnResult.CreateRectRgn(nBorder, nBorder, sz.cx + 2 * nBorder, sz.cy + 2 * nBorder); else rgnResult.CreateRectRgn(nBorder, nBorder, sz.cx - nBorder, sz.cy - nBorder); return (HRGN)rgnResult.Detach(); } rgnResult.CreateRectRgn(0, 0, sz.cx, sz.cy); FRAMEREGION* pRegion = CreateFrameRegion(pFrame, sz); if (!pRegion) { return (HRGN)rgnResult.Detach(); } FRAMEREGIONPART* pPart = &pRegion->Part[frameTop]; if (pPart->rgnLeft.GetSafeHandle()) { rgnResult.CombineRgn(&rgnResult, &pPart->rgnLeft, RGN_DIFF); } if (pPart->rgnRight.GetSafeHandle()) { CRgn rgnRight; rgnRight.CreateRectRgn(0, 0, 0, 0); rgnRight.CopyRgn(&pPart->rgnRight); rgnRight.OffsetRgn(sz.cx - pPart->rcSizingMargins.right, 0); rgnResult.CombineRgn(&rgnResult, &rgnRight, RGN_DIFF); } if (pPart->nCenter > 0) { CRgn rgnCenter; rgnCenter.CreateRectRgn(pPart->rcSizingMargins.left, 0, sz.cx - pPart->rcSizingMargins.right, pPart->nCenter); rgnResult.CombineRgn(&rgnResult, &rgnCenter, RGN_DIFF); } pPart = &pRegion->Part[frameBottom]; if (pPart->rgnLeft.GetSafeHandle()) { CRgn rgnLeft; rgnLeft.CreateRectRgn(0, 0, 0, 0); rgnLeft.CopyRgn(&pPart->rgnLeft); rgnLeft.OffsetRgn(0, sz.cy - pRegion->nBorderHeight); rgnResult.CombineRgn(&rgnResult, &rgnLeft, RGN_DIFF); } if (pPart->rgnRight.GetSafeHandle()) { CRgn rgnRight; rgnRight.CreateRectRgn(0, 0, 0, 0); rgnRight.CopyRgn(&pPart->rgnRight); rgnRight.OffsetRgn(sz.cx - pPart->rcSizingMargins.right, sz.cy - pRegion->nBorderHeight); rgnResult.CombineRgn(&rgnResult, &rgnRight, RGN_DIFF); } if (pPart->nCenter > 0) { CRgn rgnCenter; rgnCenter.CreateRectRgn(pPart->rcSizingMargins.left, sz.cy - pPart->nCenter, sz.cx - pPart->rcSizingMargins.right, sz.cy); rgnResult.CombineRgn(&rgnResult, &rgnCenter, RGN_DIFF); } pPart = &pRegion->Part[frameLeft]; if (pPart->rgnLeft.GetSafeHandle()) { CRgn rgnLeft; rgnLeft.CreateRectRgn(0, 0, 0, 0); rgnLeft.CopyRgn(&pPart->rgnLeft); rgnLeft.OffsetRgn(0, pRegion->nCaptionHeight); rgnResult.CombineRgn(&rgnResult, &rgnLeft, RGN_DIFF); } if (pPart->rgnRight.GetSafeHandle()) { CRgn rgnRight; rgnRight.CreateRectRgn(0, 0, 0, 0); rgnRight.CopyRgn(&pPart->rgnRight); rgnRight.OffsetRgn(0, sz.cy - pRegion->nBorderHeight - pPart->rcSizingMargins.bottom); rgnResult.CombineRgn(&rgnResult, &rgnRight, RGN_DIFF); } if (pPart->nCenter > 0) { CRgn rgnCenter; rgnCenter.CreateRectRgn(0, pRegion->nCaptionHeight + pPart->rcSizingMargins.top, pPart->nCenter, sz.cy - pRegion->nBorderHeight - pPart->rcSizingMargins.bottom); rgnResult.CombineRgn(&rgnResult, &rgnCenter, RGN_DIFF); } pPart = &pRegion->Part[frameRight]; if (pPart->rgnLeft.GetSafeHandle()) { CRgn rgnLeft; rgnLeft.CreateRectRgn(0, 0, 0, 0); rgnLeft.CopyRgn(&pPart->rgnLeft); rgnLeft.OffsetRgn(sz.cx - pRegion->nBorderHeight, pRegion->nCaptionHeight); rgnResult.CombineRgn(&rgnResult, &rgnLeft, RGN_DIFF); } if (pPart->rgnRight.GetSafeHandle()) { CRgn rgnRight; rgnRight.CreateRectRgn(0, 0, 0, 0); rgnRight.CopyRgn(&pPart->rgnRight); rgnRight.OffsetRgn(sz.cx - pRegion->nBorderHeight, sz.cy - pRegion->nBorderHeight - pPart->rcSizingMargins.bottom); rgnResult.CombineRgn(&rgnResult, &rgnRight, RGN_DIFF); } if (pPart->nCenter > 0) { CRgn rgnCenter; rgnCenter.CreateRectRgn(sz.cx - pPart->nCenter, pRegion->nCaptionHeight + pPart->rcSizingMargins.top, sz.cx, sz.cy - pRegion->nBorderHeight - pPart->rcSizingMargins.bottom); rgnResult.CombineRgn(&rgnResult, &rgnCenter, RGN_DIFF); } if (pRegion->bAutoDelete) delete pRegion; return (HRGN)rgnResult.Detach(); } COLORREF CXTPSkinManagerSchema::GetColor(int nIndex) const { return GetMetrics()->GetColor(nIndex); } COLORREF CXTPSkinManagerSchema::GetScrollBarSizeBoxColor(CXTPSkinObjectFrame* /*pFrame*/) { return GetColor(COLOR_3DFACE); } void CXTPSkinManagerSchema::DrawThemeScrollBar(CDC* pDC, CXTPSkinObjectFrame* pFrame, XTP_SKINSCROLLBARPOSINFO* pSBInfo) { #define ABS_UPACTIVE 17 #define ABS_DOWNACTIVE 18 #define ABS_LEFTACTIVE 19 #define ABS_RIGHTACTIVE 20 #define GETPARTSTATE(ht, pressed, hot, normal, disabled, active) \ (!bEnabled ? disabled : nPressetHt == ht ? pressed : \ nHotHt == ht ? hot : bActive ? (active) : normal) XTP_SKINSCROLLBARTRACKINFO* pSBTrack = pFrame->GetScrollBarTrackInfo(); BOOL nPressetHt = pSBTrack && pSBTrack->pSBInfo == pSBInfo ? (pSBTrack->bTrackThumb || pSBTrack->fHitOld ? pSBInfo->ht : -1) : -1; BOOL nHotHt = pSBTrack ? -1 : pSBInfo->ht; BOOL bActive = (pSBTrack && pSBTrack->pSBInfo == pSBInfo) || nHotHt > 0 ; int cWidth = (pSBInfo->pxRight - pSBInfo->pxLeft); BOOL fVert = pSBInfo->fVert; if (cWidth <= 0) { return; } HBRUSH hBrush = pFrame->GetClientBrush(pDC); FillRect(pDC->GetSafeHdc(), &pSBInfo->rc, hBrush); BOOL bEnabled = pSBInfo->posMax - pSBInfo->posMin - pSBInfo->page + 1 > 0; if (bEnabled && pSBInfo->nBar == SB_CTL) bEnabled = (pFrame->GetStyle() & WS_DISABLED) == 0; CXTPSkinManagerClass* pClassScrollBar = m_pManager->GetSkinClass(pFrame, _T("SCROLLBAR")); int nBtnTrackSize = pSBInfo->pxThumbBottom - pSBInfo->pxThumbTop; int nBtnTrackPos = pSBInfo->pxThumbTop - pSBInfo->pxUpArrow; if (!bEnabled || pSBInfo->pxThumbBottom > pSBInfo->pxDownArrow) nBtnTrackPos = nBtnTrackSize = 0; int nStateCount = pClassScrollBar->GetThemeInt(SBP_ARROWBTN, 0, TMT_IMAGECOUNT, 16); if (!fVert) { CRect rcHScroll(pSBInfo->rc); CRect rcArrowLeft(rcHScroll.left, rcHScroll.top, pSBInfo->pxUpArrow, rcHScroll.bottom); CRect rcArrowRight(pSBInfo->pxDownArrow, rcHScroll.top, rcHScroll.right, rcHScroll.bottom); pClassScrollBar->DrawThemeBackground(pDC, SBP_ARROWBTN, GETPARTSTATE(XTP_HTSCROLLUP, ABS_LEFTPRESSED, ABS_LEFTHOT, ABS_LEFTNORMAL, ABS_LEFTDISABLED, nStateCount == 20 ? ABS_LEFTACTIVE : ABS_LEFTNORMAL), rcArrowLeft); pClassScrollBar->DrawThemeBackground(pDC, SBP_ARROWBTN, GETPARTSTATE(XTP_HTSCROLLDOWN, ABS_RIGHTPRESSED, ABS_RIGHTHOT, ABS_RIGHTNORMAL, ABS_RIGHTDISABLED, nStateCount == 20 ? ABS_RIGHTACTIVE : ABS_RIGHTNORMAL), rcArrowRight); CRect rcTrack(rcArrowLeft.right, rcHScroll.top, rcArrowRight.left, rcHScroll.bottom); if (!rcTrack.IsRectEmpty()) { CRect rcLowerTrack(rcTrack.left, rcTrack.top, rcTrack.left + nBtnTrackPos, rcTrack.bottom); CRect rcBtnTrack(rcLowerTrack.right, rcTrack.top, rcLowerTrack.right + nBtnTrackSize, rcTrack.bottom); CRect rcUpperTrack(rcBtnTrack.right, rcTrack.top, rcTrack.right, rcTrack.bottom); if (!rcLowerTrack.IsRectEmpty()) pClassScrollBar->DrawThemeBackground(pDC, SBP_LOWERTRACKHORZ, GETPARTSTATE(XTP_HTSCROLLUPPAGE, SCRBS_PRESSED, SCRBS_HOT, SCRBS_NORMAL, SCRBS_DISABLED, SCRBS_NORMAL), rcLowerTrack); if (!rcBtnTrack.IsRectEmpty()) { pClassScrollBar->DrawThemeBackground(pDC, SBP_THUMBBTNHORZ, GETPARTSTATE(XTP_HTSCROLLTHUMB, SCRBS_PRESSED, SCRBS_HOT, SCRBS_NORMAL, SCRBS_DISABLED, SCRBS_NORMAL), rcBtnTrack); if (rcBtnTrack.Width() > 9) pClassScrollBar->DrawThemeBackground(pDC, SBP_GRIPPERHORZ, GETPARTSTATE(XTP_HTSCROLLTHUMB, SCRBS_PRESSED, SCRBS_HOT, SCRBS_NORMAL, SCRBS_DISABLED, SCRBS_NORMAL), rcBtnTrack); } if (!rcUpperTrack.IsRectEmpty()) pClassScrollBar->DrawThemeBackground(pDC, SBP_UPPERTRACKHORZ, GETPARTSTATE(XTP_HTSCROLLDOWNPAGE, SCRBS_PRESSED, SCRBS_HOT, SCRBS_NORMAL, SCRBS_DISABLED, SCRBS_NORMAL), rcUpperTrack); } } else { CRect rcVScroll(pSBInfo->rc); CRect rcArrowUp(rcVScroll.left, rcVScroll.top, rcVScroll.right, pSBInfo->pxUpArrow); CRect rcArrowDown(rcVScroll.left, pSBInfo->pxDownArrow, rcVScroll.right, rcVScroll.bottom); pClassScrollBar->DrawThemeBackground(pDC, SBP_ARROWBTN, GETPARTSTATE(XTP_HTSCROLLUP, ABS_UPPRESSED, ABS_UPHOT, ABS_UPNORMAL, ABS_UPDISABLED, nStateCount == 20 ? ABS_UPACTIVE : ABS_UPNORMAL), rcArrowUp); pClassScrollBar->DrawThemeBackground(pDC, SBP_ARROWBTN, GETPARTSTATE(XTP_HTSCROLLDOWN, ABS_DOWNPRESSED, ABS_DOWNHOT, ABS_DOWNNORMAL, ABS_DOWNDISABLED, nStateCount == 20 ? ABS_DOWNACTIVE : ABS_DOWNNORMAL), rcArrowDown); CRect rcTrack(rcVScroll.left, rcArrowUp.bottom, rcVScroll.right, rcArrowDown.top); if (!rcTrack.IsRectEmpty()) { CRect rcLowerTrack(rcTrack.left, rcTrack.top, rcTrack.right, rcTrack.top + nBtnTrackPos); CRect rcBtnTrack(rcTrack.left, rcLowerTrack.bottom, rcTrack.right, rcLowerTrack.bottom + nBtnTrackSize); CRect rcUpperTrack(rcTrack.left, rcBtnTrack.bottom, rcTrack.right, rcTrack.bottom); if (!rcLowerTrack.IsRectEmpty()) pClassScrollBar->DrawThemeBackground(pDC, SBP_LOWERTRACKVERT, GETPARTSTATE(XTP_HTSCROLLUPPAGE, SCRBS_PRESSED, SCRBS_HOT, SCRBS_NORMAL, SCRBS_DISABLED, SCRBS_NORMAL), rcLowerTrack); if (!rcBtnTrack.IsRectEmpty()) { pClassScrollBar->DrawThemeBackground(pDC, SBP_THUMBBTNVERT, GETPARTSTATE(XTP_HTSCROLLTHUMB, SCRBS_PRESSED, SCRBS_HOT, SCRBS_NORMAL, SCRBS_DISABLED, SCRBS_NORMAL), rcBtnTrack); if (rcBtnTrack.Height() > 13) pClassScrollBar->DrawThemeBackground(pDC, SBP_GRIPPERVERT, GETPARTSTATE(XTP_HTSCROLLTHUMB, SCRBS_PRESSED, SCRBS_HOT, SCRBS_NORMAL, SCRBS_DISABLED, SCRBS_NORMAL), rcBtnTrack); } if (!rcUpperTrack.IsRectEmpty()) pClassScrollBar->DrawThemeBackground(pDC, SBP_UPPERTRACKVERT, GETPARTSTATE(XTP_HTSCROLLDOWNPAGE, SCRBS_PRESSED, SCRBS_HOT, SCRBS_NORMAL, SCRBS_DISABLED, SCRBS_NORMAL), rcUpperTrack); } } }