Have a glass with WTL!
Introduction
Sorry, nothing to drink in here.
But if you like the Vista Aero glass effect and wish to enable it in your (existing or new) WTL applications, this article is intended to (and hopefully will) help you.
The native APIs can easily be put at work and the aero namespace allows simple adaptation of existing software.
This article is made up of two parts:
- Guided tour is a walk around some of the
WTL::aero::classes usage and resulting effects - Inside the WTL::aero namespace is a more detailed description of the toolset
References
The main documentation about the native APIs used here is the MSDN Desktop Window Manager section.
You can find in CodeProject Michael Dunn's article : Vista Goodies in C++: Using Glass in Your UI, and in Kenny Kerr's blog The Desktop Window Manager and Controls and the Desktop Window Manager.
While I was preparing this article a MFC cousin article Adding or Retrofitting Aero Glass into Legacy Windows Applications was published by Stefan Kuhr.
Prerequisites
To follow this article you need to have correctly installed on your computer:
- Visual Studio 2005 (or VCExpress) SP1 and Visual Studio 2005 Service Pack 1 Update for Windows Vista if your development system runs under Vista
- The Microsoft® Windows® Software Development Kit for Windows Vista™
- The WTL 8.0 Beta2 distribution and the included AppWizard
Obviously you should test on a Vista machine, but you can compile and run everything under XP SP2.
Guided tour
For any aero enabled application
Using the WTL AppWizard create a simple FirstTest application: just click next on the first wizard screen, uncheck the 'Use view' box and click Finish. Now make some simple changes, these steps are always to be done:
- Change the constants in 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 // ...
- Extract toolbar.bmp from WtlAero.zip into your project folder FirstTest\res\ .
- Extract WtlAero.h from
WtlAero.zip into your project folder FirstTest\ and change
FirstTest.cpp to include it:
// 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" // ...
- In MainFrm.h change the definitions of
CFrameWindowImplandm_CmdBarto theiraero::counterpart:// 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; // ...
- Change the base class definition in the message map, and move it BEFORE the
OnCreate()handler:
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()
- If you want to run the application under XP or W2k set delay loading for
uxtheme.dll and dwmapi.dll:
- That's all. Compile and run. You should get this.
![Screenshot - FirstTest.jpg]()
Let's do a little more with this first test:
- To change the toolbar to a transparent one just replace in
CMainFrame::OnCreate()the call toCreateSimpleToolBarCtrl():HWND hWndToolBar = CreateAeroToolBarCtrl(m_hWnd, IDR_MAINFRAME, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);
![Screenshot - FirstTestTB.jpg]()
- To do some drawing, insert this member in
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); }
![Screenshot - FirstTestHello.jpg]()
To get an Aero About dialog
- In the resource editor, open the
IDD_ABOUTBOXdialog and change the icon and text control IDs toIDC_APPICONandIDC_APPTEXT - Change the code in 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; } //...
AeroSamples
In the AeroSamples project, you can find other aero adapted AppWizard applications:
AeroFrameis the same as yourFirstTestAeroViewuses a simple WTL view class. The changes are the same forCMainFrameandCAboutDlg,CAeroView::Paint()can also work in unthemed runtime environments// 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 is an "AppWizard Tab View Application" using the same
CAeroViewclass whereCTabViewis replaced byaero::CTabView.![Screenshot - AeroTab.jpg]()
- AeroSplit is an "AppWizard Explorer Application" with a few more changes from the Wizard generated code in
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); //...
![Screenshot - AeroSplit.jpg]()
- AeroDialog is a "modal dialog AppWizard application" with some controls added in the dialog editor
// 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; } //...
Inside the WTL::aero namespace
The WTL::aero namespace provides the toolset enabling any WTL application for aero glass.
Namespace functions
These functions perform the runtime tests allowing backwards compatibility.
bool aero::IsSupported(): if this isfalsedon't try anythingbool aero::IsComposing(): if this istruego aheadbool aero::IsOpaqueBlend(): if this istrueVista transparency is offtemplate <class TCtrl> BOOL aero::Subclass(TCtrl& Ctrl, HWND hCtrl)subclasses thehCtrlcontrol with theTCtrltypeCtrlonly whenaero::IsSupported()
The base classes
The base classes are the engine of the library.
aero::CAeroBasegives it's derived classes access to the Theme API. TheSubclass()member accepts a control ID and callsaero::Subclass()on it'sHWND. The variousDrawText()members use::DrawThemeTextEx()when drawing on translucent background./////////////////////////////////////////////////////////////////////// // 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::CAeroImplderives fromCAeroBaseandWTL::CBufferedPaintImpland manages the translucent area through it'sm_Marginsmember.
TheSetMargins()and variousSetOpaque()members allow control of the translucent area.
TheDoPaint()member is called byCBufferedPaintImpl::OnPaint()with a system buffered DC.
In turn it calls the derived classPaint(CDCHandle dc, RECT& rClient, RECT& rView, RECT& rDest)whererClientis the Windows client rectangle,rViewis the area inside the margins,rDestis the painted area.///////////////////////////////////////////////////////////////////// // 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; } };
The adapter classes
These classes apply the aero glass effect to existing controls.
aero::CCtrlis used to subclass system and common controls.
Two members are intended for specialization:GetThemeName()returns the control's theme name for opening at creation or subclassing time,CtrlPaint(HDC hdc, RECT& rCtrl, RECT& rPaint)is called for painting through an overridenOnBufferedPaint()member.
The threeDrawCtrlxxx()members are helpers for the specialized drawing routines.
TheAERO_CONTROL()macro helps declaring and subclassing child controls in one step.////////////////////////////////////////////////////////////////////////// // 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::CCtrlImplenables Aero drawing on top of an existingTCtrlImpl. TheDoPaint()member may be overridden in derived classes to callTCtrlImplrelevant code.////////////////////////////////////////////////////////////////////////// // 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() };
The replacement classes
These are Aero enabled classes that replace the WTL:: or ATL::
classes with same name. They are used in the first part guided tour.
Derivable classes: these classes derive from 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>
Classes derived or specialized from aero::CCtrl:
aero::CEditaero::CTabCtrlaero::CToolBarCtrlaero::CStatusBarCtrlaero::CListBoxaero::CComboBoxaero::CStaticaero::CButton
Classes derived from aero::CCtrlImpl:
aero::CCommandBarCtrlaero::CTabViewaero::CPaneContaineraero::CPrintPreviewWindow
Conclusion
Enabling the nice Aero glass on existing native code applications is not so difficult. Cheers!
Revision history
- 5.31.2007 Released
- 6.5.2007 Fixed backwards compatibility issues in
aero::CTabViewand samples commonCAeroViewand adjusted the article




浙公网安备 33010602011771号