📄 atltheme.h
字号:
#endif // !_WTL_NEW_UXTHEME
}
HRESULT GetThemeSysString(int nStringID, LPWSTR pszStringBuff, int cchMaxStringChars) const
{
ATLASSERT(m_hTheme != NULL);
return ::GetThemeSysString(m_hTheme, nStringID, pszStringBuff, cchMaxStringChars);
}
HRESULT GetThemeSysInt(int nIntID, int* pnValue) const
{
ATLASSERT(m_hTheme != NULL);
return ::GetThemeSysInt(m_hTheme, nIntID, pnValue);
}
#ifdef _WTL_NEW_UXTHEME
HTHEME OpenThemeDataEx(HWND hWnd, LPCWSTR pszClassList, DWORD dwFlags)
{
if(!IsThemingSupported())
return NULL;
ATLASSERT(m_hTheme == NULL);
m_hTheme = ::OpenThemeDataEx(hWnd, pszClassList, dwFlags);
return m_hTheme;
}
HRESULT DrawThemeTextEx(HDC hDC, int nPartID, int nStateID, LPCWSTR pszText, int cchText, DWORD dwTextFlags, LPRECT lpRect, const DTTOPTS* pOptions)
{
ATLASSERT(m_hTheme != NULL);
return ::DrawThemeTextEx(m_hTheme, hDC, nPartID, nStateID, pszText, cchText, dwTextFlags, lpRect, pOptions);
}
HRESULT GetThemeTransitionDuration(int nPartID, int nFromStateID, int nToStateID, int nPropID, DWORD& dwDuration)
{
ATLASSERT(m_hTheme != NULL);
return ::GetThemeTransitionDuration(m_hTheme, nPartID, nFromStateID, nToStateID, nPropID, &dwDuration);
}
#endif // _WTL_NEW_UXTHEME
#if (_WIN32_WINNT >= 0x0600)
HRESULT GetThemeBitmap(int nPartID, int nStateID, int nPropID, ULONG uFlags, HBITMAP& hBitmap)
{
ATLASSERT(m_hTheme != NULL);
return ::GetThemeBitmap(m_hTheme, nPartID, nStateID, nPropID, uFlags, &hBitmap);
}
HRESULT GetThemeStream(int nPartID, int nStateID, int nPropID, VOID** ppvStream, DWORD* pcbStream, HINSTANCE hInstance)
{
ATLASSERT(m_hTheme != NULL);
return ::GetThemeStream(m_hTheme, nPartID, nStateID, nPropID, ppvStream, pcbStream, hInstance);
}
#endif // (_WIN32_WINNT >= 0x0600)
};
__declspec(selectany) int CTheme::m_nIsThemingSupported = -1;
///////////////////////////////////////////////////////////////////////////////
// CThemeImpl - theme support implementation
// Derive from this class to implement window with theme support.
// Example:
// class CMyThemeWindow : public CWindowImpl<CMyThemeWindow>, public CThemeImpl<CMyThemeWindow>
// {
// ...
// BEGIN_MSG_MAP(CMyThemeWindow)
// CHAIN_MSG_MAP(CThemeImpl<CMyThemeWindow>)
// ...
// END_MSG_MAP()
// ...
// };
//
// If you set theme class list, the class will automaticaly open/close/reopen theme data.
// Helper for drawing theme client edge
inline bool AtlDrawThemeClientEdge(HTHEME hTheme, HWND hWnd, HRGN hRgnUpdate = NULL, HBRUSH hBrush = NULL, int nPartID = 0, int nStateID = 0)
{
ATLASSERT(hTheme != NULL);
ATLASSERT(::IsWindow(hWnd));
CWindowDC dc(hWnd);
if(dc.IsNull())
return false;
// Get border size
int cxBorder = GetSystemMetrics(SM_CXBORDER);
int cyBorder = GetSystemMetrics(SM_CYBORDER);
if(SUCCEEDED(::GetThemeInt(hTheme, nPartID, nStateID, TMT_SIZINGBORDERWIDTH, &cxBorder)))
cyBorder = cxBorder;
RECT rect;
::GetWindowRect(hWnd, &rect);
// Remove the client edge from the update region
int cxEdge = GetSystemMetrics(SM_CXEDGE);
int cyEdge = GetSystemMetrics(SM_CYEDGE);
::InflateRect(&rect, -cxEdge, -cyEdge);
CRgn rgn;
rgn.CreateRectRgnIndirect(&rect);
if(rgn.IsNull())
return false;
if(hRgnUpdate != NULL)
rgn.CombineRgn(hRgnUpdate, rgn, RGN_AND);
::OffsetRect(&rect, -rect.left, -rect.top);
::OffsetRect(&rect, cxEdge, cyEdge);
dc.ExcludeClipRect(&rect);
::InflateRect(&rect, cxEdge, cyEdge);
::DrawThemeBackground(hTheme, dc, nPartID, nStateID, &rect, NULL);
// Use background brush too, since theme border might not cover everything
if(cxBorder < cxEdge && cyBorder < cyEdge)
{
if(hBrush == NULL)
// need conditional code because types don't match in winuser.h
#ifdef _WIN64
hBrush = (HBRUSH)::GetClassLongPtr(hWnd, GCLP_HBRBACKGROUND);
#else
hBrush = (HBRUSH)UlongToPtr(::GetClassLongPtr(hWnd, GCLP_HBRBACKGROUND));
#endif
::InflateRect(&rect, cxBorder - cxEdge, cyBorder - cyEdge);
dc.FillRect(&rect, hBrush);
}
::DefWindowProc(hWnd, WM_NCPAINT, (WPARAM)rgn.m_hRgn, 0L);
return true;
}
// Theme extended styles
#define THEME_EX_3DCLIENTEDGE 0x00000001
#define THEME_EX_THEMECLIENTEDGE 0x00000002
template <class T, class TBase = CTheme>
class CThemeImpl : public TBase
{
public:
// Data members
LPWSTR m_lpstrThemeClassList;
DWORD m_dwExtendedStyle; // theme specific extended styles
// Constructor & destructor
CThemeImpl() : m_lpstrThemeClassList(NULL), m_dwExtendedStyle(0)
{ }
~CThemeImpl()
{
delete [] m_lpstrThemeClassList;
}
// Attributes
bool SetThemeClassList(LPCWSTR lpstrThemeClassList)
{
if(m_lpstrThemeClassList != NULL)
{
delete [] m_lpstrThemeClassList;
m_lpstrThemeClassList = NULL;
}
if(lpstrThemeClassList == NULL)
return true;
int cchLen = lstrlenW(lpstrThemeClassList) + 1;
ATLTRY(m_lpstrThemeClassList = new WCHAR[cchLen]);
if(m_lpstrThemeClassList == NULL)
return false;
SecureHelper::strcpyW_x(m_lpstrThemeClassList, cchLen, lpstrThemeClassList);
return true;
}
bool GetThemeClassList(LPWSTR lpstrThemeClassList, int cchListBuffer) const
{
int cchLen = lstrlenW(m_lpstrThemeClassList) + 1;
if(cchListBuffer < cchLen)
return false;
SecureHelper::strcpyW_x(lpstrThemeClassList, cchListBuffer, m_lpstrThemeClassList);
return true;
}
LPCWSTR GetThemeClassList() const
{
return m_lpstrThemeClassList;
}
DWORD SetThemeExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
{
DWORD dwPrevStyle = m_dwExtendedStyle;
if(dwMask == 0)
m_dwExtendedStyle = dwExtendedStyle;
else
m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
return dwPrevStyle;
}
DWORD GetThemeExtendedStyle() const
{
return m_dwExtendedStyle;
}
// Operations
HTHEME OpenThemeData()
{
T* pT = static_cast<T*>(this);
ATLASSERT(::IsWindow(pT->m_hWnd));
ATLASSERT(m_lpstrThemeClassList != NULL);
if(m_lpstrThemeClassList == NULL)
return NULL;
CloseThemeData();
return TBase::OpenThemeData(pT->m_hWnd, m_lpstrThemeClassList);
}
HTHEME OpenThemeData(LPCWSTR pszClassList)
{
if(!SetThemeClassList(pszClassList))
return NULL;
return OpenThemeData();
}
HRESULT SetWindowTheme(LPCWSTR pszSubAppName, LPCWSTR pszSubIDList)
{
if(!IsThemingSupported())
return S_FALSE;
T* pT = static_cast<T*>(this);
ATLASSERT(::IsWindow(pT->m_hWnd));
return ::SetWindowTheme(pT->m_hWnd, pszSubAppName, pszSubIDList);
}
HTHEME GetWindowTheme() const
{
if(!IsThemingSupported())
return NULL;
const T* pT = static_cast<const T*>(this);
ATLASSERT(::IsWindow(pT->m_hWnd));
return ::GetWindowTheme(pT->m_hWnd);
}
HRESULT EnableThemeDialogTexture(DWORD dwFlags)
{
if(!IsThemingSupported())
return S_FALSE;
T* pT = static_cast<T*>(this);
ATLASSERT(::IsWindow(pT->m_hWnd));
return ::EnableThemeDialogTexture(pT->m_hWnd, dwFlags);
}
BOOL IsThemeDialogTextureEnabled() const
{
if(!IsThemingSupported())
return FALSE;
const T* pT = static_cast<const T*>(this);
ATLASSERT(::IsWindow(pT->m_hWnd));
return ::IsThemeDialogTextureEnabled(pT->m_hWnd);
}
HRESULT DrawThemeParentBackground(HDC hDC, const RECT* pRect = NULL)
{
if(!IsThemingSupported())
return S_FALSE;
T* pT = static_cast<T*>(this);
ATLASSERT(::IsWindow(pT->m_hWnd));
#ifdef _WTL_NEW_UXTHEME
return ::DrawThemeParentBackground(pT->m_hWnd, hDC, pRect);
#else
return ::DrawThemeParentBackground(pT->m_hWnd, hDC, (RECT*)pRect);
#endif
}
#ifdef _WTL_NEW_UXTHEME
HRESULT SetWindowThemeAttribute(WINDOWTHEMEATTRIBUTETYPE type, PVOID pvAttribute, DWORD cbAttribute)
{
if(!IsThemingSupported())
return S_FALSE;
T* pT = static_cast<T*>(this);
ATLASSERT(::IsWindow(pT->m_hWnd));
return ::SetWindowThemeAttribute(pT->m_hWnd, type, pvAttribute, cbAttribute);
}
HRESULT SetWindowThemeNonClientAttributes(DWORD dwAttributes, DWORD dwMask)
{
if(!IsThemingSupported())
return S_FALSE;
T* pT = static_cast<T*>(this);
ATLASSERT(::IsWindow(pT->m_hWnd));
WTA_OPTIONS opt = { dwAttributes, dwMask };
return ::SetWindowThemeAttribute(pT->m_hWnd, WTA_NONCLIENT, (PVOID)&opt, sizeof(opt));
}
HRESULT DrawThemeParentBackgroundEx(HDC hDC, DWORD dwFlags, const RECT* lpRect = NULL)
{
if(!IsThemingSupported())
return S_FALSE;
T* pT = static_cast<T*>(this);
ATLASSERT(::IsWindow(pT->m_hWnd));
return ::DrawThemeParentBackgroundEx(pT->m_hWnd, hDC, dwFlags, lpRect);
}
#endif // _WTL_NEW_UXTHEME
// Message map and handlers
// Note: If you handle any of these messages in your derived class,
// it is better to put CHAIN_MSG_MAP at the start of your message map.
BEGIN_MSG_MAP(CThemeImpl)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
MESSAGE_HANDLER(WM_THEMECHANGED, OnThemeChanged)
MESSAGE_HANDLER(WM_NCPAINT, OnNcPaint)
END_MSG_MAP()
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
if(m_lpstrThemeClassList != NULL)
OpenThemeData();
bHandled = FALSE;
return 1;
}
LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
CloseThemeData();
bHandled = FALSE;
return 1;
}
LRESULT OnThemeChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
CloseThemeData();
if(m_lpstrThemeClassList != NULL)
OpenThemeData();
bHandled = FALSE;
return 1;
}
LRESULT OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
T* pT = static_cast<T*>(this);
ATLASSERT(::IsWindow(pT->m_hWnd));
LRESULT lRet = 0;
bHandled = FALSE;
if(IsThemingSupported() && ((pT->GetExStyle() & WS_EX_CLIENTEDGE) != 0))
{
if((m_dwExtendedStyle & THEME_EX_3DCLIENTEDGE) != 0)
{
lRet = ::DefWindowProc(pT->m_hWnd, uMsg, wParam, lParam);
bHandled = TRUE;
}
else if((m_hTheme != NULL) && ((m_dwExtendedStyle & THEME_EX_THEMECLIENTEDGE) != 0))
{
HRGN hRgn = (wParam != 1) ? (HRGN)wParam : NULL;
if(pT->DrawThemeClientEdge(hRgn))
bHandled = TRUE;
}
}
return lRet;
}
// Drawing helper
bool DrawThemeClientEdge(HRGN hRgnUpdate)
{
T* pT = static_cast<T*>(this);
return AtlDrawThemeClientEdge(m_hTheme, pT->m_hWnd, hRgnUpdate, NULL, 0, 0);
}
};
///////////////////////////////////////////////////////////////////////////////
// Buffered Paint and Animation
#ifdef _WTL_NEW_UXTHEME
///////////////////////////////////////////////////////////////////////////////
// CBufferedPaintBase - Buffered Paint support for othe classes
class CBufferedPaintBase
{
public:
static int m_nIsBufferedPaintSupported;
CBufferedPaintBase()
{
if(IsBufferedPaintSupported())
ATLVERIFY(SUCCEEDED(::BufferedPaintInit()));
}
~CBufferedPaintBase()
{
if(IsBufferedPaintSupported())
ATLVERIFY(SUCCEEDED(::BufferedPaintUnInit()));
}
static bool IsBufferedPaintSupported()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -