將多個視圖添加到單個文檔

原文鏈接:https://docs.microsoft.com/en-us/cpp/mfc/adding-multiple-views-to-a-single-document?view=vs-2019

先聲明下,這篇文章是翻譯其他地方的,也不知道作者允不允許翻譯,在文章頁面沒找到相關說明。只是原文是英文版本的。如若,原作者看到,不希望這個存在,可以聯繫我或者平臺刪除此文。

在使用Microsoft基礎類(MFC)庫創建的單文檔界面(SDI)應用程序中,每種文檔類型都與單個視圖類型相關聯。在某些情況下,希望能夠使用新視圖切換文檔的當前視圖。

您可以通過添加新的CView類和用於將視圖動態切換到現有MFC應用程序的其他代碼來實現此功能。

步驟如下:

本主題的其餘部分假定以下內容:

  • -DerivedCWinApp對象的名稱是CMyWinApp,並CMyWinAppMYWINAPP.HMYWINAPP.CPP中聲明和定義。

  • CNewView是新CView起源對象的名稱,CNewViewNEWVIEW.HNEWVIEW.CPP中聲明和定義。

修改現有的應用程序類

要使應用程序在視圖之間切換,您需要通過添加成員變量來存儲視圖以及切換它們的方法來修改應用程序類。

下面的代碼添加到的聲明CMyWinAppMYWINAPP.H

CView *m_pOldView;
CView *m_pNewView;
CView *SwitchView();

新成員變量,m_pOldViewm_pNewView指向當前視圖和新創建的變量。新方法(SwitchView)在用戶請求時切換視圖。該方法的主體將在本主題後面的“ 實現切換功能”中討論

對應用程序類的最後一次修改需要包含一個新的頭文件,該文件定義了在切換函數中使用的Windows消息(WM_INITIALUPDATE)。

MYWINAPP.CPP的include部分插入以下行:

#include <AFXPRIV.H>

保存更改並繼續下一步。

創建和修改新視圖類

使用Class View中提供的New Class命令可以輕鬆創建新的視圖類。這個類的唯一要求是它來源於CView。將此新類添加到應用程序。有關向項目添加新類的特定信息,請參閱添加類

將類添加到項目後,需要更改某些視圖類成員的可訪問性。

通過將構造函數和析構函數的訪問說明符從protected更改爲public來修改NEWVIEW.H。這允許動態創建和銷燬類,並在視圖外觀可見之前修改它。

保存更改並繼續下一步。

創建並附加新視圖

要創建和附加新視圖,您需要修改InitInstance應用程序類的功能。修改補充說,創建一個新的查看對象,然後初始化兩個新的代碼m_pOldViewm_pNewView與兩個現有的查看對象。

由於新視圖是在InitInstance函數內創建的,因此新視圖和現有視圖在應用程序的生命週期內都會持續存在。但是,應用程序可以輕鬆地動態創建新視圖。

調用ProcessShellCommand後插入此代碼:

CView *pActiveView = ((CFrameWnd *)m_pMainWnd)->GetActiveView();
m_pOldView = pActiveView;
m_pNewView = (CView *)new CNewView;
if (NULL == m_pNewView)
   return FALSE;

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

// Initialize a CCreateContext to point to the active document.
// With this context, the new view is added to the document
// when the view is created in CView::OnCreate().
CCreateContext newContext;
newContext.m_pNewViewClass = NULL;
newContext.m_pNewDocTemplate = NULL;
newContext.m_pLastView = NULL;
newContext.m_pCurrentFrame = NULL;
newContext.m_pCurrentDoc = pCurrentDoc;

// The ID of the initial active view is AFX_IDW_PANE_FIRST.
// Incrementing this value by one for additional views works
// in the standard document/view case but the technique cannot
// be extended for the CSplitterWnd case.
UINT viewID = AFX_IDW_PANE_FIRST + 1;
CRect rect(0, 0, 0, 0); // Gets resized later.

// Create the new view. In this example, the view persists for
// the life of the application. The application automatically
// deletes the view when the application is closed.
m_pNewView->Create(NULL, _T("AnyWindowName"), WS_CHILD, rect, m_pMainWnd, viewID, &newContext);

// When a document template creates a view, the WM_INITIALUPDATE
// message is sent automatically. However, this code must
// explicitly send the message, as follows.
m_pNewView->SendMessage(WM_INITIALUPDATE, 0, 0);

保存更改並繼續下一步。

實現切換功能

在上一步中,您添加了創建和初始化新視圖對象的代碼。最後一個主要部分是實現切換方法SwitchView

在應用程序類(MYWINAPP.CPP)的實現文件的末尾,添加以下方法定義:

CView *CMyWinApp::SwitchView()
{
   CView *pActiveView = ((CFrameWnd *)m_pMainWnd)->GetActiveView();

   CView *pNewView = NULL;
   if (pActiveView == m_pOldView)
      pNewView = m_pNewView;
   else
      pNewView = m_pOldView;

      // Exchange view window IDs so RecalcLayout() works.
#ifndef _WIN32
   UINT temp = ::GetWindowWord(pActiveView->m_hWnd, GWW_ID);
   ::SetWindowWord(pActiveView->m_hWnd, GWW_ID, ::GetWindowWord(pNewView->m_hWnd, GWW_ID));
   ::SetWindowWord(pNewView->m_hWnd, GWW_ID, temp);
#else
   UINT temp = ::GetWindowLong(pActiveView->m_hWnd, GWL_ID);
   ::SetWindowLong(pActiveView->m_hWnd, GWL_ID, ::GetWindowLong(pNewView->m_hWnd, GWL_ID));
   ::SetWindowLong(pNewView->m_hWnd, GWL_ID, temp);
#endif

   pActiveView->ShowWindow(SW_HIDE);
   pNewView->ShowWindow(SW_SHOW);
   ((CFrameWnd *)m_pMainWnd)->SetActiveView(pNewView);
   ((CFrameWnd *)m_pMainWnd)->RecalcLayout();
   pNewView->Invalidate();
   return pActiveView;
}

保存更改並繼續下一步。

添加對切換視圖的支持

最後一步涉及添加SwitchView在應用程序需要在視圖之間切換時調用該方法的代碼。這可以通過多種方式完成:通過添加新菜單項供用戶選擇或在滿足某些條件時在內部切換視圖。

示例下載

附加了一個示例小程序,但是不是根據這篇文章寫的,但是大致思路是一致的,只是細節有些區分。下載地址https://download.csdn.net/download/yishang44/11686130

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章