DragonNest/Third/XTToolkitPro/Source/SkinFramework/XTPSkinManagerSchema.cpp

1601 lines
46 KiB
C++
Raw Normal View History

2024-12-19 09:48:26 +08:00
// XTPSkinManagerSchema.cpp: implementation of the CXTPSkinManagerSchema class.
//
// This file is a part of the XTREME SKINFRAMEWORK MFC class library.
// (c)1998-2008 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/XTPVC50Helpers.h"
#include "Common/XTPVC80Helpers.h"
#include "Common/XTPDrawHelpers.h"
#include "XTPSkinManagerSchema.h"
#include "XTPSkinManagerResource.h"
#include "XTPSkinManager.h"
#include "XTPSkinImage.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(CXTPSkinManager* pManager)
: m_pManager(pManager)
{
m_bPreMultiplyImages = TRUE;
m_nGlobalClassId = GetClassCode(_T("GLOBALS"));
m_nWindowClassId = GetClassCode(_T("WINDOW"));
m_mapProperties.InitHashTable(199, FALSE);
}
CXTPSkinManagerSchema::~CXTPSkinManagerSchema()
{
RemoveAllProperties();
}
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;
if (_tcsicmp(_T("Menu"), lpszClass) == 0) return 0;
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;
REMOVE_S(strSchemaPart, _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)
{
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)
{
if (m_mapProperties.Lookup(CalculatePropertyCode(iClassId, iPartId, iStateId, iPropId), pProperty))
return pProperty;
}
if (m_mapProperties.Lookup(CalculatePropertyCode(iClassId, iPartId, 0, iPropId), pProperty))
return pProperty;
if (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;
}
//////////////////////////////////////////////////////////////////////////
// CXTPSkinManagerSchemaDefault
CXTPSkinManagerSchemaDefault::CXTPSkinManagerSchemaDefault(CXTPSkinManager* pManager)
: CXTPSkinManagerSchema(pManager)
{
m_strSchemaName = _T("Default");
m_nFrameButtonOffset = 0;
}
CXTPSkinManagerSchemaDefault::~CXTPSkinManagerSchemaDefault()
{
FreeFrameRegions();
}
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(m_pManager->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(m_pManager->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 CXTPSkinManagerSchemaDefault::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(m_pManager->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 CXTPSkinManagerSchemaDefault::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(m_pManager->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 CXTPSkinManagerSchemaDefault::DrawThemeFrameButtons(CDC* pDC, CXTPSkinObjectFrame* pFrame)
{
CXTPWindowRect rc(pFrame);
rc.OffsetRect(-rc.TopLeft());
CRect rcBorders = pFrame->GetBorders();
int nCaptionHeight = rcBorders.top;
LONG lStyle = pFrame->GetStyle();
DWORD dwExStyle = pFrame->GetExStyle();
int cBorders = GetWindowBorders(lStyle, dwExStyle, TRUE, FALSE);
int cxFrame = cBorders * m_pManager->GetMetrics()->m_cxBorder;
int nTop = 0;
if (dwExStyle & WS_EX_WINDOWEDGE)
nTop++;
else if (dwExStyle & WS_EX_STATICEDGE)
nTop++;
if (lStyle & WS_SIZEBOX)
nTop += (1 + m_pManager->GetMetrics()->m_nBorderSize) / 2;
int yButton = nCaptionHeight - 5 - cxFrame + m_nFrameButtonOffset;
if (dwExStyle & WS_EX_CLIENTEDGE)
{
yButton -= 2;
nTop -= 1;
}
CXTPSkinManagerClass* pClass = m_pManager->GetSkinClass(_T("WINDOW"));
CSize szButton = dwExStyle & WS_EX_TOOLWINDOW ? CSize(yButton, yButton) : GetCaptionButtonSize(pClass, yButton);
CRect rcButton = CRect(CPoint(rc.right - szButton.cx - cBorders - 2, 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 = m_pManager->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->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, m_pManager->GetMetrics()->m_clrEdgeShadow, m_pManager->GetMetrics()->m_clrEdgeHighLight);
rc.DeflateRect(1, 1);
pDC->Draw3dRect(rc, m_pManager->GetMetrics()->m_clrEdgeDkShadow, m_pManager->GetMetrics()->m_clrEdgeLight);
rc.DeflateRect(1, 1);
}
}
HICON GetFrameSmIcon(CXTPSkinObjectFrame* pFrame)
{
DWORD dwStyle = pFrame->GetStyle();
DWORD dwExStyle = pFrame->GetExStyle();
if (dwExStyle & WS_EX_TOOLWINDOW)
return NULL;
if ((dwStyle & WS_SYSMENU) == 0)
return NULL;
HICON hIcon = (HICON)(DWORD_PTR)::SendMessage(pFrame->m_hWnd, WM_GETICON, ICON_SMALL, 0);
if (hIcon)
return hIcon;
hIcon = (HICON)(DWORD_PTR)::SendMessage(pFrame->m_hWnd, WM_GETICON, ICON_BIG, 0);
if (hIcon)
return hIcon;
hIcon = (HICON)(DWORD_PTR)::GetClassLongPtr(pFrame->m_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(pFrame->GetSafeHwnd(),
WM_QUERYDRAGICON,
0,
0,
SMTO_NORMAL,
100,
&dwResult))
{
hIcon = (HICON)dwResult;
}
if (hIcon == NULL)
{
hIcon = AfxGetApp()->LoadOEMIcon(OIC_WINLOGO);
}
}
return hIcon;
}
void CXTPSkinManagerSchemaDefault::DrawThemeFrame(CDC* pDC, CXTPSkinObjectFrame* pFrame)
{
CXTPWindowRect rc(pFrame);
rc.OffsetRect(-rc.TopLeft());
DWORD dwStyle = pFrame->GetStyle();
DWORD dwExStyle = pFrame->GetExStyle();
if ((dwStyle & WS_CAPTION) != WS_CAPTION)
{
DrawNonClientRect(pDC, rc, pFrame);
return;
}
BOOL bToolWindow = (dwExStyle & WS_EX_TOOLWINDOW) == WS_EX_TOOLWINDOW;
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(_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);
pClassWindow->DrawThemeBackground(&dc, bToolWindow? WP_SMALLCAPTION: WP_CAPTION, nFrameState, rcCaption);
CSize szIcon(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
int nTextLeft = rcBorders.left;
HICON hIcon = GetFrameSmIcon(pFrame);
int cBorders = GetWindowBorders(dwStyle, dwExStyle, TRUE, FALSE) - m_pManager->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(m_pManager->GetThemeSysColor(pFrame->IsActive() ? TMT_CAPTIONTEXT : TMT_INACTIVECAPTIONTEXT));
CFont* pOldFont = dc.SelectObject(bToolWindow ? &m_pManager->GetMetrics()->m_fntSmCaption : &m_pManager->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 CXTPSkinManagerSchemaDefault::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 += m_pManager->GetMetrics()->m_nBorderSize;
}
if (fClient)
{
if (dwExStyle & WS_EX_CLIENTEDGE)
cBorders += 2;
}
return(cBorders);
}
CRect CXTPSkinManagerSchemaDefault::CalcFrameBorders(CXTPSkinObjectFrame* pFrame)
{
DWORD dwExStyle = pFrame->GetExStyle();
DWORD dwStyle = pFrame->GetStyle();
return CalcFrameBorders(dwStyle, dwExStyle);
}
CRect CXTPSkinManagerSchemaDefault::CalcFrameBorders(DWORD dwStyle, DWORD dwExStyle)
{
BOOL bToolWindow = (dwExStyle & WS_EX_TOOLWINDOW) == WS_EX_TOOLWINDOW;
CXTPSkinManagerMetrics* pMetrics = m_pManager->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 y, int x2)
{
if (x1 < x2)
{
if (pRgn->GetSafeHandle() == NULL)
{
pRgn->CreateRectRgn(0, 0, 0, 0);
}
CRgn rgnExclude;
rgnExclude.CreateRectRgn(x1, y, x2, y + 1);
pRgn->CombineRgn(pRgn, &rgnExclude, RGN_OR);
}
}
void CXTPSkinManagerSchemaDefault::RegionFromBitmap(CDC* pDC, CRgn* pRgnLeft, CRgn* pRgnRight, int& nRgnFrameCenter, const CRect& rc, const CRect& rcSizingMargins, COLORREF clrTransparent)
{
CSize sz = rc.Size();
nRgnFrameCenter = 0;
BOOL bCheckCenter = TRUE;
for (int y = 0; y < sz.cy; y++)
{
int x = 0;
while (pDC->GetPixel(x, y) == clrTransparent && x < rcSizingMargins.left)
{
x++;
}
if (x > 0)
{
IncludeRgnPart(pRgnLeft, 0, y, x);
}
x = sz.cx - 1;
int nOffset = sz.cx - rcSizingMargins.right;
while (x >= nOffset)
{
int x0 = x;
while (x >= nOffset && pDC->GetPixel(x, y) == clrTransparent)
{
x--;
}
if (x != x0)
{
IncludeRgnPart(pRgnRight, x - nOffset + 1, y, x0 - nOffset + 1);
}
while (x >= nOffset && pDC->GetPixel(x, y) != clrTransparent)
{
x--;
}
if (x == x0)
break;
}
if (bCheckCenter)
{
x = rcSizingMargins.left;
while (pDC->GetPixel(x, y) == clrTransparent && x < sz.cx - rcSizingMargins.right)
{
x++;
}
if (x == sz.cx - rcSizingMargins.right)
{
nRgnFrameCenter++;
}
else
{
bCheckCenter = FALSE;
}
}
}
}
CXTPSkinManagerSchemaDefault::FRAMEREGION* CXTPSkinManagerSchemaDefault::CreateFrameRegion(CXTPSkinObjectFrame* pFrame, CSize szDest)
{
int nCaptionHeight = pFrame->GetBorders().top;
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)
{
if (szDest.cx < pRegion->rcFrameSizingMargins.left + pRegion->rcFrameSizingMargins.right)
break;
return pRegion;
}
}
int iPartId = bToolWindow ? WP_SMALLCAPTION : WP_CAPTION;
CXTPSkinManagerClass* pClass = m_pManager->GetSkinClass(_T("WINDOW"));
CString strImageFile = pClass->GetThemeString(iPartId, FS_ACTIVE, TMT_IMAGEFILE);
if (strImageFile.IsEmpty())
return NULL;
CSize sz = pClass->GetImages()->GetExtent(m_pManager->GetResourceFile(), strImageFile);
if (sz == CSize(0))
return NULL;
CXTPSkinImage* pImage = pClass->GetImages()->LoadFile(m_pManager->GetResourceFile(), strImageFile);
if (!pImage)
return NULL;
int nImageCount = pClass->GetThemeInt(iPartId, FS_ACTIVE, TMT_IMAGECOUNT, 1);
ASSERT(nImageCount >= 1);
if (nImageCount < 1)
return NULL;
FRAMEREGION* pRegion = new FRAMEREGION();
pRegion->bAutoDelete = FALSE;
pRegion->rcFrameSizingMargins.SetRectEmpty();
CWindowDC dcWindow(pFrame);
CDC dc;
dc.CreateCompatibleDC(&dcWindow);
CRect rcSrc(0, 0, sz.cx, sz.cy / nImageCount);
CRect rcDest(0, 0, sz.cx, nCaptionHeight);
CBitmap bmp;
bmp.CreateCompatibleBitmap(&dcWindow, rcDest.Width(), rcDest.Height());
CBitmap* pOldBitmap = dc.SelectObject(&bmp);
BOOL bTransparent = pImage->IsAlphaImage()? FALSE: pClass->GetThemeBool(iPartId, FS_ACTIVE, TMT_TRANSPARENT);
COLORREF 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));
CRect rcSizingMargins = pClass->GetThemeRect(iPartId, FS_ACTIVE, TMT_SIZINGMARGINS);
if (rcSizingMargins.top + rcSizingMargins.bottom > rcDest.Height())
{
rcSizingMargins.bottom = max(0, rcDest.Height() - rcSizingMargins.top);
}
CRect rcDestSizingMargins = rcSizingMargins;
if (szDest.cx < rcSizingMargins.left + rcSizingMargins.right)
{
rcDest.right = szDest.cx;
pRegion->bAutoDelete = TRUE;
rcDestSizingMargins.left = MulDiv(rcDest.Width(), rcSizingMargins.left, (rcSizingMargins.left + rcSizingMargins.right));
rcDestSizingMargins.right = rcDest.Width() - rcSizingMargins.left;
}
pImage->DrawImage(&dc, rcDest, rcSrc, rcSizingMargins, clrTransparent, ST_STRETCH, FALSE);
RegionFromBitmap(&dc, &pRegion->rgnFrameLeft, &pRegion->rgnFrameRight, pRegion->nRgnFrameCenter,
rcDest, rcDestSizingMargins, clrTransparent != COLORREF_NULL ? clrTransparent : RGB(0xFF, 0, 0xFF));
dc.SelectObject(pOldBitmap);
pRegion->rcFrameSizingMargins = rcDestSizingMargins;
pRegion->bToolWindow = bToolWindow;
pRegion->nCaptionHeight = nCaptionHeight;
if (!pRegion->bAutoDelete)
m_arrFrameRegions.Add(pRegion);
return pRegion;
}
void CXTPSkinManagerSchemaDefault::FreeFrameRegions()
{
for (int i = 0; i < m_arrFrameRegions.GetSize(); i++)
{
delete m_arrFrameRegions[i];
}
m_arrFrameRegions.RemoveAll();
}
void CXTPSkinManagerSchemaDefault::RefreshMetrcis()
{
FreeFrameRegions();
}
HRGN CXTPSkinManagerSchemaDefault::CalcFrameRegion(CXTPSkinObjectFrame* pFrame, CSize sz)
{
CRgn rgnResult;
if ((pFrame->GetStyle() & WS_MAXIMIZE) && ((pFrame->GetStyle() & WS_CHILD) == 0))
{
int nBorder = pFrame->GetBorders().left;
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();
}
if (pRegion->rgnFrameLeft.GetSafeHandle())
{
rgnResult.CombineRgn(&rgnResult, &pRegion->rgnFrameLeft, RGN_DIFF);
}
if (pRegion->rgnFrameRight.GetSafeHandle())
{
CRgn rgnFrameRight;
rgnFrameRight.CreateRectRgn(0, 0, 0, 0);
rgnFrameRight.CopyRgn(&pRegion->rgnFrameRight);
rgnFrameRight.OffsetRgn(sz.cx - pRegion->rcFrameSizingMargins.right, 0);
rgnResult.CombineRgn(&rgnResult, &rgnFrameRight, RGN_DIFF);
}
if (pRegion->nRgnFrameCenter > 0)
{
CRgn rgnFrameCenter;
rgnFrameCenter.CreateRectRgn(pRegion->rcFrameSizingMargins.left, 0, sz.cx - pRegion->rcFrameSizingMargins.right, pRegion->nRgnFrameCenter);
rgnResult.CombineRgn(&rgnResult, &rgnFrameCenter, RGN_DIFF);
}
if (pRegion->bAutoDelete)
delete pRegion;
return (HRGN)rgnResult.Detach();
}
COLORREF CXTPSkinManagerSchema::GetColor(int nIndex) const
{
return m_pManager->GetMetrics()->GetColor(nIndex);
}
COLORREF CXTPSkinManagerSchema::GetScrollBarSizeBoxColor(CXTPSkinObjectFrame* /*pFrame*/)
{
return GetColor(COLOR_3DFACE);
}
void CXTPSkinManagerSchemaDefault::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(_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);
}
}
}