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

このQ&Aのポイント
  • MFCでプログラミングして、ダイアログのOKボタンを押すとウィンドウが生成する方法を教えてください。
  • CMyAppクラスからCMyDlgクラスのインスタンスを生成し、メインウィンドウとして表示します。
  • CMyDlgクラスのOnOK()関数をオーバーライドし、ウィンドウの生成処理を実装します。
回答を見る
  • ベストアンサー

ダイアログの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"); } としています。 ダイアログはできるのですが、ここからウィンドウを生成する方法を教えてください

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

  • ベストアンサー
回答No.3

 こんばんは。補足頂きました。  CMyDlgクラスのコンストラクタで、m_pMyWndをNULL初期化してください。  恐らく、未初期化でポインタに不正値が入り込んでいる為、条件判定に失敗するのだと思います。 CMyDlg::CMyDlg(CWnd* pParent /*=NULL*/) : m_pMyWnd(NULL)//イニシャライザでポインタをNULLに初期化 { Create("MYDLG"); }

fwhf0162
質問者

お礼

どうもありがとうございます : m_pMyWnd(NULL)//イニシャライザでポインタをNULLに初期化 をつけたとたん、ウィンドウが開きました。感動でした。 ただ、closeとキャンセルはウィンドウズエラーが発生します そこらへんは自分で研究したいと思いますのですが、なにか気になるところがあるようでしたら、ご意見いただきたいと思います ありがとうございました。

その他の回答 (2)

回答No.2

 補足頂きました。 >>”//CMyDlgのメンバに追加”というのがこれでいいのかよくわかりません。  其処は合っています。ただ、まだ追加すべき事は残っています。 /////////////////////////////////////////////////// // dlg.h //アプリケーション class CMyApp : public CWinApp { public: virtual BOOL InitInstance(); }; //ウィンドウ class CMyWnd : public CFrameWnd { public: protected: DECLARE_MESSAGE_MAP() //(1)virtual void OnClose();此れを追加 }; //メインダイアログ class CMyDlg : public CDialog { public: CMyDlg(CWnd *pParentWnd=NULL); CMyWnd* m_pMyWnd;//此れは合っている。ただ、余程の理由が無い限り、直接アクセス出来ない様に、privateにした方が良い //(2)void DoneFromMyWnd();此れを追加 protected: //(3)void Done();此れを追加 virtual void OnOK(); virtual void OnCancel(); //(4)virtual void OnClose();此れを追加 }; /////////////////////////////////////////////////// // Test.cpp #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; } BEGIN_MESSAGE_MAP(CMyWnd, CFrameWnd) END_MESSAGE_MAP() //(1)CMyWndが「×」で閉じられる時 void CMyWnd::OnClose() { //親ダイアログを取る CMyDlg* pMyDlg = static_cast<CMyDlg*>(this->GetParent()); //親ダイアログに終了する事を伝える pMyDlg->DoneFromMyWnd(); CFrameWnd::OnClose(); } CMyDlg::CMyDlg(CWnd* pParent /*=NULL*/) { Create("MYDLG"); } //(2)CMyWndが一方的に終了した際に送り返される void CMyDlg::DoneFromWyWnd() { m_pMyWnd = 0; } //(3)此方の意思で終了させる void CMyDlg::Done() { if(m_pMyWnd) { m_pMyWnd->DestroyWindow(); m_pMyWnd = 0; } } //ココは合ってる void CMyDlg::OnOK() { if(!m_pMyWnd) { const RECT rc = {10, 10, 320, 240}; m_pMyWnd = new CMyWnd(); m_pMyWnd->Create(NULL, "MyWnd", WS_OVERLAPPEDWINDOW, rc, this); m_pMyWnd->ShowWindow(SW_SHOW); } } void CMyDlg::OnCancel() { //×DestroyWindow();此れだと自分が閉じてしまう Done(); } //(4)CMyDlgが「×」で閉じられる時 void CMyDlg::OnClose() { Done(); CMyDlg::OnClose(); }

fwhf0162
質問者

補足

たびたびどうもすみません。ご指摘とても参考になりました。ただコンパイルは通るのですが、動作がうまくいきません。ウィンドウはOKで開かず、キャンセルやクローズもウィンドウズエラーが出てしまいます。たびたびすみませんが、参考意見御願いします /////////////////////////////////////////////////// // dlg.h //アプリケーション class CMyApp : public CWinApp { public: virtual BOOL InitInstance(); }; //ウィンドウ class CMyWnd : public CFrameWnd { public: protected: virtual void OnClose(); DECLARE_MESSAGE_MAP() }; //メインダイアログ class CMyDlg : public CDialog { private: CMyWnd* m_pMyWnd; public: CMyDlg(CWnd *pParentWnd=NULL); void DoneFromMyWnd(); protected: void Done(); virtual void OnOK(); virtual void OnCancel(); virtual void OnClose(); }; /////////////////////////////////////////////////// // Test.cpp #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; } BEGIN_MESSAGE_MAP(CMyWnd, CFrameWnd) END_MESSAGE_MAP() void CMyWnd::OnClose() { //親ダイアログを取る CMyDlg* pMyDlg = static_cast<CMyDlg*>(this->GetParent()); //親ダイアログに終了する事を伝える pMyDlg->DoneFromMyWnd(); CFrameWnd::OnClose(); } CMyDlg::CMyDlg(CWnd* pParent /*=NULL*/) { Create("MYDLG"); } void CMyDlg::DoneFromMyWnd() { m_pMyWnd = 0; } void CMyDlg::Done() { if(m_pMyWnd) { m_pMyWnd->DestroyWindow(); m_pMyWnd = 0; } } void CMyDlg::OnOK() { if(!m_pMyWnd) { const RECT rc = {10, 10, 320, 240}; m_pMyWnd = new CMyWnd(); m_pMyWnd->Create(NULL, "MyWnd", WS_OVERLAPPEDWINDOW, rc, this); m_pMyWnd->ShowWindow(SW_SHOW); } } void CMyDlg::OnCancel() { Done(); } void CMyDlg::OnClose() { Done(); CMyDlg::OnClose(); }

回答No.1

 こんにちは。  取り敢えず、CFrameWndを継承してCMyWndを作成して、そのポインタをCMyDlgが持つようにすれば良いのでは?  OnOK()「OKボタン」が呼ばれたらCMyWndを開いて、その他何かのアクションでCMyWndを閉じ、CMyWndが自ら一方的に終了する際には、向こうから、CMyDlgに向かって通知させれば良さそうです。  大体こんな感じではないのでしょうか? //CMyDlgのメンバに追加 CMyWnd* m_pMyWnd; //OKボタンが押された void CMyDlg::OnOK() { // TODO: この位置にその他の検証用のコードを追加してください //適当に開く if(!m_pMyWnd) { const RECT rc = {10, 10, 320, 240}; m_pMyWnd = new CMyWnd(); m_pMyWnd->Create(NULL, "MyWnd", WS_OVERLAPPEDWINDOW, rc, this); m_pMyWnd->ShowWindow(SW_SHOW); } } //此方の意思で終了させる void CMyDlg::Done() { if(m_pMyWnd) { m_pMyWnd->DestroyWindow(); m_pMyWnd = 0; } } //CMyWndが一方的に終了した際に送り返される void CMyDlg::DoneFromWyWnd() { m_pMyWnd = 0; } ///////////////////////////////////////////////////////////////////////////// // CMyWnd メッセージ ハンドラ void CMyWnd::OnClose() { // TODO: この位置にメッセージ ハンドラ用のコードを追加するかまたはデフォルトの処理を呼び出してください //親ダイアログを取る CMyDlg* pMyDlg = static_cast<CMyDlg*>(this->GetParent()); //親ダイアログに終了する事を伝える pMyDlg->DoneFromMyWnd(); CFrameWnd::OnClose(); }

fwhf0162
質問者

お礼

回答どうもありがとうございます まだ勉強不足で、”//CMyDlgのメンバに追加”というのがこれでいいのか よくわかりません。下記のプログラムでうまく動作しません。 /////////////////////////////////////////////////// // dlg.h //アプリケーション class CMyApp : public CWinApp { public: virtual BOOL InitInstance(); }; //ウィンドウ class CMyWnd : public CFrameWnd { public: protected: DECLARE_MESSAGE_MAP() }; //メインダイアログ class CMyDlg : public CDialog { public: CMyDlg(CWnd *pParentWnd=NULL); CMyWnd* m_pMyWnd; protected: virtual void OnOK(); virtual void OnCancel(); }; /////////////////////////////////////////////////// // Test.cpp #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; } BEGIN_MESSAGE_MAP(CMyWnd, CFrameWnd) END_MESSAGE_MAP() CMyDlg::CMyDlg(CWnd* pParent /*=NULL*/) { Create("MYDLG"); } void CMyDlg::OnOK() { if(!m_pMyWnd) { const RECT rc = {10, 10, 320, 240}; m_pMyWnd = new CMyWnd(); m_pMyWnd->Create(NULL, "MyWnd", WS_OVERLAPPEDWINDOW, rc, this); m_pMyWnd->ShowWindow(SW_SHOW); } } void CMyDlg::OnCancel() { DestroyWindow(); } どうか間違いを教えてください

関連するQ&A

  • メインダイアログのデータをウィンドウに反映させたい

    メインダイアログからウィンドウを生成しています ダイアログの値を GetDlgItemText()関数で取るまではいいのですが それから、値をウィンドウに反映できません。 メンバ値を遣うと思うのですが、どうすればいいのでしょうか? プログラムを添付します ///////////////////////////////////////////////////////// // dlg.rc #include "resource.h" #include "afxres.h" ///////////////////////////////////////////////////////////////////////////// // // Dialog // MYDLG DIALOG DISCARDABLE 0, 0, 134, 80 STYLE DS_MODALFRAME | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "ダイアログからウィンドウ" FONT 9, "MS Pゴシック" BEGIN DEFPUSHBUTTON "OK",IDOK,15,55,50,14 PUSHBUTTON "キャンセル",IDCANCEL,65,55,50,14 EDITTEXT IDC_EDIT1,15,10,100,35,ES_AUTOHSCROLL END ////////////////////////////////////////////////// // resource.h #define IDC_EDIT1 1000 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 101 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif //////////////////////////////////////////////////////// // dlg.h //アプリケーション class CMyApp : public CWinApp { public: virtual BOOL InitInstance(); }; //ウィンドウ class CMyWindow : public CFrameWnd { private: CString MyMainStr; protected: afx_msg void OnPaint(); DECLARE_MESSAGE_MAP() }; //メインダイアログ class CMyDlg : public CDialog { public: CString m_MyStr; CMyDlg(CWnd *pParentWnd=NULL); CMyWindow* m_pMyWnd; protected: virtual void OnOK(); virtual void OnCancel(); }; ///////////////////////////////////////////// // DlgWnd.cpp #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*/):m_pMyWnd(NULL) //イニシャライザでポインタをNULLに初期化 { Create("MYDLG"); } BEGIN_MESSAGE_MAP(CMyWindow, CFrameWnd) ON_WM_PAINT() END_MESSAGE_MAP() void CMyDlg::OnOK() { GetDlgItemText(IDC_EDIT1, m_MyStr); const RECT rc = {10, 10, 320, 240}; m_pMyWnd = new CMyWindow(); m_pMyWnd->Create( NULL, "ダイアログから起動", WS_OVERLAPPEDWINDOW, rc, this,NULL); m_pMyWnd->ShowWindow(SW_SHOW); } void CMyDlg::OnCancel() { DestroyWindow(); } void CMyWindow::OnPaint() { CPaintDC dc(this); CMyDlg dlg; MyMainStr = dlg.m_MyStr; dc.TextOut(0, 0, MyMainStr); } よろしく御願いします

  • オーバーライドとオーバーロードについて

    1.CTestDlgクラスを作成 class CTestDlg : public CDialog { // コンストラクション public: BOOL Create(CWnd *pWnd); CWnd * m_pParent; CTestDlg(CWnd* pParent = NULL); // 標準のコンストラクタ・ ・ 2.メンバ関数の定義 BOOL CTestDlg::Create(CWnd *pWnd) { m_pParent = pWnd; BOOL bret = CDialog::Create( CTestDlg::IDD, m_pParent); if( bret == TRUE) { this->ShowWindow( SW_SHOW); } return bret; 以上のような場合において、 1.Create(CWnd *pWnd)は、引数が異なるため virtual BOOL Create( LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL ); をオーバーライドしたとは言わず、オーバーロードしたということで良いのでしょうか? 2.オーバーロードしたということであれば、 Create(CWnd *pWnd)と virtual BOOL Create( LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL ); の両方の関数が使えると思っていたのですが、後者方は引数が異なるとエラーが出て使えませんでした。 どうしてなのでしょうか? 以上、2点についてご教授ください。

  • ウィンドウ非表示のちらつきを無くすには

    <環境> WIN98 VC++6.0 MFC SDIにて 起動時に下記にてウィンドウを非表示にしていますが、最初に一瞬表示されてから、消えます。 何事も無かったかのように、こっそりと非表示にするにはどうすればよいですか? BOOL CAbcApp::InitInstance() { 省略 //m_pMainWnd->ShowWindow(SW_SHOW); m_pMainWnd->ShowWindow(SW_HIDE); m_pMainWnd->UpdateWindow(); return TRUE; }

  • メインダイアログを表示させずにファイル選択ダイアログを表示

    VC++2005のMFCダイアログベースでプログラムを作成しています。 自動生成されたプログラムを何も変更しないまま実行すると、 メインのダイアログが表示されますが、 そのダイアログを表示させずに、ファイル選択ダイアログを表示させたいのです。 自分で実装しビルド実行したところ、期待動作をしましたが、 ファイル選択ダイアログを閉じた後に、画像のようなエラーが発生してしまいます。 エラーを発生させず、期待動作をさせる良い実装方法をご存知の方おられましたら、 ご教示お願い致します。 【変更実装(エラー発生)】 BOOL CtestApp::InitInstance() { … CtestDlg dlg; m_pMainWnd = &dlg; // INT_PTR nResponse = dlg.DoModal(); //コメントアウト dlg.OnBnClickedButton1(); //ファイル選択ダイアログを表示する関数 //if (nResponse == IDOK) //コメントアウト //else if (nResponse == IDCANCEL) //コメントアウト … } void CtestDlg::OnBnClickedButton1() { CFileDialog ReadDlg( TRUE, NULL, "*.txt", OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, "txtファイル(*.txt)", this ); … }

  • DLL作成時、defファイルを使いたくない

    また質問させて下さい。 Visual Studio2005でDLLを使ったプログラムを作ろうとしています。 defファイルを利用すると、そのDLLファイルを作成できるのですが、 __declspec(dllexport)を利用すると、DLLファイルのその関数を読めなくなってしまいます。 なぜでしょうか? 下記は、MFCで、dll_test7というプロジェクトを作り、そのdll_test7.hのコードのすぐ下に その関数を書きました。(これがダメだと思うのですが…) //●Visual Studioのプロジェクト作成で、生成される部分 // dll_test7.h : dll_test7.DLL のメイン ヘッダー ファイル // #pragma once __declspec(dllexport) void __cdecl test0(void); #ifndef __AFXWIN_H__ #error "PCH に対してこのファイルをインクルードする前に 'stdafx.h' をインクルードしてください" #endif #include "resource.h" // メイン シンボル // Cdll_test7App // このクラスの実装に関しては dll_test7.cpp を参照してください。 // class Cdll_test7App : public CWinApp { public: Cdll_test7App(); // オーバーライド public: virtual BOOL InitInstance(); DECLARE_MESSAGE_MAP() }; //■作成した関数 __declspec(dllexport) void __cdecl test0(void) { CString cs; cs="aa"; ::AfxMessageBox(cs); } 上記は、defファイルを利用するとこの関数を呼び出せます。 以上、どうぞよろしくお願い致します。

  • ヘッダのインクルード時のエラー

    初歩的な質問で恐縮です。 以下のようなファイルの構成でc++のプログラムを組んでいます。 <header.h> class H { public: virtual void func() = 0; }; <fileA.cpp> #include "header.h" class A : public H { public: void func() {} }; <fileB.cpp> #include "header.h" class B : public H { public: void func() {} }; <main.cpp> #include "fileA.cpp" #include "fileB.cpp" int main() { A a; B b; a.func(); b.func(); return 0; } これをビルドしようとすると、「クラス"H"を再定義しようとしています」とエラーが出てコンパイルができません。理屈は分かるのですが、これの対処方法が分かりません。この場合、header.hはJAVAにおけるInterfaceのような役割としてそれを使うfileA.cpp、fileB.cppの両者にインクルードしておきたいのです。これはどのようにして対処すべきなのでしょうか?

  • ダイアログの再表示について

    宜しくお願いします。 <環境> WIN98 VC++6.0 MFC  ダイアログのボタン押し下げでウィンドウを生成し、 生成後はダイアログを非表示にしています。 void CInput::OnButton1()//ウィンドウの生成 { UpdateData (TRUE); pWnd = new CMyWnd( this); pWnd->m_left=100; pWnd->m_top=100; m_pAryDlg.Add ( pWnd ); //m_pAryDlg2.Add ( &m_InputData ); pWnd->m_moji=m_InputData; pWnd->Kado_Create(this); ShowWindow(SW_HIDE); //ダイアログの非表示 } ウィンドウをダブルクリックすると、ダイアログが非表示から 表示になるように以下のコードを書きましたが、表示されません。 どのようにすれば表示されるようになりますか? void CMyWnd::OnLButtonDblClk(UINT nFlags, CPoint point)  //ウィンドウのダブルクリック { CInput* pInput = (CInput*)GetParent(); // CInputは親ダイアログのクラス pInput->ShowWindow(SW_SHOW); CWnd::OnLButtonDblClk(nFlags, point); }

  • 静的でないメンバ関数の呼び出しが正しくありません

    コンパイル時に「静的でないメンバ関数の呼び出しが正しくありません」となってしまいます。 普通の関数からメンバー関数を呼び出すには、どう記述すればいいのでしょうか? void MyDataHandler(sFrameOfData* FrameOfData) { CFrrjiftestDlg::sndrobot();  ← ここがコンパイルエラー } void CFrrjiftestDlg::sndrobot() { いろいろ記述 } //*** 以下、ヘッダー class CFrrjiftestDlg : public CDialog { DECLARE_DYNAMIC(CFrrjiftestDlg); friend class CFrrjiftestDlgAutoProxy; // Construction public: CFrrjiftestDlg(CWnd* pParent = NULL); // standard constructor virtual ~CFrrjiftestDlg(); void msubInit(); void sndrobot();   ←ここで宣言 };

  • アンマネージDLLで、ダイアログを表示する方法

    現在、Visual Studio 2005の、Visual C#、C++/CLI、MFCを使ったシステムを構築しています。 具体的には、MFCで書かれた(拡張DLL)でダイアログを表示。これをC++/CLIでラップし、C#から呼び出して使いたいと思っております。 そこで、http://soudan1.biglobe.ne.jp/qa3834982.htmlを参考にして、以下のように作ったのですが、DLL内のdlg.DoModal()のコールで、 AfxGetResourceHandle()でASSERTが発生してしまいます。 //// C#のフォーム using LogGphWrap; namespace DllTestApp { public partial class Form1 : Form { private void button1_Click(object sender, EventArgs e) { Wrapdll.Wrapper.DlgOpen(this.Handle.ToInt32()); } } } //// Wrapdll(CRLのクラスライブラリ) [Wrapdll.h] [DllImport("MFCdll.dll")] bool dspDlg(int hDib); namespace Wrapdll { public ref class Wrapper { public: static bool DlgOpen(int hDib) { return ( dspDlg(hDib) ) ; } }; } //// MFCdll(MFCの拡張DLL) [MFCdll.h] #include "resource.h" bool dspDlg(HWND hDib); //// MFCdll(MFCの拡張DLL) [MFCdll.cpp] extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { :   デフォルトのまま : } bool dspDlg (HWND hDib) { AFX_MANAGE_STATE(AfxGetAppModuleState()); AfxMessageBox(_T("ちょっとお試し"), 0, 0) ;  CTestDlg *dlg = new CTestDlg(CWnd::FromHandle(hDib));  dlg->Create(IDD_DIALOG) ; <====この部分でASSERTが発生!!  return TRUE ; } ご存知の方がいらっしゃれば、ご教授ください。 よろしくお願いします。

  • ウィンドウタイトルの取得方法

    WIN98 MFC vc++6.0 2重起動を防止し、既に起動している時は、ウィンドウを最上位にもってくる以下のコードにて ウィンドウのタイトルを設定しているIDS_WINDOWTITLEはどこで定義し、どうやってタイトルを設定すれば良いのでしょうか? BOOL CMyApp::InitInstance() { 略  // アプリケーションの二重起動防止  ::CreateMutex(NULL, TRUE, m_pszExeName);  if( GetLastError() == ERROR_ALREADY_EXISTS) {   // 既に起動されている場合は、CWnd::FindWindow関数を使って   // 起動されているアプリケーションのウィンドウを取得し、   // そのウィンドウを最上位へ持ってくる   CString str;   str.LoadString(IDS_WINDOWTITLE);   // IDS_WINDOWTITLEにはウィンドウのタイトルを設定している   CWnd* pWnd = CWnd::FindWindow(NULL, str);   if( pWnd )   pWnd->SetForegroundWindow();   return FALSE;  }

専門家に質問してみよう