• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            山寨:不是最好的,是最適合我們的!歡迎體驗山寨 中文版MSDN

            Blog @ Blog

            當華美的葉片落盡,生命的脈絡才歷歷可見。 -- 聶魯達

            常用鏈接

            統(tǒng)計

            積分與排名

            BBS

            Blog

            Web

            最新評論

            視圖分割與視圖間通信資料匯總!

            VC++ 6.0中實現(xiàn)三叉切分窗口與多視圖

            一、引用
              當用戶需要同時對文當?shù)牟煌糠诌M行編輯時,常常會用到切分窗口;這些窗口可以都是相同的視,或者一個窗口為列表視,而另一個為樹型視圖。應用程序框架有多種方式來表示多視圖,切分窗口是其中的方式之一。

              切分窗口分為動態(tài)切分窗口和靜態(tài)切分窗口,它們都是由CsplitterWnd(MFC類庫)來實現(xiàn)的,在這兩種表示方式中,創(chuàng)建同一視圖類的對象是比較容易的(Cview),而在同一應用程序使用兩個或更多的視圖類(:ClistViewCtreeView),相對來說則要困難一些。

              動態(tài)切分功能多應用在編輯文本類的軟件中,在實際的開發(fā)中,我們經(jīng)常要用到的是靜態(tài)切分功能。靜態(tài)切分窗口是指在窗口創(chuàng)建時,切分窗口的窗格就已經(jīng)創(chuàng)建好了,且窗格的數(shù)量和順序不會改變,窗格為一個分隔條所分隔,用戶可以拖動分隔條調整相應窗格的大小。靜態(tài)切分窗口最多支持16´16列的窗格,而且不同的窗格往往使用不同的視圖類。本文主要闡述靜態(tài)切分窗口。

              二、實例

              以單文檔SDI應用程序為例,在框架客戶區(qū)實現(xiàn)三叉切分窗口,且每個窗格使用不同的視圖

              實現(xiàn)步驟:

              1 利用VC++6.0 AppWizard創(chuàng)建一個單文檔SDI應用程序,項目名為Test

              2 使用New Class對話框添加新的視圖類:

              CinfoView 基類為列表視圖類ClistView

              CLineView 基類為表單視圖類CFormView

              CMyEditView 基類為編輯視圖類CEditView

              要點:在添加ClineView之前,需要先創(chuàng)建一個對話模板資源,IDIDD_FORMVIEW

              3 在框架窗口類CMainFrame中聲明一個CsplitterWnd類的成員變量m_wndSplitter1,用于第一次切分。

              4 使用ClassWizard為框架窗口類添加OnCreateClient函數(shù)。

              注意:OnCreateClient函數(shù)的調用在OnCreate函數(shù)之后,在構造視圖對象和產(chǎn)生視圖窗口之前。

              5 OnCreateClient函數(shù)中調用CsplitterWnd::CreateStatic,產(chǎn)生靜態(tài)切分。該函數(shù)的原形如下:

              BOOL CreateStatic( CWnd* pParentWnd, int nRows, int nCols, DWORD dwStyle =WS_CHILD | WS_VISIBLE, UINT nID = AFX_IDW_PANE_FIRST );

              函數(shù)有5個參數(shù),意義如下:

              ● pParentWnd:切分窗口的父窗口指針

              ● nRows:水平方向分隔窗口的數(shù)目

              ● nCols:垂直方向分隔窗口的數(shù)目

              ● dwStyle:切分窗口的風格

              ● nID:子窗口的ID值,默認為系統(tǒng)定義的AFX_IDW_PANE_FIRST

              返回值:如果創(chuàng)建成功,返回非零值(TRUE),否則返回0(FALSE)

              m_wndSplitter1.CreateStatic(this, 2,1); // 切分為行列

              6 使用CreateView產(chǎn)生每個視圖窗口

              virtual BOOL CreateView( int row, int col, CRuntimeClass* pViewClass, SIZE sizeInit, CCreateContext* pContext );

              函數(shù)有5個參數(shù),意義如下:

              ● row:窗格的行標,從0開始

              ● col:窗格的列標,從0開始

              ● pViewClass:視圖的執(zhí)行期類CRuntimeClass指針,可以用宏RUNTIME_CLASS獲得

              ● sizeInit:一個SIZE(或者CSize)類型的數(shù)據(jù),指定窗格的初始大小

              ● pContext:一般是由父窗口傳遞過來,包含窗口的創(chuàng)建信息

              返回值:如果創(chuàng)建成功,返回非零值(TRUE),否則返回0(FALSE)

              OnCreateClient函數(shù)的全部代碼:

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

               {

                      // TODO: Add your specialized code here and/or call the base class

                      CRect rect;

                          GetClientRect(&rect);

                          //產(chǎn)生第一次靜態(tài)切分

                          m_wndSplitter1.CreateStatic(this, //父窗口指針

                                  , // 切分的行數(shù)

                                    ); // 切分的列數(shù)

                             //為第一個窗格產(chǎn)生視圖

                             m_wndSplitter1.CreateView(0,0, // 窗格的行、列序數(shù)

                                    RUNTIME_CLASS(CTestView),//視圖類

                                      CSize(rect.Width(),rect.Height()-rect.Height()/5),//初始化大小

                                        pContext);//父窗口的創(chuàng)建參數(shù)

                               //為第二個窗格產(chǎn)生視圖

                               m_wndSplitter1.CreateView(1,0,

                                      RUNTIME_CLASS(CMyEditView),

                                        CSize(rect.Width(),rect.Height()/5),

                                           pContext);

                                  return TRUE;//不再調用基類的OnCreateClient函數(shù)

                                    //return CFrameWnd::OnCreateClient(lpcs, pContext);

               }

             

              在這里需注意3:

               必須為每個靜態(tài)切分窗格創(chuàng)建視圖窗口,不能漏掉一個;

               必須包含相應的類的頭文件,在MainFrm.cpp文件的開始包含一下頭文件:

              #include "TestView.h"

              #include "MyEditView.h"

              產(chǎn)生靜態(tài)切分后,就不能調用默認的基類的OnCreateClient函數(shù)。

              7 在視圖窗口類CTestView中聲明一個CsplitterWnd類的成員變量m_wndSplitter2,用于第二次切分。

              8 使用ClassWizard為視圖窗口類CTestView添加OnCreate函數(shù),在該函數(shù)中調用CreateStatic函數(shù)和CreateView函數(shù),類似CMainFrame::OnCreateClient函數(shù)中的調用

              代碼如下:

              int CTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)

               {

                      if (CView::OnCreate(lpCreateStruct) == -1)

                             return -1;

                        // TODO: Add your specialized creation code here

                        CRect rect;

                          GetClientRect(&rect);

                             //獲得窗口的創(chuàng)建信息指針

                             CCreateContext *pContext = (CCreateContext*) lpCreateStruct->lpCreateParams;

                               //產(chǎn)生二次靜態(tài)切分

                               m_wndSplitter2.CreateStatic(this,1, 2);

                                  //為第一個窗格產(chǎn)生視圖

                                  m_wndSplitter2.CreateView(0,0,// 窗格的行、列序數(shù)

                                        RUNTIME_CLASS(CLineView),//視圖類

                                           CSize(rect.Width()/4,rect.Height()),//初始化大小

                                             pContext);//父窗口的創(chuàng)建參數(shù)

                                    //為第二個窗格產(chǎn)生視圖

                                    m_wndSplitter2.CreateView(0,1,

                                           RUNTIME_CLASS(CInfoView),

                                             CSize(1,1),

                                                pContext);

                                      return 0;

               }

             

              注意:二次切分的父窗口是第一次切分的第一個窗格,其視圖類是CTestView

              9、使用ClassWizard為視圖窗口類CTestView添加OnSize函數(shù),在該函數(shù)中調用子函數(shù)

              SwitchView(),子函數(shù)的代碼如下:

            void CTestView::SwitchView()

            {

              CRect rect;

              GetClientRect(&rect);

              int cx = rect.Width();

              int cy = rect.Height();

              m_wndSplitter2.MoveWindow(-2,-2,cx,cy+3);

              m_wndSplitter2.SetColumnInfo(0, cx/4,0);

              m_wndSplitter2.SetColumnInfo(1, cx-cx/4, 0);

              m_wndSplitter2.RecalcLayout();

            }

             

              該子函數(shù)主要用于設置二次切分后的各列信息,通過CSplitterWnd::SetColumnInfo函數(shù)實現(xiàn),原型為:void SetColumnInfo( int col, int cxIdeal, int cxMin );

              由3 個參數(shù),意義如下:

              ● col:切分窗口的列標識

              ● cxIdeal:列的實際寬度,單位為像素

              ● cxMin:列的最小寬度,單位為像素

            本示例的運行結果如下:

            10因為每個CView派生類都已經(jīng)繼承了GetDocument()函數(shù),因此只要在調用時直接調用無需再在其中聲明GetDocument()函數(shù)了,調用后再進行類型強制轉換應該就可以了。比方,在cmyview.h中注釋掉
            // Attributes

            // CTestDoc* GetDocument();

            cmyview.cpp中注釋掉

            //CTestDoc* CTestView::GetDocument() // non-debug version is inline

            //{

            //ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTestDoc)));

            //return (CTestDoc*)m_pDocument;

            //}

            并在OnDraw中試用如下代碼

            void CTestView::OnDraw(CDC* pDC)

            {

                 CTestDoc* pDoc =(CTestDoc*)CTestView:: GetDocument();

                 ASSERT_VALID(pDoc);

                 // TODO: add draw code for native data here

            }

             

              三、總結

              切分窗口的形式和每個窗格所使用的視圖類可以根據(jù)實際需要來確定,以滿足程序的不同應用。本示例使用了三叉切分,視圖類使用了列表視圖類CListView、表單視圖類CFormView、編輯視圖類CEditView,在VC++6.0下調試通過。

              三叉切分的方法并不唯一,本文實例是我在實際開發(fā)中總結的一種方法,讀者可以通過本例舉一反三,掌握切分窗口與多視圖相結合的精髓所在

             

             一、關于CSplitterWnd

            1、用來創(chuàng)建動態(tài)切分窗口

            BOOL   Create(CWnd*   pParentWnd,int   nMaxRows,int   nMaxCols,SIZE   sizeMin,CCreateContext*   pContext,DWORD   dwStyle,UINT   nID);

            2、用來創(chuàng)建靜態(tài)切分窗口

            BOOL   CreateStatic(CWnd*   pParentWnd,int   nRows,int   nCols,DWORD   dwStyle,UINT   nID)  

            3、為靜態(tài)切分的窗口的網(wǎng)格填充視圖

            BOOL   CreateView   (int   row,int   col,CruntimeClass*   pViewClass,SIZE   sizeinit,CcreateContext*   pContext);  

            4、參數(shù)說明

            pParentWnd   切分窗口的父框架窗口。

                    nMaxRows,nMaxCols是創(chuàng)建的最大的列數(shù)和行數(shù)。  

                    sizeMin是窗格的現(xiàn)實大小。  

                    pContext   大多數(shù)情況下傳給父窗口。  

                    nID是字窗口的ID.  

            二、創(chuàng)建嵌套分割窗口

            1、動態(tài)分割窗口

            動態(tài)分割窗口使用Create方法,例:m_wndSplitter.Create(this,2,2,CSize(100,100),pContext);   但是一般不使用動態(tài)分割,不實用

            2、靜態(tài)分割窗口(適用于SDIMDI程序)

            1)創(chuàng)建單文檔ww,生成的視類為CWwView,CFormView繼承,在增加個視類或者從視類繼承而來的派生類CView2CView3

            2)在框架類CMainFrame.cpp文件中加入頭文件,并在CWwView類定義前加上class   CWwDoc;

            #include   "view2.h "

            #include   "view3.h "

            #include   "wwView.h " //注意這里,必須在CWwView類定義前加上class   CWwDoc;否則編譯條錯誤

            3)在框架類CMainFrame中增加成員:  

                CSplitterWnd   m_wndSplitter1;

                CSplitterWnd   m_wndSplitter2;

            4)利用ClassWizard重載CMainFrame::OnCreateClient()函數(shù)

            //--------------------------------------------------

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

            {

                 //創(chuàng)建一個行列

                 m_wndSplitter1.CreateStatic(this,1,2);

                 //CWwView連接到行列窗格上

                 m_wndSplitter1.CreateView(0,0,RUNTIME_CLASS(CWwView),CSize(100,100),pContext);

                 //將窗口右邊再分開行列

                 m_wndSplitter2.CreateStatic(&m_wndSplitter1,2,1,WS_CHILD|WS_VISIBLE,   m_wndSplitter1.IdFromRowCol(0,   1));

                 m_wndSplitter2.CreateView(0,0,RUNTIME_CLASS(CView2),CSize(100,100),pContext);

                 m_wndSplitter2.CreateView(1,0,RUNTIME_CLASS(CView3),CSize(100,100),pContext);

             

                 return   TRUE;

            }

              //-------------------------------------------------

            注意:

               必須為每個靜態(tài)切分窗格創(chuàng)建視圖窗口,不能漏掉一個;

               如果從一個CformView類繼承的視類,此對話框要作如下設置

            styleChild

            BorderNone

            Visible=不選中

               若在CWwView窗口上放入一TreeCtrl,為了在改變窗口時隨窗口大小而改變(類似CB中的居中),可以在CWwView類的WM_SIZE中添加代碼如下:

            //-------------------------------------------------

            void   CWwView::OnSize(UINT nType, int cx, int cy)  

            {

                 CFormView::OnSize(nType,   cx,   cy);

             

                 //   TODO:   Add   your   message   handler   code   here

                 if   (GetSafeHwnd())

                 {

                     CRect   rect;

                     GetClientRect(&rect);

                     if   (m_TreeCtrl.GetSafeHwnd())

                          m_TreeCtrl.MoveWindow(&rect);

                 }

             

            }

            //------------------------------------------------

            //WM_ONINITALUPDATE消息中,添加初始化數(shù)據(jù)

            void   CWwView::OnInitialUpdate()

            {

                 CFormView::OnInitialUpdate();

                 GetParentFrame()-> RecalcLayout();

                 ResizeParentToFit();

                 //上面的代碼不用管,是啥就是啥,

                 m_TreeCtrl.InsertItem( "ListCtrl View ",1, 1);

                 m_TreeCtrl.InsertItem( "EditCtrl View ",2, 2);

             

            }

             

            三、實現(xiàn)各個分割區(qū)域的通信

            點擊Button1按鈕,CView2中顯示文字

            1、在CWwView.cpp文件中加入:

            #include   "view2.h "

            #include   "MainFrm.h "

            2、添加按鈕代碼:

            //-------------------------------------------------

            void   CWwView::OnButton1()  

            {

                 //得到一SplitterView的指針

                 CView2   *pView=(CView2*)(((CMainFrame*)AfxGetMainWnd())-> m_wndSplitter2.GetPane(0,0));

                 //定義ViewDC

                 CClientDC   dc(pView);

                 dc.MoveTo(10,10);

                 dc.LineTo(10,100);

                 dc.TextOut(10,10, "m_wndSplitter2的行列就是CView2 ");  

            }

            //-------------------------------------------------


              VC項目開發(fā)之單文檔多視圖實現(xiàn)

            k_eckelhttp://www.mscenter.edu.cn/blog/k_eckel

            多視圖是VC開發(fā)中經(jīng)常要用到的技術之一,一般地實現(xiàn)單文檔多視圖有兩種方式1)通過視圖分割的技術(使用CSplitterWnd實現(xiàn)),將窗口分割為多個部分,每個部分顯示各自顯示不同的視圖,這種技術實現(xiàn)起來比較簡單,并且相關的資料也很多。2)通過一個文檔關聯(lián)多個視圖,窗口顯示整個視圖。第二種實現(xiàn)較第一種復雜,這里給出詳細的實現(xiàn)方法。

            Step 1:使用VC 6.0新建一個Project,命名為:MultiView。除選擇單文檔屬性外,一切使用“默認”方式。于是你可以獲得五個類:CMainFrame CMultiViewAppCMultiViewDocCMultiViewView,和CAboutDlg

            Step 2:新建一個新的視圖View,添加一個新的MFC ClassInsert>New Class),基類為CView(或者CView的派生子類,如CEditView等)。類的名字為CAnotherView,這就是新的視圖;并為CAnotherView添加GetDocument的實現(xiàn):

            CMultiViewDoc* CAnotherView::GetDocument()

            {

                   return (CMultiViewDoc*)m_pDocument;

            }

            Step 3:在CMultiViewApp添加成員變量記錄這兩個視圖:

            private:

                   CView* m_pFirstView;

                   CView* m_pAnotherView;

            給程序菜單IDR_MAINFRAME添加一個菜單項目“視圖”,該菜單項有兩個子菜單“視圖一”和“視圖二”,添加相應函數(shù)(void CMultiViewApp:: OnShowFirstview()和void CMultiViewApp:: OnShowSecondview());

            Step 4:創(chuàng)建新的視圖:在BOOL CMultiViewApp::InitInstance()中添加代碼:

            …….

            //創(chuàng)建一個新的視圖

                   CView* m_pActiveView = ((CFrameWnd*)m_pMainWnd)->GetActiveView();

                   m_pFirstView = m_pActiveView;

                  

                   m_pAnotherView = new CAnotherView();

                   //文檔和視圖關聯(lián)

                   CDocument* m_pDoc = ((CFrameWnd*)m_pMainWnd)->GetActiveDocument();

                   CCreateContext context;

                   context.m_pCurrentDoc = m_pDoc;

                   //創(chuàng)建視圖

                   UINT m_IDFORANOTHERVIEW = AFX_IDW_PANE_FIRST + 1;

                   CRect rect;

                   m_pAnotherView->Create(NULL,NULL,WS_CHILD,rect,m_pMainWnd,

            m_IDFORANOTHERVIEW,&context);

                ……

            Step 5:現(xiàn)在已經(jīng)創(chuàng)建了視圖,并且都和文檔關聯(lián)起來了。現(xiàn)在要作的就是視圖間的轉換。在void CMultiViewApp:: OnShowFirstview()中添加實現(xiàn)代碼:

            void CMultiViewApp::OnShowFirstview()

            {

                   // TODO: Add your command handler code here

                   UINT temp = ::GetWindowLong(m_pAnotherView->m_hWnd, GWL_ID);

                ::SetWindowLong(m_pAnotherView->m_hWnd, GWL_ID, ::GetWindowLong(m_pFirstView->m_hWnd, GWL_ID));

                ::SetWindowLong(m_pFirstView->m_hWnd, GWL_ID, temp);

                   m_pAnotherView->ShowWindow(SW_HIDE);

                   m_pFirstView->ShowWindow(SW_SHOW);

                      

                   ((CFrameWnd*)m_pMainWnd)->SetActiveView(m_pFirstView);

                   ((CFrameWnd*) m_pMainWnd)->RecalcLayout();

                m_pFirstView->Invalidate();

            }

            void CMultiViewApp:: OnShowSecondview()中添加實現(xiàn)代碼:

            void CMultiViewApp::OnShowSecondview()

            {

                   // TODO: Add your command handler code here

                   UINT temp = ::GetWindowLong(m_pAnotherView->m_hWnd, GWL_ID);

                ::SetWindowLong(m_pAnotherView->m_hWnd, GWL_ID, ::GetWindowLong(m_pFirstView->m_hWnd, GWL_ID));

                ::SetWindowLong(m_pFirstView->m_hWnd, GWL_ID, temp);

                   m_pFirstView->ShowWindow(SW_HIDE);

                   m_pAnotherView->ShowWindow(SW_SHOW);     

                   ((CFrameWnd*)m_pMainWnd)->SetActiveView(m_pAnotherView);

                   ((CFrameWnd*) m_pMainWnd)->RecalcLayout();

                m_pAnotherView->Invalidate();

            }

            Step 6:為了演示,這里將不同的視圖給予一個標記,在CMultiViewViewCAnotherViewOnDraw方法中分別添加以下代碼:

            pDC->TextOut(400,300,"First View");

                   pDC->TextOut(400,320,pDoc->GetTitle());

            pDC->TextOut(400,300,"Another View");

                   pDC->TextOut(400,320,pDoc->GetTitle());

            至此就大功告成了,但是實現(xiàn)過程中有4點說明:

            1) 實現(xiàn)中由于使用到相關的類,因此在必要的地方要include相關的頭文件,這里省略;CAnotherView的默認構造函數(shù)是Protected的,需要將其改為Public,或者提供一個產(chǎn)生CAnotherView對象的方法(因要創(chuàng)建視圖對象);

            2) 這里給出的是一個示例代碼,實際開發(fā)中可以通過參考實現(xiàn)獲得自己想要實現(xiàn)的具體應用情況(例如視圖類的不同、數(shù)量不同,更重要的還有業(yè)務邏輯的不同實現(xiàn)等);

            3) 本文的示例代碼已上傳到Blog,可以通過下面的地址獲得代碼

            posted on 2008-12-22 10:17 isabc 閱讀(3039) 評論(2)  編輯 收藏 引用 所屬分類: 控件操作

            評論

            # re: 視圖分割與視圖間通信資料匯總! 2010-08-06 17:16 dengdai8

            源代碼下載不了,能不能發(fā)一份到郵箱,非常感謝。
            gongyong503@sina.com  回復  更多評論   

            # re: 視圖分割與視圖間通信資料匯總! 2011-05-07 12:41 someone

            支持!支持!支持!支持!支持!  回復  更多評論   

            廣告信息(免費廣告聯(lián)系)

            中文版MSDN:
            歡迎體驗

            日本道色综合久久影院| 亚洲伊人久久大香线蕉综合图片| 94久久国产乱子伦精品免费| 青青草国产成人久久91网| 91久久成人免费| 日韩va亚洲va欧美va久久| 99久久国产精品免费一区二区| 无码国内精品久久人妻| 国产精品久久久久久久久鸭| 97精品国产97久久久久久免费| 日本欧美国产精品第一页久久| 久久精品国产亚洲av麻豆图片| 久久婷婷国产综合精品| 精品久久久久久无码人妻热 | 久久er国产精品免费观看2| 欧美精品一本久久男人的天堂| 人人狠狠综合久久亚洲| 久久久久女人精品毛片| 久久国产精品视频| 久久亚洲精品中文字幕| 精品多毛少妇人妻AV免费久久| 亚洲成色www久久网站夜月 | 国产精品久久久久AV福利动漫| 欧美日韩中文字幕久久伊人| 国内精品伊人久久久影院| 91久久福利国产成人精品| 一本久久a久久精品vr综合| 精品国产91久久久久久久a | 欧美精品九九99久久在观看| 久久亚洲国产欧洲精品一| 久久久久久久精品成人热色戒| 青青国产成人久久91网| 欧美一区二区三区久久综| 久久免费观看视频| 99久久精品日本一区二区免费| 亚洲精品99久久久久中文字幕| 99久久人人爽亚洲精品美女| 久久人妻少妇嫩草AV无码专区| 亚洲精品美女久久久久99小说| 国产精品熟女福利久久AV| 91久久精一区二区三区大全|