欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
第7章 框架窗口、文檔和視圖

7 框架窗口、文檔和視圖

7.1框架窗口

7.2文檔及其序列化

7.3視圖及視圖類(lèi)

7.4文檔視圖結構

7.1框架窗口 

7.1.1主窗口和文檔窗口

     主窗口是應用程序直接放置在桌面上的那個(gè)窗口,每個(gè)應用程序只能有一個(gè)主窗口,主窗口的標題欄上往往顯示應用程序的名稱(chēng)。

     文檔窗口對于SDI程序來(lái)說(shuō),它和主窗口是一致的,即主窗口就是文檔窗口;而對于MDI程序,文檔窗口是主窗口的子窗口,如圖。文檔窗口一般都有相應的可見(jiàn)邊框,它的客戶(hù)區是由相應的視圖來(lái)構成的,因此可以說(shuō)視圖是文檔窗口內的子窗口。文檔窗口時(shí)刻跟蹤當前處于活動(dòng)狀態(tài)的視圖的變化,并將用戶(hù)或系統產(chǎn)生的命令消息傳遞給當前活動(dòng)視圖。而主窗口負責管理各個(gè)用戶(hù)交互對象并根據用戶(hù)操作相應地創(chuàng )建或更新文檔窗口及其視圖。

7.1框架窗口

7.1.2窗口風(fēng)格的設置

Ø     窗口風(fēng)格

     窗口風(fēng)格通常有一般和擴展兩種形式。這兩種形式的窗口風(fēng)格可在函數CWnd::CreateCWnd::CreateEx參數中指定,CreateEx函數可同時(shí)支持以上兩種風(fēng)格,而CWnd::Create只能指定窗口的一般風(fēng)格。需要說(shuō)明的是,對于控件和對話(huà)框這樣的窗口來(lái)說(shuō),它們的窗口風(fēng)格可直接通過(guò)其屬性對話(huà)框來(lái)設置。

     需要說(shuō)明的是,除了上述風(fēng)格外,框架窗口還有以下三個(gè)自己的風(fēng)格。它們都可以在PreCreateWindow重載函數中指定。

u       FWS_ADDTOTITLE

     該風(fēng)格指定相關(guān)的信息如文檔名添加到框架窗口標題的后面。

u       FWS_PREFIXTITLE

           該風(fēng)格使得框架窗口標題中的文檔名顯示在應用程序名之前。

u       FWS_SNAPTOBARS

    該風(fēng)格用來(lái)調整窗口的大小,使它剛好包含了框架窗口中的控制欄。

7.1框架窗口

Ø     MFC AppWizard設置

7.1框架窗口

Ø      修改CREATESTRUCT結構

      窗口創(chuàng )建之前,系統自動(dòng)調用PreCreateWindow虛函數。在用MFC AppWizard創(chuàng )建SDI/MDI應用程序結構時(shí),MFC已為主窗口或文檔窗口類(lèi)自動(dòng)重載了該虛函數??梢栽诖撕瘮抵型ㄟ^(guò)修改CREATESTRUCT結構來(lái)設置窗口的絕大多數風(fēng)格。

      例如,在SDI程序中,框架窗口默認的風(fēng)格是WS_OVERLAPPEDWINDOWFWS_ADDTOTITLE的組合,更改風(fēng)格代碼:

      BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

      {        // 新窗口不帶有[最大化]按鈕

                cs.style &= ~WS_MAXIMIZEBOX; 

                // 將窗口的大小設為1/3屏幕并居中

                cs.cy = ::GetSystemMetrics(SM_CYSCREEN) / 3;

                cs.cx = ::GetSystemMetrics(SM_CXSCREEN) / 3;

                cs.y = ((cs.cy * 3) - cs.cy) / 2;

                cs.x = ((cs.cx * 3) - cs.cx) / 2;

                // 調用基類(lèi)的PreCreateWindow函數

                return CFrameWnd::PreCreateWindow(cs);

      }

      對于MDI程序,文檔窗口的風(fēng)格可用下列的代碼更改:

      BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs)

      {        // 創(chuàng )建不含有[最大化]按鈕的子窗口

                cs.style &= ~WS_MAXIMIZEBOX;

                // 調用基類(lèi)的PreCreateWindow函數

                return CMDIChildWnd::PreCreateWindow(cs);

      }

7.1框架窗口

Ø     使用ModifyStyleModifyStyleEx

     CWnd類(lèi)中的成員函數ModifyStyleModifyStyleEx也可用來(lái)更改窗口的風(fēng)格,其中ModifyStyleEx還可更改窗口的擴展風(fēng)格。這兩個(gè)函數具有相同的參數,其含義如下。

     BOOL ModifyXXXX( DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0 );

     參數dwRemove用來(lái)     指定需要刪除的風(fēng)格,dwAdd用來(lái)指定需要增加的風(fēng)格,nFlags表示SetWindowPos的標志,0(默認)表示更改風(fēng)格的同時(shí)不調用SetWindowPos函數。

     由于框架窗口在創(chuàng )建時(shí)不能直接設定其擴展風(fēng)格,因此只能通過(guò)調用ModifyStyle函數來(lái)進(jìn)行。

7.1框架窗口

     [Ex_Vscroll] 多文檔(MDI)的子文檔窗口增加垂直滾動(dòng)條。

     (1)MFC AppWizard創(chuàng )建一個(gè)多文檔應用程序。

     (2)ClassWizard為子文檔窗口類(lèi)CChildFrame添加OnCreateClient消息處理,并增加下列代碼:

     BOOL CChildFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)

     {        ModifyStyle(0, WS_VSCROLL, 0);

            return CMDIChildWnd::OnCreateClient(lpcs, pContext);

     }

     (3)編譯并運行,如圖。

7.1框架窗口

Ø    設置TopMost窗口風(fēng)格

   最頂(TopMost)窗口是指那些始終出現在桌面的最前方且不會(huì )被其他窗口覆蓋的窗口。如果要創(chuàng )建這樣的一個(gè)最頂窗口,則在運行時(shí)必須指定WS_EX_TOPMOST擴展窗口風(fēng)格。此風(fēng)格的設置是在CWnd::SetWindowPos函數中進(jìn)行;作為技巧,我們可以先調用CWnd::GetExStyle函數來(lái)確定是否已經(jīng)設置了WS_EX_TOPMOST風(fēng)格。例如下面的代碼:

     void SetWindowTopMost(CWnd* pWnd)

     {        ASSERT_VALID(pWnd);

             pWnd->SetWindowPos((pWnd->GetExStyle()&WS_EX_TOPMOST)?

                                        &wndNoTopMost:&wndTopMost,0,0,0,0,

                                        SWP_NOSIZE | SWP_NOMOVE);

     }

     函數SetWindowPos具體的使用方法將在下一節中介紹。

7.1框架窗口

7.1.3窗口狀態(tài)的改變

Ø     ShowWindow改變窗口的顯示狀態(tài)

     當一個(gè)新的應用程序創(chuàng )建之后,InitInstance函數總會(huì )調用ShowWindow函數來(lái)顯示窗口

     想要改變改變窗口顯示狀態(tài),只需根據上表選擇所需的參數值,調用ShowWindow函數就可達到目的。當然,也可對CWinApp的公有型(public)成員變量m_nCmdShow進(jìn)行賦值,同樣能達到效果。下面的代碼是將窗口的初始狀態(tài)設置為最小化

     BOOL CEx_SdiApp::InitInstance()

     {      ...

             m_nCmdShow = SW_SHOWMINIMIZED;      

            // 由于CEx_SdiApp類(lèi)繼承了基類(lèi)CWinApp的特性,因此也可在派生類(lèi)

            // CEx_SdiApp使用這個(gè)公有型成員變量m_nCmdShow。

             m_pMainWnd->ShowWindow(m_nCmdShow);

             m_pMainWnd->UpdateWindow();          

            return TRUE;

     }

7.1框架窗口

Ø      SetWindowPosMoveWindow改變窗口的大小和位置

u       SetWindowPos不僅可以改變窗口的大小、位置,還可以改變所有窗口在堆棧排列的次序(Z次序),這個(gè)次序是根據它們在屏幕出現的先后來(lái)確定的。

u       函數CWnd::MoveWindow也可用來(lái)改變窗口的大小和位置,用戶(hù)必須在MoveWindow函數中指定窗口的大小。

      void MoveWindow( int x, int y, int nWidth, int nHeight, BOOL bRepaint = TRUE );

      void MoveWindow( LPCRECT lpRect, BOOL bRepaint = TRUE );

      參數xy表示          窗口新的左上角坐標,nWidthnHeight表示窗口新的寬度和高度,bRepaint用于指定窗口是否重繪,lpRect表示窗口新的大小和位置。

u       使用上述兩個(gè)函數把主窗口移動(dòng)到屏幕的(100,100)(代碼添在CEx_SdiApp::InitInstance[return TRUE]語(yǔ)句之前)。

      // 使用SetWindowPos函數的示例

      m_pMainWnd->SetWindowPos(NULL,100,100,0,0,SWP_NOSIZE|SWP_NOZORDER);

      CRect rcWindow;                  // 使用MoveWindow函數的示例

      m_pMainWnd->GetWindowRect(rcWindow);

      m_pMainWnd->MoveWindow(100,100,rcWindow.Width(),rcWindow.Height(),TRUE);

u       改變窗口的大小和位置的CWnd成員函數還不止以上兩個(gè)。例如CenterWindow函數是使窗口居于父窗口中央,就像下面的代碼:

      CenterWindow(CWnd::GetDesktopWindow());          // 將窗口置于屏幕中央

      AfxGetMainWnd()->CenterWindow(); // 將主框架窗口居中

7.2文檔及其序列化

7.2.1單文檔和多文檔

      一個(gè)多文檔應用程序的示例過(guò)程:

      (1)MFC AppWizard創(chuàng )建一個(gè)多文檔應用程序項目Ex_Mdi。由于向導默認創(chuàng )建的就是這種程序類(lèi)型,因此只要在向導的Step 1對話(huà)框中單擊[Finish]按鈕即可創(chuàng )建一個(gè)默認的多文檔應用程序。

      (2)打開(kāi)CEx_MdiApp::InitInstance可看出與默認的單文檔應用程序不同的代碼是:

      BOOL CEx_MdiApp::InitInstance()

      {       

                CMultiDocTemplate* pDocTemplate;

                pDocTemplate = new CMultiDocTemplate(

                IDR_EX_MDITYPE,

                RUNTIME_CLASS(CEx_MdiDoc),

                RUNTIME_CLASS(CChildFrame), // MDI文檔子窗口

                RUNTIME_CLASS(CEx_MdiView));

                AddDocTemplate(pDocTemplate);

                // 創(chuàng )建MDI主框架窗口

                CMainFrame* pMainFrame = new CMainFrame;

                if (!pMainFrame->LoadFrame(IDR_MAINFRAME))

                          return FALSE;

                m_pMainWnd = pMainFrame;

               

      }

7.2文檔及其序列化

      (3)ClassWizard為該項目添加一個(gè)CDocument派生類(lèi)CAnotherDoc,并在CEx_Mdi- App::InitInstance增加下列代碼:

      BOOL CEx_MdiApp::InitInstance()

      {       

                CMultiDocTemplate* pDocTemplate;

                pDocTemplate = new CMultiDocTemplate(IDR_EX_MDITYPE,

                RUNTIME_CLASS(CEx_MdiDoc),

                RUNTIME_CLASS(CChildFrame), // MDI文檔子窗口

                RUNTIME_CLASS(CEx_MdiView));

                AddDocTemplate(pDocTemplate);

                CMultiDocTemplate* pAnother;

                pAnother = new CMultiDocTemplate(IDR_EX_MDITYPE,

                RUNTIME_CLASS(CAnotherDoc),

                RUNTIME_CLASS(CChildFrame), // MDI文檔子窗口

                RUNTIME_CLASS(CEx_MdiView));

                AddDocTemplate(pAnother);

                // 創(chuàng )建MDI主框架窗口

                CMainFrame* pMainFrame = new CMainFrame;

                if (!pMainFrame->LoadFrame(IDR_MAINFRAME)) 

                          return FALSE;

                m_pMainWnd = pMainFrame;

               

      }

7.2文檔及其序列化

      (4)Ex_Mdi.cpp文件的開(kāi)始處,添加包含CAnotherDoc類(lèi)的頭文件:

                #include "AnotherDoc.h"

      (5)編譯并運行后,如圖,從中選擇一個(gè)文檔類(lèi)型。任何時(shí)候,選擇Ex_Mdi程序的文件菜單à新建命令或單擊新建工具按鈕都將彈出此對話(huà)框。

      選定第二個(gè)文檔類(lèi)型后,單擊[確定]。這時(shí)程序出現一個(gè)斷言錯誤,這是因為在視圖類(lèi)中有一個(gè)GetDocument函數,它的代碼如下:

      CEx_MdiDoc* CEx_MdiView::GetDocument() // non-debug version is inline

      {          ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CEx_MdiDoc)));

                return (CEx_MdiDoc*)m_pDocument;

      }

      創(chuàng )建的文檔類(lèi)型是CAnotherDoc時(shí),由于兩種類(lèi)型的文檔共用一個(gè)視圖,調用的GetDocument函數是同一個(gè)函數,因此斷言不成立,程序不能正常運行。

      (6)ClassWizard為該項目添加一個(gè)CView類(lèi)的派生類(lèi)CAnotherView,并將InitInstance第二模板pAnother中的CEx_MdiView改成CAnotherView,然后在該源文件前面添加CAnotherView的頭文件AnotherView.h。

      (7)再次運行,上述問(wèn)題得到解決。但是,圖7.4的文檔新建對話(huà)框中顯示的文檔類(lèi)型名稱(chēng)應該怎么修改呢?這時(shí)就需要使用文檔的字串資源。

7.2文檔及其序列化

7.2.2文檔的字串資源

     通過(guò)對文檔的字串資源修改可以改變文檔窗口標題、文檔類(lèi)型以及通用文件對話(huà)框中的某些內容。例如下面的示例過(guò)程:

     (1)打開(kāi)前面的多文檔應用程序項目Ex_Mdi。

     (2)打開(kāi)String Table,IDR_EX_MDITYPE字串資源復制,復制后的IDIDR_ANOTHERTYPE,修改這兩個(gè)字串資源,結果如下表所示。

     如果IDR_ANOTHERTYPE的值不等于130,可在其屬性對話(huà)框中直接給標識賦值,如圖。

     (3)InitInstance第二模板pAnother中的資源號IDR_EX_MDITYPE改成IDR_ANOTHERTYPE。

7.2文檔及其序列化

     (4)重新編譯并運行,如圖。測試后還發(fā)現打開(kāi)保存對話(huà)框中的文件類(lèi)型框中顯示出文檔字串資源定義的類(lèi)型名,如圖。

     文檔資源字串的內容也可在文檔應用程序創(chuàng )建時(shí)的Advanced Options對話(huà)框中指定,如圖,圖中數字表示該項的含義與表中對應串號的含義相同。

7.2文檔及其序列化

7.2.3 SDI序列化過(guò)程

Ø     創(chuàng )建空文檔 

     應用程序類(lèi)的InitInstance函數在調用了AddDocTemplate函數之后,會(huì )通過(guò)CWinApp:: ProcessShellCommand間接調用CWinApp的另一個(gè)非常有用的成員函數OnFileNew,并依次完成下列工作:

     (1)構造文檔對象,但并不從磁盤(pán)中讀數據。

     (2)構造主框架類(lèi)CMainFrame的對象,并創(chuàng )建該主框架窗口,但不顯示。

     (3)構造視圖對象,并創(chuàng )建視圖窗口,也不顯示。

     (4)通過(guò)內部機制,使文檔、主框架和視圖對象之間真正建立聯(lián)系。AddDocTemplate函數建立的是類(lèi)之間的聯(lián)系。

     (5)調用文檔對象的CDocument::OnNewDocument虛成員函數,并調用CDocument:: DeleteContents(清除文檔對象的內容)虛函數。

     (6)調用視圖對象的CView::OnInitialUpdate虛成員函數。

     (7)調用框架對象的CFrameWnd::ActiveFrame虛成員函數,以便顯示出具有菜單、工具欄、狀態(tài)欄以及視圖窗口的主框架窗口。

     MFC AppWizard為用戶(hù)在文檔類(lèi)中自動(dòng)產(chǎn)生OnNewDocument虛函數的重載,用戶(hù)利用此函數框架可以對文檔對象進(jìn)行初始化。

7.2文檔及其序列化

Ø     打開(kāi)文檔

     MFC AppWizard創(chuàng )建應用程序時(shí),它會(huì )自動(dòng)將文件(File)菜單中的打開(kāi)(Open)命令(ID號為ID_FILE_OPEN)映射到CWinAppOnFileOpen成員函數。這一結果可以從應用類(lèi)(.cpp)的消息入口處得到驗證:

     BEGIN_MESSAGE_MAP(CEx_SdiApp, CWinApp)

     ……

     ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)

     ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)

     // Standard print setup command

     ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)

     END_MESSAGE_MAP()

     OnFileOpen函數還會(huì )進(jìn)一步完成下列工作:

     (1)彈出通用打開(kāi)對話(huà)框,供用戶(hù)選擇一個(gè)文件。

     (2)調用文檔對象的CDocument:: OnOpenDocument虛成員函數。該函數將打開(kāi)文件,并調用DeleteContents清除文檔對象的內容,然后創(chuàng )建一個(gè)CArchive對象用于數據的讀取,接著(zhù)又自動(dòng)調用Serialize函數。

     (3)調用視圖對象的CView::OnInitialUpdate虛成員函數。

7.2文檔及其序列化

     MFC為我們重載了Serialize函數,使得我們不必使用CFile類(lèi)就可以完成相應的文檔操作。例如,在文檔類(lèi)中有這樣的代碼:

     void CEx_SdiDoc::Serialize(CArchive& ar)

     {      if (ar.IsStoring())                           

            {       // TODO: add storing code here        }

            else      

            {       // TODO: add loading code here        }

     }

     只需根據ar.IsStoring()結果的就可決定向文檔寫(xiě)與讀數據。例如,在此判斷體中,可以增加一些代碼來(lái)讀取文檔中的數據:

     void CEx_SdiDoc::Serialize(CArchive& ar)

     {      if (ar.IsStoring())        {}

             else

            {        for (int i=0; i<sizeof(m_ch); i++)        ar>>m_ch[i];

                    CString str;

                    str.Format(_T(%s), m_ch);         

                    AfxMessageBox(str);

            }

     }

7.2文檔及其序列化

Ø     保存文檔

     MFC AppWizard創(chuàng )建應用程序時(shí),會(huì )自動(dòng)將文件(File)菜單中的保存(Save)命令與文檔類(lèi)CDocumentOnFileSave函數在內部關(guān)聯(lián)起來(lái),在程序框架中看不到相應的代碼。OnFileSave函數還會(huì )進(jìn)一步完成下列工作:

     (1)彈出通用保存對話(huà)框,讓用戶(hù)提供一個(gè)文件名。

     (2)調用文檔對象的CDocument::OnSaveDocument虛成員函數,接著(zhù)又自動(dòng)調用Serialize函數,將CArchive對象的內容保存在文檔中。

     需要說(shuō)明的是:

u       只有在保存文檔之前還沒(méi)有存過(guò)盤(pán)或讀取的文檔是只讀的,OnFileSave函數才會(huì )彈出通用保存對話(huà)框。否則,只執行第二步。

u       文件(File)菜單中還有一個(gè)另存為(Save As)命令,它是與文檔類(lèi)CDocumentOnFileSaveAs函數相關(guān)聯(lián)。不管文檔有沒(méi)有保存過(guò),OnFileSaveAs都有會(huì )執行上述兩個(gè)步驟。

     可以用ClassWizard來(lái)重載CDocument::OnSaveDocument函數,并可在Serialize函數體的ar.IsStorinr()的條件語(yǔ)句處添加代碼來(lái)在文檔中保存用戶(hù)自己的數據,

7.2文檔及其序列化

Ø    關(guān)閉文檔

     試圖關(guān)閉文檔時(shí),應用程序會(huì )根據文檔是否修改進(jìn)一步完成下列任務(wù):

§       若文檔內容已被修改,則彈出一個(gè)消息對話(huà)框,詢(xún)問(wèn)用戶(hù)是否需要將文檔保存。若用戶(hù)選擇 ,則應用程序執行OnFileSave 過(guò)程。

§       調用CDocument::OnCloseDocument 虛成員函數,關(guān)閉所有與該文檔相關(guān)聯(lián)的文檔窗口及相應的視圖,調用文檔類(lèi)CDocument DeleteContents 清除文檔數據。

u       MFC應用程序通過(guò)CDocument的數據成員m_bModified的邏輯值來(lái)判斷用戶(hù)是否對文檔進(jìn)行修改,如果m_bModified,則表示文檔被修改。

u       protected類(lèi)型的m_bModified標記是通過(guò)CDocumentSetModifiedFlagIsModified成員函數被訪(fǎng)問(wèn)的。當文檔創(chuàng )建、從磁盤(pán)中讀出以及文檔存盤(pán)時(shí),文檔的這個(gè)標記就被置為FALSE();而當文檔數據被修改時(shí),必須使用SetModifiedFlag函數將該標記置為TRUE。關(guān)閉文檔時(shí),應用程序才會(huì )顯示詢(xún)問(wèn)消息對話(huà)框。

7.2文檔及其序列化

7.2.4使用CFileCArchive類(lèi)

Ø    使用CFile類(lèi)

     (1)文件的打開(kāi)和關(guān)閉

     MFC中,使用CFile打開(kāi)一個(gè)文件通常使用下列兩個(gè)步驟:

u       構造一個(gè)不帶指定任何參數的CFile對象;

u       調用成員函數Open并指定文件路徑以及文件標志。

     Open函數的原型如下:

     BOOL Open( LPCTSTR lpszFileName, UINT nOpenFlags, CFileException* pError = NULL ); 

7.2文檔及其序列化

     (2)文件的讀寫(xiě)和定位

     CFile類(lèi)支持文件的讀、寫(xiě)和定位操作。它們相關(guān)函數的原型如下:

u       UINT Read( void* lpBuf, UINT nCount );

     將文件中指定大小的數據讀入指定的緩沖區,返回向緩沖區傳輸的字節數。

u       void Write( const void* lpBuf, UINT nCount );

     此函數將緩沖區的數據寫(xiě)到文件中。

u       LONG Seek( LONG lOff, UINT nFrom );

     定位文件指針的位置,若要定位的位置是合法的,返回從文件開(kāi)始的偏移量。否則,返回值是不定的且激活一個(gè)CFileException對象。

u       函數void SeekToBegin( )DWORD SeekToEnd( )分別將文件指針移動(dòng)到文件開(kāi)始和結尾位置,對于后者還將返回文件的大小。     

7.2文檔及其序列化

      (3)獲取文件的有關(guān)信息

      BOOL GetStatus( CFileStatus& rStatus ) const;

      static BOOL PASCAL GetStatus( LPCTSTR lpszFileName, CFileStatus& rStatus );

      若指定文件的狀態(tài)信息成功獲得,該函數返回TRUE,否則返回FALSE。 rStatus用來(lái)存放文件狀態(tài)信息,是一個(gè)CFileStatus結構類(lèi)型,該結構具有下列成員:

      CTime m_ctime             文件創(chuàng )建日期和時(shí)間

      CTime m_mtime            文件最后一次修改日期和時(shí)間

      CTime m_atime            文件最后一次訪(fǎng)問(wèn)日期和時(shí)間

      LONG m_size             文件的邏輯大小字節數,就像DOS命令中DIR所顯示的大小

      BYTE m_attribute           文件屬性

      char m_szFullName[_MAX_PATH]   文件名

      例如下面的代碼:

      CFile theFile;

      char* szFileName = "c:\\test\\myfile.dat";

      BOOL bOpenOK;

      CFileStatus status;

      if( CFile::GetStatus( szFileName, status ) )

      {            bOpenOK = theFile.Open( szFileName, CFile::modeWrite );    }

      else

      {        bOpenOK = theFile.Open( szFileName, CFile::modeCreate | CFile::modeWrite );    }

7.2文檔及其序列化

Ø     使用CArchive類(lèi)

     (1)CArchive類(lèi)對象的創(chuàng )建和關(guān)閉

     創(chuàng )建CArchive對象,有兩種方法:一是通過(guò)框架隱式創(chuàng )建CArchive對象,另一是顯式創(chuàng )建CArchive 對象。

     (2)使用<<>>運算符 

     (3)文件文本的讀寫(xiě)

     CArchive提供成員函數ReadStringWriteString用來(lái)從一個(gè)文件對象中讀寫(xiě)一行文本,它們的原型如下:

     Bool ReadString(CString& rString );

     LPTSTR ReadString( LPTSTR lpsz, UINT nMax );

     void WriteString( LPCTSTR lpsz );

7.2文檔及其序列化

7.2.5使用簡(jiǎn)單數組集合類(lèi)

Ø     簡(jiǎn)單數組集合類(lèi)的構造及元素的添加

     對簡(jiǎn)單數組集合類(lèi)構造的方法都是一樣的,都是使用各自的構造函數,它們的原型如下:

     CByteArray            CByteArray( );

     CDWordArray                 CDWordArray( );

     CPtrArray              CPtrArray( );

     CStringArray         CStringArray( );

     CUIntArray            CUIntArray( );

     CWordArray           CWordArray( );

     為了有效使用內存,在使用簡(jiǎn)單數組集合類(lèi)之前最好調用成員函數SetSize 設置此數組的大小,與其對應的函數是GetSize,用來(lái)返回數組的大小。它們的原型如下:

     void SetSize( int nNewSize, int nGrowBy = -1 );

     int GetSize( ) const;

     向簡(jiǎn)單數組集合類(lèi)添加一個(gè)元素,可使用成員函數AddAppend,它們的原型如下:

     int Add( CObject* newElement );

     int Append( const CObArray& src );

7.2文檔及其序列化

Ø     訪(fǎng)問(wèn)簡(jiǎn)單數組集合類(lèi)的元素

     MFC中,一個(gè)簡(jiǎn)單數組集合類(lèi)元素的訪(fǎng)問(wèn)既可以使用GetAt函數,也可使用[]操作符,例如:

     //  CObArray::operator []示例

     CObArray array;                   

     CAge* pa;                     // CAge是一個(gè)用戶(hù)類(lèi)

     array.Add( new CAge( 21 ) );         // 添加一個(gè)元素

     array.Add( new CAge( 40 ) );         // 再添加一個(gè)元素

     pa = (CAge*)array[0];           // 獲取元素0

     ASSERT( *pa == CAge( 21 ) );

     array[0] = new CAge( 30 );         // 替換元素0;

     ASSERT( *(CAge*) array[0] == CAge( 30 ) );

     //  CObArray::GetAt示例

     CObArray array;

     array.Add( new CAge( 21 ) );        // 元素 0

     array.Add( new CAge( 40 ) );         // 元素 1

     ASSERT( *(CAge*) array.GetAt( 0 ) == CAge( 21 ) );

7.2文檔及其序列化

Ø     刪除簡(jiǎn)單數組集合類(lèi)的元素

     刪除簡(jiǎn)單數組集合類(lèi)中的元素一般需要進(jìn)行以下幾個(gè)步驟:

     (1)使用函數GetSize()和整數下標值訪(fǎng)問(wèn)簡(jiǎn)單數組集合類(lèi)中的元素。

     (2)若對象元素是在堆中創(chuàng )建的,則使用delete刪除每一個(gè)對象元素。

     (3)調用函數RemoveAll()刪除簡(jiǎn)單數組集合類(lèi)中的所有元素。

     例如,下面代碼過(guò)程是一個(gè)CObArray的刪除示例:

     CObArray array;

     CAge* pa1;

     CAge* pa2;

     array.Add( pa1 = new CAge( 21 ) );

     array.Add( pa2 = new CAge( 40 ) );

     ASSERT( array.GetSize() == 2 );

     for (int i=0;i<array.GetSize();i++)  delete array.GetAt(i);

     array.RemoveAll();

     函數RemoveAll是刪除數組中的所有元素,而函數RemoveAt( int nIndex, int nCount = 1)則表示要刪除數組中指定元素開(kāi)始的指定數目的元素。

7.3視圖及視圖類(lèi)

7.3.1一般視圖類(lèi)的使用

7.3視圖及視圖類(lèi)

Ø     CFormView類(lèi)

u       CFormView類(lèi)是一個(gè)非常有用的視圖類(lèi),它具有許多無(wú)模式對話(huà)框的特點(diǎn)。像CDiolog的派生類(lèi)一樣,CFormView的派生類(lèi)也和相應的對話(huà)框資源相聯(lián)系,它也支持對話(huà)框數據交換和對話(huà)框數據確認(DDXDDV)。

u       CFormView是所有表單視(CRecordView、CDaoRecordView、CHtmlView)的基類(lèi);一個(gè)基于表單的應用程序能讓用戶(hù)在程序中創(chuàng )建和使用一個(gè)或多個(gè)表單。

u       創(chuàng )建表單應用程序的基本方法除了在創(chuàng )建SDI/MDI的第六步中選擇CFormView作為應用程序視圖類(lèi)的基類(lèi)外。還可通過(guò)相關(guān)菜單命令來(lái)自動(dòng)插入一個(gè)表單,其步驟如下:

     (1)切換到ClassView標簽項,在項目名稱(chēng)上右擊鼠標按鈕。從彈出的快捷菜單中選擇New Form命令,或者直接在主菜單中選擇InsertàNew Form...菜單命令,彈出如圖7.10New Form對話(huà)框。

     (2)New Form對話(huà)框中,鍵入表單名稱(chēng)。如果想要表單支持自動(dòng)化特性,則選擇Automation單選框。在Document Template Information欄中,指定和表單并聯(lián)的文檔內容。如果想要更改文件擴展名或文檔模板字串資源,則可按擊[Change]按鈕。

     (3)單擊[OK]按鈕,這樣,一個(gè)表單視圖派生類(lèi)的程序框架就被添加到用戶(hù)程序中;此時(shí),我們就可用對話(huà)框編輯器為表單增加一些控件。

7.3視圖及視圖類(lèi)

Ø    CEditView類(lèi)

     CEditView類(lèi)對象是一種視圖,提供窗口編輯控制功能,可以執行簡(jiǎn)單文本操作。由于CEditView類(lèi)自動(dòng)封裝上述功能的映射函數,因此只要在文檔模板中使用CEditView類(lèi),那么應用程序的編輯菜單和文件菜單里的菜單項都可自動(dòng)激活。

     CEditView仍然擺脫不了所有編輯控件的限制,如:

u       CEditView不具有所見(jiàn)即所得編輯功能。

u       CEditView只能將文本作單一字體的顯示,不支持特殊格式的字符。

u       CEditView可容納的文本總數有限,在32Windows中最多不超過(guò)1M字節。 

7.3視圖及視圖類(lèi)

Ø      CRichEditView類(lèi)

     CRichEditView類(lèi)使用了復文本編輯控件,因此它支持混合字體格式和更大數據量的文本。CRichEditView類(lèi)被設計成與CRichEditDocCRichEditCntrItem類(lèi)一起使用,它們可實(shí)現一個(gè)完整的ActiveX包容器應用程序。

Ø      CHtmlView 類(lèi)

     CHtmlView 類(lèi)是在文檔視圖結構中提供WebBrowser控件的功能。WebBrowser控件可以瀏覽網(wǎng)址,也可以作為本地文件和網(wǎng)絡(luò )文件系統的窗口,它支持超級鏈接、統一資源定位(URL)導航器并維護歷史列表等。

Ø     CScrollView類(lèi)

     CScrollView類(lèi)不僅能直接支持視圖的滾動(dòng)操作,而且還能管理視口的大小和映射模式,并能響應滾動(dòng)條消息、鍵盤(pán)消息以及鼠標滾輪消息。

     滾動(dòng)視圖第一次被創(chuàng )建時(shí),往往在重載的CView::OnInitialUpdateCView::OnUpdate中調用CScrollView成員函數SetScrollSizes來(lái)設置相關(guān)參數,如映射模式、滾動(dòng)邏輯窗口的大小、水平或垂直方向的滾動(dòng)量等。如果僅需要視圖具有自動(dòng)縮放功能(而不具有滾動(dòng)特性),則用CScrollView::SetScaleToFitSize函數代替SetScrollSizes即可。

7.3視圖及視圖類(lèi)

7.3.2列表控件和列表視圖

Ø     列表控件的風(fēng)格及其修改

7.3視圖及視圖類(lèi)

Ø     列表項的基本操作

u       函數SetImageList用來(lái)為列表控件設置一個(gè)關(guān)聯(lián)的圖像列表,其原型如下:

      CImageList* SetImageList( CImageList* pImageList, int nImageList );

u       函數InsertItem用來(lái)向列表控件中插入一個(gè)列表項。該函數成功時(shí)返回新列表項的索引號,否則返回-1。函數原型如下:

      int InsertItem( const LVITEM* pItem );

      int InsertItem( int nItem, LPCTSTR lpszItem );

      int InsertItem( int nItem, LPCTSTR lpszItem, int nImage );

      pItem用來(lái)指定一個(gè)指向LVITEM結構的指針,其結構描述如下:

      typedef struct _LVITEM

      {        UINT           mask;                // 指明哪些參數有效

                       int              iItem;                // 列表項索引

                       int              iSubItem;                     // 子項索引

                       UINT             state;                // 列表項狀態(tài)

                       UINT             stateMask;      // 指明state哪些位是有效的,-1全部有效

                       LPTSTR            pszText;                     // 列表項文本標簽

                       int              cchTextMax;    // 文本大小

                       int              iImage;             // 在圖像列表中列表項圖標的索引號。

                       LPARAM           lParam;              // 32位值

                       int          iIndent;          // 項目縮進(jìn)數量,1個(gè)數量等于1個(gè)圖標的像素寬度

      } LVITEM, FAR *LPLVITEM;

7.3視圖及視圖類(lèi)

u       函數DeleteItemDeleteAllItems分別用來(lái)刪除指定的列表項和全部列表項,函數原型如下:

     BOOL DeleteItem( int nItem );

     BOOL DeleteAllItems( );

u       函數FindItem用來(lái)查尋列表項,函數成功查找時(shí)返回列表項的索引號,否則返回-1。其原型如下:

     int FindItem( LVFINDINFO* pFindInfo, int nStart = -1 ) const;

     pFindInfo表示要查找的信息,其結構描述如下:

     typedef struct tagLVFINDINFO

     {      UINT           flags;             // 查找方式

                  LPCTSTR     psz;               // 匹配的文本

                  LPARAM         lParam;          // 匹配的值

                   POINT           pt;                // 查找開(kāi)始的位置坐標。

                    UINT             vkDirection;// 查找方向,用虛擬方向健值表示。

    } LVFINDINFO, FAR* LPFINDINFO;

u       函數Arrange用來(lái)按指定方式重新排列列表項,其原型如下:

     BOOL Arrange( UINT nCode );

7.3視圖及視圖類(lèi)

u       函數InsertColumn用來(lái)向列表控件插入新的一列,函數成功調用后返回新的列的索引,否則返回-1。其原型如下:

      int InsertColumn( int nCol, const LVCOLUMN* pColumn );

      int InsertColumn( int nCol, LPCTSTR lpszColumnHeading, int nFormat = LVCFMT_LEFT,

      int nWidth = -1, int nSubItem = -1 );

      pColumn表示包含新列信息的LVCOLUMN結構地址,其結構描述如下:

      typedef struct _LVCOLUMN

      {        UINT           mask;                // 指明哪些參數有效

                       int          fmt;                   // 列的標題或子項文本格式

                       int           cx;                    // 列的像素寬度

                       LPTSTR           pszText;                     // 列的標題文本

                       int           cchTextMax;    // 列的標題文本大小

                       int           iSubItem;           // 和列相關(guān)的子項索引

                       int           iImage;              // 圖像列表中的圖像索引

                       int           iOrder;               // 列的序號,最左邊的列為0

      } LVCOLUMN, FAR *LPLVCOLUMN;

u       函數DeleteColumn用來(lái)從列表控件中刪除一個(gè)指定的列,其原型如下:

      BOOL DeleteColumn( int nCol );

u       GetItemCount用來(lái)返回列表控件中的列表項個(gè)數等。它們的原型如下:

      BOOL SetColumnWidth( int nCol, int cx );

      int GetItemCount( );

7.3視圖及視圖類(lèi)

Ø     列表控件的消息

      常用的列表控件消息有:

      LVN_BEGINDRAG                  用戶(hù)按左鼠拖動(dòng)列表列表項

      LVN_BEGINLABELEDIT           用戶(hù)對某列表項標簽進(jìn)行編輯

      LVN_COLUMNCLICK              某列被按擊

      LVN_ENDLABELEDIT            用戶(hù)對某列表項標簽結束編輯

      LVN_ITEMACTIVATE              用戶(hù)激活某列表項

      LVN_ITEMCHANGED             當前列表項已被改變

      LVN_ITEMCHANGING            當前列表項即將改變

      LVN_KEYDOWN                     某鍵被按下

      在用ClassWizard處理上述這些消息時(shí),其消息處理函數參數中往往會(huì )出現NM_LISTVIEW結構,其定義如下:

      typedef struct tagNMLISTVIEW

      {        NMHDR             hdr;                   // 包含通知消息的結構

                       int               iItem;                 // 列表項索引,沒(méi)有為-1

                       int               iSubItem;           // 子項索引,沒(méi)有為0

                       UINT              uNewState;       // 新的項目狀態(tài)

                       UINT             uOldState;          // 原來(lái)的項目狀態(tài)

                       UINT              uChanged;       // 項目屬性更改標志

                       POINT             ptAction;           // 事件發(fā)生的地點(diǎn)

                       LPARAM            lParam;              // 用戶(hù)定義的32位值

      } NMLISTVIEW, FAR *LPNMLISTVIEW;

7.3視圖及視圖類(lèi)

      [Ex_Lview] 將當前文件夾中的文件用大圖標、小圖標、列表視圖以及報表視圖四種不同方式在列表視圖中顯示出來(lái)。當雙擊某個(gè)列表項時(shí),還將該項的文本標簽內容用消息對話(huà)框的形式顯示出來(lái)。

      (1)MFC AppWziard創(chuàng )建一個(gè)單文檔應用程序Ex_List,在創(chuàng )建的第六步將視圖的基類(lèi)選擇為CListView。

      (2)CEx_ListView類(lèi)添加下列成員函數和成員函數:

      public:

                CImageList            m_ImageList;

                CImageList              m_ImageListSmall;

                CStringArray m_strArray;

                void SetCtrlStyle(HWND hWnd, DWORD dwNewStyle);

      (3)將項目工作區窗口切換到ResourceView頁(yè)面,打開(kāi)Accelerator節點(diǎn)下的IDR_MAINFRAME,為其添加一個(gè)鍵盤(pán)加速鍵Ctrl+Shift+X,ID號為ID_VIEW_CHANGE。

      (4)ClassWizardCEx_ListView類(lèi)添加ID_VIEW_CHANGECOMMAND消息映射函數,并增加下列代碼:

      void CEx_ListView::OnViewChange()

      {        static int nStyleIndex = 1;

                DWORD style[4] = {LVS_REPORT, LVS_ICON, LVS_SMALLICON, LVS_LIST };

                CListCtrl& m_ListCtrl = GetListCtrl();

                SetCtrlStyle(m_ListCtrl.GetSafeHwnd(), style[nStyleIndex]);

                nStyleIndex++;

                if (nStyleIndex>3) nStyleIndex = 0;

      }

7.3視圖及視圖類(lèi)

      (5)ClassWizardCEx_ListView類(lèi)添加NM_DBLCLK消息映射函數,增加代碼:

      void CEx_ListView::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult)

      {          LPNMITEMACTIVATE lpItem = (LPNMITEMACTIVATE)pNMHDR;

                int nIndex = lpItem->iItem;

                if (nIndex >= 0)

                {          CListCtrl& m_ListCtrl = GetListCtrl();

                          CString str = m_ListCtrl.GetItemText(nIndex, 0);

                          MessageBox(str);                        }

      *pResult = 0;

      }

      (6)CEx_ListView::OnInitialUpdate中添加下列代碼:

      void CEx_ListView::OnInitialUpdate()

      {          CListView::OnInitialUpdate();

                // 創(chuàng )建圖像列表

                m_ImageList.Create(32,32,ILC_COLOR8|ILC_MASK,1,200);

                m_ImageListSmall.Create(16,16,ILC_COLOR8|ILC_MASK,1,200);

                CListCtrl& m_ListCtrl = GetListCtrl();

                m_ListCtrl.SetImageList(&m_ImageList,LVSIL_NORMAL);

                m_ListCtrl.SetImageList(&m_ImageListSmall,LVSIL_SMALL);

                LV_COLUMN listCol;

                char* arCols[4]={"文件名", "大小", "類(lèi)型", "修改日期"};

                listCol.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;

7.3視圖及視圖類(lèi)

         for (int nCol=0; nCol<4; nCol++)

                {          listCol.iSubItem = nCol;

                          listCol.pszText = arCols[nCol];

                          if (nCol == 1)               

                                          listCol.fmt = LVCFMT_RIGHT;

                          else

                                          listCol.fmt = LVCFMT_LEFT;

                          m_ListCtrl.InsertColumn(nCol,&listCol);               }

      // 查找當前目錄下的文件

      CFileFind finder;

      BOOL bWorking = finder.FindFile("*.*");

      int nItem = 0, nIndex, nImage;

      CTime m_time;

      CString str, strTypeName;

      while (bWorking)

      {      bWorking = finder.FindNextFile();

             if (finder.IsArchived())

                {          str = finder.GetFilePath();

                          SHFILEINFO fi;

                          SHGetFileInfo(str,0,&fi,sizeof(SHFILEINFO),

                          SHGFI_ICON|SHGFI_LARGEICON|SHGFI_TYPENAME);

                          strTypeName = fi.szTypeName;

                          nImage = -1;

7.3視圖及視圖類(lèi)

               for (int i=0; i<m_strArray.GetSize(); i++)

                {          if (m_strArray[i] == strTypeName)

                                 {            nImage = i;        break;          }

                }

                if (nImage<0)

                {          nImage = m_ImageList.Add(fi.hIcon);

                                   SHGetFileInfo(str,0,&fi,sizeof(SHFILEINFO),

                          SHGFI_ICON|SHGFI_SMALLICON );

                          m_ImageListSmall.Add(fi.hIcon);

                          m_strArray.Add(strTypeName);

                }

                nIndex = m_ListCtrl.InsertItem(nItem,finder.GetFileName(),nImage);

                DWORD dwSize = finder.GetLength();

                if (dwSize> 1024)          str.Format("%dK", dwSize/1024);

                else          str.Format("%d", dwSize);

                m_ListCtrl.SetItemText(nIndex,1,str);

                m_ListCtrl.SetItemText(nIndex,2,strTypeName);

                finder.GetLastWriteTime(m_time) ;

                m_ListCtrl.SetItemText(nIndex,3,m_time.Format("%Y-%m-%d"));

                nItem++;

      }

}

7.3視圖及視圖類(lèi)

                SetCtrlStyle(m_ListCtrl.GetSafeHwnd(), LVS_REPORT);

                m_ListCtrl.SetColumnWidth(0, LVSCW_AUTOSIZE);// 設置列寬

                m_ListCtrl.SetColumnWidth(1, 100);         

                m_ListCtrl.SetColumnWidth(2, LVSCW_AUTOSIZE);  

                m_ListCtrl.SetColumnWidth(3, 200);         

      }

     (7)編譯并運行,如圖。

7.3視圖及視圖類(lèi)

7.3.3樹(shù)控件和樹(shù)視圖

Ø     樹(shù)形視圖的風(fēng)格

7.3視圖及視圖類(lèi)

Ø     樹(shù)控件的常用操作

u       函數InsertItem用來(lái)向樹(shù)控件插入一個(gè)新項,操作成功后,函數返回新項的句柄,否則返回NULL。函數原型如下:

     HTREEITEM InsertItem( UINT nMask, LPCTSTR lpszItem,int nImage, int nSelectedImage, 

     UINT nState, UINT nStateMask, LPARAM lParam,

     HTREEITEM hParent,  HTREEITEM hInsertAfter );

     HTREEITEM InsertItem( LPCTSTR lpszItem, HTREEITEM hParent = TVI_ROOT,  

     HTREEITEM hInsertAfter = TVI_LAST );

     HTREEITEM InsertItem( LPCTSTR lpszItem, int nImage, int nSelectedImage, 

     HTREEITEM hParent = TVI_ROOT,

     HTREEITEM hInsertAfter = TVI_LAST );

u       函數DeleteItemDeleteAllItems分別用來(lái)刪除指定的項和全部的項。它們的原型如下:

     BOOL DeleteAllItems( );

     BOOL DeleteItem( HTREEITEM hItem );

u       函數Expand用來(lái)用來(lái)展開(kāi)或收縮指定父項的所有子項,其原型如下:

     BOOL Expand( HTREEETEM hItem, UINT nCode );

7.3視圖及視圖類(lèi)

Ø     樹(shù)形視圖控件的通知消息

     樹(shù)視圖可以用ClassWizard映射公共控件消息和樹(shù)控件消息。常用的樹(shù)控件消息有:

     TVN_BEGINDRAG                     開(kāi)始拖放操作

     TVN_BEGINLABELEDIT         開(kāi)始編輯標簽

     TVN_BEGINRDRAG                   鼠標右按鈕開(kāi)始拖放操作

     TVN_ENDLABELEDIT                 標簽編輯結束

     TVN_ITEMEXPANDED               含有子項的父項已展開(kāi)或收縮

     TVN_ITEMEXPANDING          含有子項的父項將要展開(kāi)或收縮

     TVN_SELCHANGED                   當前選擇項發(fā)生改變

     TVN_SELCHANGING                  當前選擇項將要發(fā)生改變

     ClassWizard處理上述這些消息時(shí),其消息處理函數參數中往往會(huì )出現NM_TREEVIEW結構,定義如下:

     typedef struct tagNMTREEVIEW

     {      NMHDR         hdr;               // 含有通知代碼的信息結構

                  UINT         action;         // 通知方式標志

                  TVITEM         itemOld;         // 原有項的信息

                  TVITEM         itemNew;    // 現在項的信息

                  POINT   ptDrag;                 // 事件產(chǎn)生時(shí),鼠標的位置

     } NMTREEVIEW, FAR *LPNMTREEVIEW;

7.3視圖及視圖類(lèi)

     [Ex_Tree] 遍歷本地磁盤(pán)所有的目錄。

     (1)MFC AppWziard創(chuàng )建一個(gè)單文檔應用程序Ex_Tree,在創(chuàng )建的第六步將視圖的基類(lèi)選擇為CTreeView。

     (2)按快捷鍵Ctrl+R,選定資源類(lèi)型Icon,單擊Import按鈕,從外部調入六個(gè)圖標,分別表示我的電腦、軟驅、硬盤(pán)、光驅、文件夾以及打開(kāi)的文件夾,相應的ID號設為IDI_MYCOMP、IDI_35FLOPPY、IDI_DRIVE、IDI_CDDRIVE、IDI_CLSDFOLDIDI_OPENFOLD,如圖。

7.3視圖及視圖類(lèi)

                  (3)CEx_TreeView類(lèi)添加下列成員函數和成員函數:

      public:

                CImageList            m_ImageList;

                CString           m_strPath;                 // 文件夾路徑

                void InsertFoldItem(HTREEITEM m_hItem);

                void SetCtrlStyle(HWND hWnd, DWORD dwNewStyle);

      InsertFoldItem函數的代碼如下:

      void CEx_TreeView::InsertFoldItem(HTREEITEM m_hItem)

      {        CFileFind finder;

                BOOL bWorking = finder.FindFile(m_strPath);

                CString m_str;

                while (bWorking)

                {          bWorking = finder.FindNextFile();

                          if (finder.IsDirectory() && !finder.IsHidden())

                          {          m_str = finder.GetFileName();

                                          m_str.TrimRight();

                                          m_str.TrimLeft();

                                          if ((m_str!=_T("."))&&(m_str!=_T("..")))

                                          {          CTreeCtrl& m_TreeCtrl = GetTreeCtrl();

                                                    m_TreeCtrl.InsertItem(m_str,4,5,m_hItem);}

                          }

                }

      }

7.3視圖及視圖類(lèi)

      (4)CEx_TreeView類(lèi)添加TVN_ITEMSELECTED消息處理,增加代碼:

      void CEx_TreeView::OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult)

      {          NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;

                HTREEITEM m_hSelected = pNMTreeView->itemNew.hItem;

                CTreeCtrl& m_TreeCtrl = GetTreeCtrl();

                if ((!m_TreeCtrl.ItemHasChildren(m_hSelected))&&(m_hSelected)){

                          BOOL m_bIsTop = FALSE;

                          CString m_str;

                          m_strPath.Empty();

                          HTREEITEM m_hTemp = m_hSelected;

                          while (!m_bIsTop){

                                          m_str = m_TreeCtrl.GetItemText(m_hTemp);

                                          m_str.TrimLeft();

                                          m_str.TrimRight();

                                          m_strPath = m_str+"\\"+m_strPath;

                                          m_TreeCtrl.GetParentItem(m_hTemp);

                          if(m_TreeCtrl.GetParentItem(m_TreeCtrl.GetParentItem(m_hTemp))){

                                          m_hTemp = m_TreeCtrl.GetParentItem(m_hTemp);

                                          }else m_bIsTop=TRUE;       }

                          m_strPath += _T("*.");

                          InsertFoldItem(m_hSelected);

                          m_TreeCtrl.Expand(m_hSelected,TVE_EXPAND);          }

                *pResult = 0;

      }

7.3視圖及視圖類(lèi)

     (5)CEx_TreeView::OnInitialUpdate函數中添加下列代碼:

     void CEx_TreeView::OnInitialUpdate()

     {        CTreeView::OnInitialUpdate();

             CTreeCtrl& m_TreeCtrl = GetTreeCtrl();

             m_ImageList.Create(16, 16, ILC_COLOR|ILC_MASK, 6, 0);

             m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_MYCOMP));

             m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_35FLOPPY));

             m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_DRIVE));

             m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_CDDRIVE));

             m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_CLSDFOLD));

             m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_OPENFOLD));

             m_TreeCtrl.SetImageList(&m_ImageList,TVSIL_NORMAL);

             HTREEITEM m_hRootItem, m_hTempItem;

             m_hRootItem = m_TreeCtrl.InsertItem("我的電腦",0,0);

            // 查找并檢測已有的驅動(dòng)器

            DWORD dwDrives = GetLogicalDrives();

            UINT uType;

            CString m_strDrive, m_strTemp;

7.3視圖及視圖類(lèi)

      for( int i = 0; i < 32; i++ )

      {        DWORD dwTemp = dwDrives;

                if( dwTemp & 1 )

                {          m_strTemp.Format(_T("%c:\\."),'A'+(char)i);

                          uType = GetDriveType(m_strTemp);

                          m_strTemp.Format(_T(" %c: "),'A'+(char)i);

                          switch(uType){

                                          case DRIVE_REMOVABLE:  

                                          m_TreeCtrl.InsertItem(m_strTemp,1,1,m_hRootItem);

                                                    break;

                                          case DRIVE_FIXED:m_hTempItem = m_TreeCtrl.InsertItem(m_strTemp,2,2,m_hRootItem);

                                                    break;

                                          case DRIVE_CDROM:

                                          m_TreeCtrl.InsertItem(m_strTemp,3,3,m_hRootItem);

                                                    break;

                          }

                }

                dwDrives = dwDrives >> 1;

      }

      SetCtrlStyle(m_TreeCtrl.GetSafeHwnd(),

                                          TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS);

      m_TreeCtrl.Expand(m_hRootItem,TVE_EXPAND);

}

7.3視圖及視圖類(lèi)

     (6)編譯并運行,如圖。

7.4文檔視圖結構

7.4.1文檔與視圖的相互作用

Ø     CView::GetDocument函數

     MFC AppWizard產(chǎn)生CView的用戶(hù)派生類(lèi)時(shí),同時(shí)創(chuàng )建一個(gè)安全類(lèi)型的GetDocument函數,返回的是指向派生文檔類(lèi)的指針。該函數是一個(gè)內聯(lián)(inline)函數,類(lèi)似于下面的形式:

     CMyDoc* CMyView::GetDocument() // non-debug version is inline

     {        ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMyDoc)));

     // 斷言m_pDocument指針可以指向的CMyDoc類(lèi)是一個(gè)RUNTIME_CLASS類(lèi)型

            return (CMyDoc*)m_pDocument;

     }

Ø      CDocument::UpdateAllViews函數

     UpdateAllViews函數的原型如下。

     void UpdateAllViews( CView* pSender, LPARAM lHint = 0L, CObject* pHint = NULL );

Ø      CView::OnUpdate函數

     應用程序調用了CDocument::UpdateAllViews函數時(shí),應用程序框架就會(huì )相應地調用該函數。

     virtual void OnUpdate( CView* pSender, LPARAM lHint, CObject* pHint );

7.4文檔視圖結構

Ø      CView::OnInitialUpdate函數

     應用程序被啟動(dòng)時(shí),或從文件菜單中選擇了新建打開(kāi)時(shí),CView虛函數都會(huì )被自動(dòng)調用。該函數除了調用無(wú)提示參數(lHint = 0, pHint = NULL)OnUpdate函數之外,沒(méi)做其他任何事情。

     可以重載此函數對文檔所需信息進(jìn)行初始化操作。如果應用程序中的文檔大小是動(dòng)態(tài)的,那么就可在文檔每次改變時(shí)調用OnUpdate來(lái)更新視圖的滾動(dòng)范圍。

Ø     CDocument::OnNewDocument函數

     SDI應用程序中,從文件菜單中選擇新建命令時(shí),框架將先構造一個(gè)文檔對象,然后調用該虛函數。

     MFC AppWizard為用戶(hù)的派生文檔類(lèi)自動(dòng)產(chǎn)生了重載的OnNewDocument函數,如下面的代碼:

     BOOL CMyDoc::OnNewDocument()

     {     if (!CDocument::OnNewDocument())        // 注意一定要保證對基類(lèi)函數的調用,

                  return FALSE;  

            // Do initialization of new document here.  

            return TRUE;

     } 

7.4文檔視圖結構

7.4.2應用程序對象指針的互調

Ø     從文檔類(lèi)中獲取視圖對象指針

     在文檔類(lèi)中有一個(gè)與其關(guān)聯(lián)的各視圖對象的列表,并可通過(guò)CDocument類(lèi)的成員函數GetFirstViewPositionGetNextView來(lái)定位相應的視圖對象。

     GetFirstViewPosition函數用來(lái)獲得與文檔類(lèi)相關(guān)聯(lián)的視圖列表中第一個(gè)可見(jiàn)視圖的位置,GetNextView函數用來(lái)獲取指定視圖位置的視圖類(lèi)指針,并將此視圖位置移動(dòng)下一個(gè)位置,若沒(méi)有下一個(gè)視圖,則視圖位置為NULL。原型如下:

     virtual POSITION GetFirstViewPosition( ) const;

     virtual CView* GetNextView( POSITION& rPosition ) const;

     例如,使用CDocument::GetFirstViewPositionGetNextView重繪每個(gè)視圖

     void CMyDoc::OnRepaintAllViews()

     {        POSITION pos = GetFirstViewPosition();

                   while (pos != NULL)

                   {        CView* pView = GetNextView(pos);

                 pView->UpdateWindow();

                   }  

     }

     //  實(shí)現上述功能也可直接調用UpdateAllViews(NULL); 

7.4文檔視圖結構

Ø     從視圖類(lèi)中獲取文檔對象和主框架對象指針

     函數CWnd::GetParentFrame可實(shí)現從視圖類(lèi)中獲取主框架指針,原型:

     CFrameWnd* GetParentFrame( ) const;

Ø     在主框架類(lèi)中獲取視圖對象指針

     CFrameWnd類(lèi)的GetActiveView函數原型如下:

     CView* GetActiveView( ) const;

     在框架類(lèi)中可直接調用CFrameWnd::GetActiveDocument函數獲得當前活動(dòng)的文檔對象指針。

     在同一個(gè)應用程序的任何對象中,可通過(guò)全局函數AfxGetApp()來(lái)獲得指向應用程序對象的指針。 

7.4文檔視圖結構

7.4.3切分窗口

Ø      靜態(tài)切分和動(dòng)態(tài)切分

      靜態(tài)切分窗口,窗口第一次被創(chuàng )建時(shí),窗格就已經(jīng)被切分好了,窗格的次序和數目不能再被改變,但可以移動(dòng)切分條來(lái)調整窗格的大小。

      動(dòng)態(tài)切分窗口,允許在任何時(shí)候對窗口進(jìn)行切分,既可以通過(guò)選擇菜單項來(lái)對窗口進(jìn)行切分,也可以通過(guò)拖動(dòng)滾動(dòng)條中的切分框對窗口進(jìn)行切分。動(dòng)態(tài)切分窗口中的窗格通常使用的是同一個(gè)視圖類(lèi)。切分窗口被創(chuàng )建時(shí),左上窗格通常被初始化成一個(gè)特殊的視圖。當視圖沿著(zhù)某個(gè)方向被切分時(shí),另一個(gè)新增加的視圖對象被動(dòng)態(tài)創(chuàng )建;當視圖沿著(zhù)兩個(gè)方向被切分時(shí),新增加的三個(gè)視圖對象則被動(dòng)態(tài)創(chuàng )建。取消切分時(shí),所有新增加的視圖對象被刪除,但最先的視圖仍被保留,直到切分窗口本身消失。

Ø      切分窗口的CSplitterWnd類(lèi)

      成員函數CreateCreateStatic用來(lái)創(chuàng )建動(dòng)態(tài)切分靜態(tài)切分的文檔窗口,原型:

      BOOL Create( CWnd* pParentWnd, int nMaxRows, int nMaxCols, SIZE sizeMin,

      CCreateContext* pContext,

      DWORD dwStyle = WS_CHILD | WS_VISIBLE |WS_HSCROLL | WS_VSCROLL | SPLS_DYNAMIC_SPLIT,

      UINT nID = AFX_IDW_PANE_FIRST );

      BOOL CreateStatic( CWnd* pParentWnd, int nRows, int nCols,

      DWORD dwStyle = WS_CHILD | WS_VISIBLE,

      UINT nID = AFX_IDW_PANE_FIRST ); 

7.4文檔視圖結構

     [Ex_ SplitSDI] SDI文檔窗口靜態(tài)分成3 x 2個(gè)窗格:

     (1)MFC AppWizard創(chuàng )建一個(gè)單文檔項目Ex_SplitSDI。

     (2)打開(kāi)框架窗口類(lèi)MainFrm.h頭文件,為CMainFrame類(lèi)添加一個(gè)保護型的切分窗口的數據成員,如下面的定義:

     protected:  // control bar embedded members

             CStatusBar          m_wndStatusBar;

            CToolBar            m_wndToolBar;

     CSplitterWnd         m_wndSplitter;

     (3)ClassWizard創(chuàng )建一個(gè)新的視圖類(lèi)CDemoView(基類(lèi)為CView)用于與靜態(tài)切分的窗格相關(guān)聯(lián)。

7.4文檔視圖結構

(5) CMainFrame類(lèi)添加OnCreateClient消息函數,增加代碼:

     BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs,  CCreateContext* pContext)

     {      CRect rc;

             GetClientRect(rc);

            CSize paneSize(rc.Width()/2-16,rc.Height()/3-16);                      m_wndSplitter.CreateStatic(this,3,2);                         m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CDemoView),

             paneSize,pContext);                                m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CDemoView),

             paneSize,pContext);

             m_wndSplitter.CreateView(1,0,RUNTIME_CLASS(CDemoView),

             paneSize,pContext);

             m_wndSplitter.CreateView(1,1,RUNTIME_CLASS(CDemoView),

             paneSize,pContext);

             m_wndSplitter.CreateView(2,0,RUNTIME_CLASS(CDemoView),

             paneSize,pContext);

             m_wndSplitter.CreateView(2,1,RUNTIME_CLASS(CDemoView),

             paneSize,pContext);

            return TRUE;

     }

7.4文檔視圖結構

     (5)MainFrm.cpp源文件的開(kāi)始處,添加視圖類(lèi)CDemoView的包含文件:

     #include "DemoView.h"

     (6)編譯并運行,如圖。

7.4文檔視圖結構

     值得注意的是:

u       調用CreateStatic函數創(chuàng )建靜態(tài)切分窗口后,必須將每個(gè)窗格用CreateView函數指定相關(guān)聯(lián)的視圖類(lèi)。

u       由于切分功能只應用于文檔窗口,因而在MDI添加該功能時(shí)應在文檔子窗口類(lèi)CChildFrame中進(jìn)行操作。

u       動(dòng)態(tài)切分功能的添加過(guò)程比靜態(tài)切分要簡(jiǎn)單得多,它不需要重新為窗格指定其它視圖類(lèi),因為動(dòng)態(tài)切分窗口的所有窗格共享同一個(gè)視圖。若在文檔窗口添加動(dòng)態(tài)切分的功能可在MFC AppWizard創(chuàng )建SDI(MDI)應用程序過(guò)程中進(jìn)行設置。在Step 4對話(huà)框中單擊[Advanced]按鈕,再單擊Window Styles標簽,然后選擇Use Split Window即可。應用程序編譯運行之后,還在查看菜單中包括一個(gè)分隔菜單命令,如圖。

7.4文檔視圖結構

7.4.4一檔多視

     MFC對于一檔多視提供下列三個(gè)模式:

      (1)在各自MDI文檔窗口中包含同一個(gè)視圖類(lèi)的多個(gè)視圖對象。

      有時(shí),想要應用程序能為同一個(gè)文檔打開(kāi)另一個(gè)文檔窗口,以便同時(shí)使用兩個(gè)文檔窗口來(lái)查看文檔的不同部分內容。用MFC AppWizard創(chuàng )建的MDI應用程序支持這種模式,選擇窗口菜單的新建窗口命令時(shí),系統就會(huì )為第一個(gè)文檔窗口創(chuàng )建一個(gè)副本。

      (2)在同一個(gè)文檔窗口中包含同一個(gè)視圖類(lèi)的多個(gè)視圖對象。

      這種模式實(shí)際上是使用切分窗口機制使SDI應用程序具有多視的特征。

      (3)在單獨一個(gè)文檔窗口中包含不同視圖類(lèi)的多個(gè)視圖對象。

     實(shí)驗13的示例(項目名為Ex_Rect)就是在MDI中為同一個(gè)文檔數據提供兩種不同的顯示和編輯方式,如圖。

7.4文檔視圖結構

u       幾個(gè)視圖之間的數據傳輸是通過(guò)CDocument::UpdateAllViewsCView::OnUpdate的相互作用來(lái)實(shí)現的。例如:

     void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)

     {      ...

             GetDocument()->UpdateAllViews(NULL, 1, (CObject*)&m_ptDraw);

     ...

     }

    

     void CEx_RectView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)

     {      if (lHint == 1)

            {        ...

            }

     }

     是一一對應的。

u       在為文檔創(chuàng )建另一個(gè)視圖時(shí),該視圖的CView::OnInitialUpdate將被調用,因此該函數是放置初始化的最好地方。

u       為了能及時(shí)更新并保存文檔數據,相應的數據成員應在用戶(hù)文檔類(lèi)中定義。這樣,由于所有的視圖類(lèi)都可與文檔類(lèi)進(jìn)行交互,因而可以共享這些數據。

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
國慶MFC學(xué)習 (上)認識Windows的編程機制
理解MFC文檔/視圖框架
MFC類(lèi)中獲得其它類(lèi)指針
詳解MFC框架窗口、文檔和視圖
MFC單文檔程序架構解析
mfc 每個(gè)類(lèi)都有獲得其他類(lèi)指針的一套方法
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久