• 締切済み

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

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でのアプリケーション作成について作成手順が分からず大変苦戦しております。 何か順序を追って作成していけるような参考サイト・文献などあれば、 そちらの方もご教授頂けますと幸いです。

みんなの回答

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

その考え方は MFCの Doc/Viewのアーキテクチャーに沿いませんよ DocuemntとViewが一体であることが前提になります ファイル > 新規作成 を行うと 新たなドキュメントが生成されます このとき Viewも一緒に生成するというのが本来の姿なのです OnFileNewから呼ばれている CFrameWindow::OpenViewを呼び出すのを止めてしまえばご希望に沿う形になるでしょう スライダーバーのViewを表示させるために新たにメニュー項目を追加した方がいいかと思います 表示メニューの中あたりに スライダービューなどといった項目を設置 CDocumnetの派生クラスに CMDIChildWnd型のポインタ変数など準備して これにスライダービューのオブジェクトを記憶しておくようにするなどの仕組みが必要でしょう このメニューが選択された際に // 現在のドキュメントを取得 CDocument* pDoc = MDIGetActive()->GetDocument(); if ( !pDoc->m_pSliderFrame ) {   // スライダービューが未作成ならば作成   CMultiDocTemplate* pTemp = ((CMDITest1App*)AfxGetApp())->m_pDocTemplate2;   pDoc->m_pSliderFrame = (CMDIChildWnd*)pTemp->CreateNewFrame( pDoc, NULL );   if ( pDoc->m_pSliderFrame ) {     pTemp->InitialUpdateFrame( pDoc->m_pSliderFrame, pDoc );   } } CMDITest1Documentのコンストラクタで m_pSilderFrame = NULL; を行いましょう MDITest1Doc.hのCMDITest1Documentクラスに CMDIChildFrame* m_pSliderFrame; を追加します

zigen8513
質問者

お礼

すみません。Doc/Viewアーキテクチャについて理解していませんでした。。 現在、ご意見を参考にコーディング中ですが、 理解しながらなので、少し時間がかかりそうです。 ただ、今までと違い上手くいきそうな気がします。 redfox63様、二回に渡る質問に対し、ご丁寧に解説して頂きありがとうございました!

関連するQ&A

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

    下記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); } //☆☆☆追加☆☆☆

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

    下記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); }

  • CMainFrameクラスなどのオブジェクトはどこで定義されていますか?

    VC++6.0です。 SDIベースでスケルトンを作るとCMainFrameクラスなどが作られます。ソースの中でこれらのクラスのオブジェクトが生成されている部分を見たいのですが、見つかりません。 InitInstance()の中のRUNTIME_CLASS()があやしいような気がしますが、これなんでしょうか? ただしRUNTIME_CLASS()の関連ページを読んでもよくわかりませんでした。 今の目標はスケルトンで生成されたCMainFrameのオブジェクトのメンバにアクセスすることです。 よろしくお願いします。

  • スケルトンの中のどこでウィンドウが生成されているのか?

    VC++、MFCです。 MFC AppWizardでSDIベースのスケルトンを生成した時点で、既にウィンドウが作られるコードがソース内に存在するはずなのですが、単純にCreate関数を探しても見当たりません。 一体どこでウィンドウが作るコードはどこにあるのでしょうか?

  • 分割ウィンドウ(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) はあくまで仮の値です) 以上、宜しくお願いします。

  • ダイアログのOKボタンを押してウィンドウを生成する方法は?

    ダイアログのOKボタンを押すとウィンドウが生成する方法を教えてください。 MFCでプログラミングしてメインウィンドウをダイアロボックスにしています //アプリケーション class CMyApp : public CWinApp { public: virtual BOOL InitInstance(); }; //メインダイアログ class CMyDlg : public CDialog { public: CMyDlg(CWnd *pParentWnd=NULL); protected: virtual void OnOK(); virtual void OnCancel(); }; #include <afxwin.h> #include <afxdlgs.h> #include <string.h> #include "dlg.h" #include "resource.h" CMyApp myApp; BOOL CMyApp::InitInstance(){ m_pMainWnd = new CMyDlg; m_pMainWnd ->ShowWindow(m_nCmdShow); m_pMainWnd ->UpdateWindow(); return TRUE; } CMyDlg::CMyDlg(CWnd* pParent /*=NULL*/) { Create("MYDLG"); } としています。 ダイアログはできるのですが、ここからウィンドウを生成する方法を教えてください

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

    また気になることが出てきましたので、よろしくお願いします。 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; }

  • MDIでのダイアログ生成

    VC++2005でMDIアプリケーションを作成しています。 ダイアログベースでは、DoModal()にてダイアログを生成していましたが、 MDIでのダイアログ生成の方法が分かりません。。 調べた結果、 (1)CreateWindow()にてクライアントウィンドウを作成 (2)CreateMDIWindow()にて子ウィンドウを作成 の順序で処理を行うことは分かりましたが、 関数の一部の引数に何を設定してやれば良いのかが不明です。。 ※下記はネット上にあったサンプルソースです。  「???」の箇所が不明な引数です。 (1) CreateWindow(   TEXT("MDICLIENT"), //MDICLIENT は固定です   NULL,   WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN,   0, 0, 0, 0,   hWnd,       //メインウィンドウのハンドル←???   (HMENU)1,    //←???   hInst,       //インスタンスハンドル←???   (LPSTR)&ccs    //CLIENTCREATESTRUCT構造体のポインタ←???  ); (2) HWND CreateMDIWindow(  MDI_CHILD ,   //ウィンドウクラス名  TITLE ,     //ウィンドウのタイトルバーテキスト  0 ,       //ウィンドウスタイル。WS_MAXIMIZE(最大化表示)など  CW_USEDEFAULT , //X座標  CW_USEDEFAULT , //Y座標  CW_USEDEFAULT , //幅  CW_USEDEFAULT , //高さ  hClientWindow , //クライアントウィンドウのハンドル ←???  hIns ,      //インスタンスハンドル       ←???  0        //アプリケーション定義の値 ); なお、行いたい処理の流れとしては、 CTestDialogクラスより、CTest2Dialogクラスのダイアログを、 呼び出したいのです。 うまく説明できず申し訳ありませんが、 お詳しい方おられましたら、具体例など交えてご説明頂けると幸いです。 お手数ですが、どうか宜しくお願い致します。

  • ウィンドウ生成時の不具合について

    VC++6.0 WIN98 MFCにて ウィザードを使ってSDIにてウィンドウ1を作成し、メニューをクリックすることで、ウィンドウ2が新たに生成されるプログラムを書きました。 ウィンドウ2が生成されたときに、ウィンドウ1に重なっていると、ウィンドウ2を閉じてもウィンドウ1のクライアント領域にウィンドウ2の形が残ったままになってしまいます。 どうしてこうなるのでしょうか?

  • SDIウィンドウを動的に複数生成する方法

    ダイアログベースのアプリケーションに配置したボタンを押すたびに、 SDIのウィンドウを動的に生成・表示したいと思っています。 しかし、なにをどうすればいいのかわかりません。 とっかかりでもよいので、なにかヒントが欲しいと思って質問します。 生成するSDIウィンドウには以下のような必要条件があります。 1.CMfcToolBarがある 2.CMfcRibbonStatusBarとスライダーバーがある。 3.独自に作成したCScrollViewクラスの派生クラスを使用する 4.1アプリケーション内で複数のSDIを生成する 開発環境 VC2010, WindowsXP よろしくお願いします。 <背景> 以前、CSingleDocTemplateを使用してウィンドウを作成しが、なぜかツールバーのボタンにUPDATE_COMMAND_UIがこない事が判明。 四苦八苦したが解決できないため、別アプローチを検討したいと思った。