CDocumentの扱いの注意

CDocumentは便利な機能が結構ある。
コレを利用しないと結構面倒なこともあるみたい。

CDocumentにはいくつかあらかじめ割り当てられたイベントがあります。

ID_FILE_NEW 新しい空の文書を作成します。
ID_FILE_NEW コマンドの一般的なカスタマイズは、文書の型をグラフィカルに選択させるためのものです。
この場合には CMyApp::OnFileNew 関数をインプリメントして CWinApp::OnFileNew の代わりに、メッセージ マップに登録します。
基本クラスのインプリメントを呼び出す必要はありません。
別のカスタマイズの方法として、文書の型ごとに別々のコマンドを提供するというものがあります。
この場合は、新しいコマンド ID (ID_FILE_NEW_CHART、ID_FILE_NEW_SHEET など) を定義します。
ID_FILE_OPEN 既存の文書を開きます。
ID_FILE_OPEN コマンドの一般的なカスタマイズでは、[開く] ダイアログ ボックスをカスタマイズするか、ファイル フィルタを追加します。
お勧めするカスタマイズ方法は、デフォルトのインプリメントを独自の [開く] ダイアログ ボックスに置き換え、CWinApp::OpenDocumentFile メンバ関数を文書のファイル名またはパス名を引数として呼び出す、というものです。
ID_FILE_CLOSE 現在開いている文書を閉じます。
CDocument::OnFileClose メンバ関数は、文書が変更されていると、CDocument::SaveModified メンバ関数を呼び出してユーザーに保存するかどうを問い合わせます。
その後で、OnCloseDocument 関数を呼び出します。
文書の破棄を含む、すべてのクローズ動作は OnCloseDocument ルーチンが行います。
ID_FILE_SAVE 現在の文書を保存します。
このコマンドでは、OnFileSave メンバ関数と OnFileSaveAs メンバ関数の両方にヘルパ ルーチン CDocument::DoSave を使います。
以前に保存されたことがない文書 (FileNew された文書のようにパス名を持っていない文書) を保存する場合や、読み出し専用文書から読み込んだ文書を保存すると、OnFileSave メンバ関数が ID_FILE_SAVE_AS コマンドのように動作し、ユーザーに新しいファイル名を問い合わせます。
ファイルのオープンから保存までの実際のプロセスは、仮想関数 OnSaveDocument が処理します。
主に 2 つの理由から ID_FILE_SAVE コマンドをカスタマイズします。
まず、保存しない文書に対しては、ID_FILE_SAVE メニュー項目とツール バー ボタンをユーザー インターフェイスから取り除きます。
文書が変更されていない (CDocument::SetModifiedFlag メンバ関数が呼ばれていない) 場合には、フレームワークはその文書を保存しません。
また、ディスク ファイル以外の場所に保存されるドキュメントについては、保存のための新しいコマンドを定義する必要があります。
COleServerDoc の場合、ID_FILE_SAVE コマンドは、ファイル保 (通常のドキュメント) とファイル更新 (埋め込みドキュメント) の両方に使われます。
文書データを別々のディスク ファイルに格納するときに、CDocument のデフォルトのシリアル化機能を使いたくない場合は、OnFileSave メンバ関数ではなく、CDocument::OnSaveDocument メンバ関数をオーバーライドします。
ID_FILE_SAVE_AS 現在の文書を違う名前で保存します。
CDocument::OnFileSaveAs メンバ関数のインプリメントでは、OnFileSave コマンドと同じように CDocument::DoSave ヘルパ関数が使われます。
保存する文書にファイル名がない場合は、OnFileSaveAs コマンドは ID_FILE_SAVE コマンドと同様の処理を行います。
COleServerDoc::OnFileSaveAs メンバ関数では、通常の文書データ ファイルを保存することも、他のアプリケーションに埋め込まれている OLE オブジェクトを表すサーバー ドキュメントを別のファイルとして保存することもできます。
ID_FILE_SAVE コマンドの処理をカスタマイズすると、ID_FILE_SAVE_AS コマンドのカスタマイズも同じように必要になるはずです。
カスタマイズしないと [名前を付けて保存] を使えなくなるからです。
また、[名前を付けて保存] メニュー項目が必要がなければメニュー バーから削除できます。
ID_FILE_SAVE_COPY_AS 現在の文書のコピーを新しい名前で保存します。
COleServerDoc::OnFileSaveCopyAs メンバ関数は、保存先のファイルに文書オブジェクトが "結び付けられない" という点を除けば、CDocument::OnFileSaveAs メンバ関数とよく似ています。
これは、メモリ上の文書を保存の前に変更されていると、保存後もそのまま "変更されている" ということです。
このコマンドは文書に格納されているパス名やタイトルを変更しません。
ID_FILE_UPDATE 埋め込みドキュメントを保存するようにコンテナに通知します。
COleServerDoc::OnUpdateDocument メンバ関数は、コンテナに対して埋め込みアイテムを保存するように通知します。
コンテナは該当する OLE API を呼び出して埋め込みアイテムを保存します。
ID_FILE_PAGE_SETUP アプリケーション固有のページ セットアップ/レイアウト用ダイアログを表示します。
現在のところ、このダイアログの標準はありません。
フレームワークにもこのコマンドのデフォルトのインプリメントはありません。
このコマンドをインプリメントする場合は、このコマンド ID をそのまま使うことをお勧めします。
ID_FILE_PRINT_SETUP 標準のプリンタ設定ダイアログを起動します。
ID_FILE_PRINT 現在の文書を印刷します。
ID_FILE_PRINT_PREVIEW 現在の文書の印刷プレビュー モードに入ります。
ID_FILE_MRU_FILE1...FILE16 [ファイル] メニューの MRU リストのコマンド ID CWinApp::OnUpdateRecentFileMenu メンバ関数は、ON_UPDATE_COMMAND_UI 機構の上級利用者向けの更新コマンド UI ハンドラです。
メニュー リソースでは、ID として ID_FILE_MRU_FILE1 を持つメニュー項目を 1 つだけ定義します。
このメニュー項目は初期状態では使えないようになっています。
MRU リストが大きくなると、さらにメニュー項目がリストに追加されます。
CWinApp クラスの標準のインプリメントでは、デフォルトでは最近使ったファイルが 4 つまで表示されます。
このデフォルトを変更するには、CWinApp::LoadStdProfileSettings メンバ関数に 4 以外の値を渡すまで表示されます。
MRU リストは、アプリケーションの .INI ファイルに書き込まれます。
LoadStdProfileSettings を呼び出すと、アプリケーションの InitInstance 関数でこのリストがロードされ、アプリケーションが終了するときに保存されます。
MRU の更新コマンド UI ハンドラは、ファイル名を絶対パスから相対パスに変換してから、[ファイル] メニューに表示します。
CWinApp::OnOpenRecentFile は、実際のコマンドを実行する ON_COMMAND ハンドラです。
これは単に MRU リストからファイル名を取得し、CWinApp::OpenDocumentFile を呼び出して、ファイルを開き、MRU リストを更新します。
このコマンド ハンドラのカスタマイズはお勧めできません。
ID_EDIT_CLEAR 現在の選択範囲を消去します。
現在、このコマンドの標準のインプリメントはありません。
各 CView 派生クラスごとにインプリメントしてください。
CEditView は、CEdit::Clear メンバ関数を使ってこのコマンドをインプリメントします。
何も選択されていないと、このコマンドは使えません。
このコマンドをインプリメントする場合は、このコマンド ID をそのまま使うことをお勧めします。
ID_EDIT_CLEAR_ALL ドキュメント全体を消去します。
現在、このコマンドの標準のインプリメントはありません。
CView からの派生クラスごとにインプリメントしてください。
このコマンドをインプリメントする場合は、このコマンド ID をそのまま使うことをお勧めます。
インプリメントの例については、「SCRIBBLE」チュートリアルを参照してください。
ID_EDIT_COPY 現在の選択範囲を切り取り、クリップボードにコピーします。
現在、このコマンドの標準のインプリメントはありません。
CView からの派生クラスごとにインプリメントしてください。
CEditView で、このコマンドをインプリメントします。
このコマンドは CEdit::Copy メンバ関数を使って、現在選択されているテキストをクリップボードに CF_TEXT としてコピーします。
何も選択されていないと、このコマンドは使えません。
このコマンドをインプリメントする場合は、このコマンド ID をそのまま使うことをお勧めします。
ID_EDIT_CUT 現在の選択範囲を切り取り、クリップボードに移します。
現在、このコマンドの標準のインプリメントはありません。
CView からの派生クラスごとにインプリメントしてください。
CEditView で、このコマンドをインプリメントします。
このコマンドは、CEdit::Cut メンバ関数を使って、現在選択されているテキストを切り取り、クリップボードに CF_TEXT として転送します。
何も選択されていないと、このコマンドは使えません。
このコマンドをインプリメントする場合は、このコマンド ID をそのまま使うことをお勧めします。
ID_EDIT_FIND 検索用のモードレス ダイアログ ボックスを表示し、検索を開始します。
現在、このコマンドの標準のインプリメントはありません。
CView からの派生クラスごとにインプリメントしてください。
CEditView で、このコマンドをインプリメントします。
このコマンドは、補助関数 OnEditFindReplace を呼び出して、以前の検索置換の設定を使ったり、これをプライベート変数に格納します。
CFindReplaceDialog クラスでは、ユーザーに入力を求めるモードレス ダイアログ ボックスを表示します。
このコマンドをインプリメントする場合は、このコマンド ID をそのまま使うことをお勧めします。
ID_EDIT_PASTE 現在のクリップボードの内容を挿入します。
現在、このコマンドの標準のインプリメントはありません。
CView からの派生クラスごとにインプリメントしてください。
CEditView で、このコマンドをインプリメントします。
このコマンドは、CEdit::Paste メンバ関数を使って、選択されているテキストをクリップボードの現在のデータに置き換えます。
クリップボードに CF_TEXT がないときは、このコマンドは使えません。
COleClientDoc が、このコマンドの更新コマンド UI ハンドラを提供します。
クリップボードに埋め込み可能な OLE アイテムや OLE オブジェクトが入っていない場合は、このコマンドを使えません。
実際に貼り付けを行うコマンドのハンドラは自分で作成してください。
OLE アプリケーションが他のフォーマットでも貼り付けを行える場合は、自分のビューまたはドキュメントに (つまり、コマンド ターゲットのルーティング (振り分け) で COleClientDoc の前のどこかに) 独自の更新コマンド UI ハンドラを用意する必要があります。
このコマンドをインプリメントする場合は、このコマンド ID をそのまま使うことをお勧めします。
OLE の標準インプリメントを置き換えるには、COleClientItem::CanPaste メンバ関数を使ってください。
ID_EDIT_PASTE_LINK 現在のクリップボード内容からのリンクを挿入します。
現在、このコマンドの標準のインプリメントはありません。
CView 派生クラスごとにインプリメントしてください。
COleDocument が、このコマンドの更新コマンド UI ハンドラを提供します。
クリップボードに埋め込み可能な OLE アイテムや OLE オブジェクトが入っていないと、このコマンドは使えません。
実際に貼り付けを行うコマンドのハンドラは自分で作成してください。
OLE アプリケーションが他のフォーマットでも貼り付けを行える場合は、ビューまたはドキュメントに (つまり、コマンド ターゲットのルーティングで COleDocument の前のどこかに)、独自の更新コマンド UI ハンドラを用意する必要があります。
このコマンドをインプリメントする場合は、このコマンド ID をそのまま使うことをお勧めします。
OLE の標準インプリメントを置き換えるには、COleClientItem::CanPasteLink メンバ関数を使ってください。
ID_EDIT_PASTE_SPECIAL 現在のクリップボードの内容を特別な方法で挿入します。
現在、このコマンドの標準のインプリメントはありません。
CView の派生クラスごとにインプリメントしてください。
MFC ではこのダイアログは提供していません。
このコマンドをインプリメントする場合は、このコマンド ID をそのまま使うことをお勧めします。
ID_EDIT_REPEAT 直前の操作を繰り返します。
現在、このコマンドの標準のインプリメントはありません。
CView の派生クラスごとにインプリメントしてください。
CEditView で、この関数をインプリメントします。
このコマンドは直前の操作を繰り返します。
直前の操作の内容はプライベート変数に保持されています。
直前の操作を見つけられないときは、このコマンドは使えません。
このコマンドをインプリメントする場合は、このコマンド ID をそのまま使うことをお勧めします。
ID_EDIT_REPLACE 置換用のモードレス ダイアログ ボックスを表示し、置換操作を開始します。
現在、このコマンドの標準のインプリメントはありません。
CView の派生クラスごとにインプリメントしてください。
CEditView で、このコマンドをインプリメントします。
このコマンドは補助関数 OnEditFindReplace を呼び出して、プライベート変数に格納されている直前の検索/置換の設定を使ったり、CFindReplaceDialog クラスでは、ユーザーに入力を求めるモードレス ダイアログ ボックスを表示します。
このコマンドをインプリメントする場合は、このコマンド ID をそのまま使うことをお勧めします。
ID_EDIT_SELECT_ALL 文書全体を選択します。
現在、このコマンドの標準のインプリメントはありません。
CView の派生クラスごとにインプリメントしてください。
CEditView で、このコマンドをインプリメントします。
このコマンドは、文書内のすべてのテキストを選択します。
選択するテキストがないときは、このコマンドを使えません。
このコマンドをインプリメントする場合は、このコマンド ID をそのまま使うことをお勧めします。
ID_EDIT_UNDO 最後の操作を取り消します。
現在、このコマンドの標準のインプリメントはありません。
CView の派生クラスごとにインプリメントしてください。
CEditView で、このコマンドをインプリメントします。
このコマンドは、CEdit::Undo メンバ関数を使って取り消しを行います。
CEdit::CanUndo が FALSE を返したときは、このコマンドを使えません。
このコマンドをインプリメントする場合は、このコマンド ID をそのまま使うことをお勧めします。
ID_EDIT_REDO 最後の操作を取り消した結果を取り消します。
現在、このコマンドの標準のインプリメントはありません。
CView の派生クラスごとにインプリメントしてください。
このコマンドをインプリメントする場合は、このコマンド ID をそのまま使うことをお勧めします。
ID_WINDOW_NEW アクティブな文書上に別のウィンドウを開きます。
CMDIFrameWnd::OnWindowNew メンバ関数は、現在の文書のドキュメント テンプレートを使って、現在の文書の別のビューを持つフレームを作成します。
アクティブな MDI 子ウィンドウがない場合は、MDI の [ウィンドウ] メニューのほとんどのコマンドと同じように、このコマンドを使えません。
このコマンド ハンドラのカスタマイズはお勧めしません。
さらにビューやフレーム ウィンドウを作成するコマンドを提供したいときは、独自のコマンドを開発することをお勧めします。
CMDIFrameWnd::OnWindowNew メンバ関数のコードをコピーし、このクローンを独自のフレーム クラスやビュー クラスに合わせて変更します。
ID_WINDOW_ARRANGE MDI ウィンドウの下部にアイコンを整列させます。
この標準 MDI コマンドは CMDIFrameWnd の補助関数 OnMDIWindowCmd でインプリメントします。
この補助関数は、コマンド ID を MDI Windows メッセージにマップするので、多くのコードを共有できます。
アクティブな MDI 子ウィンドウがない場合は、MDI の [ウィンドウ] メニューのほとんどのコマンドと同様、このコマンドは使えません。
このコマンド ハンドラのカスタマイズはお勧めしません。
ID_WINDOW_CASCADE ウィンドウを重ねて表示します。
この標準 MDI コマンドは CMDIFrameWnd の補助関数 OnMDIWindowCmd でインプリメントします。
この補助関数は、コマンド ID を MDI Windows メッセージにマップするので、多くのコードを共有できます。
アクティブな MDI 子ウィンドウがない場合は、MDI の [ウィンドウ] メニューのほとんどのコマンドと同様、このコマンドは使えません。
このコマンド ハンドラのカスタマイズはお勧めしません。
ID_WINDOW_TILE_HORZ ウィンドウを水平方向に並べて表示します。
このコマンドは、方向によって異なる Windows メッセージが使われることを除くと、ID_WINDOW_CASCADE と同じように CMDIFrameWnd でインプリメントされます。
アプリケーションのデフォルトの整列方向を選択してください。
これは、[ウィンドウ] メニューの [並べて表示] メニュー項目の ID を ID_WINDOW_TILE_HORZ または ID_WINDOW_TILE_VERT のどちらかに変更することによって行うことができます。
ID_WINDOW_TILE_VERT ウィンドウを垂直方向に並べて表示します。
このコマンドは、方向によって異なる Windows メッセージが使われることを除くと、ID_WINDOW_CASCADE と同じように CMDIFrameWnd でインプリメントされます。
アプリケーションのデフォルトの整列方向を選択してください。
これは、[ウィンドウ] メニューの [並べて表示] メニュー項目の ID を ID_WINDOW_TILE_HORZ または ID_WINDOW_TILE_VERT のどちらかに変更することによって行うことができます。
ID_WINDOW_SPLIT 分割ウィンドウに対するキーボード インターフェイスです。
CView はこのコマンドを使って、CSplitterWnd をインプリメントします。
ビューが分割ウィンドウの一部であると、このコマンドは関数 CSplitterWnd::DoKeyboardSplit で代行されます。
このコマンドを実行すると分割モードになるので、ユーザーがキーボードで分割ウィンドウの分割や分割解除を行えます。
ビューが分割ウィンドウでないときは、このコマンドは使えません。
このコマンド ハンドラのカスタマイズはお勧めしません。
ID_APP_ABOUT [バージョン情報] ダイアログ ボックスを表示します。
アプリケーションの [バージョン情報] ダイアログ ボックス の標準のインプリメントはありません。
AppWizard で作成されたデフォルトのアプリケーションは、アプリケーションのカスタム ダイアログ クラスを作成し、それを [バージョン情報] ダイアログ ボックスとして使います。
AppWizard は、このコマンドを処理し、ダイアログを起動するコマンド ハンドラも作成します。
ほとんどの場合、このコマンドをインプリメントします。
ID_APP_EXIT アプリケーションを終了します。
CWinApp::OnAppExit は、アプリケーションのメイン ウィンドウに WM_CLOSE メッセージを送って、このコマンドを処理します。
アプリケーションの標準のシャットダウン処理 (変更されたファイルの確認など) は、CFrameWnd で処理されます。
このコマンド ハンドラのカスタマイズはお勧めしません。
CWinApp::SaveAllModified メンバ関数や、CFrameWnd のクローズ関数をオーバーライドしてください。
このコマンドをインプリメントする場合は、このコマンド ID をそのまま使うことをお勧めします。
ID_HELP_INDEX .HLP ファイルのヘルプ トピックの一覧を表示します。
ID_HELP_USING ヘルプの使い方のヘルプを表示します。
ID_CONTEXT_HELP Shift + F1 ヘルプ モードに入ります。
ID_HELP 現在のコンテキストにおけるヘルプを表示します。
ID_DEFAULT_HELP コンテキストのデフォルトのヘルプを表示します。
ID_NEXT_PANE 次のペインに移動します。
CView は、CSplitterWnd のインプリメントに対してこのコマンドを処理します。
ビューが分割ウィンドウの一部であると、このコマンドは関数 CSplitterWnd::OnNextPaneCmd で代行されます。
このコマンドは、アクティブなビューを分割ウィンドウの次のペインに移動します。
ビューが分割ウィンドウ内にない場合や、次のペインがない場合には、このコマンドは使えません。
このコマンド ハンドラのカスタマイズはお勧めしません。
ID_PREV_PANE 直前のペインに移動します。
CView は、CSplitterWnd のインプリメントに対してこのコマンドを処理します。
ビューが分割ウィンドウの一部であると、このコマンドは関数 CSplitterWnd::OnNextPaneCmd で代行されます。
このコマンドは、アクティブなビューを分割ウィンドウの直前のペインに移動します。
ビューが分割ウィンドウ内にない場合や、次のペインがない場合には、このコマンドは使えません。
このコマンド ハンドラのカスタマイズはお勧めしません。
ID_OLE_INSERT_NEW 新しい OLE オブジェクトを挿入します。
現在、このコマンドの標準のインプリメントはありません。
現在の選択範囲に新しい OLE アイテム/オブジェクトを挿入するには、CView の派生クラスごとにこのコマンドをインプリメントしてください。
すべての OLE クライアント アプリケーションで、このコマンドをインプリメントしてください。
AppWizard の OLE オプションをオンにすると、ビュー クラスに OnInsertObject のスケルトンが作成されます。
このコマンドの完全なインプリメントの例については、「OCLIENT」を参照してください。
ID_OLE_EDIT_LINKS OLE リンクを編集します。
COleDocument は、MFC の提供する標準 OLE リンク ダイアログ ボックスを使って、このコマンドを処理します。
このダイアログ ボックスには、COleLinksDialog クラスを使ってアクセスします。
現在のドキュメントにリンクがないときは、このコマンドは使えません。
このコマンド ハンドラのカスタマイズはお勧めしません。
ID_OLE_VERB_FIRST...LAST OLE verb の ID。
COleDocument は、現在選択されている OLE アイテム/オブジェクトがサポートする verb に対して、このID 範囲のコマンドを使います。
この範囲は、所定の OLE アイテム/オブジェクトがサポートしているカスタム verb の個数と等しくなければなりません。
アプリケーションのメニューには、ID_OLE_VERB_FIRST の ID を持つメニュー項目を 1 つ用意してください。
プログラムが実行されると、このメニュー項目は、該当するメニュー verb の記述 (または、複数の verb を含んだポップアップ メニュー) で更新されます。
OLE メニューの管理は、AfxOleSetEditMenu で処理され、このコマンドの更新コマンド UI ハンドラで実行されます。
この ID 範囲の各コマンドは、別々のコマンド ハンドラで処理されるわけではありません。
COleDocument::OnCmdMsg メンバ関数をオーバーライドして、この範囲内のすべてのコマンド ID をトラップします。
トラップされたコマンド ID は、ゼロから始まる verb 番号に変換され、その verb に対するサーバーが (COleClientItem::DoVerb を使って) 起動されます。
このコマンド ID 範囲のカスタマイズや別の使い方はお勧めしません。
ID_VIEW_TOOLBAR ツールバーのオン/オフを切り替えします。
CFrameWnd がこのコマンドを処理し、更新コマンド UI ハンドラがツールバーの状態 (表示/非表示) を切り替えます。
ツールバーは、フレームの子ウィンドウでなければなりません (ID は AFX_IDW_TOOLBAR)。
このコマンド ハンドラが、ツールバー ウィンドウの表示状態を実際に切り替えます。
CFrameWnd::RecalcLayout ではフレーム ウィンドウを再描画して、ツールバーの状態を更新します。
ツールバーが表示されているときは、更新コマンド UI ハンドラがメニュー項目を調べます。
このコマンド ハンドラのカスタマイズはお勧めしません。
さらにツールバーを追加したいときは、このコマンド ハンドラとこのコマンドの更新コマンド UI ハンドラの複製 (クローン) を作って修正を行ってください。
ID_VIEW_STATUS_BAR ステータス バーのオン/オフを切り替えます。
このコマンドは、別の子ウィンドウ ID (AFX_IDW_STATUS_BAR) が使われていること以外は、ID_VIEW_TOOLBAR と同じように CFrameWnd で インプリメントされています。