乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Visual C .NET編程講座之七

       dazuo0312 2006-09-09
      摘要

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

        MFC"一檔多視"模式

        我們知道,MFC應(yīng)用程序用一種編程模式使程序中數(shù)據(jù)與它的顯示形式和用戶交互分離開來,這種模式就是"文檔/視圖結(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ì)打開一個(gè)新的窗口顯示出相同的文檔內(nèi)容。在界面上表現(xiàn)為,一個(gè)框架窗口中有多個(gè)文檔窗口,如圖1(a)所示。

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

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


      (a)


      (b)


      (c)

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

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


      (a)


      (b)

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

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

        1. 添加視圖類CWebView

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

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

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


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

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


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

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

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

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

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


      圖5 在OnInitialUpdate中添加的代碼

         (3) 打開CViewerApp::InitInstance函數(shù),將CSingleDocTemplate中的第4個(gè)參數(shù)的視圖類由原來的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++程序員普遍采用的一種方法。具體過程如下:

        (1) 打開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)用,我們來看看其代碼執(zhí)行過程。

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

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

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

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

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


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


      圖10 在MainFrm.h中添加的語句

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

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

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

        (6) 分別在ViewerView.h和WebView.h文件中,將構(gòu)造函數(shù)CViewerView()和CWebView()前面的訪問方式改成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來切換

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

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

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

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

        (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方法是通過CDocument類的AddView和RemoveView來改變一個(gè)文檔與多個(gè)視圖的關(guān)聯(lián)。

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

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

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

        結(jié)束語

        在本講中,我們重點(diǎn)討論了視圖類的添加、單文檔的視圖切換方法和技巧。對(duì)于初學(xué)者來說,學(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)購買等信息,謹(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)論公約

        類似文章 更多