!!!MFC ドキュメント {{category MFC}} {{amazon 4891000503}} MFC ドキュメントとビューの分離 !!SDIアプリケーション !MFCアプリケーションの開始 以下の順序でMFCアプリケーションは開始される +グローバルオブジェクト '''theApp'''(CWinAppの派生クラス AppWizardが作成)を生成 +MFCライブラリの一部であるグローバル関数 '''WinMain'''(エントリポイント)を呼び出す +WinMainは、CWinAppから派生されているクラスの唯一のインスタンスを探す +WinMainは、theAppの'''InitInstance'''メンバ関数を呼び出す +派生クラスでオーバーライドされたInitInstance関数は、ドキュメントのロードと、メイン フレーム ウィンドウ および ビュー ウィンドウの表示処理を開始 +WinMainはtheAppの'''Run'''メンバ関数を呼び出す +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''' クラスから派生 ,ビュー クラス,ドキュメント クラスのデータを表示します。このクラスは、'''CView'''、'''CScrollView'''、'''CFormView'''、または '''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のフレームウィンドウとビューウィンドウの関係 {{ref_image mdi_relation.jpg}} !空のドキュメントの作成 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つの重要な相違点がある ++ドキュメントファイルをディスクからロードするたびに新しいドキュメントオブジェクトが生成される ++子ウィンドウが閉じられるとドキュメントオブジェクトも破棄される *ロードを行う前に、ドキュメント内容の消去の心配はしなくてよいが、SDIとの互換性を維持するために、CDocument::DeleteContens関数はオーバーライドすべき !複数のドキュメントテンプレート *MDIアプリケーションでは、AddDocTemplate関数を複数回呼び出すことで、複数のドキュメントをサポートすることができる。 *それぞれのテンプレートは異なるドキュメント、ビュー、MDI子フレームクラスの組み合わせを指定することができる