小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Visual C .NET編程講座之七

 dazuo0312 2006-09-09
摘要

  本講先來(lái)介紹MFC中的"一檔多視"模式,并為Viewer添加一個(gè)用于顯示Web頁(yè)的視圖CWebView,然后討論兩種比較常用的單文檔視圖的切換方法,最后對(duì)這兩種方法進(jìn)行分析和比較。

  MFC"一檔多視"模式

  我們知道,MFC應(yīng)用程序用一種編程模式使程序中數(shù)據(jù)與它的顯示形式和用戶交互分離開(kāi)來(lái),這種模式就是"文檔/視圖結(jié)構(gòu)"。在單文檔應(yīng)用程序結(jié)構(gòu)中,一個(gè)文檔對(duì)應(yīng)于一個(gè)視圖。但有時(shí)一個(gè)文檔可能需要多個(gè)視圖以改變文檔數(shù)據(jù)的顯示方式,稱為"一檔多視",MFC對(duì)于這種"一檔多視"提供下列三個(gè)模式:
  第一種模式是用在多文檔應(yīng)用程序中,用同一個(gè)視圖類創(chuàng)建多個(gè)視圖對(duì)象,并在各自的窗口中顯示。例如,當(dāng)我們選擇"窗口"菜單的"新建窗口"命令,程序就會(huì)打開(kāi)一個(gè)新的窗口顯示出相同的文檔內(nèi)容。在界面上表現(xiàn)為,一個(gè)框架窗口中有多個(gè)文檔窗口,如圖1(a)所示。

  第二種模式是動(dòng)態(tài)切分窗口方式,即在同一個(gè)文檔窗口中創(chuàng)建多個(gè)視圖,用同一方式來(lái)顯示相同的文檔內(nèi)容。如圖1(b)所示。

  第三種模式是靜態(tài)切分窗口方式,即在同一個(gè)文檔窗口中創(chuàng)建多個(gè)視圖,但每個(gè)視圖可用不同的方式來(lái)顯示文檔內(nèi)容。如圖1(c)所示。


(a)


(b)


(c)

  圖1 "一檔多視"的三種模式

  但在本講中所討論的"一檔多視"是指在單文檔應(yīng)用程序中具體多個(gè)視圖的特性。文檔窗口每次只有一個(gè)視圖顯示,但可以通過(guò)菜單等命令在多個(gè)視圖中進(jìn)行切換。我們的目是將文檔內(nèi)容在"普通文本"和"HTML瀏覽"視圖之間進(jìn)行切換,如圖2(a)和2(b)所示。


(a)


(b)

圖2 視圖切換的結(jié)果
添加"HTML瀏覽"視圖

  為了使我們的這個(gè)文本瀏覽器功能更加強(qiáng)大,我們添加一個(gè)"HTML瀏覽"視圖用來(lái)正確顯示出擴(kuò)展名為.htm或.html等的Web頁(yè)效果。

  1. 添加視圖類CWebView

  我們先來(lái)添加一個(gè)視圖類CWebView,具體步驟如下:

  (1) 啟動(dòng)Visual Studio .net,打開(kāi)上一講的單文檔應(yīng)用程序項(xiàng)目Viewer。

  (2) 打開(kāi)"項(xiàng)目"菜單,單擊"添加類",彈出"添加資源"對(duì)話框,展開(kāi)左邊的所有"類別",單擊"MFC",在右側(cè)模板中選中"MFC類",如圖3所示。


圖3 "添加類"對(duì)話框

  (3) 單擊"打開(kāi)"按鈕,彈出"MFC類向?qū)?對(duì)話框。在對(duì)話框中輸入"類名"CWebView,然后將基類選擇為CHtmlView,CHtmlView類封裝了URL資源的瀏覽和鏈接等功能。其它為默認(rèn)值,結(jié)果如圖4所示。


圖4 使用"MFC類向?qū)?

  (4) 單擊"完成"按鈕。

  2. 添加代碼并測(cè)試CWebView

   (1) 打開(kāi)CWebView類的接口文件WebView.h,在最前面加上CHtmlView類的包含文件" "。

   (2) 為CWebView類添加OnInitialUpdate函數(shù)的重載,并添加如圖5加框部分的代碼。


圖5 在OnInitialUpdate中添加的代碼

   (3) 打開(kāi)CViewerApp::InitInstance函數(shù),將CSingleDocTemplate中的第4個(gè)參數(shù)的視圖類由原來(lái)的CViewerView改為CWebView。

   (4) 在CViewerApp類的實(shí)現(xiàn)文件前面加上" "。

   (5) 運(yùn)行程序。圖6是顯示某個(gè)文件的結(jié)果。


圖6 CWebView類的顯示效果

   (6) 再把CViewerApp::InitInstance函數(shù)中的CSingleDocTemplate參數(shù)CWebView改回到CViewerView。
最一般的切換方法

  對(duì)于單文檔框架窗口中的多個(gè)視圖的切換,我們先看看大多數(shù)Visual C++程序員普遍采用的一種方法。具體過(guò)程如下:

  (1) 打開(kāi)Viewer項(xiàng)目的Menu資源IDR_MAINFRAME,在"視圖"菜單中添加三個(gè)菜單項(xiàng),一個(gè)是水平線(分隔符),一個(gè)是"普通文本(&G)",ID號(hào)設(shè)為ID_VIEW_TEXT,最后一個(gè)是"HTML瀏覽(&H)",ID號(hào)設(shè)為ID_VIEW_HTML。結(jié)果如圖7所示。


圖7 在"視圖"中添加的菜單項(xiàng)

  (2) 視圖切換的代碼應(yīng)該添加在CMainFrame類中。我們先在CMainFrame類添加一個(gè)切換函數(shù)SwitchToView1,代碼如圖8所示。


圖8 SwitchToView1函數(shù)代碼

  函數(shù)SwitchToView1用了一些底層的MFC調(diào)用,我們來(lái)看看其代碼執(zhí)行過(guò)程。

  如果主程序框架窗口一開(kāi)始就激活CViewerView,即pOldView指向CViewerView,則當(dāng)在程序中調(diào)用SwitchToView1(1)時(shí),即參數(shù)nView為1,該函數(shù)中的第一行代碼用來(lái)獲得當(dāng)前活動(dòng)的視圖,第二行代碼是通過(guò)GetDlgItem獲得標(biāo)識(shí)為1的窗口指針,由于視圖也是一個(gè)窗口,所以可以直接進(jìn)行指針類型的強(qiáng)制轉(zhuǎn)換。第一次調(diào)用時(shí),標(biāo)識(shí)為1的窗口指針是不存在的,因而這個(gè)視圖指針就是NULL,從而執(zhí)行if語(yǔ)句中的代碼,該代碼是通過(guò)CCreateContext來(lái)創(chuàng)建一個(gè)新的視圖對(duì)象指針。

  CCreateContext是用來(lái)將框架窗口、文檔和視圖關(guān)聯(lián)起來(lái),在主程序創(chuàng)建框架窗口以及文檔相關(guān)聯(lián)的視圖時(shí),會(huì)自動(dòng)使用CCreateContext類結(jié)構(gòu);該結(jié)構(gòu)包含了指向文檔、框架窗口和文檔模板的指針,以及一個(gè)CRuntimeClass指針。該結(jié)構(gòu)還包含一些成員變量指針,如m_pCurrentDoc是用來(lái)指定和新創(chuàng)建的視圖相關(guān)聯(lián)的文檔指針。

  接下來(lái)的代碼比較好理解,pOldView->SetDlgCtrID以及SetWindowLong均是用來(lái)為新舊視圖窗口重新指定一個(gè)標(biāo)識(shí)。需要說(shuō)明的是,在MFC底層機(jī)制中,應(yīng)用程序框架窗口中默認(rèn)的文檔窗口(視圖)標(biāo)識(shí)是使用預(yù)定義的AFX_IDW_PANE_FIRST。最后一行的RecalcLayout用來(lái)重新布置框架窗口中的所有對(duì)象,包括文檔窗口和視圖。

  當(dāng)再一次調(diào)用SwitchToView1(1)時(shí),由于上次SwitchToView1調(diào)用將CViewerView類指針與標(biāo)識(shí)1建立聯(lián)系,因而SwitchToView1中的if語(yǔ)句中的代碼就不會(huì)被執(zhí)行,從而避免了CViewerView類視圖對(duì)象再一次被創(chuàng)建。這也是為什么要使用SetDlgCtrID語(yǔ)句的原因。

  (3) 在MainFrm.cpp文件的前面添加一些文件包含語(yǔ)句,如圖9所示的加框部分。


圖9 添加的包含文件語(yǔ)句
 (4) 在MainFrm.h文件的前面添加下列代碼,如圖10所示的加框部分。


圖10 在MainFrm.h中添加的語(yǔ)句

  不少人對(duì)上述語(yǔ)句不理解:既然使用了包含文件,為什么還要在class CMainFrame前添加"class CViewerView;"等代碼?如果用包含文件代替它,行不行?

  很多Visual C++書(shū)籍對(duì)這些問(wèn)題避而不談,但實(shí)際上這是一個(gè)重要的問(wèn)題。如果不能理解上述代碼,我們很可能為無(wú)法通過(guò)編譯而大傷腦筋。這些問(wèn)題的出現(xiàn)是基于這樣的一些事實(shí):在我們用標(biāo)準(zhǔn)C/C++設(shè)計(jì)程序時(shí),有一個(gè)原則即兩個(gè)代碼文件不能相互包含,而且多次包含還會(huì)造成重復(fù)定義的錯(cuò)誤。為了解決這個(gè)難題,Visual C++使用#pragma once來(lái)通知編譯器在生成時(shí)只包含(打開(kāi))一次,也就是說(shuō),在第一次#include之后,編譯器重新生成時(shí)不會(huì)再對(duì)這些包含文件進(jìn)行包含(打開(kāi))和讀取,因此我們看到在用向?qū)?chuàng)建的所有類的頭文件中有#pragma once語(yǔ)句就不會(huì)覺(jué)得奇怪了。然而正是由于這個(gè)語(yǔ)句而造成了在第二次#include后編譯器無(wú)法正確識(shí)別所引用的類。因此,我們?cè)谙嗷グ瑫r(shí)還需要加入類似class CViewerView這樣的語(yǔ)句來(lái)通知編譯器這個(gè)類是一個(gè)實(shí)際的調(diào)用。

  (5) 重新生成解決方案后運(yùn)行程序,看看有沒(méi)有出現(xiàn)編譯錯(cuò)誤,此時(shí)提示出SwitchToView1函數(shù)中,CViewerView和CWebView類無(wú)法構(gòu)造,因?yàn)樗鼈兊臉?gòu)造函數(shù)是protected。

  (6) 分別在ViewerView.h和WebView.h文件中,將構(gòu)造函數(shù)CViewerView()和CWebView()前面的訪問(wèn)方式改成public。再運(yùn)行程序。

  (7) 為CMainFrame類添加一個(gè)int類型的成員變量m_nViewID,并將其初值設(shè)為1。

  (8) 為CMainFrame類添加菜單項(xiàng)ID_VIEW_TEXT的COMMAND和UPDATE_COMMAND_UI的事件映射,并在映射函數(shù)添加如圖11所示的代碼。


圖11 ID_VIEW_TEXT的映射函數(shù)代碼

  (9) 為CMainFrame類添加菜單項(xiàng)ID_VIEW_HTML的COMMAND和UPDATE_COMMAND_UI的事件映射,并在映射函數(shù)添加如圖12所示的代碼。


圖12 ID_VIEW_HTML的映射函數(shù)代碼

  (10) 運(yùn)行程序,結(jié)果如前面圖2所示。
使用CDocument類的AddView和RemoveView來(lái)切換

  在CDocument類中,AddView和RemoveView可以說(shuō)是專門用于單文檔視圖的切換的,具體實(shí)現(xiàn)過(guò)程如下:

  (1) 在CMainFrame類添加兩個(gè)變量,一個(gè)是CViewerView類指針對(duì)象m_pMainView,另一個(gè)是CWebView類指針對(duì)象m_pWebView。需要說(shuō)明的是,用"添加成員變量向?qū)?添加指針對(duì)象m_pMainView時(shí),指定的類型名應(yīng)是CViewerView*,注意后面的星號(hào)。m_pWebView添加時(shí)也類似。

  (2) 為CWebView類添加一個(gè)CString類成員變量strFileName。

  (3) 將CWebView::OnInitialUpdate中的語(yǔ)句" "刪除。

  (4) 在CMainFrame類添加成員函數(shù)SwitchToView2,用于切換視圖,其代碼如圖13所示。


圖13 SwitchToView2函數(shù)代碼

  (5) 將CMainFrame::OnViewText和OnViewHtml中的SwitchToView1函數(shù)調(diào)用改為SwitchToView2,其余不變。

  (6) 運(yùn)行程序,結(jié)果如前圖2所示。

  兩種切換方法的比較

  SwitchToView1切換方法實(shí)質(zhì)上是創(chuàng)建兩個(gè)具有與文檔相關(guān)聯(lián)的視圖,即視圖創(chuàng)建時(shí)指定CCreateContext結(jié)構(gòu),具有很直接的"一檔多視"的關(guān)系。而SwitchToView2方法是通過(guò)CDocument類的AddView和RemoveView來(lái)改變一個(gè)文檔與多個(gè)視圖的關(guān)聯(lián)。

  由于SwitchToView1中創(chuàng)建的視圖帶有文檔關(guān)聯(lián),因此可以直接在視圖類中通過(guò)GetDocument()函數(shù)來(lái)獲取相關(guān)聯(lián)的文檔指針,從而可以訪問(wèn)文檔中的數(shù)據(jù)。而SwitchToView2中創(chuàng)建的視圖本身不帶文檔關(guān)聯(lián),因此無(wú)法直接訪問(wèn)文檔中的數(shù)據(jù)。

  由于SwitchToView2中需要在函數(shù)外指定視圖類指針變量,因此在各個(gè)視圖中可以通過(guò)AfxGeMainWnd()獲取CMainFrame類指針,從而可以直接該問(wèn)到CMainFrame類中定義的public視圖類指針變量,這樣便可在視圖類之間直接訪問(wèn)。而SwitchToView1中的視圖類指針變量是在函數(shù)內(nèi)定義的,因此無(wú)法在各個(gè)視圖類中進(jìn)行視圖之間的訪問(wèn),并且在本例中CViewerView類對(duì)象被創(chuàng)建了兩次。SwitchToView2中,CViewerView類對(duì)象只創(chuàng)建一次。

  除了上述兩種方法外,還有一種方法,那就是使用靜態(tài)切分機(jī)制來(lái)進(jìn)行。由于它涉及過(guò)多的底層方法,對(duì)初學(xué)者而言,相對(duì)較難,因此這里不再給出。

  結(jié)束語(yǔ)

  在本講中,我們重點(diǎn)討論了視圖類的添加、單文檔的視圖切換方法和技巧。對(duì)于初學(xué)者來(lái)說(shuō),學(xué)習(xí)并掌握這些技巧能對(duì)MFC的文檔/視圖機(jī)制有一個(gè)較為深入的了解。當(dāng)然,MFC文檔/視圖機(jī)制本身是非常復(fù)雜的,在以后的學(xué)習(xí)中應(yīng)慢慢地體會(huì)和理解。在最后一講中,我們將重點(diǎn)應(yīng)用程序的安裝和部署。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多