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:
Obviously you should test on a Vista machine, but you can compile and run everything under XP SP2.
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:
#pragma once
#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:
#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
and m_CmdBar
to their aero::
counterpart:
#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 to CreateSimpleToolBarCtrl()
:
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 to IDC_APPICON
and IDC_APPTEXT
- Change the code in aboutdlg.h:
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 , WPARAM ,
LPARAM , BOOL& )
{
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 your FirstTest
AeroView
uses a simple WTL view class. The changes are the same for CMainFrame
and CAboutDlg
, CAeroView::Paint()
can also work in unthemed runtime environments
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 where CTabView
is replaced by aero::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 , WPARAM , LPARAM ,
BOOL& )
{
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
#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 , WPARAM ,
LPARAM , BOOL& )
{
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;
}
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 is false
don't try anything bool aero::IsComposing()
: if this is true
go ahead bool aero::IsOpaqueBlend()
: if this is true
Vista transparency is off template <class TCtrl> BOOL aero::Subclass(TCtrl& Ctrl, HWND hCtrl)
subclasses the hCtrl
control with the TCtrl
type Ctrl
only when aero::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. The Subclass()
member accepts a control ID and calls aero::Subclass()
on it's HWND
. The various DrawText()
members use ::DrawThemeTextEx()
when drawing on translucent background.
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 from CAeroBase
and WTL::CBufferedPaintImpl
and manages the translucent area through it's m_Margins
member.
The SetMargins()
and various SetOpaque()
members allow control of the translucent area.
The DoPaint()
member is called by CBufferedPaintImpl::OnPaint()
with a system buffered DC.
In turn it calls the derived class Paint(CDCHandle dc, RECT& rClient, RECT& rView, RECT& rDest)
where rClient
is the Windows client rectangle, rView
is the area inside the margins, rDest
is the painted area.
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));
}
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);
}
void Paint(CDCHandle , RECT& ,
RECT& , RECT& )
{}
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 , WPARAM ,
LPARAM , BOOL& bHandled)
{
if (IsThemingSupported())
OpenThemeData();
if (IsComposing())
::DwmExtendFrameIntoClientArea(static_cast<T*>(this)->m_hWnd,
&m_Margins);
return bHandled = FALSE;
}
LRESULT OnActivate(UINT , WPARAM ,
LPARAM , BOOL& bHandled)
{
if (!IsComposing() && IsTheming())
static_cast<T*>(this)->Invalidate(FALSE);
return bHandled = FALSE;
}
LRESULT OnCompositionChanged(UINT , WPARAM ,
LPARAM , BOOL& bHandled)
{
if (IsComposing())
SetMargins(m_Margins);
static_cast<T*>(this)->OnComposition();
return bHandled = FALSE;
}
LRESULT OnColorizationChanged(UINT , WPARAM ,
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 overriden OnBufferedPaint()
member.
The three DrawCtrlxxx()
members are helpers for the specialized drawing routines.
The AERO_CONTROL()
macro helps declaring and subclassing child controls in one step.
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())
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;
}
static LPCWSTR GetThemeName()
{
return TBase::GetWndClassName();
}
void CtrlPaint(HDC hdc, RECT& , RECT& rPaint)
{
DefCtrlPaint(hdc, rPaint);
}
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;
}
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 , RECT& )
{
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 , WPARAM ,
LPARAM , BOOL& bHandled)
{
if(!IsComposing())
return DefWindowProc();
else
return bHandled = FALSE;
}
};
#define AERO_CONTROL(type, name, id)\
static aero::type name;\
Subclass(name, id);
aero::CCtrlImpl
enables Aero drawing on top of an existing TCtrlImpl
. The DoPaint()
member may be overridden in derived classes to call TCtrlImpl
relevant code.
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 common CAeroView
and adjusted the article