• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • 怎樣在一個Pane中顯示多種View?

    發表于:2007-07-04來源:作者:點擊數: 標簽:
    河南大學數學系 祁文文 在MS Windows 中,一個窗口可以分割成若干個子窗口,每一個子窗口稱作一個窗片(pane),每個窗片可以獨立控制,這給界面設計提供了很大的方便。 利用VC 可以很方便地實現分割窗口。分割的方法有兩種:動態和靜態。動態分割時可以根據用
    河南大學數學系 祁文文

      在MS Windows 中,一個窗口可以分割成若干個子窗口,每一個子窗口稱作一個窗片(pane),每個窗片可以獨立控制,這給界面設計提供了很大的方便。

      利用VC 可以很方便地實現分割窗口。分割的方法有兩種:動態和靜態。動態分割時可以根據用戶的需要分割成數目不同的窗片,但所有窗片的屬性和父窗口都是一樣的;而靜態分割的窗片的數目在程序中指定,運行時是固定的,但每個窗片可以有各自不同類型的視(View),因此其使用范圍更為廣泛。本文所討論的問題僅限于靜態分割。

      窗片中視的類型大多是在主窗口的創建過程中指定的。這也就意味著,一個窗片雖然可以顯示任意類型的視,但是這種類型一旦確定,在程序運行過程中就難以改變。

      一、我要的是這樣的!

      但是我們有時確實需要改變一個窗片所顯示的視的類型,也就是說,需要讓一個窗片顯示多種類型的視。例如一個窗口被分割成兩部分,一邊是命令窗口,另一邊是工作窗口,根據命令窗口中發出的不同命令,需要變換不同的工作類型,這就需要工作窗口中能夠顯示多種類型的視窗,那么,如何做到這一點呢?

      二、你可以這樣做!

      從圖1 中可以看到,本程序共有三個視類,分別是:

      * 命令視類CCmdView:用來控制右邊窗片中不同視的顯示;

      * 選項按鈕視類CRdiView:顯示在右窗片中的選項視類;

      * 檢查按鈕視類CChkView:顯示在右窗片中的檢查視類。

      這三個視類都是CFormView 的子類。

      下面我們來看如何在右窗片內進行兩類視間的切換。實際上,由視A 切換到視B 的原理很簡單,那就是:

      1. 從窗片中刪除視A;

      2. 往窗片中添加視B。

      步驟1 的實現非常簡單,僅用一條語句即可:

      m_wndSplitter.DeleteView(0, 1);

      但它是必不可少的,因為你不能讓一個窗片同時包含兩個視。我本來希望往一個窗片中添加新的視時,VC 會自動將原來的視刪掉,可是它不干。

      我們來看如何實現步驟2,當一個窗片是空的時候,怎樣往里面添加一個視呢?其實這樣的功能在程序里我們已經用過了,看下面的語句:

    BOOL CMainFrame::OnCreateClient

    (LPCREATESTRUCT lpcs, CCreateContext* pContext)

    {

    ......

        if (!m_wndSplitter.CreateView(0, 0,

    pContext->m_pNewViewClass,

    size,

    pContext))

        ......

    }


      是的,用的就是CSplitterWnd::CreateView(),要注意的是它共有五個參數,其中前兩個用來指定分割窗口的窗片,第三個用來指定視的類型,第四個指定視的大小。最后的一個我們暫時用不上,用空值NULL 就可以了。

      這樣我們就可以編寫視切換的代碼了。因為視切換要操縱m_wndSplitter,而它是主窗口的成員,因此切換過程最好設計為主窗口的成員函數。但是切換命令是CCmdView 接受的,因而可以讓CCmdView 接受到視更改消息后,將消息傳給主窗口,由主窗口完成視更改。具體的代碼是這樣的:

      命令視類中的消息映射:

    BEGIN_MESSAGE_MAP(CCmdView, CFormView)

        ......

        ON_BN_CLICKED(IDC_CHECK, OnSwitchToCheckView)

        ON_BN_CLICKED(IDC_RADIO, OnSwitchToRadioView)

        ......

    END_MESSAGE_MAP()

    命令視類中的消息響應:

    void CCmdView::OnSwitchToCheckView()

    {

        AfxGetApp()->m_pMainWnd->

    SendMessage(WM_COMMAND, ID_CHECK);

    }

    void CCmdView::OnSwitchToRadioView()

    {

        AfxGetApp()->m_pMainWnd->

    SendMessage(WM_COMMAND, ID_RADIO);

    }

    主窗口中的消息映射:

    BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)

        ......

        ON_COMMAND(ID_CHECK, OnSwitchToCheckView)

        ON_COMMAND(ID_RADIO, OnSwitchToRadioView)

        ......

    END_MESSAGE_MAP()

    主窗口中的消息響應:

    void CMainFrame::OnSwitchToCheckView()

    {

        m_wndSplitter.DeleteView(0, 1);

        m_wndSplitter.CreateView(0, 1,

    RUNTIME_CLASS(CChkView),

    CSize(0, 0),

    NULL);

        m_wndSplitter.RecalcLayout();

    }



    void CMainFrame::OnSwitchToRadioView()

    {

        m_wndSplitter.DeleteView(0, 1);

        m_wndSplitter.CreateView(0, 1,

    RUNTIME_CLASS(CRdiView),

    CSize(0, 0),

    NULL);

        m_wndSplitter.RecalcLayout();

    }


      好啦,運行一下這個程序,感覺是否不錯?看來大功告成了,可是……

      三、還有一個問題

      在運行我們辛辛苦苦編出來的程序時,回頭看看VC 的調試窗口,你會發現有很多行這樣的話:

      Create view without document.

      這是說我們創建了視,可是沒有相應的文檔。好在這只是警告信息,不是什么錯誤,如果你不需要相應的文檔,就完全不用去管它??墒?,VC 中一種很重要的結構就是文檔- 視結構,利用這種結構,對數據操縱起來非常方便。如果需要建立與視相對應的文檔,應該怎么辦呢?

      這就涉及到VC 中文檔- 視結構的知識,不過不用怕麻煩,與本文有關的就只有這么兩點而已:

      1. 利用VC 創建的應用程序一般都會管理一些文檔模板(Document Template),文檔類和視類的對應關系就是在文檔模板里描述的。

      2. 一個文檔可以有多個視,創建視的時候,需要根據文檔和視的對應關系,給出它所依附的文檔。

      怎樣實現上述第一點呢?

      首先建立相應的文檔類:CRdiDoc 和CChkDoc。

      其次是定義相應的文檔模板,這是應用類的成員變量。因為在別的類中要使用它們,我們將之定義為公共類型:

    class CViewSwitcherApp : public CWinApp

    {

    ......

    public:

        CSingleDocTemplate* m_pRdiDocTemplate;

        CSingleDocTemplate* m_pChkDocTemplate;

    ......

    }

    然后創建這兩個文檔模板,并加入到模板列表中:

    BOOL CViewSwitcherApp::InitInstance()

    {

        ......

        m_pRdiDocTemplate = new CSingleDocTemplate(

            IDR_MAINFRAME,

            RUNTIME_CLASS(CRdiDoc),

            RUNTIME_CLASS(CMainFrame),

            RUNTIME_CLASS(CRdiView));

        AddDocTemplate(m_pRdiDocTemplate);

        m_pChkDocTemplate = new CSingleDocTemplate(

            IDR_MAINFRAME,

            RUNTIME_CLASS(CChkDoc),

            RUNTIME_CLASS(CMainFrame),

            RUNTIME_CLASS(CChkView));

        AddDocTemplate(m_pChkDocTemplate);

        ......

    }

      至于第二點,是在創建視時完成的。還記得創建視的情況么?當時有一個叫做pCreateContext 的參數,我們將之置為空,這里就要用到它了。

      pCreateContext 是一個指向被稱作" 創建上下文"(CreateContext) 結構的指針,這個結構中保存一些與創建視相關的內容。在創建主窗口時,系統會構造這樣一個結構,并將它作為參數傳遞到與創建視有關的函數中。但現在我們不創建主窗口,因此不得不自己構造這樣一個結構。實際上,該結構中我們所要使用的字段只有三個:

      1. 新視所屬的文檔模板m_pNewDocTemplate;

      2. 新視的類型m_pNewViewClass;

      3. 新視所屬的文檔m_pCurrentDoc;

      其中僅有第三項需要新建,前兩項都是已知的,只要指定即可。以切換到選項視為例,修改后的代碼是:



    void CMainFrame::OnSwitchToRadioView()

    {

        m_wndSplitter.DeleteView(0, 1);

        CCreateContext createContext;

    // 定義并初始化CreateContext

        // 獲取新視所屬的文檔模板

        CSingleDocTemplate* pDocTemplate =

    ((CViewSwitcherApp*)AfxGetApp())->    m_pRdiDocTemplate;

        // 創建新文檔并初始化

        CDocument* pDoc = pDocTemplate->CreateNewDocument();

        pDoc->OnNewDocument();

       

        // 設置CreateContext 相關字段

        createContext.m_pNewViewClass = RUNTIME_CLASS(CChkView);

        createContext.m_pCurrentDoc = pDoc;

        createContext.m_pNewDocTemplate = pDocTemplate;

        m_wndSplitter.CreateView(0, 1,

    RUNTIME_CLASS(CRdiView),

    CSize(0, 0),

    &createContext);

        m_wndSplitter.RecalcLayout();

    }

      四、最后的修改

      為了使這個程序更符合要求,我們還要做一些與更換視無關的修改。在這個程序中我們一共定義了三種類型的文檔,程序啟動時一般要新建一個文檔開始工作,可是它不知道要選擇哪一種,就彈出一個對話框來詢問。而這是我們不希望看到的。修改的方法是不讓VC 選擇新文檔類型,而我們指定創建哪一種類型的文檔,即把CViewSwitcherApp::CViewSwitcherApp() 中的語句

      if (!ProcessShellCommand(cmdInfo)) return FALSE;

      更改為

      m_pDocTemplate->OpenDocumentFile(NULL)。

    back.gif (1185 字節)

    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>