代碼運行效果圖如下:
1.前言
雖然MFC的功能很強大,但Windows Template Library(WTL)的出現,無疑說明了MFC有一定的弊病。和MFC相比,功能並沒有MFC完善。比如MFC支持doc/view架構,而WTL並不支持。同時,WTL也沒有Microsoft的官方支持。但是,WTL是基於模版(template)的,其應用程序最小只有24KB,同時不象MFC,依賴DLL。但是WTL也實現了CString、CRect、CSize、CPoint等常用的類,還CStaticT<TBase>、CButtonT<TBase>、CListBoxT<TBase>、CComboBoxT<TBase>(這些在WTL庫文件atlctrls.h、atlctrlw.h、atlctrlx.h中就能看到)等用起來和MFC版本也沒太大不同。
2.准備工作
首先安裝WTL AppWizard,現在最高版本應該是WTL7.0,直接運行setup腳本文件就可以了
這樣當你啟動VC6.0後,File/New時,在Project屬性頁就能看到添加了一項ATL/WTL AppWizard。你可以直接把WTL的庫文件( 共16個.h文件)拷貝到vc的安裝目錄VC98/Include中,也可以放到你的工程文件夾中。
3.應用實例1---SDI中狀態欄的應用
(1) File/New,如圖:
(2) OK後,
SDI(Single Document Interface)應用程序通常只有一個主窗口(通常是一個框架窗口,Frame Window)。框架窗口包含菜單、工具欄、狀態欄和稱為視(View)的客戶工作區。
Multip-SDI(Multiple Threads SDI),就像IE浏覽器,使用"文件/新建/窗口"命令後,會出現另一個IE窗口。
MDI(Multiple Document Interface)應用程序有一個主框架窗口,但有多個子框架窗口。每個子窗口都有自己的視(View),和MFC的相似。
Dialog應用程序是基於對話框的。
(3) Next
(4) 在產生的文件中可以看到WTL確實不支持Doc/View.
WTL對單界面線程的封裝:WTL使用一個_Module全局變量來保存全局數據,並通過它來引用應用程序級的代碼。在WTL中,該變量是CAppModule的實例,想象MFC的theApp。
●下面對MyTestWTL.cpp文件中的函數作一些說明:
Ⅰ:
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); //程序邏輯,調用全局函數Run()
_Module.Term(); // 終止模塊
::CoUninitialize();
return nRet;
}
入口函數名為_tWinMain()。當使用UNICODE時,編譯器會將它替換為wWinMain(),否則,為WinMain()。入口函數其實就是主線程(_Module)的起始點,這和SDK,MFC一個道理。一個_Module還維持一個消息循環Map。
Ⅱ:
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;
}
該函數創建了一個CMessageLoop實例,該實例包含了這個線程的消息循環。這些消息循環都放在模塊的全局消息循環中,通過線程的ID來索引。這樣,該線程的其它代碼就能訪問得到。每一個應用程序維護一個消息循環隊列Map,應用程序中的每個線程都通過"_Module.AddMessageLoop(&theLoop)",把該線程的消息循環加入到_Module的消息循環Map中。消息循環對象包含了消息過濾和空閒處理。每個線程都可以加入空閒處理代碼和消息過濾。
● 添加代碼:
Ⅰ:在stdafx.h中添加:
#include <atlctrls.h>
#include <atlctrlx.h>
#include <atlctrlw.h> //這三個是WTL 中實現常用控件類
#include <atldlgs.h>
#include <atlmisc.h> //WTL 使用類像 CString等
#include <atlddx.h> //WTL 使用像MFC中DDX/DDV 機制
Ⅱ:添加3個圖標資源:IDR_DEFAULT, IDR_DATE, IDR_TIME
Ⅲ:在MainFrm.h中添加 CMultiPaneStatusBarCtrl m_Mstatus;
Ⅳ:在MainFrm.cpp中添加
在函數最前面聲明兩個數組:
static int arrPanes[] = { IDR_DEFAULT, IDR_DATE, IDR_TIME };
static int arrWidths[] = { 450,200, 600 }; //你自己修改一下值看看有什麼不同
在OnCreate函數中添加:
CreateSimpleStatusBar();
m_Mstatus.SubclassWindow(m_hWndStatusBar);
m_Mstatus.SetPanes(arrPanes,sizeof(arrPanes)/sizeof(int), false);
m_Mstatus.SetPaneWidth(IDR_DEFAULT,400);
m_Mstatus.SetPaneWidth(IDR_DATE,200);
m_Mstatus.SetPaneWidth(IDR_TIME,900);
m_Mstatus.SetPaneIcon(IDR_DEFAULT,AtlLoadIconImage(IDR_DEFAULT, LR_DEFAULTCOLOR));
m_Mstatus.SetPaneIcon(IDR_DATE, AtlLoadIconImage(IDR_DATE, LR_DEFAULTCOLOR));
m_Mstatus.SetPaneIcon(IDR_TIME, AtlLoadIconImage(IDR_TIME, LR_DEFAULTCOLOR));
m_Mstatus.SetPaneText(IDR_DATE,"WTL is very wonderful!",0);
m_Mstatus.SetPaneText(IDR_TIME,"WWW.VCKBASE.COM",0);
這些代碼相信大家一看就會明白!
參考資料:
深入剖析WTL——Win32模型,作者:建新
WTL for MFC Programmers 作者:Michael Dunn
在此深表感謝
本文配套源碼