トップ 差分 一覧 ping ソース 検索 ヘルプ PDF RSS ログイン

MFC ドキュメント



目次



記事一覧

キーワード

MFC ドキュメント

[MFC]


MFC ドキュメントとビューの分離

 SDIアプリケーション

MFCアプリケーションの開始

以下の順序でMFCアプリケーションは開始される

  1. グローバルオブジェクト theApp(CWinAppの派生クラス AppWizardが作成)を生成
  2. MFCライブラリの一部であるグローバル関数 WinMain(エントリポイント)を呼び出す
  3. WinMainは、CWinAppから派生されているクラスの唯一のインスタンスを探す
  4. WinMainは、theAppのInitInstanceメンバ関数を呼び出す
  5. 派生クラスでオーバーライドされたInitInstance関数は、ドキュメントのロードと、メイン フレーム ウィンドウ および ビュー ウィンドウの表示処理を開始
  6. WinMainはtheAppのRunメンバ関数を呼び出す
  7. Runメンバ関数は、ウィンドウメッセージとコマンドメッセージのディスパッチ処理を開始

ドキュメントテンプレート

  • InitInstance関数に、以下のようなコードが含まれている
BOOL CSdiSampleApp::InitInstance()
{
      :
 // アプリケーション用のドキュメント テンプレートを登録します。ドキュメント テンプレート
 //  はドキュメント、フレーム ウィンドウとビューを結合するために機能します。
 CSingleDocTemplate* pDocTemplate;
 pDocTemplate = new CSingleDocTemplate(
   IDR_MAINFRAME,
   RUNTIME_CLASS(CSdiSampleDoc),
   RUNTIME_CLASS(CMainFrame),       // メイン SDI フレーム ウィンドウ
   RUNTIME_CLASS(CSdiSampleView));
 if (!pDocTemplate)
   return FALSE;
 AddDocTemplate(pDocTemplate);

  • 次の 3 つのクラス間の関係を定義
クラス 内容
ドキュメント クラス CDocument クラスから派生
ビュー クラス ドキュメント クラスのデータを表示します。このクラスは、CViewCScrollViewCFormView、または CEditView から派生
フレーム ウィンドウ クラス ビューを保持。SDI のドキュメント テンプレートは、CFrameWnd から派生。メイン フレーム ウィンドウの動作をカスタマイズする必要がない場合、派生クラスを作らずに直接 CFrameWnd を使用できます

空のドキュメントを生成 CWinApp::OnFileNew関数

InitInstance関数は、AddDocTemplateメンバ関数を呼び出した後、OnFileNewを呼び出し(CWinApp::ProcessShellCommandを介して)次のことを行う。

処理内容 備考
1.ドキュメントオブジェクトを生成 ディスクからのデータ読み出しは行わない
2.CMainFrameメインフレームオブジェクトを生成 メインフレームウィンドウも生成するが、表示は行わない。メインフレームウィンドウはIDR_MAINFRAMEメニュー、ツールバー、ステータスバーを含む
3.ビューオブジェクトを生成 ビューウィンドウも生成するが表示は行わない
4.ドキュメント、メインフレーム、ビューの各オブジェクト間の接続 AddDocTemplate関数によるクラスの接続と混同しない
5.ドキュメントオブジェクトのCDocument::OnNewDocument仮想メンバ関数を呼び出す DeleteContents仮想関数が呼び出される
6.ビューオブジェクトのCView::OnInitialUpdate仮想メンバ関数を呼び出す
7.フレームオブジェクトのCFrameWnd::ActivateFrame仮想関数を呼び出す メニュー、ビューウィンドウ、コントロールバーを含むメインフレームウィンドウを表示する

  • CDocument::OnNewDocumentやCView::OnInitialなどの関数は初期化の作業を行うのに最適

ファイルを開く OnFileOpen関数

AppWizardは、アプリケーション生成時に、「ファイル−開く」メニューをCWinApp::OnFileOpenメンバ関数にマップする。この関数が呼び出されると、以下の処理を行う。

処理内容 備考
ユーザにファイルの選択を要求 CWinApp の DoPromptFileName メンバ関数は、標準の FileOpen ダイアログを呼び出し、現在のドキュメント テンプレートから得たファイル拡張子を表示
既に存在しているドキュメントオブジェクトのCDocument::OnOpenDocument仮想関数を呼び出す この関数はファイルを開き、CDocument::DeleteContentsを呼び出し、CArchiveオブジェクトを生成しロード状態に設定。次にSerialize関数を呼び出し、データをロード
ビューのOnInitialUpdate関数を呼び出す

  • 現在のドキュメントの内容を消去するのに適した方法は、CDocument::DeleteContents仮想関数をオーバーライドする。
  • CDocument::DeleteContents関数は、OnNewDocument関数や、OnOpenDocument関数、ドキュメントを閉じる場合も呼び出される。
  • デストラクタは、オブジェクトの終了時まで存続するアイテムの後始末に利用する

ファイルの上書き保存、名前をつけて保存 CDocument::OnFileSave

  • AppWizardは、「ファイル−上書き保存」メニューを、CDocument::OnFileSaveメンバ関数にマップする
処理内容 備考
CDocument::OnFileSaveメンバ関数の呼び出し。上書き保存の場合、OnFileSaveAs関数
CDocument::OnSaveDocument関数の呼び出 OnFileSaveにより呼び出される
CDocument::Siliarize関数を呼び出す

  • CDocumentのm_bModified データメンバはドキュメントが変更されている場合TRUEとなる
  • ドキュメントが変更された場合SetModifiedFlag関数を使ってフラグをTRUEに設定する

 MDIアプリケーション

MFCアプリケーションの開始

  • 実行開始のシーケンスは、SDIアプリケーションとほとんど同じ。
  • MDIのInitInstance関数は、AddDocTemplate関数の呼び出し以降がSDIと若干ことなる。

MDIドキュメントテンプレートクラス


BOOL CMdiSampleApp::InitInstance()
{
         :
   // アプリケーション用のドキュメント テンプレートを登録します。ドキュメント テンプレート
   //  はドキュメント、フレーム ウィンドウとビューを結合するために機能します。
   CMultiDocTemplate* pDocTemplate;
   pDocTemplate = new CMultiDocTemplate(IDR_MdiSampleTYPE,
     RUNTIME_CLASS(CMdiSampleDoc),
     RUNTIME_CLASS(CChildFrame), // カスタム MDI 子フレーム
     RUNTIME_CLASS(CMdiSampleView));
   if (!pDocTemplate)
     return FALSE;
   AddDocTemplate(pDocTemplate);

  • MDIアプリケーションでは、複数のドキュメントタイプを使うことができ、同時に複数のドキュメントオブジェクトを存在させることができる

基本クラス AppWizard作成 オブジェクト数 メニューとコントロール ビュー 生成
CMDIFrameWnd CMainFrame 1つ あり なし アプリケーションクラスのInitInstance
CMDIChildWnd CCHildFrame それぞれの子ウィンドウに1つずつ なし あり 新しい子ウィンドウが開かれたときに、アプリケーションフレームワークが生成

  • MDIのフレームウィンドウとビューウィンドウの関係

空のドキュメントの作成 CWinApp::OnFileNew関数


  • SDIのInitInstance関数と同様に、MDIのInitInstance関数は、ProcessShellCommand関数を通じて、OnFileNewを呼び出す。
  • このときメインフレームウィンドウは既に生成されている。

OnFileNewは、CMultiDocTemplateのOpenDocumentFile関数の呼び出しを行ってから、次の手順を実行する

処理 備考
1.ドキュメントオブジェクトを生成 ディスクからのデータ読み込みは行わない
2.子フレームウィンドウオブジェクト(CChildFrame)を生成 子フレームウィンドウを生成するが、表示しない。IDR_MAINFRAMEメニューをIDR_[アプリ名]TYPEメニューで置き換える
3.ビューオブジェクトを生成 ビューウィンドウも生成するが表示はしない
4.ドキュメント、メインフレームウィンドウ、ビューの各オブジェクト間の接続を確立 AddDocTemplateによって確立されるクラス間の関連と混同しないこと
ドキュメントオブジェクト用のOnNewDocument仮想メンバ関数を呼び出す
ビューオブジェクトのOnInitialUpdate仮想メンバ関数を呼び出す
子フレームオブジェクト用のActivateFrame仮想メンバ関数を呼び出す フレームウィンドウ、ビューウィンドウを表示

既存のドキュメントに追加のビューを作成する


メニューから、新規ウィンドウを選択すると、現在選択中のドキュメントにリンクされた新しい子ウィンドウを開く。

処理内容 備考
1.子フレームオブジェクト(CChildFrame)を生成 子フレームウィンドウを生成するが表示しない
2.ビューオブジェクトを生成 ビューウィンドウも生成するが表示しない
3.新しいビューオブジェクトと既存のドキュメントとメインフレームオブジェクト間の接続
4.ビューオブジェクトのOnInitialUpdate仮想メンバ関数を呼び出す
5.子フレームオブジェクトのActivateFrame仮想メンバ関数を呼び出し、フレームウィンドウとビューウィンドウを表示

ドキュメントのロードと保存

  • SDIと同様ドキュメントのロードと保存を行うが、2つの重要な相違点がある
    1. ドキュメントファイルをディスクからロードするたびに新しいドキュメントオブジェクトが生成される
    2. 子ウィンドウが閉じられるとドキュメントオブジェクトも破棄される
  • ロードを行う前に、ドキュメント内容の消去の心配はしなくてよいが、SDIとの互換性を維持するために、CDocument::DeleteContens関数はオーバーライドすべき

複数のドキュメントテンプレート

  • MDIアプリケーションでは、AddDocTemplate関数を複数回呼び出すことで、複数のドキュメントをサポートすることができる。
  • それぞれのテンプレートは異なるドキュメント、ビュー、MDI子フレームクラスの組み合わせを指定することができる



YAGI Hiroto (piroto@a-net.email.ne.jp)
twitter http://twitter.com/pppiroto

Copyright© 矢木 浩人 All Rights Reserved.