本ページは公開が終了した情報の複製であり、掲載時点での情報です。本ページに記載されている内容について各所に問い合わせることはご遠慮下さい。
サポート技術情報

[MSVC] MFC ベースの SDI アプリケーションで複数のビューを切り替える方法

文書番号: 99562

最終更新日: 2003/07/21


この資料は以下の製品について記述したものです。


この記事は、以前は次の ID で公開されていました: JP99562

概要



この資料は、MFC ベースの SDI アプリケーションで複数の異なるビューを使用する 1 つの方法を紹介したものです。

詳細

以下の手順により CSingleDocTemplate で指定したビューとは別の CView 派生クラスを作成してアプリケーションで複数のビューを切り替えて表示することができます。

下記の例ではアプリケーション クラス名を CMywinApp、追加する CView の派生クラス名を CNewView としています。

AppWizard を使用して、プロジェクト名 mywin のスケルトンにすると CMywinapp、CMywinView クラスを持つスケルトンが生成されます。CMywinapp クラスのヘッダー、ソース ファイルは、それぞれ MYWIN.H、MYWIN.CPP、CNewView クラスに対応するファイルは NEWVIEW.H、NEWVIEW.CPP です。

必要に応じてクラス名やファイル名を置き換えてください。

手順

  1. CMywinApp クラスにメンバを追加 (MYWINAPP.H を編集) Visual C++ 4.0 以降では、ClassView ペインからメンバを追加できます。
         CView* m_pOldView;
         CView* m_pNewView;
         CView* SwitchView(CView* pNewView);
    
  2. 新規クラス CNewView を作成。ClassWizard で作成した場合には、コンストラクタ、デストラクタのアクセス指定子を protected から public に修正します。
  3. MYWINAPP.CPP にて AFXPRIV.H をインクルード。AFXPRIV.H には、手順 4 で利用する WM_INITIALUPDATE などの MFC プライベート Windows メッセージの定義などが含まれています。
  4. 新規ビューを作成して、それをドキュメントにアタッチ。(下記コードを使用) 以下のコードは CMywinApp オブジェクトの InitInstance メンバ関数の中で新規ビューを作成するものです。この方法により、新規ビューと既存ビューのどちらもアプリケーションと同じ寿命を持つことになります。同程度の容易さで、動的に新規ビューを作成することもできます。CMyWinApp::InitInstance に以下のコードを追加するとき、メインフレーム ウィンドウ、ドキュメント、デフォルト ビューが準備されたあとに追加しなければなりません。Visual C++ 2.0 以下では OnFileNew 関数の呼び出しによりこれらの要素を作成していますので OnFileNew 呼び出しの後ろに挿入します。Visual C++ 4.0 以降の場合、このコードを ProcessShellCommand 関数呼び出しの後ろに挿入します。
          ...
          CView* pActiveView = ((CFrameWnd*) m_pMainWnd)->GetActiveView();
          m_pOldView = pActiveView;
          m_pNewView = (CView*) new CNewView;
    
          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, "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);
          ...
    
  5. CMywinApp::SwitchView 関数を定義します。(SwitchView は、メインフレームクラスのメンバとして宣言定義しても構いません)
          CView* CMyWinApp::SwitchView(CView* pNewView)
          {
              CView* pActiveView = ((CFrameWnd*) m_pMainWnd)->GetActiveView();
    
              // Exchange view window ID's 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;
          }
    
    この関数は古いビュー オブジェクトのポインタを返すので、これを利用して古いビューを破棄することもできます。ただし、ビューを破棄する前にビューとドキュメント間の関連を解消するために CDocument::RemoveView を呼び出してください。
  6. コマンド ハンドラなど、アプリケーションがビューを切り替える必要がある部分に SwitchView を呼び出すコードを追加。

関連情報

文書番号 : 141334
タイトル : [VC50] 複数のビューを切り替え表示する SDI サンプル



文書番号 : 141499
タイトル : [VC50] CMDIChildWnd 内のビューを置き換えるサンプル

関連情報

この資料は米国 Microsoft Corporation から提供されている Knowledge Base の Article ID 99562 (最終更新日 1997-12-12) をもとに作成したものです。


Additional query words: destructor multiple

Keywords: kbdss KBHOWTO VC10 VC15 VC20 VC40 VC41 VC42 VC4x VC50 KB99562
Technology: kbAudDeveloper kbMFC kbvc100 kbvc150 kbVC151 kbVC152 kbVC16bitSearch kbVC200 kbVC210 kbVC32bitSearch kbVC400 kbVC500 kbVC500Search kbVC600 kbVCsearch

inserted by FC2 system