WTL起步-玩轉(zhuǎn)圖形界面_第1頁(yè)
WTL起步-玩轉(zhuǎn)圖形界面_第2頁(yè)
WTL起步-玩轉(zhuǎn)圖形界面_第3頁(yè)
WTL起步-玩轉(zhuǎn)圖形界面_第4頁(yè)
WTL起步-玩轉(zhuǎn)圖形界面_第5頁(yè)
已閱讀5頁(yè),還剩63頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、WTL起步 - 玩轉(zhuǎn)圖形界面Microsoft2008WTL起步玩轉(zhuǎn)圖形界面吳助建目錄序言3第一部分 基礎(chǔ)篇5第一章 WTL的基礎(chǔ)-ATL5第二章 WTL之路11第三章 命令條14第四章 帶視圖的框架窗口15第五章 使用MRU17第六章 創(chuàng)建多線程SDI應(yīng)用程序19第七章 創(chuàng)建MDI應(yīng)用程序23第八章 分隔窗口26第九章 GDI的封裝31第十章 CString及其它34第十一章 動(dòng)態(tài)數(shù)據(jù)交換(DDX)的WTL支持35第十二章 WTL向?qū)?7第十三章 WTL例程39第二部分 提高篇40第一章 位圖視圖的例程40第二章 上下文菜單41第三章 滾動(dòng)視圖43第四章 通用對(duì)話框45第五章 控件封裝47第

2、六章 打印與打印預(yù)覽52第七章 屬性頁(yè)56第八章 消息過濾59第九章 空閑處理62第十章 UI更新63第十一章 消息分解65第十二章 WTL的未來(lái)67序言WTL是2000年1月隨Windows的平臺(tái)SDK始發(fā)的。起初是ATL項(xiàng)目組寫的一個(gè)基于ATL的,封裝了相關(guān)win32窗口API的例程。自ATL2.0開始,ATL就已經(jīng)有一些簡(jiǎn)單的相關(guān)窗口函數(shù)的封裝類,例如:CWindow,CWindowImpl和CDialogImpl。然而,當(dāng)我們比較MFC的界面相關(guān)部分的功能時(shí),ATL對(duì)界面編程的支持簡(jiǎn)直就是一個(gè)玩笑。甚至到了ATL3.0,ATL仍然沒有對(duì)諸如MDI,命令條,DDX,打印,GDI等流行功能

3、的支持。最被人喜愛的MFC的CString也沒被支持進(jìn)來(lái)。沒有對(duì)這些功能的支持,ATL很難滿足擁有壓倒性數(shù)量的使用MFC的編程人員的需求。WTL就是ATL項(xiàng)目組認(rèn)為ATL風(fēng)格的窗口編程模型應(yīng)該有的樣子。表1列出了WTL與MFC在界面編程相關(guān)功能方面的比較。特性MFCWTL依賴庫(kù)支持不支持 (構(gòu)建ATL之上)應(yīng)用向?qū)еС种С种С诸愊驅(qū)еС种С植恢С郑ǖ谌讲寮isualFC支持)微軟的公開支持支持不支持(微軟內(nèi)部的志愿者支持)支持OLE文檔支持不支持支持視圖支持支持支持文檔支持不支持基本win32/通用控件封裝支持支持高級(jí)通用控件封裝(平坦?jié)L動(dòng)條、IP地址控件、頁(yè)面控件等)不支持支持命令條支持

4、(包含bitmapped context menus)不支持 (MFC提供對(duì)話條)支持CString支持支持GDI封裝支持支持輔助類(CRect, CPoint, 等)支持支持Wizards屬性頁(yè)/向?qū)еС种С諷DI, MDI支持支持支持多線程SDI支持不支持支持MRU支持支持支持可??看翱?條支持不支持分隔窗口支持支持DDX支持支持 (不是MFC的擴(kuò)展)打印/打印預(yù)覽支持支持滾動(dòng)視圖支持支持客戶自畫封裝不支持支持消息/命令路由支持支持通用對(duì)話框支持支持HTML視圖支持支持簡(jiǎn)單實(shí)例應(yīng)用不支持不支持UI更新支持支持基于模板不支持支持帶工具條,狀態(tài)條和菜單的不做任何情事的SDI應(yīng)用靜態(tài)鏈接時(shí)大小超

5、過228KB(+MSVCRT.DLL (288KB)24k (帶 /OPT:NOWIN98)(+ MSVCRT.DLL如果使用 CString)帶工具條,狀態(tài)條和菜單的不做任何情事的SDI應(yīng)用動(dòng)態(tài)鏈接時(shí)大小24KB +MFC42.DLL (972KB) +MSVCRT.DLL (288KB)N/A對(duì)運(yùn)行時(shí)庫(kù)的依賴 CRT (+ MFC42.DLL, 如果動(dòng)態(tài)鏈接)None (如果使用需要CStringCRT)表1 WTL與MFC的比較當(dāng)然,WTL不可能(也不愿意)做所有MFC都能做的事兒。MFC支持經(jīng)典的OLE,文檔/視圖框架和可??看翱?,而WTL沒有。而且還缺乏微軟的“官方”支持。然而,來(lái)自

6、于前ATL項(xiàng)目組成員,以及活躍在ATL開發(fā)社區(qū)的“非官方”支持,可以減輕您對(duì)支持方面的擔(dān)心。為何ATL開發(fā)社區(qū)喜歡WTL?因?yàn)檫@四點(diǎn):1> WTL是基于C+模板技術(shù)的;2> 應(yīng)用程序的最小編譯代碼小于24K;3> 沒有任何多如的動(dòng)態(tài)鏈接庫(kù)依賴(如果您用CString,會(huì)鏈接CRT);4> 擁有ATL一樣的靈活和小巧。此外,WTL和MFC的界面編程模型非常接近,還包括了從它移植過來(lái)的CString。在我們這本分兩部分的書里,我將揭開WTL神秘的面紗。在第一部分里,我們討論WTL框架窗口的實(shí)現(xiàn)結(jié)構(gòu)。我們將解釋如何編寫基于WTL的SDI,MDI和多線程SDI,以及IE瀏覽器樣

7、式的應(yīng)用程序。進(jìn)而,我們討論WTL的輔助類,包括對(duì)DDX的封裝。最后,我們看一下WTL的AppWizard和本書附帶的例程。在本書的第二部分,我們討論WTL命令條的實(shí)現(xiàn)結(jié)構(gòu),以及對(duì)Windows通用控件的封裝和一些自定義的用戶界面小部件。我們還將進(jìn)一步討論WTL的Windows消息路由結(jié)構(gòu),包括消息分解,過濾和空閑處理。我們的WTL之旅沒有結(jié)束,直到我們討論完通用對(duì)話框,屬性頁(yè)/屬性表,打印支持,以及滾動(dòng)窗口。所有的這一切我們計(jì)劃放在第二部分。在我們告訴你如何用WTL開發(fā)程序之前,讓我們先復(fù)習(xí)一下怎樣用純ATL(即不包含WTL)來(lái)開發(fā)應(yīng)用程序。第一部分 基礎(chǔ)篇第一章 WTL的基礎(chǔ)-ATLATL

8、提供了一套編寫Windows用戶界面的C+模板類。ATL本來(lái)的目的是用來(lái)支持COM組件和OLE屬性頁(yè)框架的。這套C+模板類當(dāng)然成為WTL的基礎(chǔ)。這套類提供了對(duì)所有基本的Windows窗口函數(shù)的封裝,包括窗口/對(duì)話框的創(chuàng)建和管理,窗口函數(shù),消息路由,窗口子類化,超類化和消息鏈。圖1展示了ATL這套C+模板類的層次。圖1:ATL界面相關(guān)類的層次如果想直接用ATL來(lái)創(chuàng)建一個(gè)窗口或者對(duì)話框,你需要從CWindowImpl或者CDialogImpl派生類。給你一個(gè)具體的例子。圖2提供了一個(gè)簡(jiǎn)單的用前面講到的這套C+類來(lái)開發(fā)SDI程序的示意圖。圖2 簡(jiǎn)單SDI應(yīng)用程序這個(gè)例子的應(yīng)用程序有一個(gè)SDI的框架窗

9、口,這個(gè)窗口有一個(gè)菜單條,狀態(tài)條和客戶區(qū)。它也提供了一個(gè)對(duì)話框用來(lái)演示在ATL里怎樣使用對(duì)話框。我們就從vc6創(chuàng)建一個(gè)簡(jiǎn)單win32工程以及添加一些必要的啟動(dòng)ATL的代碼來(lái)開始這個(gè)例子。圖3展示了這個(gè)例子的主要源文件的源代碼。stdafx.h :#if !defined(AFX_STDAFX_H_DE06DA2F_25B6_41BA_9B20_A17362C38C8C_INCLUDED_)#define AFX_STDAFX_H_DE06DA2F_25B6_41BA_9B20_A17362C38C8C_INCLUDED_#if _MSC_VER > 1000#pragma once#en

10、dif / _MSC_VER > 1000#define STRICT#ifndef _WIN32_WINNT#define _WIN32_WINNT 0x0400#endif#define _ATL_APARTMENT_THREADED#include <atlbase.h>/ 如果想重載某些方法,你可以從CComModule類派生一個(gè)類/ 但是不得改變_Module的名字extern CComModule _Module;#include <atlwin.h>/AFX_INSERT_LOCATION/ Microsoft Visual C+ 將即時(shí)從此行之前插

11、入附加聲明。#endif / !defined(AFX_STDAFX_H_DE06DA2F_25B6_41BA_9B20_A17362C38C8C_INCLUDED)MainFrame.H#pragma once#ifndef _MAINFRAME_H_#define _MAINFRAME_H_#include "commctrl.H"class CMainFrame : public CWindowImpl<CMainFrame,CWindow, CWinTraits<WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN , WS_EX_AP

12、PWINDOW | WS_EX_WINDOWEDGE> >public:CMainFrame():m_hWndStatusBar(NULL),m_hBmp(NULL) m_hBmp =LoadBitmap(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDB_ATLWINDOWING);CMainFrame() if(m_hBmp) :DeleteObject(m_hBmp); m_hBmp = NULL;BEGIN_MSG_MAP(CMainFrame)MESSAGE_HANDLER(WM_PAINT, OnPaint)MESSAG

13、E_HANDLER(WM_CREATE, OnCreate)MESSAGE_HANDLER(WM_SIZE, OnSize)MESSAGE_HANDLER(WM_CLOSE, OnClose)COMMAND_ID_HANDLER(ID_FILE_EXIT, OnFileExit)COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAbout)END_MSG_MAP()void OnFinalMessage(HWND /*hWnd*/) LRESULT OnCreate(UINT, WPARAM wParam, LPARAM lParam, BOOL& bHandled

14、) DefWindowProc();m_hWndStatusBar = :CreateStatusWindow(WS_CHILD | WS_VISIBLE |WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, _T("Ready"), m_hWnd, 1);return 0L;LRESULT OnSize(UINT, WPARAM wParam, LPARAM lParam, BOOL& bHandled) DefWindowProc();:SendMessage(m_hWndStatusBar, WM_SIZE,

15、 0, 0);return 0L;LRESULT OnPaint(UINT, WPARAM, LPARAM, BOOL&) PAINTSTRUCT ps; HDC hdc = BeginPaint(&ps); RECT rect; GetClientRect(&rect); / 位圖HDC hDCMem = :CreateCompatibleDC(hdc);HBITMAP hBmpOld = (HBITMAP):SelectObject(hDCMem,m_hBmp);BITMAP bmp;:GetObject(m_hBmp, sizeof(BITMAP), &b

16、mp);SIZE size = bmp.bmWidth,bmp.bmHeight ;:BitBlt(hdc, rect.left, rect.top, (size.cx), (size.cy), hDCMem, 0,0,SRCCOPY);/ 清除:SelectObject(hDCMem,hBmpOld);:DeleteDC(hDCMem);hDCMem = NULL; EndPaint(&ps); return 0;LRESULT OnClose(UINT,WPARAM,LPARAM, BOOL&) DestroyWindow();PostQuitMessage(0);retu

17、rn 0L;LRESULT OnFileExit(WORD,WORD wID, HWND,BOOL&) SendMessage(WM_CLOSE);return 0L;LRESULT OnAbout(WORD, WORD wID, HWND, BOOL&) CAboutDialog dlg;dlg.DoModal();return 0L;private:struct CAboutDialog : public CDialogImpl<CAboutDialog> enum IDD = IDD_ABOUT ;BEGIN_MSG_MAP(CAboutDialog)COMM

18、AND_ID_HANDLER(IDOK, OnClose)END_MSG_MAP()LRESULT OnClose(WORD, WORD wID, HWND, BOOL&) EndDialog(wID);return 0L;HWNDm_hWndStatusBar;HBITMAPm_hBmp;#endifAtlHelloWindowing.Cpp#include "stdafx.h"#include "resource.h"#include "MainFrame.H"CComModule _Module;extern "

19、;C" int WINAPI _tWinMain(HINSTANCE hInstance,HINSTANCE, LPTSTR lpCmdLine, int nShowCmd) lpCmdLine = GetCommandLine(); / 該行_ATL_MIN_CRT 所必要的_Module.Init(0, hInstance,NULL);/ 加載通用控件INITCOMMONCONTROLSEX iccx;iccx.dwSize = sizeof(iccx);iccx.dwICC = ICC_WIN95_CLASSES |ICC_BAR_CLASSES ;:InitCommonCon

20、trolsEx(&iccx);HMENU hMenu = LoadMenu(_Module.GetResourceInstance(),MAKEINTRESOURCE(IDR_MAINFRAME);CMainFrame wndFrame;wndFrame.GetWndClassInfo().m_wc.hIcon = :LoadIcon(_Module.GetResourceInstance(),MAKEINTRESOURCE(IDI_FORM);wndFrame.GetWndClassInfo().m_wc.style = 0;/CS_HREDRAW|CS_VREDRAW;wndFra

21、me.Create(GetDesktopWindow(), CWindow:rcDefault, _T("ATL Windowing is cool"), 0, 0, (UINT)hMenu);wndFrame.ShowWindow(nShowCmd);wndFrame.UpdateWindow();MSG msg;while (GetMessage(&msg, 0, 0, 0) TranslateMessage(&msg); DispatchMessage(&msg);_Module.Term();return 0;在MainFrame.h里,CM

22、ainFrame有兩個(gè)數(shù)據(jù)成員:狀態(tài)條的HWND和HBITMAP。CMainFrame通過通過調(diào)用 comctl32.dll的CreateStatusWindow()函數(shù),在WM_CREATRE消息處理函數(shù)里把狀態(tài)條創(chuàng)建成一個(gè)子窗口,而且通過發(fā)送WM_SIZE消息,調(diào)整狀態(tài)條的大小。WM_PAINT消息的處理函數(shù)使用上述的HBITMAP演示了一點(diǎn)ATL里的 GDI編程。由于ATL對(duì)GDI沒有提供包裝類,所以這里的GDI編程是直接調(diào)用Win32的API來(lái)完成的。然而 MESSAGE_HANDLER宏需要你做你自己的消息分解,ATL通過一系列的宏為你分解了WM_ COMMAND和WM_NOTIFY

23、消息。MainFrame.h展示了如何使用COMMAND_ID_HANDLER宏,CMainFrame用這個(gè)宏來(lái)處理它的菜單命令。最后,CAboutDialog是一個(gè)對(duì)話框類,繼承自CDialogImpl類。OnAbout命令處理函數(shù)調(diào)用了DoModal用來(lái)顯示這個(gè)對(duì)話框。HelloAtlWindowing.cpp里有個(gè)_tWinMain,這是ATL程序的入口函數(shù),它創(chuàng)建了一個(gè)CMainFrame的實(shí)例,而后調(diào)用該實(shí)例的Create()函數(shù),以及ShowWindow()和UpdateWindow()這些成員函數(shù),這些成員函數(shù)很明顯是與他們名字相似的win32 API的封裝。最后,因?yàn)檫@個(gè)程序從

24、根本上來(lái)說,是一個(gè)Win32窗口程序,我們必須從窗口的消息隊(duì)列里通過GetMessage、DispatchMessage循環(huán)來(lái)抽出消息。如果你熟悉win32 API編程的話,你會(huì)注意到這個(gè)程序缺少RegisterClass()的調(diào)用和處理窗口消息的窗口過程,其他的部分你都能理解。如果你熟悉MFC,你可能奇怪ATL 沒有提供那些最基本的支持,比如創(chuàng)建狀態(tài)條和菜單。好吧,程序既然能運(yùn)行,事實(shí)證明ATL肯定支持了。不過ATL并沒有做足這方面的支持。我們不要忘記ATL的主要目的(ATL主要目的是支持COM編程)。ATL允許你,但是并沒有直接支持MDI,多線程SDI,或IE瀏覽器樣式的應(yīng)用程序,也沒有封

25、裝通用控件,DDX,和GDI相關(guān)函數(shù)。如果你對(duì)這些感興趣,那么我們就進(jìn)入WTL的世界。第二章 WTL之路 WTL類使得我們更加容易地創(chuàng)建SDI框架窗口成為可能,這個(gè)類就是CFrameWindowImpl。圖3 WTL的SDI窗口層次關(guān)系 類CFrameWindowImpl從類CFrameWindowImplBase派生,因此繼承了標(biāo)準(zhǔn)應(yīng)用程序框架窗口的所有功能。下面列出了一個(gè)WTL創(chuàng)建的框架窗口提供和支持的特性:1) 集合了工具條,菜單條,狀態(tài)條和Rebar條;2) 基本視圖處理,包括視圖與框架同步大小,Rebar帶維護(hù)(包括添加或調(diào)整帶的大?。?) 命令條菜單;4) 鍵盤快捷鍵;5) 工具

26、條按鈕的工具提示;6) 在狀態(tài)條顯示幫助字符串;7) 顯示框架圖標(biāo)。為了創(chuàng)建一個(gè)SDI應(yīng)用,步驟如下:1) 從類CFrameWindowImpl派生你的框架類;2) 添加WTL的宏DECLARE_FRAME_WND_CLASS,指定工具條和菜單的資源ID;3) 添加消息映射和消息響應(yīng)處理,需要包含鏈入框架基類的鏈路。例子:class CMainFrame : public CFrameWindowImpl<CMainFrame> public: DECLARE_FRAME_WND_CLASS(NULL, IDR_MAINFRAME) BEGIN_MSG_MAP(CMainFrame

27、) MESSAGE_HANDLER(WM_PAINT, OnPaint) MESSAGE_HANDLER(WM_CREATE, OnCreate) COMMAND_ID_HANDLER(ID_FILE_EXIT, OnFileExit) COMMAND_ID_HANDLER(ID_HELP_ABOUT, OnAbout) CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>) END_MSG_MAP() LRESULT OnCreate(UINT, WPARAM, LPARAM, BOOL&) CreateSimpleToolBar(); /

28、 創(chuàng)建工具條并設(shè)置為CFrameWindowImplBase:m_hWndToolBar成員 CreateSimpleStatusBar(); / 并創(chuàng)建狀態(tài)條 return 0; LRESULT OnFileExit(WORD,WORD wID, HWND,BOOL&) SendMessage(WM_CLOSE); / 框架知道PostQuitMessage return 0L; ;宏DECLARE_FRAME_WND_CLASS為框架設(shè)置通用資源ID。相同資源ID可以用在字符串表中用來(lái)作為框架標(biāo)題,菜單資源,快捷鍵表,圖標(biāo)和工具條資源等。如果WTL在創(chuàng)建框架窗口時(shí),用通用資源ID找

29、到了資源,就自動(dòng)加載。唯一的例外是工具條資源,你需要使用成員函數(shù)Create SimpleToolBar()來(lái)手工加載。狀態(tài)條不需要通用資源。在消息映射中,使用宏CHAIN_MSG_MAP來(lái)路由消息給類CFrameWindowImpl,小心處理像WM_SIZE(重置工具條和狀態(tài)條的大小)和WM_DESTROY(調(diào)用 PostQuitMessage)之類的消息。為了支持WTL的功能,你需要在stdafx.h中包含atlapp.h和atlframe.h:#define WIN32_LEAN_AND_MEAN#include <atlbase.h>#include <atlapp.

30、h>extern CAppModule _Module;#include <atlwin.h>#include <atlframe.h> 頭文件atlapp.h定義了CAppModule結(jié)構(gòu),它是從標(biāo)準(zhǔn)ATL的CComModule類派生,并添加有消息循環(huán)的變量。頭文件atlframe.h定義CFrameWindowImpl類。為了在我們WTL世界中創(chuàng)建SDI窗口,你需要實(shí)例化CMainFrame對(duì)象,并在winMain()調(diào)用基類的成員函數(shù)Create Ex()。CAppModule _Module;int APIENTRY WinMain() :InitComm

31、onControls(); _Module.Init(NULL, hInstance); CMainFrame wndMain; wndMain.CreateEx(); wndMain.ShowWindow(nCmdShow); wndMain.UpdateWindow(); CMessageLoop theLoop; _Module.AddMessageLoop(&theLoop); int nRet = theLoop.Run(); _Module.RemoveMessageLoop(); _Module.Term(); return nRet; CreateEx()成員函數(shù)調(diào)用基

32、類的CWindowImpl:Create()成員函數(shù),并使用通用資源ID來(lái)加載資源。CMessageLoop對(duì)象代替我們需要的手工消息隊(duì)列。ATL允許每個(gè)線程有一個(gè)消息隊(duì)列,這就是多線程SDI的實(shí)現(xiàn)。當(dāng)我們學(xué)習(xí)WTL的消息路由框架時(shí),我們將第二部分分析CMessage Loop類和CAppModule類的細(xì)節(jié)。 就這樣,我們的SDI應(yīng)用看起來(lái)就如圖4所示:圖4 使用WTL創(chuàng)建的SDI應(yīng)用我們?cè)O(shè)法簡(jiǎn)化了我們的代碼,并添加了一個(gè)新的特性:工具條。當(dāng)然,工具條和菜單條是老的風(fēng)格。用戶更喜歡命令條,就像他們?cè)贗E和MS Office中所看到的那樣。第三章 命令條 命令條是一種看起來(lái)像Windows菜單

33、的工具條,并擁有位圖的菜單項(xiàng)。從無(wú)到有寫命令條是很痛苦的。如果你是一員MFC程序員,Paul DiLascia在1998年1月就已經(jīng)那么做了,MSJ(給你應(yīng)用程序添加看起來(lái)像酷菜單按鈕的新的接口)。同樣,如果你是一員WTL程序員,僅限于在你的WM_ CREAT處理函數(shù)中使用WTL的CCommandBarCtrl類。LRESULT CMainFrame:OnCreate(UINT, WPARAM, LPARAM, BOOL&) / m_CmdBar是CCommandBarCtrl類型,在AtlCtrlw.h中定義 HWND hWndCmdBar = m_CmdBar.Create(m_h

34、Wnd, rcDefault, 0, ATL_SIMPLE_CMDBAR_PANE_STYLE); m_CmdBar.AttachMenu(GetMenu(); / 當(dāng)命令條代替當(dāng)前的菜單 m_CmdBar.LoadImages(IDR_MAINFRAME); SetMenu(NULL); / 首先創(chuàng)建簡(jiǎn)單工具條,設(shè)置m_hWndToolBar成員變量 HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME,FALSE,ATL_SIMPLE_TOOLBAR_PANE_STYLE); CreateSimpleReBar(A

35、TL_SIMPLE_REBAR_NOBORDER_STYLE); AddSimpleReBarBand(hWndCmdBar); / 添加m_hWndCmdBar作為Rebar條的一條帶 AddSimpleReBarBand(hWndToolBar, NULL, TRUE); / 添加m_hWndToolBar作為Rebar條的另一條帶 CreateSimpleStatusBar(); / 創(chuàng)建狀態(tài)條 return 0; 類CCommandBarCtrl是WTL封裝命令條功能和特性的類,類CMainFrame中包含了該類的成員。在上述WM_CREATE處理函數(shù)的程序片段中,我們首先通過調(diào)用CC

36、ommandBarCtrl: Create()創(chuàng)建命令條,把主框架作為父窗口參數(shù)傳遞。然后,我們通過調(diào)用CCommandBarCtrl: AttachMenu()來(lái)attach我們的菜單資源,再調(diào)用CCommandBarCtrl:LoadImages()來(lái)傳遞工具條資源。命令條使用工具條位圖,并把他們映射到菜單項(xiàng)的命令I(lǐng)D響應(yīng)中。因?yàn)槊顥l管理酷菜單,我們需要通過調(diào)用SetMenu(NULL)來(lái)剔除原來(lái)缺省的應(yīng)用程序菜單。然后,我們分別地通過調(diào)用CreateSimpleToolBarCtrl()和CreateSimpleRebar()來(lái)創(chuàng)建工具條控件和一個(gè)Rebar控件,傳遞工具條資源作為參數(shù)

37、。最后,我們通過調(diào)用CFrameWindowImplBase:Add SimpleRebarBand()添加命令條和工具條作為Rebar控件的2條帶。圖4顯示帶命令條的SDI的應(yīng)用程序。同時(shí)也顯示了程序片段中UI元素的映射關(guān)系。圖4 帶命令條的SDI應(yīng)用程序第四章 帶視圖的框架窗口就MFC程序員的通常習(xí)慣而言,框架窗口的客戶區(qū)是作為獨(dú)立的子窗口而存在的,被稱為視圖??蚣艽翱谪?fù)責(zé)窗口的修飾,比如菜單條和工具條;而視圖僅僅被用來(lái)呈現(xiàn)信息,而這些信息是運(yùn)行應(yīng)用程序的重要地方。當(dāng)包含分隔窗口或MDI時(shí),這一點(diǎn)特別重要,這將在后面講到。視圖可以是包含任何窗口句柄HWND的窗口。在處理WM_CREATE消

38、息期間,把視圖的HWND賦給框架窗口的成員變量m_hWndClient。例如,給我們SDI應(yīng)用添加位圖繪制功能,你可以如下所示那樣定義一個(gè)視圖類:class CBitmapView : public CWindowImpl<CBitmapView>public: CBitmapView(); CBitmapView(); BEGIN_MSG_MAP(CBitmapView) MESSAGE_HANDLER(WM_PAINT, OnPaint) END_MSG_MAP() LRESULT OnPaint(UINT, WPARAM, LPARAM, BOOL&);private

39、: HBITMAP m_hBmp;為了使用該視圖,如下所示操作:LRESULT OnCreate(UINT, WPARAM, LPARAM, BOOL&) / 創(chuàng)建視圖View (m_view是CBitmapView類型) m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE, WS_EX_CLIENTEDGE); return 0; 現(xiàn)在,框架窗口無(wú)論何時(shí)調(diào)整大小,這個(gè)視圖都會(huì)被工具條,命令條和狀態(tài)條所包圍。ATL/WTL提供大量窗口類可以作為視圖。你可以使用所有的窗口控件和通用控件封裝

40、類作為視圖。比如,通過把m_view類的類型從CBitmapView變?yōu)镃Edit(在atlctrls.h中定義),你就有簡(jiǎn)單的文本編輯器(見圖5)。圖5 簡(jiǎn)單的文本編輯器 如果你想從ATL的窗口封裝類中選一個(gè)類派生出來(lái)作為視圖,你可以有2個(gè)方面的繼承:C+方法與窗口方法。這就是超類化,這樣你可以添加功能和處理消息。比如,通過從CAxWindow繼承,我們可以有一個(gè)支持HTML的客戶視圖。/ 繼承C+方法為來(lái)繼承CAxWindow功能class CHtmlView : public CWindowImpl<CHtmlView, CAxWindow>public: / 繼承Windo

41、ws方法來(lái)預(yù)處理Windows消息 DECLARE_WND_SUPERCLASS(NULL, CAxWindow:GetWndClassName() BEGIN_MSG_MAP(CHtmlView) END_MSG_MAP()CHtmlView() AtlAxWinInit(); / 初始化控件宿主(在atlhost.h定義) ; 我們可以使用新的視圖來(lái)打開一個(gè)web頁(yè)面(圖6 顯示這個(gè)結(jié)果)LRESULT CMainFrame:OnCreate(UINT, WPARAM, LPARAM, BOOL&) / 創(chuàng)建該視圖(m_view 的類型是CHtmlView) m_hWndClien

42、t = m_view.Create(m_hWnd, rcDefault, "", WS_CHILD | WS_VISIBLE, WS_EX_CLIENTEDGE); return 0;圖6 使用新的視圖來(lái)打開網(wǎng)頁(yè)第五章 使用MRU盡管WTL提供支持視圖,但跟MFC不一樣,它沒有文檔的概念。如果你想在WTL應(yīng)用程序中支持文檔/視圖模型,你是很自由的。作為開始,我們已經(jīng)寫了一系列提供非常基本文檔功能的類,你可以用在你應(yīng)用程序中。這一章的WTLDocView例子就可見到這些類。如果你做過文檔工作,你幾乎可以肯定會(huì)在文件菜單中支持MRU(Most Recently Used)文件列

43、表。具有諷刺意味的是,盡管WTL不支持文檔,它通過CRecentDocumentList類(在atlmisc.h中定義)提供全功能MRU支持。主框架窗口通常管理CRecentDocumentList類的一個(gè)實(shí)例。在主框架窗口的WM_CREATE消息處理中,主框架窗口用一個(gè)文件菜單句柄來(lái)初始化CRecent DocumentList對(duì)象,這樣它就可以管理了。為了擁有MRU功能,框架窗口調(diào)用CRecentDocument List:ReadFromRegistry()成員函數(shù)來(lái)從指定的注冊(cè)表鍵查找16個(gè)入口。缺省情況下,限制的MRU文檔是4個(gè),但你也可以通過調(diào)用CRecentDocumentLis

44、t:SetMaxEntries()來(lái)改變這個(gè)值。LRESULT CMainFrame:OnCreate(UINT, WPARAM, LPARAM, BOOL&) m_mru.SetMenuHandle(GetMenu().GetSubMenu(0); m_mru.ReadFromRegistry(_T("SoftwareMyCompanyMyCoolApp"); m_mru.SetMaxEntries(16); 為了首次添加一個(gè)文檔到MRU列表,你可以調(diào)用CRecentDocumentList:AddToList():LRESULT CMainFrame:OnFil

45、eOpen(WORD, WORD, HWND, BOOL&)if (m_dlgOpen.DoModal(m_hWnd) = IDOK) / 試著打開文件if (bFileOpened) m_mru.AddToList(m_dlgOpen.m_bstrName);return 0; 你添加MRU的菜單項(xiàng)介于ID_FILE_MRU_FIRST和ID_FILE_MRU_LAST(在atlres.h定義)之間。你可以宏COMMAND_RANGE_HANDLER來(lái)處理這個(gè)范圍。當(dāng)用戶點(diǎn)擊MRU菜單項(xiàng)時(shí),處理函數(shù)可以調(diào)用CRecentDocumentList:GetFromList()返回文檔名。

46、在文檔打開后,處理函數(shù)應(yīng)該調(diào)用CRecentDocument List:MoveToTop()或CRecentDocumentList:Remove From List()來(lái)指示文檔打開與否。LRESULT CMainFrame:OnOpenUsingMRU(WORD, WORD wID, HWND, BOOL&) TCHAR szDocumentMAX_PATH;m_mru.GetFromList(wID, szDocument);/ Try to open the file specified by the menu item if (bFileOpened)m_mru.MoveT

47、oTop(wID);else m_mru.RemoveFromList(wID);return 0; 最后,當(dāng)你的應(yīng)用程序關(guān)閉時(shí),你需要調(diào)用CRecentDocumentList:WriteToRegistry()來(lái)把文件名列表寫入注冊(cè)表。void CMainFrame:OnFinalMessage(HWND /*hWnd*/)m_mru.WriteToRegistry(_T("SoftwareMyCompanyMyCoolApp");:PostQuitMessage(0);第六章 創(chuàng)建多線程SDI應(yīng)用程序與多個(gè)SDI應(yīng)用程序不同,IE瀏覽器使用一個(gè)應(yīng)用程序來(lái)管理多個(gè)頂級(jí)S

48、DI窗口。如果你想在應(yīng)用程序使用這個(gè)特性,你可以就使用WTL提供的多線程SDI支持。多線程SDI應(yīng)用程序的設(shè)計(jì)原理是很簡(jiǎn)單的:1> 每個(gè)頂級(jí)窗口(包括它們的子窗口)運(yùn)行在一個(gè)獨(dú)立的線程;2> 每個(gè)線程都有一個(gè)獨(dú)立的消息隊(duì)列,都是UI線程,具有消息處理和分派窗口消息的能力。這意味著不僅所有的線程共享進(jìn)程數(shù)據(jù),而且當(dāng)一個(gè)線程忙于處理某些事情的同時(shí),其它線程仍可以作出及時(shí)的響應(yīng);3> 這樣,每個(gè)頂級(jí)框架窗口對(duì)于用戶來(lái)說,就像一個(gè)獨(dú)立的應(yīng)用。創(chuàng)建這樣一個(gè)應(yīng)用程序的技巧在于設(shè)計(jì)一個(gè)線程管理類,它擁有:1> 為每個(gè)線程創(chuàng)建一個(gè)新的框架窗口;2> 管理線程類保存活動(dòng)線程的數(shù)量;

49、3> 保持命令行參數(shù)和初始化窗口大小。 WTL沒有為多線程SDI應(yīng)用提供任何基類。然而,它的應(yīng)用程序向?qū)Э梢詣?chuàng)建這種類型的應(yīng)用程序(本章節(jié)后面有充分的說明)。WTL向?qū)Мa(chǎn)生如下的線程管理器類:class CThreadManager public:struct _RunData / 線程初始化參數(shù)LPTSTR lpstrCmdLine;int nCmdShow;DWORD m_dwCount;/ 線程數(shù)HANDLE m_arrThreadHandlesMAXIMUM_WAIT_OBJECTS - 1;CThreadManager() : m_dwCount(0) DWORD AddThr

50、ead(LPTSTR lpstrCmdLine, int nCmdShow);void RemoveThread(DWORD dwIndex);int Run(LPTSTR lpstrCmdLine, int nCmdShow);WinMain將實(shí)例化線程管理類。 int WINAPI WinMain()hRes = _Module.Init(NULL, hInstance);CThreadManager mgr;int nRet = mgr.Run(lpstrCmdLine, nCmdShow);_Module.Term();return nRet; CThreadManager:Run()

51、方法創(chuàng)建一個(gè)新的UI線程,并使用MsgWaitForMultipleObjects()等待所有UI線程。當(dāng)MsgWaitForMultipleObjects()指出有一個(gè)線程已經(jīng)終止,它減少線程數(shù),并繼續(xù)等待。一旦所有線程結(jié)束,Run()方法返回,我們應(yīng)用程序也就結(jié)束。另一方面,如果MsgWaitForMultipleObjects()指出有一個(gè)窗口消息,而這個(gè)消息是WM_ USER,則線程管理類創(chuàng)建一個(gè)新的UI線程。int CThreadManager:Run(LPTSTR lpstrCmdLine, int nCmdShow) MSG msg;:PeekMessage(&msg,

52、NULL, WM_USER, WM_USER, PM_NOREMOVE); / 強(qiáng)迫創(chuàng)建消息隊(duì)列AddThread(lpstrCmdLine, nCmdShow);int nRet = m_dwCount;DWORD dwRet;while(m_dwCount > 0)dwRet = :MsgWaitForMultipleObjects(m_dwCount, m_arrThreadHandles, FALSE, INFINITE, QS_ALLINPUT);if(dwRet = 0xFFFFFFFF) :MessageBox(NULL, _T("ERROR: Wait for

53、multiple objects failed!"), _T("MultiSDI_HTMLView"), MB_OK);else if(dwRet >= WAIT_OBJECT_0 && dwRet <= (WAIT_OBJECT_0 + m_dwCount - 1) RemoveThread(dwRet - WAIT_OBJECT_0);else if(dwRet = (WAIT_OBJECT_0 + m_dwCount):GetMessage(&msg, NULL, 0, 0);if(msg.message = WM_USER)AddThread("", SW_SHOWNORMAL);else:MessageBeep(UINT)-1);else:MessageBeep(UINT)-1);return nRet; 注意:WTL向?qū)Мa(chǎn)生的代碼使用WM_USER消息來(lái)

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論