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
CFrameWindowImpl
andm_CmdBar
to 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.
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);
- 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); }
To get an Aero About dialog
- In the resource editor, open the
IDD_ABOUTBOX
dialog and change the icon and text control IDs toIDC_APPICON
andIDC_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:
AeroFrame
is the same as yourFirstTest
AeroView
uses a simple WTL view class. The changes are the same forCMainFrame
andCAboutDlg
,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
CAeroView
class whereCTabView
is replaced byaero::CTabView
. - 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); //...
- 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 isfalse
don't try anythingbool aero::IsComposing()
: if this istrue
go aheadbool aero::IsOpaqueBlend()
: if this istrue
Vista transparency is offtemplate <class TCtrl> BOOL aero::Subclass(TCtrl& Ctrl, HWND hCtrl)
subclasses thehCtrl
control with theTCtrl
typeCtrl
only whenaero::IsSupported()
The base classes
The base classes are the engine of the library.
aero::CAeroBase
gives 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::CAeroImpl
derives fromCAeroBase
andWTL::CBufferedPaintImpl
and manages the translucent area through it'sm_Margins
member.
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)
whererClient
is the Windows client rectangle,rView
is the area inside the margins,rDest
is 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::CCtrl
is 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::CCtrlImpl
enables Aero drawing on top of an existingTCtrlImpl
. TheDoPaint()
member may be overridden in derived classes to callTCtrlImpl
relevant 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::CEdit
aero::CTabCtrl
aero::CToolBarCtrl
aero::CStatusBarCtrl
aero::CListBox
aero::CComboBox
aero::CStatic
aero::CButton
Classes derived from aero::CCtrlImpl
:
aero::CCommandBarCtrl
aero::CTabView
aero::CPaneContainer
aero::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::CTabView
and samples commonCAeroView
and adjusted the article