ボタン押下で子画面を表示させたい – プログラミング – Home

ボタン押下で子画面を表示させたい
 
通知
すべてクリア

[解決済] ボタン押下で子画面を表示させたい


VCビギナー
 VCビギナー
(@VCビギナー)
ゲスト
結合: 18年前
投稿: 8
Topic starter  

動作環境:Win XP Pro
開発環境:VS2005 VC++(MFC)

MDIを使用してアプリケーションを作成しようと考えています。

やりたいこと
・2種類の子画面を用意(子画面①、子画面②)
・起動時には親画面の中に子画面①のみ表示される
・子画面①にボタンを配置し、ボタンを押下すると子画面②が表示される

イメージに近いものとしては、
http://www.alpha-net.ne.jp/users2/uk413/vc/VCT_MDI1.html

こちらのサイトで解説されているやり方は、アプリ起動時に2つの画面が同時に起動しま
すが、
私はあくまでも、ボタンを押したら子画面②が表示される、というものを作成しようとし
ています。

サイトや掲示板を探しましたが、なかなかやりたいことに近いものが見つけられずに困っ
ています。

やり方をご存知の方、または解説しているサイト等ございましたら、教えていただけます
でしょうか?
よろしくお願いします。


引用未解決
トピックタグ
いろは
 いろは
(@いろは)
ゲスト
結合: 21年前
投稿: 43
 

ちゃんとは読んでいませんが、やり方は提示されたHP内に書いてあると思います。

今回はボタンが押されたタイミングでCreateNewFrame()で子ウィンドウを表示するようにすればOK
です。
ただ新規ウィンドウを表示するときに、新規ウィンドウを作成するときに聞いてくるダイアログが出
てしまうので、これを消すようにしないといけないですね。
で、やり方は… 今 過去のソースを見てますので、しばしお待ちを。。。


返信引用
いろは
 いろは
(@いろは)
ゲスト
結合: 21年前
投稿: 43
 

提示されたHPに新規ウィンドウを出さない方法は書いてありましたね。
リソースを修正すれば良いようです。(何せ数年前にやったので忘れてました)

これ以上は、もう少し具体的にどこがわからないのかはっきりさせてもらわないと答えられませ
ん。。


返信引用
VCビギナー
 VCビギナー
(@VCビギナー)
ゲスト
結合: 18年前
投稿: 8
Topic starter  

いろはさん、ありがとうございます。

具体的につまづいている箇所を書いていませんでした。
申し訳ありません。

HPのサンプル通りに作成し、まずは起動時の同時表示をしました。
ステップ実行を行い、子画面②を表示させている処理はわかりました。
それをボタンのコントロールの箇所で行えば良いだろう、というところまでは行き着きま
した。
起動時に子画面②が起動しないように、サンプルに記載されていた、

・テンプレートの記述
・pMainFrame->OpenView(pDocTemplate2);

をコメントアウトし、ボタンが押下されたところの処理を、以下のように記述し、コンパ
イルしました。(コンパイルは問題なかったです)

 void CxxxView::OnBnClickedButton1()
 {
   CMultiDocTemplate* pDocTemplate2 = new CMultiDocTemplate(
   IDR_xxxTYPE2,
   RUNTIME_CLASS(CxxxDoc),
   RUNTIME_CLASS(CChildFrame), // カスタム MDI 子フレーム
   RUNTIME_CLASS(CxxxView2));

   CMainFrame* pMainFrame = new CMainFrame;
   pMainFrame->OpenView(pDocTemplate2);
 }

実行すると、起動時には親画面の中に子画面①だけが表示されました。
しかし、子画面①のボタンを押すと、

 xxx.exeの 0x00413cd9 でハンドルされていない例外が発生しました:
 0xC0000005: 場所0x00000000 を読み込み中にアクセス違反が発生しました。

というメッセージが表示され、エラーになってしまいます。
ステップ実行してみると、OpenView関数内の

CDocument* pDoc = MDIGetActive()->GetActiveDocument();

で落ちているようなのですが・・・。


返信引用
いろは
 いろは
(@いろは)
ゲスト
結合: 21年前
投稿: 43
 

過去のソースはあるのですが、動くソースが無いので確かなことは言えませんが。。。

MFCのソース内にステップ実行すれば何が悪いのかわかるかもしれませんよ。
予想で書きますが、CreateしたMultiDocTemplateをAddDocTemplate()していないのが原因かと思
います。
HPに書いてあったようにCXXApp::InitInstance()内でMultiDocTemplateをCreateして
AddDoctemplate()したらどうでしょうか。


返信引用
ITO
 ITO
(@ITO)
ゲスト
結合: 22年前
投稿: 1235
 

いろはさんも書いておられますが

 >  CMultiDocTemplate* pDocTemplate2 = new CMultiDocTemplate(
 >  IDR_xxxTYPE2,
 >  RUNTIME_CLASS(CxxxDoc),
 >  RUNTIME_CLASS(CChildFrame), // カスタム MDI 子フレーム
 >  RUNTIME_CLASS(CxxxView2));

普通これは、CXXApp::InitInstance()内で書きます。
通常、MDIでスケルトンを作成すれば、下記の様な者をVCが作ってくれます。
------ ココカラ -------
CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(IDR_xxx,
RUNTIME_CLASS(CxxxDoc),
RUNTIME_CLASS(CChildFrame), // カスタム MDI 子フレーム
RUNTIME_CLASS(CxxxView));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);

------ ココマデ -------
後は、
コピーして
   登録するドキュメントテンプレート pDocTemplate 
   表示させたいメニュ-  IDR_xxx
   ウインドウのクラス   CxxxDoc、CChildFrame、CxxxView
を変更してして
表示したいウインドウ分作ります。   


返信引用
ITO
 ITO
(@ITO)
ゲスト
結合: 22年前
投稿: 1235
 

追記
 あと
> CMainFrame* pMainFrame = new CMainFrame;
> pMainFrame->OpenView(pDocTemplate2);
は、
CXXApp内じゃないと実行できないです。

pDocTemplate2をnewしているのはCXXApp内なのでViewで実行したい時は、
PostMessage/SendMessage等でメッセージをCXXAppに送るなりしないと駄目かもしれませ
んね。
theAppがグローバルになっているから使えるかも知れませんが、僕は前者を進めます
が。


返信引用
ITO
 ITO
(@ITO)
ゲスト
結合: 22年前
投稿: 1235
 

追記2
HP内
>\nMDITes\n\n\n\nMDITest1.Document\nMDITes Document
これもウインドウ分追加しないといけないはずです。
MDITesが確かテンプレート名


返信引用
VCビギナー
 VCビギナー
(@VCビギナー)
ゲスト
結合: 18年前
投稿: 8
Topic starter  

いろはさん、ITOさん、ありがとうございます。

お二人が仰る通り、CxxxApp::InitInstance()内でMultiDocTemplateをCreateして
AddDoctemplate()しました。

また、HPやITOさんの仰る通り、
 リソースビュー -> String Table -> String Table
のIDR_xxxTYPEをコピー&ペーストし、
 IDR_xxxTYPE2 \nxxx\n\n\n\nxxx.Document\nxxx.Document
を追加しました。

その上で、子画面①のボタンが押されたところでSendMesasgeで子画面②を呼び出そうと思い、

 void CxxxView::OnBnClickedButton1()
 {
   // TODO: ここにコントロール通知ハンドラ コードを追加します。
   GetParent()->SendMessage(WM_COMMAND, IDR_xxxTYPE2);
 }

と記述し、実行したのですが、子画面②が表示されませんでした。

  GetParent()->SendMessage(WM_COMMAND, ID_FILE_NEW);

  GetParent()->SendMessage(WM_COMMAND, ID_APP_ABOUT);

とすると、子画面①やバージョン情報ダイアログは開くのですが・・・。


返信引用
いろは
 いろは
(@いろは)
ゲスト
結合: 21年前
投稿: 43
 

> GetParent()->SendMessage(WM_COMMAND, IDR_xxxTYPE2);
↑これじゃダメじゃないかな。。
もしやるならIDR_XXXTYPE2をID_FILE_NEWにしないと。でもこれだと子ウィンドウ1が出てしまいま
すけどね。

アプリケーションクラスにOpenChild2とか作って、この関数内でDocTemplateを検索
(CWinApp::GetFirstTemplatePositionとCWinApp::GetNextDocTemplateを使用)し
て、CreateNewFrameすれば良いと思います。

たとえば、、

CWinApp::OpenChild2()
{
// GetFirstTemplatePositionとGetNextDocTemplateを使って
//

}


返信引用
いろは
 いろは
(@いろは)
ゲスト
結合: 21年前
投稿: 43
 

途中で送っちゃった…

CxxxApp::OpenChild2( CDocument* pDoc )
{
CDocTemplate* pTemplate;
// GetFirstTemplatePositionとGetNextDocTemplateを使って
// 対象とするテンプレートを取得

CMDIChildWnd* pNewFrame = (CMDIChildWnd*)pTemplate->CreateNewFrame(pDoc,
NULL);
if( pNewFrame )
pTemplate->InitialUpdateFrame(pNewFrame, pDoc);
}

void CxxxView::OnBnClickedButton1()
{
   ((CxxxApp*)AfxGetApp())->OpenChild2( GetDocument() );
}

こんな感じ。


返信引用
VCビギナー
 VCビギナー
(@VCビギナー)
ゲスト
結合: 18年前
投稿: 8
Topic starter  

いろはさん、返事が遅くなり申し訳ありませんでした。

いろはさんからのヒントを元に、

void CxxxApp::OpenChild2(CDocument* pDoc)
{
CWinApp* pApp = AfxGetApp();
POSITION pos = pApp->GetFirstDocTemplatePosition();

CDocTemplate* pTemplate;
while (pos != NULL)
pTemplate = pApp->GetNextDocTemplate(pos);

CMDIChildWnd* pNewFrame = (CMDIChildWnd*)pTemplate->CreateNewFrame(pDoc, NULL);
if(pNewFrame)
pTemplate->InitialUpdateFrame(pNewFrame, pDoc);
}

と記述して実行したところ、こちらの意図する動きをしてくれました。

いろはさん、ITOさん、本当にありがとうございました。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました