ツールバーから選択でウィンドウ生成

このQ&Aのポイント
  • VC++2005(MFC)にてMDIアプリケーションを作成しています。
  • サンプルコードを参考に、プログラム起動時にMDIウィンドウを生成することは出来ましたが、これを『ツールバーからメニューを選択し、ウィンドウを出す』ように改良したいのです。
  • 解決策ご存知の方おられましたら、お手数ですがご教授お願い致します。
回答を見る
  • ベストアンサー

ツールバーから選択でウィンドウ生成

下記URLのサンプルコード http://www.alpha-net.ne.jp/users2/uk413/vc/VCT_MDI1.html​ を参考に、VC++2005(MFC)にてMDIアプリケーションを作成しています。 サンプルを参照にソースコードを記述し、プログラム起動時に MDIウィンドウを生成することは出来ましたが、 これを『ツールバーからメニューを選択し、ウィンドウを出す』ように 改良したいのです。 下記に起動時にMDIウィンドウを生成するソースコードを記載します。 「☆☆☆追加☆☆☆」で囲まれた箇所が、 上記URL解説を元に自分で追加した箇所で、それ以外はスケルトンです。 解決策ご存知の方おられましたら、お手数ですがご教授お願い致します。 【呼び出し元クラス:CMDITest1App】 BOOL CMDITest1App::InitInstance(){ INITCOMMONCONTROLSEX InitCtrls; InitCtrls.dwSize = sizeof(InitCtrls); InitCtrls.dwICC = ICC_WIN95_CLASSES; InitCommonControlsEx(&InitCtrls); CWinApp::InitInstance(); if (!AfxOleInit()) { AfxMessageBox(IDP_OLE_INIT_FAILED); return FALSE; } AfxEnableControlContainer(); SetRegistryKey(_T("アプリケーション ウィザードで生成されたローカル アプリケーション")); LoadStdProfileSettings(4); // 標準の INI ファイルのオプションをロードします (MRU を含む) // アプリケーション用のドキュメント テンプレートを登録します。ドキュメント テンプレート // はドキュメント、フレーム ウィンドウとビューを結合するために機能します。 CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate(IDR_MDITest1TYPE, RUNTIME_CLASS(CMDITest1Doc), RUNTIME_CLASS(CChildFrame), // カスタム MDI 子フレーム RUNTIME_CLASS(CMDITest1View)); if (!pDocTemplate) return FALSE; AddDocTemplate(pDocTemplate); //☆☆☆追加☆☆☆ CMultiDocTemplate* pDocTemplate2; pDocTemplate2 = new CMultiDocTemplate(IDR_MDITest1TYPE2, RUNTIME_CLASS(CMDITest1Doc), RUNTIME_CLASS(CChildFrame), // カスタム MDI 子フレーム RUNTIME_CLASS(CMDITest1View2)); if (!pDocTemplate2) return FALSE; AddDocTemplate(pDocTemplate2); //☆☆☆追加☆☆☆ // メイン MDI フレーム ウィンドウを作成します。 CMainFrame* pMainFrame = new CMainFrame; if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME)) { delete pMainFrame; return FALSE; } m_pMainWnd = pMainFrame; // 接尾辞が存在する場合にのみ DragAcceptFiles を呼び出します。 // MDI アプリケーションでは、この呼び出しは、m_pMainWnd を設定した直後に発生しなければなりません。 // DDE、file open など標準のシェル コマンドのコマンド ラインを解析します。 CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo); // コマンド ラインで指定されたディスパッチ コマンドです。アプリケーションが // /RegServer、/Register、/Unregserver または /Unregister で起動された場合、False を返します。 if (!ProcessShellCommand(cmdInfo)) return FALSE; // メイン ウィンドウが初期化されたので、表示と更新を行います。 pMainFrame->ShowWindow(m_nCmdShow); pMainFrame->UpdateWindow(); //☆☆☆追加☆☆☆ pMainFrame->OpenView(pDocTemplate2); //☆☆☆追加☆☆☆ return TRUE; } 【呼び出し先クラス:CMainFrame】 //☆☆☆追加☆☆☆ void CMainFrame::OpenView(CDocTemplate *pTemplate){ CDocument* pDoc = MDIGetActive()->GetActiveDocument(); CMDIChildWnd* pNewFrame = (CMDIChildWnd*)pTemplate->CreateNewFrame(pDoc, NULL); if( pNewFrame ) pTemplate->InitialUpdateFrame(pNewFrame, pDoc); } //☆☆☆追加☆☆☆

質問者が選んだベストアンサー

  • ベストアンサー
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

OnFileNewをオーバーライドしてやればいいように思います まず追加のテンプレートをメンバー変数に持つようにします CMDITest1App.hの CMDITest1Appクラス定義内に CMultiDocTemplate* m_pDocTemplate2; を追加 CMDITest1App.cppの中で テンプレートを追加した部分で AddDocTemplate(pDocTemplate2); //☆☆☆追加☆☆☆ m_pDocTemplate2 = pDocTemplate2; を追加 // ここで行うと後々面倒 //☆☆☆追加☆☆☆ // pMainFrame->OpenView(pDocTemplate2); //☆☆☆追加☆☆☆ の部分をコメントアウト クラスビューで CMDITest1Appを選択してプロパティウィンドウの『雷マーク』をクリック ID_FILE_NEWを選択 COMMANDの右側をクリックして OnFileNewを追加 自動挿入されたコードを void CMDITest1App::OnFileNew() { CWinApp::OnFileNew(); ((CMainFrame*)m_pMainWnd)->OpenView( m_pDocTemplate2 ); } と変更 このコードの先頭付近に元からある ファイル > 新規作成用のハンドラを修正 BEGIN_MESSAGE_MAP(CMFCTest1App, CWinApp)   ON_COMMAND(ID_APP_ABOUT, &CMFCTest1App::OnAppAbout)   // 標準のファイル基本ドキュメント コマンド   // コノ下の行をコメントアウト CWinApp::OnFileNewへは行かないようにする   //ON_COMMAND(ID_FILE_NEW, &CWinApp::OnFileNew)   ON_COMMAND(ID_FILE_OPEN, &CWinApp::OnFileOpen)   // 自前の OnFileNewを使うようにする   ON_COMMAND(ID_FILE_NEW, &CMFCTest1App::OnFileNew) END_MESSAGE_MAP() といった手順で動作すると思いますよ ファイル > 開く の部分に関しても同様な修正が必要でしょう

zigen8513
質問者

お礼

失礼しましたm_pDocTemplate2に値が代入されていなかったようです。。 修正し、正常に動作させることが出来ました。 大変助かりました。ありがとうございました!

zigen8513
質問者

補足

ご回答ありがとうございます。 ご指摘通りにコーディングしたところ、コンパイルは通りましたが、 【呼び出し先クラス:CMainFrame】内の、 CDocument* pDoc = MDIGetActive()->GetActiveDocument(); にて、 「MDITest1.exe の 0x00413ae0 でハンドルされていない例外が発生しました: 0xC0000005: 場所 0x00000000 を読み込み中にアクセス違反が発生しました。」 とのエラーが出ました。 デバッグを試みたところ、OpenView関数の引数(CDocTemplate *pTemplate)に NULLが入っているので、NULLアクセスが原因かと思われますが。。 自分でも色々調べてみますが、初心者なもので解決は難しいかと思います。 申し訳ありませんが、今一度解決策をご教授頂けませんでしょうか?

関連するQ&A

  • ウィンドウ生成時にアクセス違反エラー

    下記URLのサンプルコード http://www.alpha-net.ne.jp/users2/uk413/vc/VCT_MDI1.html を参考に、VC++2005(MFC)にてMDIアプリケーションを作成しています。 正常に動作すれば、プログラム起動時に2つのウィンドウが表示されるはずですが、 問題箇所「DEBUG!!!」にて、 「MDITest1.exe の 0x00416420 でハンドルされていない例外が発生しました: 0xC0000005: 場所 0x00000000 を読み込み中にアクセス違反が発生しました。」 といったエラーが発生し、実行が出来ない状態です。 下記にソースコードを記載します。ベタ貼りで申し訳ありません。。 「☆☆☆追加☆☆☆」で囲まれた箇所が上記URL解説を元に自分で追加した箇所で、 それ以外はスケルトンなので、基本的にサンプルコードと同じです。 解決策ご存知の方おられましたら、お手数ですがご教授お願い致します。 【呼び出し元クラス:CMDITest1App】 BOOL CMDITest1App::InitInstance(){ INITCOMMONCONTROLSEX InitCtrls; InitCtrls.dwSize = sizeof(InitCtrls); InitCtrls.dwICC = ICC_WIN95_CLASSES; InitCommonControlsEx(&InitCtrls); CWinApp::InitInstance(); if (!AfxOleInit()) { AfxMessageBox(IDP_OLE_INIT_FAILED); return FALSE; } AfxEnableControlContainer(); SetRegistryKey(_T("アプリケーション ウィザードで生成されたローカル アプリケーション")); LoadStdProfileSettings(4); // 標準の INI ファイルのオプションをロードします (MRU を含む) // アプリケーション用のドキュメント テンプレートを登録します。ドキュメント テンプレート // はドキュメント、フレーム ウィンドウとビューを結合するために機能します。 CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate(IDR_MDITest1TYPE, RUNTIME_CLASS(CMDITest1Doc), RUNTIME_CLASS(CChildFrame), // カスタム MDI 子フレーム RUNTIME_CLASS(CMDITest1View)); if (!pDocTemplate) return FALSE; AddDocTemplate(pDocTemplate); //☆☆☆追加☆☆☆ CMultiDocTemplate* pDocTemplate2; pDocTemplate2 = new CMultiDocTemplate(IDR_MDITest1TYPE2, RUNTIME_CLASS(CMDITest1Doc), RUNTIME_CLASS(CChildFrame), // カスタム MDI 子フレーム RUNTIME_CLASS(CMDITest1View2)); if (!pDocTemplate2) return FALSE; AddDocTemplate(pDocTemplate2); //☆☆☆追加☆☆☆ // メイン MDI フレーム ウィンドウを作成します。 CMainFrame* pMainFrame = new CMainFrame; if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME)) { delete pMainFrame; return FALSE; } m_pMainWnd = pMainFrame; // 接尾辞が存在する場合にのみ DragAcceptFiles を呼び出します。 // MDI アプリケーションでは、この呼び出しは、m_pMainWnd を設定した直後に発生しなければなりません。 //☆☆☆追加☆☆☆ pMainFrame->OpenView(pDocTemplate2); //☆☆☆追加☆☆☆ // DDE、file open など標準のシェル コマンドのコマンド ラインを解析します。 CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo); // コマンド ラインで指定されたディスパッチ コマンドです。アプリケーションが // /RegServer、/Register、/Unregserver または /Unregister で起動された場合、False を返します。 if (!ProcessShellCommand(cmdInfo)) return FALSE; // メイン ウィンドウが初期化されたので、表示と更新を行います。 pMainFrame->ShowWindow(m_nCmdShow); pMainFrame->UpdateWindow(); return TRUE; } 【呼び出し先クラス:CMainFrame】※問題箇所有り void CMainFrame::OpenView(CDocTemplate *pTemplate){ CDocument* pDoc = MDIGetActive()->GetActiveDocument();   //DEBUG!!! CMDIChildWnd* pNewFrame = (CMDIChildWnd*)pTemplate->CreateNewFrame(pDoc, NULL); if( pNewFrame ) pTemplate->InitialUpdateFrame(pNewFrame, pDoc); }

  • ツールバーから選択で一つだけウィンドウ生成

    VC++2005(MFC)にてMDIアプリケーションを作成しております。 前回当サイトの質問 http://oshiete1.goo.ne.jp/qa4708537.html にて、参照URL(http://www.alpha-net.ne.jp/users2/uk413/vc/VCT_MDI1.html)と、 回答者様のご指摘により問題解決したのですが、 このままだと、メニュー選択するとウィンドウ1とウィンドウ2が 再び現れてしまい、合計4つのウィンドウが現れることになります。 (ウィンドウ1:2個、ウィンドウ2:2個) 起動時にウィンドウ1のみ表示させる方法は自力で作成したのですが、 メニュー選択でウィンドウを一つ(ウィンドウ2)だけ 追加生成するようにし、合計2つの別々のウィンドウが現れるようにしたいのです。 下記に改良した現時点でのソースコードを記載します。 「☆☆☆追加☆☆☆」で囲まれた箇所が、上記質問URLを元に改変した ソースコードになります。他はスケルトンです。 【呼び出し元クラス:CMDITest1App】 CMDITest1App::CMDITest1App(){ //コンストラクタ //☆☆☆追加☆☆☆ m_WndFlg == false; //☆☆☆追加☆☆☆ } BOOL CMDITest1App::InitInstance(){ ・・・ //スケルトン //☆☆☆追加☆☆☆ CMultiDocTemplate* pDocTemplate2; pDocTemplate2 = new CMultiDocTemplate(IDR_MDITest1TYPE2, RUNTIME_CLASS(CMDITest1Doc), RUNTIME_CLASS(CChildFrame), // カスタム MDI 子フレーム RUNTIME_CLASS(CMDITest1View2)); if (!pDocTemplate2) return FALSE; AddDocTemplate(pDocTemplate2); m_pDocTemplate2 = pDocTemplate2; //☆☆☆追加☆☆☆ ・・・ return TRUE; } 【オーバーライドした関数:OnFileNew()】 //☆☆☆追加☆☆☆ void CMDITest1App::OnFileNew(){ CWinApp::OnFileNew(); if( m_WndFlg == true ){ //初回起動時は生成しない ((CMainFrame*)m_pMainWnd)->OpenView( m_pDocTemplate2 ); } m_WndFlg = true; } //☆☆☆追加☆☆☆ 何か良い方法ございましたら、ご教授お願い致します。 また、現在MDIでのアプリケーション作成について作成手順が分からず大変苦戦しております。 何か順序を追って作成していけるような参考サイト・文献などあれば、 そちらの方もご教授頂けますと幸いです。

  • 分割ウィンドウ(CSplitterWnd)について

    分割ウィンドウ(CSplitterWnd)についての質問です。開発環境はVC++2003です。 右側に2X2の4つの作業用のビュー(CWorkView)、左側に別画面(CCmdForm)を作成したいのですが、画面サイズが指定通りに表示されません。初期状態では左の画面だけ表示されます。作業ビューの縦方向の分割は正しくされていますが、横方向のビューサイズが0になって隠れた状態になります。後から分割枠を移動させて作業ビューを表示させることはできます。またCMainFrame::RecalcLayout() の中でCSplitterWnd::SetColumnInfo() で調整を試みましたが効果がありませんでした。 ちなみにCCmdFormを左にして、作業ビュー(CWorkView) を右にすると問題なく表示されます。どうしてもこの画面構成でなければならないため困っています。何かいい方法は無いでしょうか? 以下参考までにソース CMainFrame::OnCreateClient() で if(!_Splitter.CreateStatic(this, 1, 2, WS_CHILD | WS_VISIBLE)) return FALSE; if(!_Splitter2.CreateStatic(&_Splitter, 2, 2, WS_CHILD | WS_VISIBLE | WS_BORDER, _Splitter.IdFromRowCol(0,0))) return FALSE; if( !_Splitter.CreateView(0, 1, RUNTIME_CLASS(CCmdForm), CSize(100, 100), pContext)) return FALSE; if(!_Splitter2.CreateView(0, 0, RUNTIME_CLASS(CWorkView), CSize(100, 100), pContext)) return FALSE; if(!_Splitter2.CreateView(0, 1, RUNTIME_CLASS(CWorkView), CSize(100, 100), pContext)) return FALSE; if(!_Splitter2.CreateView(1, 0, RUNTIME_CLASS(CWorkView), CSize(100, 100), pContext)) return FALSE; if(!_Splitter2.CreateView(1, 1, RUNTIME_CLASS(CWorkView), CSize(100, 100), pContext)) return FALSE; (画面サイズ CSize(100, 100) はあくまで仮の値です) 以上、宜しくお願いします。

  • フレームのデフォルトのサイズについて

    また気になることが出てきましたので、よろしくお願いします。 VC++6.0 MFC MDIにて フレーム(親ウィンドウ)のサイズは、MainFrm.cpp内の以下にて変更することができますが、変更しないときは、デフォルトのサイズのウィンドウが生成されます。 そのデフォルトのサイズは、rectDefaultで定義されてるらしいということまでは調べたのですが、具体的にはどこでどのように定義されているのでしょうか? ご存知の方、よろしくお願いします。 ************************** BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { if( !CMDIFrameWnd::PreCreateWindow(cs) ) return FALSE; // TODO: この位置で CREATESTRUCT cs を修正して、Window クラスやスタイルを // 修正してください。 return TRUE; }

  • MFC CSplitter内にコントロールを表示させるには

    Viewクラスを作り中に表示させる方法はわかったのですが、 分割ウィンドウ内にListCtrlなどを表示させるにはどうすればいいのでしょうか? コンパイルはできるのですが、afxcmn.inl Line:266の ASSERT(::IsWindow(m_hWnd));でエラーが出てしまいます。 何がいけないのか教えてください。お願いします。 //.h CSplitterWnd m_wndSplitter; virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext); //.cpp BOOL CWnd::OnCreateClient(LPCREATESTRUCT /*lpcs*/,CCreateContext* pContext) { if(!m_wndSplitter.CreateStatic( this, 1, 2, WS_CHILD | WS_VISIBLE ) ) return FALSE; if(!m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CListCtrlA),CSize(200,300),pContext)) return FALSE; if(!m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CListCtrlB) ,CSize( 200,300),pContext)) return FALSE; }

  • MFC オリジナルDLLからエクスポートしたビュークラスを CMultiDocTemplate で登録すると Assert Failed! が出る

    環境はVisualStudio2005、MDIプロジェクトと拡張DLLプロジェクトを1つのソリューションに作成しています。 MDIアプリを作成していますが InitInstance() 関数内の CMultiDocTemplateの引数 RUNTIME_CLASS() 実行時にAssert Failed!が出ます。 CMultiDocTemplate に登録するビュークラスはオリジナルの拡張DLL内でCFormViewクラスから派生させたクラスです。 特に変わったことをしている訳ではなく、ほとんどウィザードがソースを吐いた状態のままです。 "COriginalView" をデフォルトの "CMyView" にするとエラーは出ません。 また、"COriginalView" もコントロールを1ヶ置いてビューフォームとクラスを作成し、 AFX_EXT_CLASS でエクスポートして参照できています。 また、MDI側でフォームとクラスを作成しそれを使用した場合はエラーは出ません。 ドキュメント/ビューアーキテクチャの理解が足りない為起きている問題だと思います。 宜しくお願い致します。 --- 詳細 ------------------------------------------------ CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate(IDR_MAINFRAME,   RUNTIME_CLASS(CMyDoc),   RUNTIME_CLASS(CChildFrame),   RUNTIME_CLASS(CDllView)); ←これ実行時に Assert が出る AddDocTemplate(pDocTemplate); ---------------------------------------------------------

  • メッセージボックスが表示されないのですが?

    WIN98 VC++6.0 MFCにて mmmというプロジェクト名でウィザードに従いダイアログベースのPGを作りました。 下記のようにコードの2箇所にAfxMessageBox("3",MB_OK);を追加しましたが、どちらもメッセージボックスが表示されません。 どうしてなのでしょうか? お分かりも方是非教えてください。 ************************** BOOL CMmmApp::InitInstance() { AfxEnableControlContainer(); #ifdef _AFXDLL Enable3dControls(); #else Enable3dControlsStatic(); #endif CMmmDlg dlg; m_pMainWnd = &dlg; int nResponse = dlg.DoModal(); AfxMessageBox("3",MB_OK);//■追加 if (nResponse == IDOK) { AfxMessageBox("3",MB_OK);//■追加 } else if (nResponse == IDCANCEL) { } // ダイアログが閉じられてからアプリケーションのメッセージ ポンプを開始するよりは、 // アプリケーションを終了するために FALSE を返してください。 return FALSE; }

  • ウインドウサイズについて

    起動時のウインドウサイズは以下で指定することが出来ますが、タイマーなどを使って、例えば起動後1分後にサイズを変えることは出来ますか? <VC++6.0 MFCにて> BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { if( !CFrameWnd::PreCreateWindow(cs) ) return FALSE; // TODO: この位置で CREATESTRUCT cs を修正して、Window クラスやスタイルを // 修正してください。 // ウィンドウの左上が X軸200,Y軸100の場所に指定 cs.x = 200; cs.y = 100; // ウィンドウのサイズを、幅500,高さ300に指定 cs.cx = 500; cs.cy = 300; return TRUE; }

  • ピクチャーコントロールのデバイスコンテキストを取得するためには?

    VC2005についてです ピクチャーコントロールのデバイスコンテキストを操作するためには どうすればよいでしょうか? void CMainFrame::OnButton() { // ここに処理を書く CMainFrame *pFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd; CButton *pButton =  (CButton*)pFrame->m_wndDialogBar.GetDlgItem(IDC_BUTTON1); pButton->SetWindowText("button"); MDIGetActive()->GetDC()->TextOutA(0,0,"文字列です"); } この様にすれば、アクティブになった 子ウィンドウデバイスコンテキストを取得することができますが、 アクティブになった、この子ウィンドウの上にある ピクチャーコントロールに 描画するためには どうすればよいでしょうか? MDIで、複数のウィンドウのうちで アクティブになった ものだけを 操作したいのです。 MDIGetActive()->GetDlgItem(IDC_PICTURE1)->GetDC()->TextOutA(0,0,"文字列です"); この方法では、エラーがでます。 よろしくお願いします。

  • Javaでウインドウを表示する方法

    Javaで簡単なアプリケーションを作成してみようと思いつき調べながらやってみたところ中身だけはできましたがウインドウを開けませんでした。開けないというのは「推奨されないAPIを使用またはオーバーライドしてます。詳細については-Xlint:deprecationオプションを指定して再コンパイルしてください」と表示されてコンパイルエラーになってしまうからです。 使用したプログラムは以下のようになっています。 import java.awt.*; public class window2 extends java.applet.Applet { Frame win=new NewFrame("ボタン付きウインドウ"); public void init(){ win.resize(200,150); win.move(300,100); add(new Button("開く")); } public boolean action(Event e, Object o){ if(o.equals("開く")) win.show(); return true; } class NewFrame extends Frame { NewFrame(String title) { super(title); Label mesg=new Label("ウインドウ 3",Label.CENTER); add("Center",mesg); add("South",new Button("閉じる")); } public boolean action(Event e, Object o){ if(o.equals("閉じる")) this.hide(); return true; } } }

専門家に質問してみよう