-
2006-12-06
Part II - WTL GUI Base Classes - [WTL]
WTL for MFC Programmers, Part II - WTL GUI Base Classes
WTL Overview
The WTL classes can be divided into a few major categories:
1. Frame window implementation - CFrameWindowImpl, CMDIFrameWindowImpl
2. Control wrappers - CButton, CListViewCtrl
3. GDI wrappers - CDC, CMenu
4. Special UI features - CSplitterWindow, CUpdateUI, CDialogResize, CCustomDraw
5. Utility classes and macros - CString, CRect, BEGIN_MSG_MAP_EXBeginning a WTL EXE
#define STRICT
#define WIN32_LEAN_AND_MEAN
#define _WTL_USE_CSTRING
#include // base ATL classes
#include // base WTL classes
extern CAppModule _Module; // WTL version of CComModule
#include // ATL GUI classes
#include // WTL frame window classes
#include // WTL utility classes like CString
#include // WTL enhanced msg map macros// MyWindow.h:
class CMyWindow : public CFrameWindowImpl
{
public:
DECLARE_FRAME_WND_CLASS(_T("First WTL window"), IDR_MAINFRAME);
BEGIN_MSG_MAP(CMyWindow)
CHAIN_MSG_MAP(CFrameWindowImpl)
END_MSG_MAP()
};
DECLARE_FRAME_WND_CLASS takes two parameters, the window class name (which can be NULL to have ATL generate a name for you), and a resource ID. WTL will look for an icon, menu, and accelerator table with that ID, and load them when the window is created. It will also look for a string with that ID and use it as the window title. We also chain messages to CFrameWindowImpl as it has some message handlers of its own (most notably WM_SIZE and WM_DESTROY).For ATL 7.0/7.1, you can use BEGIN_MSG_MAP for CWindowImpl/CDialogImpl derived classes, but must use BEGIN_MSG_MAP_EX for classes that don't derive from CWindowImpl/CDialogImpl
(The _EX macro is needed in VC 6 because it contains some code that the message handler macros use. For the sake of readability, I won't show the VC 6 and VC 7 versions of the header file here, since they only differ in that one macro. Just keep in mind that the _EX macro is not needed in VC 7.)class CMyWindow : public CFrameWindowImpl
{
public:
BEGIN_MSG_MAP_EX(CMyWindow)
MSG_WM_CREATE(OnCreate)
CHAIN_MSG_MAP(CFrameWindowImpl)
END_MSG_MAP()
LRESULT OnCreate(LPCREATESTRUCT lpcs)
{
SetTimer ( 1, 1000 );
SetMsgHandled(false);
return 0;
}
};class CMyWindow : public CFrameWindowImpl
{
public:
BEGIN_MSG_MAP_EX(CMyWindow)
MSG_WM_CREATE(OnCreate)
MSG_WM_DESTROY(OnDestroy)
MSG_WM_TIMER(OnTimer)
MSG_WM_ERASEBKGND(OnEraseBkgnd)
CHAIN_MSG_MAP(CFrameWindowImpl)
END_MSG_MAP()
LRESULT OnEraseBkgnd ( HDC hdc )
{
CDCHandle dc(hdc);
CRect rc;
SYSTEMTIME st;
CString sTime;
// Get our window's client area.
GetClientRect ( rc );
// Build the string to show in the window.
GetLocalTime ( &st );
sTime.Format ( _T("The time is %d:%02d:%02d"),
st.wHour, st.wMinute, st.wSecond );
// Set up the DC and draw the text.
dc.SaveDC();
dc.SetBkColor ( RGB(255,153,0) );
dc.SetTextColor ( RGB(0,0,0) );
dc.ExtTextOut ( 0, 0, ETO_OPAQUE, rc, sTime,
sTime.GetLength(), NULL );
// Restore the DC.
dc.RestoreDC(-1);
return 1; // We erased the background (ExtTextOut did it)
}
};What You Get with the WTL AppWizard
#pragma onceclass CMainFrame : public CFrameWindowImpl, public CUpdateUI,
public CMessageFilter, public CIdleHandler
{
public:
DECLARE_FRAME_WND_CLASS(NULL, IDR_MAINFRAME)CWTLClockView m_view;
CCommandBarCtrl m_CmdBar;
virtual BOOL PreTranslateMessage(MSG* pMsg);
virtual BOOL OnIdle();BEGIN_UPDATE_UI_MAP(CMainFrame)
UPDATE_ELEMENT(ID_VIEW_TOOLBAR, UPDUI_MENUPOPUP)
UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP)
END_UPDATE_UI_MAP()BEGIN_MSG_MAP(CMainFrame)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
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)
CHAIN_MSG_MAP(CFrameWindowImpl)
END_MSG_MAP()// Handler prototypes (uncomment arguments if needed):
// LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
// LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
// LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
};#include "stdafx.h"
#include "resource.h"#include "aboutdlg.h"
#include "WTLClockView.h"
#include "MainFrm.h"BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
{
if(CFrameWindowImpl::PreTranslateMessage(pMsg))
return TRUE;return m_view.PreTranslateMessage(pMsg);
}BOOL CMainFrame::OnIdle()
{
UIUpdateToolBar();
return FALSE;
}LRESULT CMainFrame::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
//menu bar
// create command bar window
HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault, NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);
// attach menu
m_CmdBar.AttachMenu(GetMenu());
// load command bar images
m_CmdBar.LoadImages(IDR_MAINFRAME);
// remove old menu
SetMenu(NULL);//tool bar
HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);
//set frame can resize
CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);//add menu bar and tool bar to frame
AddSimpleReBarBand(hWndCmdBar);
AddSimpleReBarBand(hWndToolBar, NULL, TRUE);//status Bar
CreateSimpleStatusBar();
//client view
m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE);
//update tool bar
UIAddToolBar(hWndToolBar);//set these two item checked.
UISetCheck(ID_VIEW_TOOLBAR, 1);
UISetCheck(ID_VIEW_STATUS_BAR, 1);// register object for message filtering and idle updates
CMessageLoop* pLoop = _Module.GetMessageLoop();
ATLASSERT(pLoop != NULL);
pLoop->AddMessageFilter(this);
pLoop->AddIdleHandler(this);return 0;
}LRESULT CMainFrame::OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
PostMessage(WM_CLOSE);
return 0;
}LRESULT CMainFrame::OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
// TODO: add code to initialize documentreturn 0;
}LRESULT CMainFrame::OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
static BOOL bVisible = TRUE; // initially visible
bVisible = !bVisible;
CReBarCtrl rebar = m_hWndToolBar;
int nBandIndex = rebar.IdToIndex(ATL_IDW_BAND_FIRST + 1); // toolbar is 2nd added band
rebar.ShowBand(nBandIndex, bVisible);
UISetCheck(ID_VIEW_TOOLBAR, bVisible);
UpdateLayout();
return 0;
}LRESULT CMainFrame::OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
BOOL bVisible = !::IsWindowVisible(m_hWndStatusBar);
::ShowWindow(m_hWndStatusBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
UISetCheck(ID_VIEW_STATUS_BAR, bVisible);
UpdateLayout();
return 0;
}LRESULT CMainFrame::OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
CAboutDlg dlg;
dlg.DoModal();
return 0;
}
#pragma onceclass CWTLClockView : public CWindowImpl
{
public:
DECLARE_WND_CLASS(NULL)BOOL PreTranslateMessage(MSG* pMsg);
BEGIN_MSG_MAP(CWTLClockView)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
END_MSG_MAP()// Handler prototypes (uncomment arguments if needed):
// LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
// LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
// LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
};
#include "stdafx.h"
#include "resource.h"#include "WTLClockView.h"
BOOL CWTLClockView::PreTranslateMessage(MSG* pMsg)
{
pMsg;
return FALSE;
}LRESULT CWTLClockView::OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
CPaintDC dc(m_hWnd);//TODO: Add your drawing code here
CRect rect(0,0,100,100);dc.DrawText("Sun Hai Min",16,rect,2);
return 0;
}
lass CMessageLoop
{
public:
ATL::CSimpleArray m_aMsgFilter;
ATL::CSimpleArray m_aIdleHandler;
MSG m_msg;// Message filter operations
BOOL AddMessageFilter(CMessageFilter* pMessageFilter)
{
return m_aMsgFilter.Add(pMessageFilter);
}BOOL RemoveMessageFilter(CMessageFilter* pMessageFilter)
{
return m_aMsgFilter.Remove(pMessageFilter);
}// Idle handler operations
BOOL AddIdleHandler(CIdleHandler* pIdleHandler)
{
return m_aIdleHandler.Add(pIdleHandler);
}BOOL RemoveIdleHandler(CIdleHandler* pIdleHandler)
{
return m_aIdleHandler.Remove(pIdleHandler);
}#ifndef _ATL_NO_OLD_NAMES
// for compatilibility with old names only
BOOL AddUpdateUI(CIdleHandler* pIdleHandler)
{
ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIObject and AddUpdateUI are deprecated. Please change your code to use CIdleHandler and OnIdle\n"));
return AddIdleHandler(pIdleHandler);
}BOOL RemoveUpdateUI(CIdleHandler* pIdleHandler)
{
ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIObject and RemoveUpdateUI are deprecated. Please change your code to use CIdleHandler and OnIdle\n"));
return RemoveIdleHandler(pIdleHandler);
}
#endif // !_ATL_NO_OLD_NAMES// message loop
int Run()
{
BOOL bDoIdle = TRUE;
int nIdleCount = 0;
BOOL bRet;for(;;)
{
while(bDoIdle && !::PeekMessage(&m_msg, NULL, 0, 0, PM_NOREMOVE))
{
if(!OnIdle(nIdleCount++))
bDoIdle = FALSE;
}bRet = ::GetMessage(&m_msg, NULL, 0, 0);
if(bRet == -1)
{
ATLTRACE2(atlTraceUI, 0, _T("::GetMessage returned -1 (error)\n"));
continue; // error, don't process
}
else if(!bRet)
{
ATLTRACE2(atlTraceUI, 0, _T("CMessageLoop::Run - exiting\n"));
break; // WM_QUIT, exit message loop
}if(!PreTranslateMessage(&m_msg))
{
::TranslateMessage(&m_msg);
::DispatchMessage(&m_msg);
}if(IsIdleMessage(&m_msg))
{
bDoIdle = TRUE;
nIdleCount = 0;
}
}return (int)m_msg.wParam;
}static BOOL IsIdleMessage(MSG* pMsg)
{
// These messages should NOT cause idle processing
switch(pMsg->message)
{
case WM_MOUSEMOVE:
#ifndef _WIN32_WCE
case WM_NCMOUSEMOVE:
#endif // !_WIN32_WCE
case WM_PAINT:
case 0x0118: // WM_SYSTIMER (caret blink)
return FALSE;
}return TRUE;
}// Overrideables
// Override to change message filtering
virtual BOOL PreTranslateMessage(MSG* pMsg)
{
// loop backwards
for(int i = m_aMsgFilter.GetSize() - 1; i >= 0; i--)
{
CMessageFilter* pMessageFilter = m_aMsgFilter[i];
if(pMessageFilter != NULL && pMessageFilter->PreTranslateMessage(pMsg))
return TRUE;
}
return FALSE; // not translated
}// override to change idle processing
virtual BOOL OnIdle(int /*nIdleCount*/)
{
for(int i = 0; i < m_aIdleHandler.GetSize(); i++)
{
CIdleHandler* pIdleHandler = m_aIdleHandler[i];
if(pIdleHandler != NULL)
pIdleHandler->OnIdle();
}
return FALSE; // don't continue
}
};UI Updating types:
menu bar items: UPDUI_MENUBAR
popup menu items: UPDUI_MENUPOPUP
toolbar buttons: UPDUI_TOOLBAR
status bar panes: UPDUI_STATUSBAR
child windows: UPDUI_CHILDWINDOWCUpdateUI can set the enabled state, checked state, and text of items (but of course not all items support all states; you can't put a check on an edit box).
To hook up UI updating, we need to do four things:Derive the frame window class from CUpdateUI and CIdleHandler
Chain messages from CMainFrame to CUpdateUI
Add the frame window to the module's list of idle handlers
Fill in the frame window's UPDATE_UI_MAP -
2006-12-06
WTL for MFC Programmers, Part II - WTL GUI Base Classes - [WTL]
WTL for MFC Programmers, Part II - WTL GUI Base Classes
WTL Overview
The WTL classes can be divided into a few major categories:
1. Frame window implementation - CFrameWindowImpl, CMDIFrameWindowImpl
2. Control wrappers - CButton, CListViewCtrl
3. GDI wrappers - CDC, CMenu
4. Special UI features - CSplitterWindow, CUpdateUI, CDialogResize, CCustomDraw
5. Utility classes and macros - CString, CRect, BEGIN_MSG_MAP_EXBeginning a WTL EXE
#define STRICT
#define WIN32_LEAN_AND_MEAN
#define _WTL_USE_CSTRING
#include // base ATL classes
#include // base WTL classes
extern CAppModule _Module; // WTL version of CComModule
#include // ATL GUI classes
#include // WTL frame window classes
#include // WTL utility classes like CString
#include // WTL enhanced msg map macros// MyWindow.h:
class CMyWindow : public CFrameWindowImpl
{
public:
DECLARE_FRAME_WND_CLASS(_T("First WTL window"), IDR_MAINFRAME);
BEGIN_MSG_MAP(CMyWindow)
CHAIN_MSG_MAP(CFrameWindowImpl)
END_MSG_MAP()
};
DECLARE_FRAME_WND_CLASS takes two parameters, the window class name (which can be NULL to have ATL generate a name for you), and a resource ID. WTL will look for an icon, menu, and accelerator table with that ID, and load them when the window is created. It will also look for a string with that ID and use it as the window title. We also chain messages to CFrameWindowImpl as it has some message handlers of its own (most notably WM_SIZE and WM_DESTROY).For ATL 7.0/7.1, you can use BEGIN_MSG_MAP for CWindowImpl/CDialogImpl derived classes, but must use BEGIN_MSG_MAP_EX for classes that don't derive from CWindowImpl/CDialogImpl
(The _EX macro is needed in VC 6 because it contains some code that the message handler macros use. For the sake of readability, I won't show the VC 6 and VC 7 versions of the header file here, since they only differ in that one macro. Just keep in mind that the _EX macro is not needed in VC 7.)class CMyWindow : public CFrameWindowImpl
{
public:
BEGIN_MSG_MAP_EX(CMyWindow)
MSG_WM_CREATE(OnCreate)
CHAIN_MSG_MAP(CFrameWindowImpl)
END_MSG_MAP()
LRESULT OnCreate(LPCREATESTRUCT lpcs)
{
SetTimer ( 1, 1000 );
SetMsgHandled(false);
return 0;
}
};class CMyWindow : public CFrameWindowImpl
{
public:
BEGIN_MSG_MAP_EX(CMyWindow)
MSG_WM_CREATE(OnCreate)
MSG_WM_DESTROY(OnDestroy)
MSG_WM_TIMER(OnTimer)
MSG_WM_ERASEBKGND(OnEraseBkgnd)
CHAIN_MSG_MAP(CFrameWindowImpl)
END_MSG_MAP()
LRESULT OnEraseBkgnd ( HDC hdc )
{
CDCHandle dc(hdc);
CRect rc;
SYSTEMTIME st;
CString sTime;
// Get our window's client area.
GetClientRect ( rc );
// Build the string to show in the window.
GetLocalTime ( &st );
sTime.Format ( _T("The time is %d:%02d:%02d"),
st.wHour, st.wMinute, st.wSecond );
// Set up the DC and draw the text.
dc.SaveDC();
dc.SetBkColor ( RGB(255,153,0) );
dc.SetTextColor ( RGB(0,0,0) );
dc.ExtTextOut ( 0, 0, ETO_OPAQUE, rc, sTime,
sTime.GetLength(), NULL );
// Restore the DC.
dc.RestoreDC(-1);
return 1; // We erased the background (ExtTextOut did it)
}
};What You Get with the WTL AppWizard
#pragma onceclass CMainFrame : public CFrameWindowImpl, public CUpdateUI,
public CMessageFilter, public CIdleHandler
{
public:
DECLARE_FRAME_WND_CLASS(NULL, IDR_MAINFRAME)CWTLClockView m_view;
CCommandBarCtrl m_CmdBar;
virtual BOOL PreTranslateMessage(MSG* pMsg);
virtual BOOL OnIdle();BEGIN_UPDATE_UI_MAP(CMainFrame)
UPDATE_ELEMENT(ID_VIEW_TOOLBAR, UPDUI_MENUPOPUP)
UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP)
END_UPDATE_UI_MAP()BEGIN_MSG_MAP(CMainFrame)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
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)
CHAIN_MSG_MAP(CFrameWindowImpl)
END_MSG_MAP()// Handler prototypes (uncomment arguments if needed):
// LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
// LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
// LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
};#include "stdafx.h"
#include "resource.h"#include "aboutdlg.h"
#include "WTLClockView.h"
#include "MainFrm.h"BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
{
if(CFrameWindowImpl::PreTranslateMessage(pMsg))
return TRUE;return m_view.PreTranslateMessage(pMsg);
}BOOL CMainFrame::OnIdle()
{
UIUpdateToolBar();
return FALSE;
}LRESULT CMainFrame::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
//menu bar
// create command bar window
HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault, NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);
// attach menu
m_CmdBar.AttachMenu(GetMenu());
// load command bar images
m_CmdBar.LoadImages(IDR_MAINFRAME);
// remove old menu
SetMenu(NULL);//tool bar
HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);
//set frame can resize
CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);//add menu bar and tool bar to frame
AddSimpleReBarBand(hWndCmdBar);
AddSimpleReBarBand(hWndToolBar, NULL, TRUE);//status Bar
CreateSimpleStatusBar();
//client view
m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE);
//update tool bar
UIAddToolBar(hWndToolBar);//set these two item checked.
UISetCheck(ID_VIEW_TOOLBAR, 1);
UISetCheck(ID_VIEW_STATUS_BAR, 1);// register object for message filtering and idle updates
CMessageLoop* pLoop = _Module.GetMessageLoop();
ATLASSERT(pLoop != NULL);
pLoop->AddMessageFilter(this);
pLoop->AddIdleHandler(this);return 0;
}LRESULT CMainFrame::OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
PostMessage(WM_CLOSE);
return 0;
}LRESULT CMainFrame::OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
// TODO: add code to initialize documentreturn 0;
}LRESULT CMainFrame::OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
static BOOL bVisible = TRUE; // initially visible
bVisible = !bVisible;
CReBarCtrl rebar = m_hWndToolBar;
int nBandIndex = rebar.IdToIndex(ATL_IDW_BAND_FIRST + 1); // toolbar is 2nd added band
rebar.ShowBand(nBandIndex, bVisible);
UISetCheck(ID_VIEW_TOOLBAR, bVisible);
UpdateLayout();
return 0;
}LRESULT CMainFrame::OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
BOOL bVisible = !::IsWindowVisible(m_hWndStatusBar);
::ShowWindow(m_hWndStatusBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
UISetCheck(ID_VIEW_STATUS_BAR, bVisible);
UpdateLayout();
return 0;
}LRESULT CMainFrame::OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
CAboutDlg dlg;
dlg.DoModal();
return 0;
}
#pragma onceclass CWTLClockView : public CWindowImpl
{
public:
DECLARE_WND_CLASS(NULL)BOOL PreTranslateMessage(MSG* pMsg);
BEGIN_MSG_MAP(CWTLClockView)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
END_MSG_MAP()// Handler prototypes (uncomment arguments if needed):
// LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
// LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
// LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
};
#include "stdafx.h"
#include "resource.h"#include "WTLClockView.h"
BOOL CWTLClockView::PreTranslateMessage(MSG* pMsg)
{
pMsg;
return FALSE;
}LRESULT CWTLClockView::OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
CPaintDC dc(m_hWnd);//TODO: Add your drawing code here
CRect rect(0,0,100,100);dc.DrawText("Sun Hai Min",16,rect,2);
return 0;
}
lass CMessageLoop
{
public:
ATL::CSimpleArray m_aMsgFilter;
ATL::CSimpleArray m_aIdleHandler;
MSG m_msg;// Message filter operations
BOOL AddMessageFilter(CMessageFilter* pMessageFilter)
{
return m_aMsgFilter.Add(pMessageFilter);
}BOOL RemoveMessageFilter(CMessageFilter* pMessageFilter)
{
return m_aMsgFilter.Remove(pMessageFilter);
}// Idle handler operations
BOOL AddIdleHandler(CIdleHandler* pIdleHandler)
{
return m_aIdleHandler.Add(pIdleHandler);
}BOOL RemoveIdleHandler(CIdleHandler* pIdleHandler)
{
return m_aIdleHandler.Remove(pIdleHandler);
}#ifndef _ATL_NO_OLD_NAMES
// for compatilibility with old names only
BOOL AddUpdateUI(CIdleHandler* pIdleHandler)
{
ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIObject and AddUpdateUI are deprecated. Please change your code to use CIdleHandler and OnIdle\n"));
return AddIdleHandler(pIdleHandler);
}BOOL RemoveUpdateUI(CIdleHandler* pIdleHandler)
{
ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIObject and RemoveUpdateUI are deprecated. Please change your code to use CIdleHandler and OnIdle\n"));
return RemoveIdleHandler(pIdleHandler);
}
#endif // !_ATL_NO_OLD_NAMES// message loop
int Run()
{
BOOL bDoIdle = TRUE;
int nIdleCount = 0;
BOOL bRet;for(;;)
{
while(bDoIdle && !::PeekMessage(&m_msg, NULL, 0, 0, PM_NOREMOVE))
{
if(!OnIdle(nIdleCount++))
bDoIdle = FALSE;
}bRet = ::GetMessage(&m_msg, NULL, 0, 0);
if(bRet == -1)
{
ATLTRACE2(atlTraceUI, 0, _T("::GetMessage returned -1 (error)\n"));
continue; // error, don't process
}
else if(!bRet)
{
ATLTRACE2(atlTraceUI, 0, _T("CMessageLoop::Run - exiting\n"));
break; // WM_QUIT, exit message loop
}if(!PreTranslateMessage(&m_msg))
{
::TranslateMessage(&m_msg);
::DispatchMessage(&m_msg);
}if(IsIdleMessage(&m_msg))
{
bDoIdle = TRUE;
nIdleCount = 0;
}
}return (int)m_msg.wParam;
}static BOOL IsIdleMessage(MSG* pMsg)
{
// These messages should NOT cause idle processing
switch(pMsg->message)
{
case WM_MOUSEMOVE:
#ifndef _WIN32_WCE
case WM_NCMOUSEMOVE:
#endif // !_WIN32_WCE
case WM_PAINT:
case 0x0118: // WM_SYSTIMER (caret blink)
return FALSE;
}return TRUE;
}// Overrideables
// Override to change message filtering
virtual BOOL PreTranslateMessage(MSG* pMsg)
{
// loop backwards
for(int i = m_aMsgFilter.GetSize() - 1; i >= 0; i--)
{
CMessageFilter* pMessageFilter = m_aMsgFilter[i];
if(pMessageFilter != NULL && pMessageFilter->PreTranslateMessage(pMsg))
return TRUE;
}
return FALSE; // not translated
}// override to change idle processing
virtual BOOL OnIdle(int /*nIdleCount*/)
{
for(int i = 0; i < m_aIdleHandler.GetSize(); i++)
{
CIdleHandler* pIdleHandler = m_aIdleHandler[i];
if(pIdleHandler != NULL)
pIdleHandler->OnIdle();
}
return FALSE; // don't continue
}
};UI Updating types:
menu bar items: UPDUI_MENUBAR
popup menu items: UPDUI_MENUPOPUP
toolbar buttons: UPDUI_TOOLBAR
status bar panes: UPDUI_STATUSBAR
child windows: UPDUI_CHILDWINDOWCUpdateUI can set the enabled state, checked state, and text of items (but of course not all items support all states; you can't put a check on an edit box).
To hook up UI updating, we need to do four things:Derive the frame window class from CUpdateUI and CIdleHandler
Chain messages from CMainFrame to CUpdateUI
Add the frame window to the module's list of idle handlers
Fill in the frame window's UPDATE_UI_MAP







