用 WTL 喝一杯!






4.99/5 (23投票s)
为您的原生 (WTL) 应用程序启用 Aero glass 并保持向后兼容。
引言
抱歉,这里没什么可喝的。
但是,如果您喜欢 Vista Aero 玻璃效果并希望在您的(现有或新的)WTL 应用程序中启用它,本文旨在(并希望)帮助您。
原生 API 可以很容易地投入使用,并且 aero 命名空间允许对现有软件进行简单修改。
本文由两部分组成
- 入门指南将介绍一些
WTL::aero::
类的用法和产生效果 - WTL::aero 命名空间内部是对工具集的更详细描述
参考文献
这里使用的原生 API 的主要文档是 MSDN 桌面窗口管理器 部分。
您可以在 CodeProject 中找到 Michael Dunn 的文章:C++ 中的 Vista 炫酷功能:在 UI 中使用玻璃效果,以及 Kenny Kerr 的博客 桌面窗口管理器 和 控件和桌面窗口管理器。
在我准备这篇文章时,Stefan Kuhr 发表了一篇 MFC 姊妹文章 向旧版 Windows 应用程序添加或改造 Aero 玻璃效果。
必备组件
要阅读本文,您需要在计算机上正确安装以下软件
- Visual Studio 2005 (或 VCExpress) SP1 以及 Visual Studio 2005 Service Pack 1 更新(适用于 Windows Vista),如果您的开发系统运行在 Vista 下
- Microsoft® Windows® 软件开发工具包(适用于 Windows Vista™)
- WTL 8.0 Beta2 分发版和随附的 AppWizard
显然您应该在 Vista 机器上测试,但您可以在 XP SP2 下编译和运行所有内容。
入门指南
对于任何启用 aero 的应用程序
使用 WTL AppWizard 创建一个简单的 FirstTest 应用程序:只需在第一个向导屏幕上单击“下一步”,取消选中“使用视图”框,然后单击“完成”。现在进行一些简单的更改,这些步骤总是需要完成的
- 更改 stdafx.h 中的常量
// stdafx.h : include file for the standard system include files, // or project specific include files that are used frequently, but // are changed infrequently #pragma once // Change these values to use different versions #define WINVER 0x0600 #define _WIN32_WINNT 0x0600 #define _WIN32_IE 0x0700 #define _RICHEDIT_VER 0x0200 // ...
- 将 toolbar.bmp 从 WtlAero.zip 解压到您的项目文件夹 FirstTest\res\ 中。
- 将 WtlAero.h 从 WtlAero.zip 解压到您的项目文件夹 FirstTest\ 中,并修改 FirstTest.cpp 以包含它
// FirstTest.cpp : main source file for FirstTest.exe #include "stdafx.h" #include<atlframe.h> #include <atlctrls.h> #include <atldlgs.h> #include <atlctrlw.h> #include "WtlAero.h" #include "resource.h" // ...
- 在 MainFrm.h 中,将
CFrameWindowImpl
和m_CmdBar
的定义更改为它们对应的aero::
版本// MainFrm.h : interface of the CMainFrame class // //////////////////////////////////////////////////////////////// #pragma once class CMainFrame : public aero::CFrameWindowImpl<CMainFrame>, public CUpdateUI<CMainFrame>, public CMessageFilter, public CIdleHandler { public: DECLARE_FRAME_WND_CLASS(NULL, IDR_MAINFRAME) CFirstTestView m_view; aero::CCommandBarCtrl m_CmdBar; // ...
- 在消息映射中更改基类定义,并将其移到
OnCreate()
处理程序之前
BEGIN_MSG_MAP(CMainFrame) CHAIN_MSG_MAP(aero::CFrameWindowImpl<CMainFrame>) MESSAGE_HANDLER(WM_CREATE, OnCreate) MESSAGE_HANDLER(WM_DESTROY, OnDestroy) COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit) COMMAND_ID_HANDLER(ID_FILE_NEW, OnFileNew) COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR, OnViewToolBar) COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar) COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout) CHAIN_MSG_MAP(CUpdateUI<CMainFrame>) END_MSG_MAP()
- 如果您想在 XP 或 W2k 下运行应用程序,请为 uxtheme.dll 和 dwmapi.dll 设置延迟加载
- 就这样。编译并运行。您应该会得到这个。
让我们用这个首次测试做更多的事情
- 要将工具栏更改为透明的,只需在
CMainFrame::OnCreate()
中替换对CreateSimpleToolBarCtrl()
的调用HWND hWndToolBar = CreateAeroToolBarCtrl(m_hWnd, IDR_MAINFRAME, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);
- 要进行一些绘图,请在
CMainFrame
中插入此成员void Paint(CDCHandle dc, RECT& rClient, RECT& rView, RECT& rDest) { CLogFont lf; GetThemeSysFont(TMT_MSGBOXFONT, &lf); lf.lfHeight *= 3; CFont f = lf.CreateFontIndirect(); HFONT hfOld = dc.SelectFont(f); DrawText(dc, L"Hello Aero", &rClient, DT_CENTER | DT_VCENTER | DT_SINGLELINE); dc.SelectFont(hfOld); }
获取 Aero 关于对话框
- 在资源编辑器中,打开
IDD_ABOUTBOX
对话框并将图标和文本控件 ID 更改为IDC_APPICON
和IDC_APPTEXT
- 更改 aboutdlg.h 中的代码
// aboutdlg.h : interface of the CAboutDlg class //... class CAboutDlg : public aero::CDialogImpl<CAboutDlg > { public: enum { IDD = IDD_ABOUTBOX }; BEGIN_MSG_MAP(CAboutDlg) CHAIN_MSG_MAP(aero::CDialogImpl<CAboutDlg >) MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) COMMAND_ID_HANDLER(IDOK, OnCloseCmd) COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd) END_MSG_MAP() //... LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { CenterWindow(GetParent()); AERO_CONTROL(CStatic, m_Icon, IDC_APPICON) AERO_CONTROL(CStatic, m_Text, IDC_APPTEXT) AERO_CONTROL(CButton, m_OK, IDOK) return TRUE; } //...
Aero 示例
在 AeroSamples 项目中,您可以找到其他 aero 适配的 AppWizard 应用程序
AeroFrame
与您的FirstTest
相同AeroView
使用一个简单的 WTL 视图类。对CMainFrame
和CAboutDlg
的更改是相同的,CAeroView::Paint()
也可以在未应用主题的运行时环境中工作// AeroView.h : interface of the CAeroView class // ////////////////////////////////////////////////////////////// class CAeroView : public aero::CWindowImpl<CAeroView> { public: DECLARE_WND_CLASS(NULL) BOOL PreTranslateMessage(MSG* pMsg) { pMsg; return FALSE; } void Paint(CDCHandle dc, RECT& rClient, RECT& rView, RECT& rDest) { CLogFont lf; if (IsTheming()) { GetThemeSysFont(TMT_MSGBOXFONT, &lf); if (!aero::IsSupported()) DrawThemeBackground(dc, 1, 1, &rClient, &rDest); } else { NONCLIENTMETRICS ncm = { sizeof(NONCLIENTMETRICS) }; SystemParametersInfo ( SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, false ); lf = ncm.lfMessageFont; dc.FillSolidRect(&rClient, GetSysColor(COLOR_WINDOW)); } lf.lfHeight *= 3; CFont f = lf.CreateFontIndirect(); HFONT hfOld = dc.SelectFont(f); DrawText(dc, L"Hello Aero", &rClient, DT_CENTER | DT_VCENTER | DT_SINGLELINE); dc.SelectFont(hfOld); } BEGIN_MSG_MAP(CAeroView) CHAIN_MSG_MAP(aero::CWindowImpl<CAeroView>) END_MSG_MAP() };
- AeroTab 是一个“AppWizard 选项卡视图应用程序”,使用与
CAeroView
相同的类,其中CTabView
被aero::CTabView
替换。 - AeroSplit 是一个“AppWizard 资源管理器应用程序”,在 MainFrm.h 中的向导生成代码中进行了一些额外更改
class CMainFrame : public aero::CFrameWindowImpl<CMainFrame>, public CUpdateUI<CMainFrame>, public CMessageFilter, public CIdleHandler { public: DECLARE_FRAME_WND_CLASS(NULL, IDR_MAINFRAME) aero::CSplitterWindow m_splitter; aero::CPaneContainer m_pane; aero::CCtrl<CTreeViewCtrl> m_treeview; CAeroView m_view; aero::CCommandBarCtrl m_CmdBar; //... LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { //... m_treeview.SetWindowTheme(L"explorer", NULL); HTREEITEM hti = m_treeview.InsertItem(L"Test", TVI_ROOT, TVI_LAST); m_treeview.InsertItem(L"Child Test", hti, TVI_LAST); //...
- AeroDialog 是一个“模态对话框 AppWizard 应用程序”,在对话框编辑器中添加了一些控件
// MainDlg.h : interface of the CMainDlg class // ////////////////////////////////////////////////////////////////////// #pragma once class CMainDlg : public aero::CDialogImpl<CMainDlg> { public: enum { IDD = IDD_MAINDLG }; BEGIN_MSG_MAP(CMainDlg) CHAIN_MSG_MAP(aero::CDialogImpl<CMainDlg>) //... LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { //... AERO_CONTROL(CButton, m_OK, IDOK) AERO_CONTROL(CButton, m_Cancel, IDCANCEL) AERO_CONTROL(CButton, m_About, ID_APP_ABOUT) AERO_CONTROL(CEdit, m_Edit, IDC_EDIT1) AERO_CONTROL(CButton, m_C1, IDC_CHECK1) AERO_CONTROL(CButton, m_C2, IDC_CHECK2) AERO_CONTROL(CButton, m_R1, IDC_RADIO1) AERO_CONTROL(CButton, m_R2, IDC_RADIO2) AERO_CONTROL(CButton, m_Group, IDC_GROUP) AERO_CONTROL(CListBox, m_LB, IDC_LIST1) AERO_CONTROL(CComboBox, m_CB, IDC_COMBO1) m_LB.AddString(L"TEST Item"); m_CB.AddString(L"Combo Test"); SetOpaqueUnder(IDC_MONTHCALENDAR1); return TRUE; } //...
WTL::aero 命名空间内部
WTL::aero
命名空间提供了使任何 WTL 应用程序支持 aero 玻璃效果的工具集。
命名空间函数
这些函数执行运行时测试以实现向后兼容性。
bool aero::IsSupported()
:如果此函数返回false
,则不要尝试任何操作bool aero::IsComposing()
:如果此函数返回true
,则继续执行bool aero::IsOpaqueBlend()
:如果此函数返回true
,则 Vista 透明度已关闭template <class TCtrl> BOOL aero::Subclass(TCtrl& Ctrl, HWND hCtrl)
仅当aero::IsSupported()
时才使用TCtrl
类型Ctrl
对hCtrl
控件进行子类化
基类
基类是库的引擎。
aero::CAeroBase
使其派生类可以访问 Theme API。Subclass()
成员接受一个控件 ID,并对其HWND
调用aero::Subclass()
。各种DrawText()
成员在半透明背景上绘图时使用::DrawThemeTextEx()
。/////////////////////////////////////////////////////////////////////// // aero::CAeroBase - Base class for Aero translucency (when available) template <class T> class CAeroBase : public WTL::CThemeImpl<T> { public: CAeroBase(LPCWSTR lpstrThemeClassList = L"globals") { SetThemeClassList(lpstrThemeClassList); } bool IsTheming() const { return m_hTheme != 0; } template <class TCtrl> BOOL Subclass(TCtrl& Ctrl, INT idCtrl) { return aero::Subclass(Ctrl, static_cast<T*>(this)->GetDlgItem(idCtrl)); } bool DrawPartText(HDC dc, int iPartID, int iStateID, LPCTSTR pStr, LPRECT prText, UINT uFormat, DTTOPTS &dto) { HRESULT hr = S_FALSE; if(IsTheming()) if (IsSupported()) hr = DrawThemeTextEx (dc, iPartID, iStateID, pStr, -1, uFormat, prText, &dto ); else hr = DrawThemeText(dc, iPartID, iStateID, pStr, -1, uFormat, 0, prText); else hr = CDCHandle(dc).DrawText(pStr, -1, prText, uFormat) != 0 ? S_OK : S_FALSE; return SUCCEEDED(hr); } bool DrawPartText(HDC dc, int iPartID, int iStateID, LPCTSTR pStr, LPRECT prText, UINT uFormat, DWORD dwFlags = DTT_COMPOSITED, int iGlowSize = 0) { DTTOPTS dto = {sizeof(DTTOPTS)}; dto.dwFlags = dwFlags; dto.iGlowSize = iGlowSize; return DrawPartText(dc, iPartID, iStateID, pStr, prText, uFormat, dto); } bool DrawText(HDC dc, LPCTSTR pStr, LPRECT prText, UINT uFormat, DTTOPTS &dto) { return DrawPartText(dc, 1, 1, pStr, prText, uFormat, dto); } bool DrawText(HDC dc, LPCTSTR pStr, LPRECT prText, UINT uFormat, DWORD dwFlags = DTT_COMPOSITED, int iGlowSize = 0) { return DrawPartText(dc, 1, 1, pStr, prText, uFormat, dwFlags, iGlowSize); } };
aero::CAeroImpl
派生自CAeroBase
和WTL::CBufferedPaintImpl
,并通过其m_Margins
成员管理半透明区域。SetMargins()
和各种SetOpaque()
成员允许控制半透明区域。DoPaint()
成员由CBufferedPaintImpl::OnPaint()
使用系统缓冲的 DC 调用。
反过来,它会调用派生类的Paint(CDCHandle dc, RECT& rClient, RECT& rView, RECT& rDest)
,其中rClient
是 Windows 客户端矩形,rView
是边距内的区域,rDest
是绘制区域。///////////////////////////////////////////////////////////////////// // aero::CAeroImpl - implementation of Aero translucency (when available) template <class T> class CAeroImpl : public WTL::CBufferedPaintImpl<T>, public CAeroBase<T> { public: CAeroImpl(LPCWSTR lpstrThemeClassList = L"globals") : CAeroBase<T>(lpstrThemeClassList) { m_PaintParams.dwFlags = BPPF_ERASE; MARGINS m = {-1}; m_Margins = m; } MARGINS m_Margins; bool SetMargins(MARGINS& m) { m_Margins = m; T* pT = static_cast<T*>(this); return pT->IsWindow() && IsComposing() ? SUCCEEDED(DwmExtendFrameIntoClientArea (pT->m_hWnd, &m_Margins)) : true; } bool SetOpaque(bool bOpaque = true) { MARGINS m = {bOpaque - 1}; return SetMargins(m); } bool SetOpaque(RECT &rOpaque) { T* pT = static_cast<T*>(this); RECT rClient; pT->GetClientRect(&rClient); MARGINS m = {rOpaque.left, rClient.right - rOpaque.right, rOpaque.top, rClient.bottom - rOpaque.bottom}; return SetMargins(m); } bool SetOpaqueUnder(ATL::CWindow wChild) { T* pT = static_cast<T*>(this); ATLASSERT(wChild.IsWindow()); ATLASSERT(pT->IsChild(wChild)); RECT rChild; wChild.GetWindowRect(&rChild); pT->ScreenToClient(&rChild); return SetOpaque(rChild); } bool SetOpaqueUnder(UINT uID) { return SetOpaqueUnder(static_cast<T*>(this)->GetDlgItem(uID)); } // implementation void DoPaint(CDCHandle dc, RECT& rDest) { T* pT = static_cast<T*>(this); RECT rClient; pT->GetClientRect(&rClient); RECT rView = {rClient.left + m_Margins.cxLeftWidth, rClient.top + m_Margins.cyTopHeight, rClient.right - m_Margins.cxRightWidth, rClient.bottom - m_Margins.cyBottomHeight}; if (!IsComposing()) if (IsTheming()) pT->DrawThemeBackground(dc, WP_FRAMEBOTTOM, pT->m_hWnd == GetFocus() ? FS_ACTIVE : FS_INACTIVE, &rClient, &rDest); else dc.FillSolidRect(&rClient, ::GetSysColor(COLOR_MENUBAR)); if ((m_Margins.cxLeftWidth != -1) && !::IsRectEmpty(&rView)) { dc.FillSolidRect(&rView, ::GetSysColor(COLOR_WINDOW)); if (!m_BufferedPaint.IsNull()) m_BufferedPaint.MakeOpaque(&rView); } else ::SetRectEmpty(&rView); pT->Paint(dc, rClient, rView, rDest); } // Overrideables void Paint(CDCHandle /*dc*/, RECT& /*rClient*/, RECT& /*rView*/, RECT& /*rDest*/) {} void OnComposition() {} void OnColorization() {} BEGIN_MSG_MAP(CAeroImpl) CHAIN_MSG_MAP(CThemeImpl<T>) MESSAGE_HANDLER(WM_CREATE, OnCreate) MESSAGE_HANDLER(WM_ACTIVATE, OnActivate) MESSAGE_HANDLER(WM_DWMCOMPOSITIONCHANGED, OnCompositionChanged) MESSAGE_HANDLER(WM_DWMCOLORIZATIONCOLORCHANGED, OnColorizationChanged) CHAIN_MSG_MAP(CBufferedPaintImpl<T>) END_MSG_MAP() LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) { if (IsThemingSupported()) OpenThemeData(); if (IsComposing()) ::DwmExtendFrameIntoClientArea(static_cast<T*>(this)->m_hWnd, &m_Margins); return bHandled = FALSE; } LRESULT OnActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) { if (!IsComposing() && IsTheming()) static_cast<T*>(this)->Invalidate(FALSE); return bHandled = FALSE; } LRESULT OnCompositionChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) { if (IsComposing()) SetMargins(m_Margins); static_cast<T*>(this)->OnComposition(); return bHandled = FALSE; } LRESULT OnColorizationChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) { static_cast<T*>(this)->OnColorization(); return bHandled = FALSE; } };
适配器类
这些类将 aero 玻璃效果应用于现有控件。
aero::CCtrl
用于对系统和通用控件进行子类化。
有两个成员用于专门化:GetThemeName()
返回控件的主题名称,用于在创建或子类化时打开,CtrlPaint(HDC hdc, RECT& rCtrl, RECT& rPaint)
通过重写的OnBufferedPaint()
成员进行绘图时调用。
三个DrawCtrlxxx()
成员是专门绘图例程的辅助函数。AERO_CONTROL()
宏有助于一步声明和子类化子控件。////////////////////////////////////////////////////////////////////////// // aero::CCtrl - implementation of Aero drawing for system controls // Note: This class is intended for system themed control specializations template<class TBase> class CCtrl : public WTL::CBufferedPaintWindowImpl<CCtrl<TBase>, TBase>, public CAeroBase<CCtrl<TBase> > { public: typedef CAeroBase<CCtrl<TBase> > baseAero; typedef WTL::CBufferedPaintWindowImpl<CCtrl<TBase>, TBase> baseWindow; DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName()) // creation and initialization CCtrl(LPCWSTR lpstrThemeClassList = GetThemeName()) : baseAero(lpstrThemeClassList) { m_PaintParams.dwFlags = BPPF_ERASE; } CCtrl<TBase>& operator =(HWND hWnd) { TBase::m_hWnd = hWnd; return *this; } HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, ATL::_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) { TBase baseCtrl; if (baseCtrl.Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam) != NULL) SubclassWindow(baseCtrl.m_hWnd); return m_hWnd; } BOOL SubclassWindow(HWND hWnd) { ATLASSERT(IsSupported()); if(baseWindow::SubclassWindow(hWnd)) OpenThemeData(); return m_hWnd != NULL; } // specializables static LPCWSTR GetThemeName() { return TBase::GetWndClassName(); } void CtrlPaint(HDC hdc, RECT& /*rCtrl*/, RECT& rPaint) { DefCtrlPaint(hdc, rPaint); } // operations void DefCtrlPaint(HDC hdc, RECT& rPaint, bool bEraseBkGnd = false) { if (bEraseBkGnd) DefWindowProc(WM_ERASEBKGND, (WPARAM)hdc, NULL); DefWindowProc(WM_PAINT, (WPARAM)hdc, 0); m_BufferedPaint.MakeOpaque(&rPaint); } BOOL DrawCtrlBackground(HDC hdc, int nPartID, int nStateID, RECT &rCtrl, RECT &rPaint) { return SUCCEEDED(DrawThemeBackground(hdc, nPartID, nStateID, &rCtrl, &rPaint)); } BOOL DrawCtrlEdge(HDC hdc, int nPartID, int nStateID, RECT &rCtrl, UINT uEdge = EDGE_ETCHED, UINT uFlags = BF_RECT, LPRECT pContentRect = NULL) { return SUCCEEDED(DrawThemeEdge(hdc, nPartID, nStateID, &rCtrl, uEdge, uFlags, pContentRect)); } BOOL DrawCtrlText(CDCHandle dc, int nPartID, int nStateID, UINT uFormat, RECT &rCtrl, HFONT hFont = 0, DWORD dwFlags = DTT_COMPOSITED, int iGlowSize = 0) { HRESULT hr; RECT rText; hr = GetThemeBackgroundContentRect (dc, nPartID, nStateID, &rCtrl, &rText); MARGINS m = {0}; hr = GetThemeMargins(dc, nPartID, nStateID, TMT_CONTENTMARGINS, &rText, &m); rText.left += m.cxLeftWidth; rText.right -= m.cxRightWidth; int iLength = GetWindowTextLength(); if (iLength > 0) { CTempBuffer<wchar /> sText(++iLength); GetWindowText(sText, iLength); HFONT hf = dc.SelectFont(hFont == 0 ? GetFont() : hFont); hr = DrawPartText(dc, nPartID, nStateID, sText, &rText , uFormat, dwFlags, iGlowSize); dc.SelectFont(hf); } return SUCCEEDED(hr) && iLength > 0; } // implementation void DoBufferedPaint(HDC hdc, RECT& rPaint) { HDC hDCPaint = NULL; RECT rCtrl; GetClientRect(&rCtrl); m_BufferedPaint.Begin(hdc, &rCtrl, m_dwFormat, &m_PaintParams, &hDCPaint); ATLASSERT(hDCPaint != NULL); CtrlPaint(hDCPaint, rCtrl, rPaint); m_BufferedPaint.End(); } void DoPaint(HDC /*hdc*/, RECT& /*rCtrl*/) { DefWindowProc(); } BEGIN_MSG_MAP(CCtrl) MESSAGE_HANDLER(WM_PAINT, OnPaintMsg) MESSAGE_HANDLER(WM_ERASEBKGND, OnPaintMsg) CHAIN_MSG_MAP(baseAero) CHAIN_MSG_MAP(baseWindow) END_MSG_MAP() LRESULT OnPaintMsg(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) { if(!IsComposing()) return DefWindowProc(); else return bHandled = FALSE; } }; ///////////////////////////////////////////////////////////////////////// // Macro declaring and subclassing a control // (static declaration to use in OnCreate or OnInitDialog members) #define AERO_CONTROL(type, name, id)\ static aero::type name;\ Subclass(name, id);
aero::CCtrlImpl
在现有TCtrlImpl
之上启用 Aero 绘图。DoPaint()
成员可以在派生类中重写以调用TCtrlImpl
相关代码。////////////////////////////////////////////////////////////////////////// // aero::CCtrlImpl - implementation of Aero drawing for user and WTL // defined controls // Note: This class is intended for derivation template <class T, class TCtrlImpl, bool t_bOpaque = false> class ATL_NO_VTABLE CCtrlImpl : public TCtrlImpl, public CAeroImpl<T> { public: DECLARE_WND_SUPERCLASS(NULL, TCtrlImpl::GetWndClassName()) CCtrlImpl(LPCWSTR lpstrThemeClassList = L"window") : CAeroImpl(lpstrThemeClassList) { m_PaintParams.dwFlags = BPPF_ERASE; } void DoPaint(HDC hdc, RECT& rect) { BOOL bHandled = TRUE; TCtrlImpl::OnPaint(WM_PAINT, (WPARAM) hdc, NULL, bHandled); if (t_bOpaque) m_BufferedPaint.MakeOpaque(&rect); } BEGIN_MSG_MAP(CCtrlImpl) CHAIN_MSG_MAP(CAeroImpl<T>) CHAIN_MSG_MAP(TCtrlImpl) END_MSG_MAP() };
替换类
这些是启用 Aero 的类,它们替换了具有相同名称的 WTL::
或 ATL::
类。它们用于第一部分的入门指南。
可派生类:这些类派生自 aero::CAeroImpl
aero::CWindowImpl< T, TBase, TWinTraits >
aero::CDialogImpl<T, TBase>
aero::CFrameWindowImpl<T, TBase, TWinTraits>
aero::CPropertySheetImpl<T, TBase>
aero::CPropertyPageImpl<T, TBase>
aero::CSplitterImpl<T, t_bVertical>
aero::CSplitterWindowImpl<T, t_bVertical, TBase, TWinTraits>
aero::CSplitterWindowT<t_bVertical>
从 aero::CCtrl
派生或专门化的类
aero::CEdit
aero::CTabCtrl
aero::CToolBarCtrl
aero::CStatusBarCtrl
aero::CListBox
aero::CComboBox
aero::CStatic
aero::CButton
从 aero::CCtrlImpl
派生的类
aero::CCommandBarCtrl
aero::CTabView
aero::CPaneContainer
aero::CPrintPreviewWindow
结论
在现有的原生代码应用程序中启用漂亮的 Aero 玻璃效果并非难事。干杯!
修订历史
- 2007 年 5 月 31 日发布
- 2007 年 6 月 5 日 修复了
aero::CTabView
和示例通用CAeroView
中的向后兼容性问题,并调整了文章