作者:朱金灿
来源:http://blog.csdn.net/clever101
WTL的安装程序提供了提供了一个类似的MFC的应用程序向导,开发环境为Win XP + sp3,VS 2005+ sp1,WTL8.0。今天就让我们使用这个向导学习一下如何使用WTL创建一个单文档程序。
1. 选择WTL程序项目,输入项目名,如下图:
2. 使用如下设置生成项目,如下面图:
让我们编译一下程序,看看程序的效果图:
是不是和MFC的单文档程序的效果差不多呢?让我们看看生成哪些类及重要的代码。先看看主函数吧:
CAppModule _Module; int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT) { CMessageLoop theLoop; _Module.AddMessageLoop(&theLoop); CMainFrame wndMain; if(wndMain.CreateEx() == NULL) { ATLTRACE(_T("Main window creation failed!\n")); return 0; } wndMain.ShowWindow(nCmdShow); int nRet = theLoop.Run(); _Module.RemoveMessageLoop(); return nRet; } int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow) { HRESULT hRes = ::CoInitialize(NULL); // If you are running on NT 4.0 or higher you can use the following call instead to // make the EXE free threaded. This means that calls come in on a random RPC thread. // HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); ATLASSERT(SUCCEEDED(hRes)); // this resolves ATL window thunking problem when Microsoft Layer for Unicode (MSLU) is used ::DefWindowProc(NULL, 0, 0, 0L); AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES); // add flags to support other controls hRes = _Module.Init(NULL, hInstance); ATLASSERT(SUCCEEDED(hRes)); int nRet = Run(lpstrCmdLine, nCmdShow); _Module.Term(); ::CoUninitialize(); return nRet; }
CAppModule _Module可以看做是MFC程序的应用程序类对象,起着初始化和建立消息循环的作用。我们再分析下WinMain函数做了哪些工作:
- ::CoInitialize(NULL); —— 初始化COM环境
- ::DefWindowProc(NULL, 0, 0, 0L); ——貌似是解决在使用微软的unicode层时ATL窗口的thunking的问题,看不明白,暂且放过。
- AtlInitCommonControls —— 支持ATL的其它控件的特殊属性。
- _Module.Init —— 应用程序初始化
- 调用Run函数,Run函数的主要作用是创建主框架窗口,进入消息循环。
- _Module.Term(); —— 销毁应用程序
- ::CoUninitialize();—— COM环境销毁。
我们再看看主框架窗口类——CMainFrame。这个类的作用类似于MFC程序的CMainFrame类,不过其类结构和MFC程序的CMainFrame类有很大不同。CMainFrame类主要派生自四个类:CFrameWindowImpl、CUpdateUI、CMessageFilter和CIdleHandler。从名字上我们可以猜得出CFrameWindowImpl是窗口基类、CUpdateUI负责界面更新、CMessageFilter负责消息截取,CIdleHandler负责空闲处理。
我们再看看CMainFrame类的数据成员:
CWtlToolbarView m_view; —— 视图窗口,相当于MFC的视图类。
CCommandBarCtrl m_CmdBar; —— 菜单栏
CMainFrame类的创建顺序实际上是这样的:
1. CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);——创建空的rebar风格的工具栏
2.下面代码是创建菜单栏,并把它加到之前创建空的工具栏
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); AddSimpleReBarBand(hWndCmdBar);
- 下面代码是创建实际的工具栏,并把它加到之前创建空的工具栏:
HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE); AddSimpleReBarBand(hWndToolBar, NULL, TRUE); UIAddToolBar(hWndToolBar); // 确保可以更新工具栏界面
4. 创建一个简单的状态栏,代码如下:
CreateSimpleStatusBar();
- 创建视图窗口,代码如下:
m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE);
还有两个类:
视图类:class CWtlToolbarView : public CWindowImpl<CWtlToolbarView>
和关于对话框类:class CAboutDlg : public CDialogImpl<CAboutDlg>。因为这个类比较简单,这里就不作介绍了。
比起MFC程序,你会发现WTL程序少了文档类。我觉得这倒是WTL程序设计巧妙的地方。我常常觉得MFC程序中的文档类是一个比较鸡肋的类,理由很简单:文档类主要做的是序列化方面的工作,一是没那么多程序需要序列化;二是序列化工作只是一个简单功能,你可以在视图类做,也可以在框架类做,有什么必要专门创建一个类来做这个工作?你可能觉得视图类有时也是多余的,实际上也有可能,而WTL也考虑到了,向导的最后一步允许你是否选择:Use a view window。这也是WTL库比起MFC库的优点:MFC库不管你需要不需要,一股脑给你一堆类,而WTL则是允许你自由组装和裁剪,就使用自由度WTL比MFC要好。
如果你觉得我的博客对你有帮助,请在下面网址中博客之星评选活动投我一票:
http://vote.blog.csdn.net/item/blogstar/clever101(单击候选人介绍下面的投他一票那个按钮)
参与投票有机会获奖:
最佳贡献奖:通过微博分享活动就有机会获得30元充值卡一张(每周抽选5名)
幸运奖:凡参与投票用户就有机会获得精美小礼品一份。(每周抽选5名)
积极参与奖:所有参与投票并符合条件的用户均可获得20个下载积分。