themed.cpp

来自「管理项目进度工具的原代码」· C++ 代码 · 共 616 行 · 第 1/2 页

CPP
616
字号
// Themed.cpp: implementation of the CThemed class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Themed.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

// theme function definitions
typedef BOOL (STDAPICALLTYPE *PFNISTHEMEACTIVE)();
typedef DWORD (STDAPICALLTYPE *PFNGETTHEMEAPPPROPERTIES)();
typedef HTHEME (STDAPICALLTYPE *PFNOPENTHEMEDATA)(HWND hwnd, LPCWSTR pszClassList);
typedef HRESULT (STDAPICALLTYPE *PFNCLOSETHEMEDATA)(HTHEME hTheme);
typedef HRESULT (STDAPICALLTYPE *PFNDRAWTHEMEBACKGROUND)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, 
														 const RECT *pRect, const RECT *pClipRect);
typedef HRESULT (STDAPICALLTYPE *PFNDRAWTHEMEPARENTBACKGROUND)(HWND hWnd, HDC hdc, RECT *pRect);
typedef HRESULT (STDAPICALLTYPE *PFNDRAWTHEMETEXT)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, 
												   LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, 
												   DWORD dwTextFlags2, const RECT *pRect);
typedef HRESULT (STDAPICALLTYPE *PFNDRAWTHEMEEDGE)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, 
												   const RECT *pDestRect, UINT uEdge, UINT uFlags, 
												   RECT *pContentRect);
typedef HRESULT (STDAPICALLTYPE *PFNDRAWTHEMEICON)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, 
												   const RECT *pRect, HIMAGELIST himl, int iImageIndex);
typedef HRESULT (STDAPICALLTYPE *PFNDRAWTHEMEBORDER)(HTHEME hTheme, HDC hdc, int iStateId, const RECT *pRect);
typedef HRESULT (STDAPICALLTYPE *PFNGETTHEMEPARTSIZE)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId,
                                                      RECT *prc, THEMESIZE eSize, SIZE *psz);
typedef HRESULT (STDAPICALLTYPE *PFNGETTHEMETEXTEXTENT)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, 
													  LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, 
													  const RECT *pBoundingRect, RECT *pExtentRect);
typedef HRESULT (STDAPICALLTYPE *PFNGETTHEMECOLOR)(HTHEME hTheme, int iPartId, int iStateId, int iPropID,
												   COLORREF* pColor);
typedef HRESULT (STDAPICALLTYPE *PFNGETTHEMEBACKGROUNDCONTENTRECT)(HTHEME hTheme, HDC hdc, int iPartId,
												int iStateId, LPCRECT pBoundingRect, LPRECT pContentRect);


#define WSTR(string) (LPCWSTR)COleVariant(string).bstrVal

#ifndef DFCS_TRANSPARENT
#	define DFCS_TRANSPARENT        0x0800
#	define DFCS_HOT                0x1000
#	define DFC_POPUPMENU           5
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

HMODULE CThemed::s_hUxTheme = HMODULE(-1);

CThemed::CThemed(CWnd* pWnd, LPCTSTR szClassList) : m_hWnd(NULL), m_hTheme(NULL)
{
	InitUxTheme();
	
	if (pWnd && pWnd->GetSafeHwnd())
		Open(pWnd, szClassList);
}

CThemed::~CThemed()
{
	Close();
}

BOOL CThemed::InitUxTheme()
{
	if (s_hUxTheme == HMODULE(-1)) // one time only
		s_hUxTheme = LoadLibrary("UxTheme.dll");
	
	return (NULL != s_hUxTheme);
}

BOOL CThemed::SupportsTheming(int nFlag)
{
	return (IsThemeActive() && (GetAppThemeProperties() & nFlag));
}

BOOL CThemed::Open(const CWnd* pWnd, LPCTSTR szClassList)
{
	if (pWnd && pWnd->GetSafeHwnd())
	{
		if (!s_hUxTheme)
		{
			s_hUxTheme = LoadLibrary("UxTheme.dll");

			if (!s_hUxTheme)
				return FALSE;
		}
		else
			Close();
		
		CString sClassList(szClassList);
		
		if (sClassList.IsEmpty())
		{
			::GetClassName(pWnd->GetSafeHwnd(), sClassList.GetBuffer(128), 128);
			sClassList.ReleaseBuffer();
		}
		
		m_hTheme = OpenThemeData(pWnd->GetSafeHwnd(), WSTR(sClassList));
		m_hWnd = pWnd->GetSafeHwnd();
		
		return (NULL != m_hTheme);
	}
	
	return FALSE;
}

BOOL CThemed::Close()
{
	if (CloseThemeData(m_hTheme))
		m_hTheme = NULL;
	
	return (NULL == m_hTheme);
}

BOOL CThemed::AreControlsThemed()
{
	return SupportsTheming(STAP_ALLOW_CONTROLS);
}

BOOL CThemed::IsNonClientThemed()
{
	return SupportsTheming(STAP_ALLOW_NONCLIENT);
}

BOOL CThemed::IsWebContentThemed()
{
	return SupportsTheming(STAP_ALLOW_WEBCONTENT);
}

// static 
BOOL CThemed::DrawFrameControl(const CWnd* pWnd, CDC* pDC, LPRECT pRect, UINT nType, UINT nState, LPCRECT pClip)
{
	CThemed th;
	
	if (th.SupportsTheming(STAP_ALLOW_CONTROLS) && th.SupportsTheming(STAP_ALLOW_NONCLIENT))
	{
		// determine the appropriate class, part and state
		CString sThClass;
		int nThPart = 0, nThState = 0;
		
		if (!th.GetThemeClassPartState(nType, nState, sThClass, nThPart, nThState))
			return FALSE;
		
		if (!th.Open(pWnd, sThClass))
			return FALSE;
		
		th.DrawParentBackground(pWnd, pDC, (LPRECT)(pClip ? pClip : pRect));
		th.DrawBackground(pDC, nThPart, nThState, pRect, pClip);
		
		return TRUE;
	}
	else
		return pDC->DrawFrameControl(pRect, nType, nState);
}

BOOL CThemed::DrawEdge(const CWnd* pWnd, CDC* pDC, LPRECT pRect, UINT nType, UINT nState, UINT nEdge, UINT nFlags)
{
	CThemed th;
	
	if (th.SupportsTheming(STAP_ALLOW_CONTROLS) && th.SupportsTheming(STAP_ALLOW_NONCLIENT))
	{
		// determine the appropriate class, part and state
		CString sThClass;
		int nThPart = 0, nThState = 0;
		
		if (!th.GetThemeClassPartState(nType, nState, sThClass, nThPart, nThState))
			return FALSE;
		
		if (!th.Open(pWnd, sThClass))
			return FALSE;
		
		th.DrawEdge(pDC, nThPart, nThState, pRect, nEdge, nFlags);
		
		return TRUE;
	}
	else
		return pDC->DrawFrameControl(pRect, nType, nState);
}

BOOL CThemed::DrawBackground(CDC* pDC, int nPart, int nState, const CRect& rect, LPCRECT prClip)
{
	ASSERT (m_hTheme);
	ASSERT_VALID (pDC);
	
	return DrawThemeBackground(*pDC, nPart, nState, rect, prClip);
}

BOOL CThemed::DrawParentBackground(const CWnd* pWnd, CDC* pDC, LPRECT pRect)
{
	ASSERT (m_hTheme);
	ASSERT_VALID (pDC);
	ASSERT_VALID (pWnd);
	
	return DrawThemeParentBackground(*pWnd, *pDC, pRect);
}

BOOL CThemed::DrawText(CDC* pDC, int nPart, int nState, const CString& sText, DWORD dwTextFlags, DWORD dwTextFlags2, const CRect& rect)
{
	ASSERT (m_hTheme);
	ASSERT_VALID (pDC);
	
	return DrawThemeText(*pDC, nPart, nState, WSTR(sText), sText.GetLength(), dwTextFlags, dwTextFlags2, rect);
}

BOOL CThemed::DrawEdge(CDC* pDC, int nPart, int nState, const CRect& rDest, UINT nEdge, UINT nFlags, LPRECT prContent)
{
	ASSERT (m_hTheme);
	ASSERT_VALID (pDC);
	
	return DrawThemeEdge(*pDC, nPart, nState, rDest, nEdge, nFlags, prContent);
}

BOOL CThemed::DrawIcon(CDC* pDC, int nPart, int nState, const CRect& rect, const CImageList* pIL, int nImage)
{
	ASSERT (m_hTheme);
	ASSERT_VALID (pDC);
	ASSERT_VALID (pIL);
	
	return DrawThemeIcon(*pDC, nPart, nState, rect, *pIL, nImage);
}

BOOL CThemed::DrawBorder(CDC* pDC, int nState, const CRect& rect)
{
	ASSERT (m_hTheme);
	ASSERT_VALID (pDC);
	
	return DrawThemeBorder(*pDC, nState, rect);
}

BOOL CThemed::GetSize(int nPart, int nState, CSize& size, BOOL bMin)
{
	ASSERT (m_hTheme);
	
	return GetThemePartSize(nPart, nState, bMin ? TS_MIN : TS_TRUE, &size);
}

BOOL CThemed::GetTextExtent(CDC* pDC, int nPart, int nState, const CString& sText, DWORD dwTextFlags, CRect& rExtent, LPCRECT prBounding)
{
	ASSERT (m_hTheme);
	
	return GetThemeTextExtent(pDC ? *pDC : (HDC)NULL, nPart, nState, WSTR(sText), sText.GetLength(), dwTextFlags, prBounding, rExtent);
}

BOOL CThemed::BuildImageList(CImageList& il, int nPart, const int nStates[], int nNumStates, COLORREF crMask)
{
	ASSERT (!il.GetSafeHandle());
	
	if (il.GetSafeHandle())
		return FALSE;
	
	if (!nNumStates)
		return FALSE;
	
	CSize size;
	GetSize(nPart, 1, size);

	// little cheat for check boxes
	const UINT BORDER = (nPart == BP_CHECKBOX) ? 1 : 0;

	// create a bitmap containing the required images
	HWND hWnd = m_hWnd ? m_hWnd : GetDesktopWindow();
	CClientDC dc(CWnd::FromHandle(hWnd));
	CDC dcBack;
	
	if (dcBack.CreateCompatibleDC(&dc))
	{
		CBitmap bitmap;

		int nImWidth = (size.cx + 2 * BORDER);
		int nImHeight = (size.cy + 2 * BORDER);
		
		if (bitmap.CreateCompatibleBitmap(&dc, nImWidth * nNumStates, nImHeight))
		{
			CGdiObject* pOld = dcBack.SelectObject(&bitmap);
			dcBack.FillSolidRect(0, 0, nImWidth * nNumStates, nImHeight, crMask);
			
			CRect rState(BORDER, BORDER, size.cx + BORDER, size.cy + BORDER);

			for (int nState = 0; nState < nNumStates; nState++)
			{
				if (nStates[nState] != -1)
					DrawBackground(&dcBack, nPart, nStates[nState], rState);
				
				// next state
				rState.OffsetRect(nImWidth, 0);
			}
			
			dcBack.SelectObject(pOld);
			
			// create imagelist
			if (il.Create(nImWidth, nImHeight, ILC_COLOR32 | ILC_MASK, 0, 1))
				il.Add(&bitmap, crMask);
		}
	}
	
	return (il.GetSafeHandle() != NULL);
}

COLORREF CThemed::GetThemeColor(int nPart, int nState, int nProp)
{
	ASSERT (m_hTheme);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?