ZZZYと申します。VisualC++は初心者です。
環境:WindowsXP VisualStudio.net2003 MFC使用
SDIで複数のフォームを切り替えるアプリを考えています。
フォームの切り替え自体はできたのですが、切り替えたビュー側から対応するドキュメン
トを受け取ることが出来ません。(GetDocumentが失敗します)
CWinApp継承クラスのInitInstance()でドキュメントテンプレートへの追加は行っている
のですが、ドキュメントクラスの生成が行われていないようです。(デバッグでコンスト
ラクタが呼ばれない)
自分で追加したドキュメントクラスを生成させるにはどのようにしたらよいでしょうか?
「SDI = SingleDocumentInterface」
なので通常、ドキュメントを追加することが出来ません。
「MDI = MultipleDocumentInterface」をアプリケーションウイザードで作成して、
「InitInstance()」の 「CMultiDocTemplate」に追加します。
SDIの制約は、1つのフレームに1つのドキュメント、ということなので、
ドキュメントを追加することはできると思います。
フォームの切り替えを行っているところあたりに抜けがあるのではないかと思います。
切り替えを行っているところのコードを提示して頂けませんか?
同時に1つのドキュメントしか開けない、という制約だったかもしれません。
どちらにせよ、複数のドキュメントを用意して切り替えることは可能だと思います。
ビュー入替については MSDN の COLLECT サンプルがありますね。
上記サンプルのビュー入替の処理途中に、
CRuntimeClass::CreateObject() で新規ドキュメントを作成する
CSingleDocTemplate::RemoveDocument() で古いドキュメントを破棄する
CSingleDocTemplate::AddDocument() で新規ドキュメントを登録する
という処理を加えればドキュメント入替もできそうですが...
「SDI」には、元になるフレーム「CMDIFrameWnd」がないですよね。
でも、「CSingleDocTemplate::RemoveDocument()」も大丈夫なんですね。
とても参考になりました。
時間があるときに、試してみます。
ITO様、MASATO様、r様
ご指導ありがとうございます。
私のコードでは、ドキュメントの生成、テンプレートのドキュメントの切り替えのコード
が抜けていました。そこが原因と思われます。
今から修正を行いたいと思います。
出来ましたら、またご報告させていただきます。
ありがとうございました。
申し訳ございません。行き詰ってしまいました。
> CRuntimeClass::CreateObject() で新規ドキュメントを作成する
> CSingleDocTemplate::RemoveDocument() で古いドキュメントを破棄する
> CSingleDocTemplate::AddDocument() で新規ドキュメントを登録する
RemoveDocument(),AddDocument()の実行で行き詰っています。
これらの関数を実行するCSingleDocTemplateオブジェクトの生成が行えません。
CORRECTサンプルと同様にmainfrm.cpp内でビューの切り替え処理を行っています。また、
プロジェクト名.cpp(WinApp継承クラス)のInitInstanceでDocumentTemplateの登録
AddDocTemplate()を行っております。2種類のビュー、ドキュメントの切り替えを考えて
いるので、AddDocTemplate()を2回実行する形としております。(この方法が正しいかも
よくわかっておりません)
登録したドキュメントテンプレートのポインタを受け取るなどの方法があるのでしょう
か?MSDNでSingleDocTemplate,DocumentTemplateを調べてみたのですが、関数など見つ
かりませんでした。
>登録したドキュメントテンプレートのポインタを受け取るなどの方法があるのでしょう
>か?MSDNでSingleDocTemplate,DocumentTemplateを調べてみたのですが、関数など見つ
>かりませんでした。
CWinApp::GetFirstDocTemplatePosition()
CWinApp::GetNextDocTemplate()
で取得できます。
別の方法としては、アプリケーションクラスのメンバー変数として
CSingleDocTemplate* m_pDocTemplate;
などを作り、InitInstance()時にそこに代入しておくのでもいいです。
以下は補足。
通常の SDI では、起動時に CDocument 派生クラスオブジェクトと
CView 派生クラスオブジェクトを生成すると、
それ以後は終了するまでこれらのオブジェクトを使い続けます。
#[ファイル]-[新規]や[開く]の場合も Doc/View は破棄せず、
#起動時に生成したものを再利用します。
#結果、Doc/View のコンストラクタ、デストラクタは1回しか
#動きません。
おそらく、CWinApp 派生クラスの InitInstance() で
CSingleDocTemplate を生成するときに渡す Doc/View のランタイム情報が
参照されるのは起動時の1回限りで、その後はこのランタイム情報と
実際の Doc / View オブジェクトの種類が違っていたとしても問題なく
動作するのではないかと思われます。
ですので、AddDocTemplate() は起動時に表示したい Doc/View に関して
1つだけ行い、あとは Doc / View の差し替えだけすれば大丈夫なのでは
ないかと思います。
注)僕は実際にはそのようなことを試したわけではありませんし、
しっかり調査したわけでもありません。
従って、すべて想像の範囲でこの回答を書いているということを
ご承知ください。
僕も「CORRECTサンプル」を見ましたが、「STATIC_DOWNCAST」マクロを使用したりし
て、手がこんでいます。
いきなり自分のプログラムに組み込むのでなく、よく確かめながら組み込んだほうが
いいです。
特に、「CMainFrame::OnExample(UINT nCmdID)」の中とかは、崩さずにまずそのまま
使ってみて、自信がついたとこから崩していくぐらいの慎重さが必要だと思います。
せっかくrさんに探していただいたサンプルなのでよくZZZYさんなりに調べたほうが
いいです。
僕も、MDIのソフトを製作するとき、ウインドウの切替え部分とかは、サンプルを
そのまま引用しています。
実際に、SDIでウインドウを切替えるソフトを作ったわけではないのですみませんがこんなア
ドバイスしか出来ません。
r様、ITO様、ご指導ありがとうございます。
r様に教えていただいたようにCSingleDocTemplate* m_pDocTemplateをメンバに用意し、
その値を切り替えを行うMainFrmで受け取れるようにしました。
その結果、ビューの切り替え、ドキュメントの切り替えが出来るようになりました。あり
がとうございます。
まだ細かい点(サンプルからコピーしている部分)などを詰めていかねばなりませんが、
皆様の丁寧なご指導により道が開けました。本当にありがとうございました。