版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1VisualC++的可視化集成開發(fā)環(huán)境2Windows消息與命令
3單文檔與多文檔程序 4對話框與常用組件
5通用對話框大綱:1、VisualC++
的可視化集成開發(fā)環(huán)境教學(xué)目標(biāo):掌握VC++IDE,能夠在該環(huán)境下熟練使用AppWizard生成應(yīng)用程序框架。了解一個C++應(yīng)用程序的主要組成以及運行特點,掌握一些必要的相關(guān)理論知識。重點、難點:重點:熟悉VC++IDE,掌握AppWizard的使用方法,了解C++程序的主要組成。難點:一些必要的理論知識:MFC庫,Win32API等。教學(xué)方法:以演示為主,輔以實驗教學(xué)。教學(xué)內(nèi)容:
集成開發(fā)環(huán)境,或者說是IDE,是一個集成了源代碼編輯器、資源編輯器、程序編譯器、程序調(diào)試工具等相關(guān)工具的集合體。整個環(huán)境的構(gòu)建使得編輯應(yīng)用程序源代碼以及生成一個Windows應(yīng)用程序等工作變得相對輕松。IDE提供了大量的實用工具來支持可視化編程。這些實用工具包括:項目工作區(qū)、AppWizard,ClassWizard,WizardBar等。(一)項目工作區(qū)項目工作區(qū)是IDE的一個最重要的組成部分。每一個應(yīng)用程序都是由多個源文件組成的,另外還需要包含編譯和1.1
集成開發(fā)環(huán)境調(diào)試時的參數(shù)文件和庫文件名等,通常把這樣一組完整的文件集合稱作一個項目(或工程)。在一個項目工作區(qū)中可以處理:(1)一個工程和它所包含的文件。(2)一個工程的子工程。(3)多個相互獨立的工程。(4)多個相互依賴的工程(可以是不同編程語言編寫的)。項目工作區(qū)一般位于屏幕的左側(cè),它包含下面三種視圖:(1)文件視圖(FileView)顯示所創(chuàng)建的工程。展開該文件夾可以查看工程中所包含的文件,一般包括:項目的源文件,頭文件,資源文件等等。(2)類視圖(ClassView)
顯示項目中定義的C++類。展開該文件夾顯示當(dāng)前工程中定義的所有類,展開類可查看類的數(shù)據(jù)成員和成員函數(shù)以及全局變量等。利用ClassView可以方便快速地瀏覽應(yīng)用程序所包含的類的定義或類中成員函數(shù)的定義。(3)資源視圖(ResourceView)顯示當(dāng)前活動項目中所包含的資源。包括對話框、菜單快捷鍵等。(二)AppWizard(應(yīng)用程序向?qū)В谋举|(zhì)上講它是一個代碼生成器,它創(chuàng)建一個帶有特性(或者定制的)、含有類名及源代碼文件名的Windows應(yīng)用程序的基本框架。這些特性、類名都是通過對話框由用戶指定的。AppWizard可以使你迅速開始一個應(yīng)用程序,在以后的學(xué)習(xí)中我們要經(jīng)常和它打交道。(三)ClassWizard(類向?qū)В?/p>
ClassWizard使程序員從維護(hù)VisualC++類代碼這樣繁瑣復(fù)雜的工作中解脫出來。在需要定義一個新類、一個新的虛函數(shù)、或者一個新的消息處理函數(shù)時,ClassWizard可以編寫函數(shù)原型、函數(shù)體以及進(jìn)行Windows消息映射等??傊瓹lassWizard起到幫助程序員編寫源代碼、管理源代碼的作用。(四)資源編輯器單擊VisualC++Workspace窗口的ResourceView選項卡時,你可以選擇一個資源,以進(jìn)行編輯。這個主窗口中容納了一個適合資源類型的資源編輯器。此窗口也可以容納一個所見及所得的菜單編輯器和一個強大的對話框圖形編輯器,并且,它還包含了編輯圖標(biāo)、位圖和字符串的工具。在對話框編輯器中,除了標(biāo)準(zhǔn)的Windows控件和新的Windows常用控件之外,還允許你插入ActiveX控件。通常,每一個工程都有一個文本格式的資源腳本(RC)文件,它描述工程的菜單、對話框、字符串和快捷鍵資源。RC文件也可以有#include語句,以便從其他子目錄中引進(jìn)資源。這些資源包括特定的項目,例如位圖(BMP)和圖標(biāo)(ICO)文件,以及所有VisualC++程序公有的資源。1.2Vc++編程中的一些相關(guān)的概念(一)MFC庫
MFC是MicrosoftFoundationClass的縮寫。MFC庫是微軟公司開發(fā)出的功能強大的類庫,用來供程序員開發(fā)Windows應(yīng)用程序使用,換句話說,MFC庫是可以在應(yīng)用程序中使用的已經(jīng)定義好的有關(guān)C++類的集合,根據(jù)約定MFC庫類名以字母C作為開頭。MFC庫是我們學(xué)習(xí)的重點,我們所涉及到的是6.0版本的MFC庫。根據(jù)約定,MFC庫類名以字母C作為開頭。(二)應(yīng)用程序框架應(yīng)用程序框架的一種定義是:提供一般應(yīng)用程序需要的全部面向?qū)ο筌浖M件的集成集合。這個定義有點晦澀,通過一個具體的實例就很容易理解了。應(yīng)用程序框架是類庫的超集,一般的類庫只是一種孤立的類的集合,用來嵌入到任何程序中,但是應(yīng)用程序框架卻定義了程序的結(jié)構(gòu)。(三)Win32API
早期的Windows程序員使用C語言編寫Win16API的應(yīng)用程序。今天,如果要編寫32位應(yīng)用程序,你必須直接或間接地使用新的Win32API。大多數(shù)的Win16函數(shù)都有對應(yīng)的Win32函數(shù),但是參數(shù)會有變化。在MFC庫中的許多類封裝了Win32的API函數(shù),因而在實際的MFC編程中,你可以使用全局的Win32API函數(shù),也可以使用MFC庫中類的成員函數(shù)。(四)關(guān)于ActiveX控件
VB自1991年面世以來一直非常流行,它成功的原因要歸于其開放性,VB的16位版本支持VisualBasic控件(VBX),它是VB開發(fā)者可購買或者自己編寫的隨時可用的軟件組件。在微軟MFC開發(fā)小組也為MicrosoftVisualC++程序員找到了在他們程序中使用VBX的方法。VBX是建立在16位段式結(jié)構(gòu)的基礎(chǔ)上的,不適于32位結(jié)構(gòu),現(xiàn)在ActiveX控件(以前稱為OLE,或者OCX)以MicrosoftCOM(ComponentObjectModel)技術(shù)為基礎(chǔ),可以替代VBX。應(yīng)用程序開發(fā)者可以在VB和VisualC++6.0中使用ActiveX,ActiveX是用C++編寫的。我們可以不知道ActiveX的編寫技術(shù),我們只要學(xué)習(xí)在VisualC++應(yīng)用程序中如何使用它們。
ActiveX控件是軟件模塊,它插入到的C++程序中,與普通的Windows控件插入到程序中的方法一樣,至少表面上是這樣的。(五)Windows圖形設(shè)備接口(GDI)許多MS-DOS程序直接寫顯存和打印機接口。這種技術(shù)的缺點是對每一種顯示卡和每一種打印機型號,都需要提供驅(qū)動程序軟件。Windows引入了一個名為圖形設(shè)備接口(GDI)的抽象層。Windows提供視頻和打印機驅(qū)動程序,所以,你的程序不必知道系統(tǒng)連接的顯卡和打印機的類型。程序不是尋址硬件,而是調(diào)用GDI函數(shù),這些函數(shù)引用名為設(shè)備環(huán)境(DC)的數(shù)據(jù)結(jié)構(gòu)Windows把設(shè)備環(huán)境結(jié)構(gòu)映射到物理設(shè)備,并發(fā)出適當(dāng)?shù)妮斎?輸出指令。圖形設(shè)備接口幾乎與直接視頻一樣快,并且它允許不同的Windows應(yīng)用程序來共享顯示。1.3MFC類庫的框架結(jié)構(gòu)
前面提到,MFC庫是微軟公司為了用戶開發(fā)應(yīng)用程序需要而開發(fā)出的功能強大的類庫。MFC為程序員實現(xiàn)了所有應(yīng)用程序的公共部分,它不僅包含了C++基類,還包含了WinMain函數(shù)(Windows下的主函數(shù))以及其它一些支持菜單、窗口、對話框、設(shè)備上下文等的組件。MFC的核心是以C++形式封裝了大部分的WindowsAPI,因此MFC向用戶提供了一個面向Windows中結(jié)構(gòu)的簡單的C++成員函數(shù)的接口。
MFC類庫可分為:基礎(chǔ)類、宏和全局函數(shù)兩個主要部分(1)基礎(chǔ)類。MFC中的基礎(chǔ)類按功能可以分為一下幾類:基類、應(yīng)用程序框架類、命令相關(guān)類、文檔/視圖類、線程類、可視對象類、窗口類、對話框類、屬性表類、控制類、菜單類、設(shè)備描述表類、繪圖對象類、文件類、診斷類、異常類數(shù)據(jù)庫類等等。(2)宏和全局函數(shù)。若某個函數(shù)或變量不是屬于某一個具體的類,那么它就是一個全局函數(shù)或者是全局變量。宏和全局函數(shù)提供以下功能:數(shù)據(jù)類型、運行時刻對象類型服務(wù)、診斷服務(wù)、異常處理、CString格式化及信息框顯示、消息映射、應(yīng)用信息管理對象連接和嵌入(OLE)等。全局函數(shù)以“Afx”為前綴。所有全局變量都是以“afx”為前綴,宏不帶任何前綴,但是全部是大寫。從繼承關(guān)系來看,又可將MFC中的類分成兩大類:大多數(shù)的MFC類是從Cobject繼承下來的,Cobject類描述了幾乎所有的MFC中其它類的一些公共特性。Cobject類為派生類提供的服務(wù)主要包括:對象診斷、輸出對象內(nèi)部信息、對象有效性檢查、運行時訪問類的信息、安全可靠地把通用的Cobject指針轉(zhuǎn)化為派生類的指針,等等。另外一些類則不是從Cobject類繼承下來的,這些類包括:字符串類(CString)、日期時間類(CTime)、矩形類(CRect)等。下圖是MFC庫的框架圖1.4
對一個最簡單的應(yīng)用程序框架的分析
下面的代碼是MyApp應(yīng)用程序的頭文件和實現(xiàn)文件。類CMyApp和CMyFrame都是從MFC庫基類派生出來的://MyApp.h//applicationclassclassCMyApp:publicCWinApp{public:virtualBOOLInitInstance();};//framewindowclassclassCMyFrame:publicCFrameWnd{public:CMyFrame();protected://"afx_msg"indicatesthatthenexttwofunctionsarepartoftheMFClibrarymessagedispatchsystemafx_msgvoidOnLButtonDown(UINTnFlags,CPointpoint);afx_msgvoidOnPaint();DECLARE_MESSAGE_MAP()};下面是MyApp應(yīng)用程序的實現(xiàn)文件:#include<afxwin.h>//MFClibraryheaderfiledeclaresbaseclasses#include"myapp.h"CMyApptheApp;//theoneandonlyCMyAppobjectBOOLCMyApp::InitInstance(){m_pMainWnd=newCMyFrame();m_pMainWnd->ShowWindow(m_nCmdShow);m_pMainWnd->UpdateWindow();returnTRUE;}BEGIN_MESSAGE_MAP(CMyFrame,CFrameWnd)ON_WM_LBUTTONDOWN()ON_WM_PAINT()END_MESSAGE_MAP()CMyFrame::CMyFrame(){Create(NULL,"MYAPPApplication");}voidCMyFrame::OnLButtonDown(UINTnFlags,CPointpoint){TRACE("EnteringCMyFrame::OnLButtonDown-%lx,%d,%d\n",(long)nFlags,point.x,point.y);//在調(diào)試窗口顯示}voidCMyFrame::OnPaint(){CPaintDCdc(this);dc.TextOut(0,0,“Hello,world!”);//在客戶區(qū)輸出
}下面給出一些程序元素的分析:WinMain函數(shù):Windows要求應(yīng)用程序有一個WinMain函數(shù)。在這個例子中,我們看不到WinMain函數(shù),因為它被隱藏到應(yīng)用程序框架內(nèi)部了。CMyApp類:類CMyApp的一個對象代表一個應(yīng)用程序。程序定義了一個全局的CMyApp對象,即theApp。CWinApp基類決定theApp的大多數(shù)行為。應(yīng)用程序啟動:當(dāng)用戶啟動應(yīng)用程序時,Windows調(diào)用應(yīng)用程序框架內(nèi)置的WinMain函數(shù),并且,WinMain尋找CWinApp派生出的全局構(gòu)造的應(yīng)用程序?qū)ο蟆2灰?,在C++程序中,全局對象在主程序之前構(gòu)造。成員函數(shù)CMyApp::InitInstance:當(dāng)WinMain函數(shù)找到應(yīng)用程序?qū)ο髸r,它調(diào)用虛成員函數(shù)InitInstance,這個成員函數(shù)調(diào)用所需要的構(gòu)造和顯示應(yīng)用程序的主框架窗口。我們必須在派生的應(yīng)用程序類中重載InitInstance,因為CWinApp基類不知道需要什么樣的主框架窗口。成員函數(shù)CWinApp::run函數(shù)run隱藏在基類中,但是它發(fā)送應(yīng)用程序的消息到它的窗口,這樣可以保持應(yīng)用程序的運行。在WinMain調(diào)用InitInstance之后,便調(diào)用run。CMyFrame類:類CMyFrame的一個對象代表應(yīng)用程序的主框架窗口。當(dāng)構(gòu)造函數(shù)調(diào)用基類CFrameWnd的成員函數(shù)Create時,Windows創(chuàng)建實際窗口結(jié)構(gòu),應(yīng)用程序框架把它連接到C++對象。函數(shù)ShowWindow和UpdateWindow也是基類的成員函數(shù),必須調(diào)用他們來顯示來顯示窗口。CMyFrame::OnLButtonDown函數(shù):鼠標(biāo)左鍵按下映射到CMyFrame的一個成員函數(shù)。應(yīng)用程序執(zhí)行時,鼠標(biāo)左鍵按下時,會調(diào)用這個函數(shù),該函數(shù)調(diào)用MFC庫的TRACE宏,以便在調(diào)試窗口顯示信息。CMyFrame::OnPaint函數(shù):每次重新繪圖時(在程序的開始,當(dāng)用戶改變窗口的大小,全部或部分窗口重新顯現(xiàn)時),應(yīng)用程序框架就調(diào)用CMyFrame的這個重要的映射成員函數(shù)。語句CpaintDC與圖形設(shè)備接口(GDI)有關(guān)。關(guān)閉應(yīng)用程序:用戶通過主框架窗口來關(guān)閉應(yīng)用程序。這個操作激發(fā)一系列事件的發(fā)生,包括CMyFrame對象的析構(gòu),從Run中退出、從WinMain中退出CMyApp對象的析構(gòu)。1.5標(biāo)識符命名方法
好的表示符命名方法使變量、函數(shù)易于記憶,并且程序的可都性大大提高。在VC++中對于變量、函數(shù)的命名有自己的一套方法,它是由微軟的一個名叫西蒙尼的開發(fā)人員提出來的,由于西蒙尼的國籍是匈牙利,所以這種標(biāo)識符命名法稱作匈牙利命名法。匈牙利命名法主要有兩條規(guī)則:(一)標(biāo)識符的名字以一個或者多個小寫字母開頭,這些小寫字母用來指定數(shù)據(jù)類型。下面是常見的數(shù)據(jù)類型的標(biāo)準(zhǔn)前綴:
前綴數(shù)據(jù)類型
c字符(char)
s短整型(short)n整數(shù)(integer)
sz以‘\0’結(jié)尾的字符串
b字節(jié)
iint(整數(shù))
fBOOLW字(WORD,無符號短整數(shù))
l長整數(shù)(long)
hHANDLE(句柄,無符號int)
m_類的成員變量
fn函數(shù)
dw雙字(DWORD,無符號長整數(shù))2Windows消息與命令教學(xué)目標(biāo):了解Windows編程模式中的消息驅(qū)動機制,熟練使用ClassWizard進(jìn)行變量定義,消息映射等。能夠編寫菜單并進(jìn)行必要的命令消息映射重點、難點:重點:使用ClassWizard進(jìn)行消息映射難點:消息的分類以及消息映射使用的模型。教學(xué)方法:以演示為主,輔以實驗教學(xué)。教學(xué)內(nèi)容:2.1消息驅(qū)動機制消息是一種報告有關(guān)事件發(fā)生的通知,類似于DOS下的用戶輸入。Windows應(yīng)用程序是由消息驅(qū)動的。Windows操作系統(tǒng)允許多個任務(wù)同時運行,應(yīng)用程序的輸入輸出由Windows統(tǒng)一管理;Windows系統(tǒng)下每一個窗口都維護(hù)一個消息隊列,操作系統(tǒng)接收和管理所有輸入消息、系統(tǒng)消息,并把它們發(fā)送給相應(yīng)窗口的消息隊列。應(yīng)用程序初始化完成后,進(jìn)入消息循環(huán),維護(hù)自己的消息隊列,從中取出消息,對其進(jìn)行處理。編寫消息處理函數(shù)是Windows編程的主要工作之一。Windows應(yīng)用程序的消息來源有以下四種:
(1)輸入消息:包括鍵盤和鼠標(biāo)的輸入。這一類消息首先放在系統(tǒng)消息隊列中,然后由Windows將它們送入應(yīng)用程序消息隊列中,由應(yīng)用程序來處理消息。
(2)控制消息:用來與Windows的控制對象,如列表框、按鈕、檢查框等進(jìn)行雙向通信。當(dāng)用戶在列表框中改動當(dāng)前選擇或改變了檢查框的狀態(tài)時發(fā)出此類消息。這類消息一般不經(jīng)過應(yīng)用程序消息隊列,而是直接發(fā)送到控制對象上去。
(3)系統(tǒng)消息:對程序化的事件或系統(tǒng)時鐘中斷作出反應(yīng)。一些系統(tǒng)消息,像DDE消息(動態(tài)數(shù)據(jù)交換消息)要通過Windows的系統(tǒng)消息隊列,而有的則不通過系統(tǒng)消息隊列而直接送入應(yīng)用程序的消息隊列,如創(chuàng)建窗口消息。
(4)用戶消息:這是程序員自己定義并在應(yīng)用程序中主動發(fā)出的,一般由應(yīng)用程序的某一部分內(nèi)部處理?;贛FC類庫的應(yīng)用程序完成初始化后,調(diào)用Run()函數(shù)進(jìn)入消息循環(huán)。在CWnd類(所有窗口類的基類)中預(yù)定義標(biāo)準(zhǔn)Windows消息的處理函數(shù),處理函數(shù)的名稱以“On”開始,用戶可以根據(jù)需要重寫這些函數(shù)。
在CWnd類中,標(biāo)準(zhǔn)Windows消息的處理函數(shù)聲明都帶有afx_msg關(guān)鍵字,例如消息WM_PAINT的處理函數(shù)被聲明為:
afx_msgvoidOnPaint();
關(guān)鍵字afx_msg用于把消息處理函數(shù)與其它CWnd成員函數(shù)分開,這些函數(shù)是通過消息映射實現(xiàn)的,依賴于標(biāo)準(zhǔn)的預(yù)處理宏。預(yù)處理之后,關(guān)鍵字afx_msg的位置就變成了空白。以全局對象theApp為例,其中的消息映射如下:
BEGIN_MESSAGE_MAP(CEx01App,CWinApp) //{{AFX_MSG_MAP(CEx01App)ON_COMMAND(ID_APP_ABOUT,OnAppAbout)//注意:ClassWizard(類向?qū)В⒖赡芴砑踊騽h除消息映射宏
//}}AFX_MSG_MAP //標(biāo)準(zhǔn)的基于文檔的文件命令
ON_COMMAND(ID_FILE_NEW,CWinApp::OnFileNew) ON_COMMAND(ID_FILE_OPEN,CWinApp::OnFileOpen) //標(biāo)準(zhǔn)的打印設(shè)置命令
ON_COMMAND(ID_FILE_PRINT_SETUP,CWinApp::OnFilePrintSetup)END_MESSAGE_MAP()
其中的BEGIN_MESSAGE_MAP和END_MESSAGE_MAP都是預(yù)處理宏,用于聲明消息映射的開始和結(jié)束。而在類中重新修改的消息處理函數(shù)聲明形式為:
//Generatedmessagemapfunctions protected: //{{AFX_MSG(CEx01Ciew) afx_msgvoidOnPaint(); //}}AFX_MSG DECLARE_MESSAGE_MAP()
最后的DECLARE_MESSAGE_MAP宏,聲明在該類中使用消息映射。2.2應(yīng)用程序菜單
Windows菜單是應(yīng)用程序命令項列表,菜單項可以是文字或位圖。通過選擇菜單項使應(yīng)用程序完成與菜單項相關(guān)的命令。下面通過一個例子來介紹如何在應(yīng)用程序中建立新菜單、如何在菜單中加入新的菜單項、如何為菜單項建立相應(yīng)的命令處理函數(shù)以實現(xiàn)消息映射。首先看看如何在已有的下拉菜單中增加一個菜單項。第一步,編輯菜單項資源,步驟如下:
(1)運行AppWizard創(chuàng)建Ex02,選中“Singledocument”(單文檔SDI)單選項后,直接按下Finish按鈕。(2)在項目工作區(qū)窗口中打開ResourceView(資源視圖)。
(3)雙擊該視圖中的Menu圖標(biāo),展開菜單資源。
(4)雙擊IDR_MAINFRAME,打開菜單編輯器,如圖2.1所示。
(5)可以看到,在“文件”菜單的最下方有一個空白菜單項,用戶可以編輯這個菜單項來添加菜單項。也可以單擊某個菜單項,然后按鍵盤上的Insert鍵,在選定的菜單項前面插入一個新的菜單項。
(6)雙擊空白菜單項,打開MenuItemProperties對話框,如圖2.2所示。圖2.1菜單編輯器圖2.2MenuItemProperties對話框(7)在Caption文本框中輸入新菜單項名,輸入的名字是“Demo”。在ID組合框中輸入新菜單項的ID。注意,這個ID必須是唯一的,不能和別的ID重名。一般菜單項ID的命令規(guī)則是:ID_菜單名_菜單項名。因此將該菜單項命名為ID_FILE_DEMO。
(8)關(guān)閉該對話框,新的菜單項已經(jīng)添加到原有的菜單中。運行這個程序可以看到,在“文件”菜單的最下方有一個“Demo”菜單項,如圖2.3所示。注意:這里選SDI類型,一是為了簡化程序設(shè)計,二是想讓讀者對比SDI應(yīng)用程序(如本例的Ex02)和MDI應(yīng)用程序在外觀和使用上的一些區(qū)別,對SDI和MDI有一個簡單了解。
第二步,進(jìn)行消息映射。圖2.3中Demo菜單項是灰色的,不可用,因為它沒有命令處理函數(shù)。為此必須要對菜單項進(jìn)行消息映射,為新的菜單項建立處理函數(shù)。操作步驟如下:(1)在View菜單中選擇ClassWizard選項或使用加速鍵Ctrl+W,打開ClassWizard對話框,選中其中的MessageMaps選項卡,如圖1.4所示。(2)在ClassName下拉列表框中選擇CEx02View。(3)在ObjectIDs列表框中選擇菜單項Demo的ID,即ID_FILE_DEMO。(4)在Messages列表框中單擊COMMAND,此時AddFunction按鈕變亮,表示可以圖23添加了Demo菜單項的應(yīng)用程序圖2.4ClassWizard的MessageMaps選項卡
添加處理函數(shù)。單擊AddFunction按鈕或雙擊COMMAND,彈出AddMemberFunction對話框,如圖2.5所示。在Memberfunctionname編輯框中給出了系統(tǒng)推薦使用的函數(shù)名是OnFileDemo。通??梢允褂眠@個缺省的名字,如果有特殊需要也可以修改它。單擊OK按鈕,這時可以在Memberfunctions列表框中看到Demo菜單項的處理函數(shù)已經(jīng)創(chuàng)建,如圖1.6所示。也就是說,當(dāng)用戶選擇Demo菜單項時,應(yīng)用程序?qū)⒄{(diào)用OnFileDemo函數(shù)實現(xiàn)消息映射。在圖2.6中單擊OK按鈕完成消息映射。
圖2.5AddMemberFunction對話框圖2.6創(chuàng)建Demo的處理函數(shù)OnFileDemo
第三步,編寫響應(yīng)程序代碼。現(xiàn)在為OnFileDemo函數(shù)編寫實際的處理程序。比如,當(dāng)用戶選擇菜單項Demo時,在窗口中顯示“您選擇了Demo菜單項。”信息。操作步驟如下:
(1)在文檔類CEx02Doc中聲明一個CString對象m_String。從上一章可以知道,程序中的文檔對象用于存儲在視圖中的數(shù)據(jù),因此這里選擇在文檔類中創(chuàng)建字符串對象。在項目工作區(qū)中選ClassView類視圖,雙擊CEx02Doc,打開類編輯器,如圖2.7所示。對CEx02Doc.h頭文件中修改CEx02Doc類的定義:
classCEx02Doc:publicCDocument{protected://createfromserializationonly CEx02Doc(); DECLARE_DYNCREATE(CEx02Doc)
CStringm_String; //輸入本行內(nèi)容
……}
程序中的黑體字部分表示需要輸入的內(nèi)容,本書下面章節(jié)的片段中均使用此方法?!癿_”前綴聲明成員變量是VisualC++的標(biāo)準(zhǔn),讀者應(yīng)該習(xí)慣于使用這種變量聲明方法。(2)在CEx02Doc的構(gòu)造函數(shù)中初始化m_String。在類視圖中單擊文檔類CEx02Doc前面的“+”,將其展開。雙擊CEx02Doc()函數(shù),將會在正文窗口內(nèi)打開代碼編輯器。對CEx02Doc()函數(shù)編輯如下:CEx02Doc::CEx02Doc(){ //TODO:addone-timeconstructioncodehere m_String=""; //輸入本行內(nèi)容}(3)編輯OnFileDemo()函數(shù),將m_String賦值為“您選擇了Demo菜單項?!?。在圖2.6(若在屏幕上看不到它,按下Ctrl+W加速鍵)的Memberfunction列表框中單擊OnFileDemo,然后按下EditCode按鈕或雙擊OnFileDemo,出現(xiàn)Ex02View.cpp代碼編輯窗口,并且光標(biāo)已經(jīng)處于需要編輯的函數(shù)OnFileDemo中。編輯OnFileDemo()函數(shù):
voidCEx02View::OnFileDemo(){//TODO:Addyourcommandhandlercodehere
CEx02Doc*pDoc=GetDocument();//輸入以下四行內(nèi)容
ASSERT_VALID(pDoc); pDoc->m_String="您選擇了Demo菜單項。"; Invalidate();}
由于對象m_String處于文檔類CEx02Doc中,要在視圖類中對這一對象進(jìn)行存取,必須先獲得一個指向文檔對象的指針,這可通過GetDocument函數(shù)完成。//ASSERT_VALID()函數(shù)則用于確保一定能獲取該指針,這是VisualC++的技術(shù),如果不使用這一函數(shù),可能會產(chǎn)生錯誤信息。Invalidate()函數(shù)使客戶區(qū)內(nèi)容失效,強迫程序調(diào)用OnDraw()函數(shù),重新繪制視圖。
(4)用OnDraw()函數(shù)重新繪制客戶區(qū)。視圖對象管理程序客戶區(qū),對客戶區(qū)的繪制工作由成員函數(shù)OnDraw()完成。幾乎所有應(yīng)用程序的繪制工作都通過這一函數(shù)實現(xiàn),編程時必須修改這個函數(shù)。
在項目工作區(qū)中單擊類視圖中CEx02View前面的“+”將其展開,雙擊OnDraw()函數(shù),打開CEx02View.cpp編輯窗口,光標(biāo)位于OnDraw()函數(shù)中。按下述內(nèi)容對OnDraw函數(shù)進(jìn)行編輯:voidCEx02View::OnDraw(CDC*pDC){ CEx02Doc*pDoc=GetDocument(); ASSERT_VALID(pDoc); //TODO:adddrawcodefornativedatahere
pDC->TextOut(0,0,pDoc->m_String);//輸入本行}
這里使用了CDC類的成員函數(shù)TextOut()函數(shù),該函數(shù)用于在CDC設(shè)備類中顯示字符串。它有三個參數(shù),前兩個參數(shù)用于指示字符串顯示的相對位置,第三個參數(shù)用于傳遞要顯示的字符串?,F(xiàn)在編譯運行這個程序。在“文件”菜單中選擇Demo菜單項,窗口中顯示“您選擇了Demo菜單項?!钡男畔?,如圖2.8所示。建立新菜單的方法與添加菜單項類似,首先編輯菜單資源,然后為相應(yīng)的菜單項建立消息映射,編寫消息處理函數(shù)。在資源編輯器中建立新菜單的一般步驟如下:圖2.8Ex02程序運行的結(jié)果(1)打開菜單編輯器,可以看到在菜單的最右邊有一個空白的菜單項,如圖2.9所示。
(2)編輯該空白菜單項(雙擊它,出現(xiàn)對話框),將其命名為NewMenu,如圖2.10所示??梢钥吹?,Pop-up復(fù)選框是被選中的,表示本菜單帶有彈出式子菜單,因此無須定義本菜單的ID。
(3)關(guān)閉MenuItemProperties對話框,NewMenu菜單下方已經(jīng)自動增加了一個空白的菜單項,如圖2.11所示。用戶可以通過編輯該空白菜單項,向NewMenu菜單添加菜單項。圖2.9菜單編輯器
圖2.10NewItemProperties對話框圖2.11為NewMenu添加菜單項(4)向NewMenu菜單中添加兩個菜單項New1和New2,并將其ID分別命名為ID_NEWMENU_NEW1和ID_NEWMENU_NEW2,如圖2.12所示。在Windows中常??梢钥吹?,點擊某個菜單項還可以顯示下一級子菜單。例如為NewMenu的New2添加子菜單Sub1和Sub2的步驟如下:
(1)在菜單編輯器中雙擊New2菜單項,打開MenuItemProperties對話框,如圖2.13所示。
(2)選中對話框中的Pop-up復(fù)選框,此時ID下拉列表框中的ID_NEWMENU_NEW2自動消失。關(guān)閉該對話框后,在菜單項New2右邊出現(xiàn)一個黑色的三角和一個空的子菜單,如圖2.14所示。圖2.12新菜單建立完成圖2.13MenuItemProperties對話框圖2.14New2帶有下一級子菜單(3)編輯New2的空白子菜單,添加Sub1和Sub2兩個菜單項,如圖2.15所示。并將它們的ID分別命名為ID_NEWMENU_NEW2_SUB1和ID_NEWMENU_NEW2_SUB2。無論菜單項在哪一級菜單中,建立它們的命令處理函數(shù)的方法都是一樣的。因為所有的菜單項都有一個唯一的ID標(biāo)識,菜單項所處的位置不影響它們的處理函數(shù)的編寫。圖2.15為NewMenu添加子菜單
2.3快捷鍵和加速鍵
1.快捷鍵“文件”菜單中的“F”帶有下劃線,這表示用戶可以通過按下Alt+F打開“文件”菜單,而無須用鼠標(biāo)選取。F稱為“文件”菜單的快捷鍵。增加快捷鍵非常簡單,只要在給定菜單名或菜單項名中的某個位置多寫一個“&”字符,就把該字符后面的那個字符定義成了快捷鍵。比如把NewMenu中的字母Mp定義為快捷鍵,只需將菜單名設(shè)置為New&Menu即可,如圖2.16所示。圖2.16增加快捷鍵2.加速鍵加速鍵是用于某個菜單項的控制鍵,用戶可以通過按這些鍵直接打開相應(yīng)的菜單選項,而無須打開菜單選取。例如,在Windows中,按Ctrl+V與“編輯”菜單中的“粘貼”選擇是相同的。注意,只有菜單項才有加速鍵。下面是向NewMenu菜單中的New1菜單項增加加速鍵Ctrl+F1的步驟:
(1)在項目工作區(qū)的資源視圖中雙擊Accelerator圖標(biāo)。
(2)雙擊IDR_MAINFRAME圖標(biāo),打開加速鍵編輯器,如圖2.17所示。
(3)雙擊加速鍵編輯器中的最后一個空白項,打開AccelProperties對話框,如圖2.18所示。圖2.17加速鍵編輯器圖2.18AccelProperties對話框(4)在ID下拉列表框中選擇New1菜單項的ID,即“ID_NEWMENU_NEW1”。
(5)在Key下拉列表框中選擇VK_F1,關(guān)閉對話框,把Ctrl+F1加入到New1菜單項中。
(6)最后還要將New1的標(biāo)題改為“New1Ctrl+F1”。
2.4工具欄和狀態(tài)欄
1.工具欄工具欄顯示一組按鈕,每個按鈕對應(yīng)一個菜單項。工具欄按鈕是方便直觀的用戶界面,用戶可以直接點擊某個按鈕,其作用和選取相應(yīng)菜單選項是相同的??梢园讶魏尾藛雾椷B接到工具欄中的按鈕。以“文件”菜單中的Demo菜單項為例,將其添加到工具欄的步驟如下:
(1)在項目工作區(qū)的資源視圖中,雙擊Toolbar圖標(biāo)。
(2)雙擊IDR_MAINFRAME圖標(biāo),打開工具欄編輯器,同時在它的右邊出現(xiàn)一組工具欄繪圖工具,如圖2.19所示。圖2.19工具欄編輯器(3)選取工具欄編輯器中工具欄最右邊的空白按鈕,使用繪圖工具在新按鈕中畫出如圖2.19所示的圖形。
(4)雙擊工具欄編輯器中編輯好的新按鈕,打開ToolbarButtonProperties對話框,如圖2.20所示。
(5)在ID下拉列表框中選擇ID_FILE_DEMO,新的按鈕已經(jīng)連接到Demo菜單項上。運行程序,單擊新按鈕,可以看到窗口中顯示出與選擇Demo菜單項相同的信息,如圖2.21所示。
2.狀態(tài)欄狀態(tài)欄用于顯示某些提示信息。當(dāng)用戶把鼠標(biāo)移到某個菜單項或工具欄按鈕上時,狀態(tài)欄中通常會顯示一些簡單的信息,提示用戶該選項可以做哪些操作。圖2.20ToolbarProperties對話框圖2.21添加了工具欄按鈕的應(yīng)用程序
增加工具欄按鈕的狀態(tài)欄提示,只需在圖2.20所示的ToolbarProperties對話框的Prompt文本框中放置相應(yīng)信息即可。其操作步驟如下:
(1)打開需要增加提示的按鈕的ToolbarProperties對話框。這里為Demo按鈕增加提示信息,如圖2.22所示。
(2)在Prompt文本框中輸入這個按鈕的說明:“在窗口顯示相關(guān)的信息\n演示信息”,這意味著當(dāng)用戶將鼠標(biāo)移到Demo按鈕上時,狀態(tài)欄中將顯示“在窗口顯示相關(guān)信息”,而在鼠標(biāo)旁邊將顯示“演示信息”。再次運行程序,看一看當(dāng)鼠標(biāo)移到Demo按鈕上時,是否會出現(xiàn)如圖2.23所示的提示信息。圖2.22為工具欄按鈕增加提示信息圖2.23添加了提示信息的工具欄按鈕3單文檔與多文檔程序教學(xué)目標(biāo):了解文檔/視圖的模式,掌握單文檔和多文檔主要區(qū)別。能夠開發(fā)簡單的單文檔應(yīng)用程序,進(jìn)一步強化應(yīng)用前面所學(xué)的知識。重點、難點:重點:文檔對象與視圖對象之間的關(guān)系。難點:對文檔/視圖模式的理解。教學(xué)方法:以演示為主,輔以實驗教學(xué)。教學(xué)內(nèi)容:3.1文檔—視圖結(jié)構(gòu)使用MFCAppWizard創(chuàng)建應(yīng)用程序,首先要求用戶確定應(yīng)用程序的基本結(jié)構(gòu):單文檔(SDI)、多文檔(MDI)或基于對話框的應(yīng)用程序界面。其中單文檔或多文檔創(chuàng)建的應(yīng)用程序是基于文檔的應(yīng)用程序。創(chuàng)建基于文檔的應(yīng)用程序一般需要經(jīng)過以下幾步:①為每一種類型的文檔定義一個派生自CDocument類的派生類;②添加用于存儲文檔數(shù)據(jù)的成員變量;③編寫用于實現(xiàn)讀取和修改文檔數(shù)據(jù)的函數(shù)成員。
在MFC中,用文檔—視圖結(jié)構(gòu)可將數(shù)據(jù)從用戶對數(shù)據(jù)的觀察中分離出來。文檔用來管理應(yīng)用程序的數(shù)據(jù),視圖用于顯示文檔并管理與用戶的交互過程。實際上,視圖在用戶與文檔之間起橋梁作用,如圖3.1所示。MFCAppWizard創(chuàng)建的文檔是從CDocument類派生的,視圖類是從CView類派生的。
CDocument類為應(yīng)用程序定義的文檔類提供基本功能,而CView類為應(yīng)用程序定義的視圖類提供基本功能。視圖和文檔連接在一起,在文檔與用戶間起中介作用。視圖在屏幕上顯示文檔數(shù)據(jù)并把用戶輸入轉(zhuǎn)換成對文檔的操作。
圖3.1文檔—視圖之間的關(guān)系
3.2單文檔應(yīng)用程序的建立上一節(jié)的例子通過菜單顯示了一行字符,是通過菜單完成的,本節(jié)直接在應(yīng)用程序的窗口中顯示一些信息,如“VisualC++的單文檔應(yīng)用程序很簡單”,按如下步驟進(jìn)行操作:
(1)利用MFCAppWizard創(chuàng)建單文檔的應(yīng)用程序Ex03。
(2)在項目工作區(qū)的類視圖中單擊CEx03View類前面“+”,展開該類。
(3)雙擊OnDraw()函數(shù)名,打開Ex03View.cpp編輯窗口。
(4)對OnDraw()函數(shù)按如下內(nèi)容編輯:voidCEx03View::OnDraw(CDC*pDC){ CEx03Doc*pDoc=GetDocument(); ASSERT_VALID(pDoc);
CStringm_Message="VisualC++的單文檔應(yīng)用程序很簡單";
pDC->TextOut(30,30,m_Message);}
現(xiàn)在編譯運行程序?!癡isualC++的單文檔應(yīng)用程序很簡單”顯示在程序窗口中,但是,一個好的程序必然少不了與用戶之間的交互。在Windows中,用戶最常用的輸入工具無非是鍵盤和鼠標(biāo),如果要顯示由鍵盤輸入的字符串,應(yīng)該如何處理呢?下面演示如何處理鍵盤和鼠標(biāo)輸入以及存儲和讀取文檔數(shù)據(jù)。首先,建立鍵盤輸入存儲區(qū),用于存儲鍵盤輸入的字符串。程序中的文檔對象用于存儲在視圖中顯示的數(shù)據(jù),因此下面在文檔類中創(chuàng)建鍵盤輸入存儲區(qū)。當(dāng)用戶擊鍵時,把鍵入的數(shù)據(jù)加到一個字符串中,并在視圖中顯示這個字符串。下面修改CEx03Doc類,增加字符串?dāng)?shù)據(jù)成員m_Message:(1)在類視圖中雙擊CEx03Doc圖標(biāo),在Ex03Doc.h編輯窗口修改CEx03Doc的類聲明:classCEx03Doc:publicCDocument{protected://createfromserializationonly CEx03Doc(); DECLARE_DYNCREATE(CEx03Doc)
CStringm_Message; //在此加入變量聲明
……}(2)在文檔類CEx03Doc的構(gòu)造函數(shù)中,把這個字符串變量初始化為空字符串。在類視圖中單擊CEx03Doc圖標(biāo)前的“+”,展開該類。雙擊CEx03Doc()函數(shù),在Ex03Doc.cpp編輯窗口修改CEx03Doc的構(gòu)造函數(shù):CEx03Doc::CEx03Doc(){ //TODO:addone-timeconstructioncodehere
m_Message="
"; //對m_Message變量初始化}
現(xiàn)在來處理鍵盤輸入。鍵盤輸入產(chǎn)生WM_CHAR消息,處理鍵盤輸入就必須編寫相應(yīng)的消息處理函數(shù)。首先按照下面的步驟使用ClassWizard來完成消息的映射:
(1)按下Ctrl+W打開MFCClassWizard對話框,并選擇MessageMaps選項卡。由于需要添加的消息處理函數(shù)屬于CEx03View類,在Classname下拉列表框中選擇CEx03View,如圖10.25所示。
(2)在Messages列表框中選擇WM_CHAR消息,并雙擊它(或單擊AppFunction按鈕),這時可以在Memberfunctions列表框中看到添加了這一OnChar函數(shù)。MFCClassWizard對話框的MessageMaps選項卡
現(xiàn)在可以通過OnChar函數(shù)來讀取鍵盤輸入并將讀取的字符存入到m_Message變量中。在圖10.25中按下EditCode按鈕,編輯OnChar函數(shù)如下:voidCEx03View::OnChar(UINTnChar,UINTnRepCnt,UINTnFlags){ CEx03Doc*pDoc=GetDocument();//獲取文檔對象指針
ASSERT_VALID(pDoc); //確保一定能獲取該指針
pDoc->m_Message+=nChar;//將讀取的字符加到m_Message中
Invalidate();
//強行調(diào)用OnDraw函數(shù),重繪視圖
CView::OnChar(nChar,nRepCnt,nFlags);}
最后,對OnDraw函數(shù)進(jìn)行修改,去掉對m_Message的聲明(已經(jīng)在CEx03Doc類中聲明過),使之成為:voidCEx03View::OnDraw(CDC*pDC){ CEx03Doc*pDoc=GetDocument(); ASSERT_VALID(pDoc); //TODO:adddrawcodefornativedatahere
pDC->TextOut(30,30,pDoc->m_Message);}
編譯運行該程序并鍵入某些字符,相應(yīng)的字符將在窗口中顯示出來。
視圖中顯示的文檔數(shù)據(jù)通過文檔的串行化方法來實現(xiàn)磁盤的存取。所謂文檔的串行化,是指在文檔打開時,能夠自動把文檔中的數(shù)據(jù)轉(zhuǎn)換為文檔類所支持的對象;在保存文檔時,能夠自動將文檔類對象轉(zhuǎn)換為文檔數(shù)據(jù)格式。文檔串行化方法是由CEx03Doc類中的Serialize函數(shù)完成的。在項目工作區(qū)的類視圖中單擊CEx03Doc前面的“+”,展開該類。雙擊Serialize函數(shù),在代碼編輯窗口對其編輯如下:voidCEx03Doc::Serialize(CArchive&ar){ if(ar.IsStoring()) ar<<m_Message; //存入文檔
else ar>>m_Message; //讀入文檔}
現(xiàn)在運行這個程序。在窗口中輸入“這是第一次的輸入”,再選擇“文件”菜單中的“保存”,在“文件名”編輯框中輸入“1”。再運行一次,輸入“這是第二次的輸入”,將其存為“2”,如圖所示。在Ex03程序中存儲文件
現(xiàn)在可以使用“文件”菜單中的“打開”菜單項分別打開這兩個文件,可以看到程序窗口中顯示的字符串與存儲的字符串完全一致。接下來看看如何處理鼠標(biāo)輸入。按照下面的步驟修改上面的程序,將允許用戶通過在客戶區(qū)的某個位置單擊鼠標(biāo)來確定新文本輸入的位置。當(dāng)用戶輸入文本時,將會在單擊鼠標(biāo)的位置開始輸入;當(dāng)用戶用鼠標(biāo)選擇新位置時,清除字符串對象m_Message中的字符,以便接收新的字符串。由于鼠標(biāo)左鍵被按下時,文本顯示位置也隨之變化,必須首先建立一個新的存儲區(qū),用以記錄鼠標(biāo)單擊的位置。鼠標(biāo)位置可以通過鼠標(biāo)消息處理函數(shù)傳遞的參數(shù)獲得。所有鼠標(biāo)消息處理函數(shù)都傳遞兩個參數(shù):UINTnFlags,CPointpoint
其中,point參數(shù)是CPoint類的一個對象,用于存入鼠標(biāo)當(dāng)前位置??梢栽诔绦蛞晥D類的頭文件中創(chuàng)建一個CPoint類的對象,命名為m_Point,用于記錄point參數(shù)。編輯Ex03View.h,修改CEx03View類的聲明:classCEx03View:publicCView{protected://createfromserializationonly CEx03View(); DECLARE_DYNCREATE(CEx03View) CPointm_Point; //用戶加入本行
……}
與m_Message對象一樣,需要對m_Point做初始化工作,這一工作在視圖類的構(gòu)造函數(shù)CEx03View()中完成:CEx03View::CEx03View(){ //TODO:addconstructioncodehere
m_Point.x=0; //用戶加入以下兩行// m_Point.y=0;}
現(xiàn)在使用ClassWizard創(chuàng)建WM_LBUTTONDOWN消息(被鼠標(biāo)左鍵單擊)的處理函數(shù),該函數(shù)記錄鼠標(biāo)新位置,并在該位置顯示新輸入的文本。步驟如下:
(1)按下Ctrl+W加速鍵,啟動ClassWizard對話框,選擇MessageMaps選項卡。
(2)在Classname下拉列表框中選擇CEx03View,在Messages列表框中選擇WM_LBUTTONDOWN消息。
(3)按下AddFunction按鈕,這時可以在Memberfunctions列表框中看到WM_LBUTTONDOWN的處理函數(shù)已被創(chuàng)建,函數(shù)名為OnLButtonDown。編輯OnLButtonDown函數(shù)如下:voidCEx03View::OnLButtonDown(UINTnFlags,CPointpoint){ //TODO:Addyourmessagehandlercodehereand/orcalldefault
m_Point=point; //記錄鼠標(biāo)位置
CEx03Doc*pDoc=GetDocument();//定義pDoc使用其指向CEx03Doc對象
ASSERT_VALID(pDoc); pDoc->m_Message.Empty(); //清空字符串
Invalidate(); //強迫重新繪圖
CView::OnLButtonDown(nFlags,point);}
新位置已經(jīng)記錄在m_Point中了。改寫OnDraw函數(shù),在新位置顯示文本:voidCEx03View::OnDraw(CDC*pDC){ CEx03Doc*pDoc=GetDocument(); ASSERT_VALID(pDoc); //TODO:adddrawcodefornativedatahere pDC->TextOut(m_Point.x,m_Point.y,pDoc->m_Message);}
運行程序。在客戶區(qū)的任何位置單擊鼠標(biāo)左鍵,然后輸入文本,新文本將會在該位置出現(xiàn)。程序中讀者可能發(fā)現(xiàn)一個問題:輸入字符或單擊鼠標(biāo)的時候,無法確認(rèn)當(dāng)前字符的輸入位置。在Windows中,通常使用光標(biāo)指示用戶輸入字符時顯示的位置。下面介紹如何在程序中建立和使用光標(biāo)。要建立一個新光標(biāo),必須確定光標(biāo)的大小。通常,光標(biāo)與當(dāng)前字符高度相同,寬度為平均字符寬度的1/8。文本字符串大小的相關(guān)信息由MFC提供的結(jié)構(gòu)類型TEXTMETRIC記錄,只要說明該類型的一個變量,然后使用CDC類中的GetTextMetrics方法對其進(jìn)行填充即可。TEXTMETRIC類型中包括的成員有:tmHeight(字符高度)、tmAveCharWidth(平均字符寬度)、thMaxCharWidth(最大字符寬度)、thWeight(磅數(shù))、tmItalic(斜體)等等。上面程序建立和使用光標(biāo)的步驟如下:(1)在視圖類中建立指示光標(biāo)是否已經(jīng)建立的布爾變量m_Created和光標(biāo)位置m_Pos:classCEx03View:publicCView{protected://createfromserializationonly CEx03View();DECLARE_DYNCREATE(CEx03View) CPointm_Point;
BOOLm_Created; //光標(biāo)是否建立// CPointm_Pos; //光標(biāo)位置//
……}(2)在視圖構(gòu)造函數(shù)中將m_Created初始化為False,表示尚未創(chuàng)建;將m_Pos初始化為0:CEx03View::CEx03View(){ //TODO:addconstructioncodehere m_Point.x=0; m_Point.y=0;
m_Created=FALSE; m_Pos=m_Point;}(3)使用GetTextMetrics方法獲取當(dāng)前字符的大小,并用CreateSolidCaret方法實際建立光標(biāo),編輯OnDraw函數(shù):voidCEx03View::OnDraw(CDC*pDC){ CEx03Doc*pDoc=GetDocument(); ASSERT_VALID(pDoc); //TODO:adddrawcodefornativedatahere
pDC->TextOut(m_Point.x,m_Point.y,pDoc->m_Message); if(!m_Created){TEXTMETRICmetric; pDC->GetTextMetrics(&metric); CreateSolidCaret(metric.tmAveCharWidth/8,metric.tmHeight); }}
創(chuàng)建光標(biāo)后,使用SetCarePos設(shè)置光標(biāo)位置,并使用ShowCaret在視圖中顯示光標(biāo),還需要將m_Created設(shè)置為TRUE,表示光標(biāo)已被創(chuàng)建。重新修改OnDraw函數(shù):voidCEx03View::OnDraw(CDC*pDC){ CEx03Doc*pDoc=GetDocument(); ASSERT_VALID(pDoc); //TODO:adddrawcodefornativedatahere pDC->TextOut(m_Point.x,m_Point.y,pDoc->m_Message); if(!m_Created){ TEXTMETRICmetric; pDC->GetTextMetrics(&metric);CreateSolidCaret(metric.tmAveCharWidth/8,metric.tmHeight);
SetCaretPos(m_Pos); ShowCaret(); m_Created=TRUE; }}
現(xiàn)在編譯并運行程序??梢钥吹焦鈽?biāo)在窗口的左上角閃動。但在新位置點下鼠標(biāo)左鍵時,光標(biāo)并沒有跟著移動。
光標(biāo)需要指示下一個字符的輸入位置。因此,當(dāng)用戶輸入字符時,光標(biāo)應(yīng)該隨之移動而出現(xiàn)在字符串的尾部??砂聪旅娴姆椒ㄌ幚恚?/p>
(1)首先計算字符串結(jié)尾的位置。通過使用GetTextExtent函數(shù)可以獲得字符串的高度和長度。需要注意,這里的長度不是指字符串中字符的個數(shù),而是字符串在視圖中以像素為單位計算的長度。
(2)隱藏光標(biāo),將光標(biāo)移動到字符串的尾部并再次顯示它。修改OnDraw函數(shù)如下:voidCEx03View::OnDraw(CDC*pDC){ CEx03Doc*pDoc=GetDocument(); ASSERT_VALID(pDoc);//TODO:adddrawcodefornativedatahere pDC->TextOut(m_Point.x,m_Point.y,pDoc->m_Message); if(!m_Created){ TEXTMETRICmetric; pDC->GetTextMetrics(&metric); CreateSolidCaret(metric.tmAveCharWidth/8,metric.tmHeight); SetCaretPos(m_Pos); ShowCaret(); m_Created=TRUE; }CSizeStringSize=pDC->GetTextExtent(pDoc->m_Message);//字符串長度
m_Pos.x=m_Point.x+StringSize.cx;
//計算光標(biāo)位置
m_Pos.y=m_Point.y;HideCaret(); //隱藏光標(biāo)
SetCaretPos(m_Pos); //移動光標(biāo)到新位置
ShowCaret(); //顯示光標(biāo)}(3)最后還應(yīng)該考慮到,在程序窗口失去輸入焦點時,需要隱藏光標(biāo),當(dāng)窗口重新獲得焦點時再次顯示光標(biāo)。程序窗口失去焦點和獲得焦點的消息分別是WM_KILLFOCUS和WM_SETFOCUS。使用ClassWizard分別創(chuàng)建這兩個消息的處理函數(shù),并編輯它們?nèi)缦拢?/p>
voidCEx03View::OnKillFocus(CWnd*pNewWnd){
CView::OnKillFocus(pNewWnd); HideCaret();}voidCEx03View::OnSetFocus(CWnd*pOldWnd){
CView::OnSetFocus(pOldWnd); ShowCaret();}
再次編譯運行這個程序,可以看到閃動的光標(biāo)指示下一個字符的輸入位置。當(dāng)用戶用鼠標(biāo)在其它位置點擊時,所輸入的字符串消失,光標(biāo)又在新位置閃動。
3.3多文檔應(yīng)用程序的建立單文檔應(yīng)用程序與多文檔應(yīng)用程序在外觀上是有區(qū)別的。可以再次運行Ex01程序,將它與單文檔應(yīng)用程序相比較(如Ex02、Ex03)。多文檔應(yīng)用程序多出一個“窗口”菜單,并且在主窗口中可以同時打開多個子窗口。這些子窗口中的內(nèi)容可以是不同的。利用MFCAppWizard生成單文檔(SDI)應(yīng)用程序時,只派生文檔類、視圖類、主窗口類和應(yīng)用程序類。而生成多文檔(MDI)應(yīng)用程序時,它有一個主窗口和嵌在該窗口中的子窗口,所以具有CChildFrame類,而且每個窗口可以使用不同的文檔模板。單文檔應(yīng)用程序的主窗口類派生自CFrameWnd類,而多文檔應(yīng)用程序的主窗口類則是CMDIFrameWnd類的派生類。
在文檔模板方面,單文檔應(yīng)用程序的文檔模板是CSingleDocTemplate類,多文檔應(yīng)用程序的文檔模板則是CMultiDocTemplate類。CSingleDocTemplate類構(gòu)造函數(shù)的用法與CMultiDocTemplate類相同,但從建立文檔模板所給定的參數(shù)不難發(fā)現(xiàn),單文檔應(yīng)用程序文檔模板的框架窗口與其主框架窗口使用相同的類(CMainFrame),而多文檔應(yīng)用程序文檔模板的文件框架窗口使用的是子窗口類(CChildFrame)。多文檔應(yīng)用程序中可以有多個子窗口,因此多文檔應(yīng)用程序中可以有多個文檔模板。通過觀察單文檔和多文檔應(yīng)用程序的InitInstance()函數(shù),可以明顯看出它們之間的差別:
//單文檔應(yīng)用程序的InitInstance()函數(shù)BOOLCEx02App::InitInstance(){ …… //建立文檔模板
CSingleDocTemplate*pDocTemplate; pDocTemplate=newCSingleDocTemplate( IDR_MAINFRAME, RUNTIME_CLASS(CEx02Doc), RUNTIME_CLASS(CMainFrame),//mainSDIframewindowRUNTIME_CLASS(CEx02View)); AddDocTemplate(pDocTemplate);…… //只有一個窗口
m_pMainWnd->ShowWindow(SW_SHOW); m_pMainWnd->UpdateWindow(); returnTRUE;}//多文檔應(yīng)用程序的InitInstance()函數(shù)BOOLCEx01App::InitInstance(){ …… //建立文檔模板CMultiDocTemplate*pDocTemplate; pDocTemplate=newCMultiDocTemplate( IDR_EX01TYPE, RUNTIME_CLASS(CEx01Doc), RUNTIME_CLASS(CChildFrame),//customMDIchildframe RUNTIME_CLASS(CEx01View)); AddDocTemplate(pDocTemplate); //建立MDI主窗口框架CMainFrame*pMainFrame=newCMainFrame; if(!pMainFrame->LoadFrame(IDR_MAINFRAME)) returnFALSE; m_pMainWnd=pMainFrame; …… //顯示主窗口
pMainFrame->ShowWindow(m_nCmdShow); pMainFrame->UpdateWindow();
returnTRUE;}
下面是建立一個多文檔應(yīng)用程序的例子。操作如下:
(1)利用MFCAppwizard創(chuàng)建多文檔的應(yīng)用程序Ex04。
(2)在項目工作區(qū)的類視圖中雙擊CEx04Doc圖標(biāo),出現(xiàn)類編輯
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 《柴油機燃料供給》課件
- 三年級數(shù)學(xué)下冊總復(fù)習(xí)課件
- 乙酸的說課課件
- 《畜禽免疫學(xué)》課件
- 中醫(yī)診斷學(xué)課件-中醫(yī)診斷學(xué)緒論
- 2024年高考?xì)v史總復(fù)習(xí)考前沖刺攻略 第4講 高考應(yīng)試能力的培養(yǎng)
- 單位管理制度集粹匯編【職工管理】十篇
- 單位管理制度匯編大合集【職工管理】
- 單位管理制度合并匯編職員管理十篇
- 單位管理制度范文大合集人事管理篇十篇
- 檢修平臺施工方案
- 第六單元大單元教學(xué)設(shè)計統(tǒng)編版語文八年級上冊
- GB/T 713.2-2023承壓設(shè)備用鋼板和鋼帶第2部分:規(guī)定溫度性能的非合金鋼和合金鋼
- 寵物養(yǎng)護(hù)與經(jīng)營專業(yè)《寵物解剖生理》課程標(biāo)準(zhǔn)
- 滬教2011課標(biāo)版三年級起點五年級下冊《Buying Clothes》說課稿
- 幼兒園教職工教代會會議記錄
- 車輛移交安全協(xié)議書
- 《涑水記聞》2021年江蘇鎮(zhèn)江中考文言文閱讀真題(含答案與翻譯)
- 家庭家教家風(fēng)·家庭美德·文明家庭主題班會
- 廬山云霧閱讀答案千姿百態(tài)
- 個人營業(yè)執(zhí)照注銷委托書范文
評論
0/150
提交評論