第13章 ダイアログボックスとのデータのやりとり


今回は、親ウィンドウ側にだけデータメンバを持たせて ダイアログボックスとのやりとりをする方法を考えます。 また、前章のプログラムではダイアログボックスが表示されたとき に入力項目には全く何も記入されていません。前回入力した テキストなどが表示されていると便利なこともあります。 また、新たなボタンも付けてみます。


親ウィンドウのクライアント領域を左クリックすると 左の図のようなダイアログボックスが出現します。 エジットフィールドには前回入力した文字列が表示されます。 全部消去して新たに入力し直すときは「クリア」ボタンを 押します。


前回までは、親ウィンドウとダイアログボックスの両方に データメンバを持たせていました。今回は親だけに持たせます。 ダイアログボックスの法からもこのデータを見たり、書いたりするので 当然publicになります。

// dlg03.rcの一部 ///////////////////////////////////////////////////////////////////////////// // // Dialog // MYDLG DIALOG DISCARDABLE 0, 0, 127, 67 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "テキスト入力" FONT 9, "MS Pゴシック" BEGIN DEFPUSHBUTTON "OK",IDOK,7,46,26,14 PUSHBUTTON "キャンセル",IDCANCEL,52,46,26,14 EDITTEXT IDC_EDIT1,7,7,113,30,ES_AUTOHSCROLL PUSHBUTTON "クリア",IDC_CLEAR,97,46,26,14 END

今回のリソース・スクリプトはシンプルです。

// dlg03.h class CMyApp : public CWinApp { public: virtual BOOL InitInstance(); }; class CMyWindow : public CFrameWnd { public: CMyWindow(); CString str; protected: afx_msg void OnPaint(); afx_msg void OnClose(); afx_msg void OnLButtonDown(UINT, CPoint); DECLARE_MESSAGE_MAP() }; class CMyDlg : public CDialog { public: CMyDlg(CWnd *pParentWnd = NULL) : CDialog("MYDLG", pParentWnd) {} protected: virtual void OnOK(); virtual BOOL OnInitDialog(); void OnClear(); DECLARE_MESSAGE_MAP() };

ダイアログボックスに入力されたテキストはCMyWindowのstrです。 また、今回は自作の「クリア」ボタンが押されたときの処理 をするOnClear()関数を記述するので、CMyDlgクラスにも DECLARE_MESSAGE_MAP()が必要です。さらに、ダイアログボックスの 初期化関数もオーバーライドします。

// dlg03.cpp #include <afxwin.h> #include "dlg03.h" #include "resource.h" CMyApp myApp; BOOL CMyApp::InitInstance() { m_pMainWnd = new CMyWindow; m_pMainWnd->ShowWindow(m_nCmdShow); m_pMainWnd->UpdateWindow(); return TRUE; }

これは、いつもと同じです。

BEGIN_MESSAGE_MAP(CMyWindow, CFrameWnd) ON_WM_PAINT() ON_WM_CLOSE() ON_WM_LBUTTONDOWN() END_MESSAGE_MAP() CMyWindow::CMyWindow() { Create(NULL, "猫でもわかる"); } void CMyWindow::OnPaint() { CPaintDC dc(this); dc.TextOut(0, 0, str); } void CMyWindow::OnClose() { int id; id = MessageBox("終了しますか", "終了の確認", MB_OKCANCEL | MB_ICONQUESTION); if (id == IDOK) CWnd::OnClose(); } void CMyWindow::OnLButtonDown(UINT nFlags, CPoint pt) { CMyDlg dlg(this); if(dlg.DoModal() == IDOK) Invalidate(); }

ダイアログボックスで「OK」ボタンが押されたときはInvalidate()関数を 実行しているだけです。ダイアログボックス側でデータ処理をしています。

BEGIN_MESSAGE_MAP(CMyDlg, CDialog) ON_COMMAND(IDC_CLEAR, OnClear) END_MESSAGE_MAP() BOOL CMyDlg::OnInitDialog() { CDialog::OnInitDialog(); CMyWindow *pParent; CEdit *pEdit; pParent = (CMyWindow *)GetParent(); pEdit = (CEdit *)GetDlgItem(IDC_EDIT1); pEdit->SetWindowText(pParent->str); return TRUE; } void CMyDlg::OnOK() { CEdit *pStr; CMyWindow *pParent; pParent = (CMyWindow *)GetParent(); pStr = (CEdit *)GetDlgItem(IDC_EDIT1); pStr->GetWindowText(pParent->str); CDialog::OnOK(); } void CMyDlg::OnClear() { CEdit *pEdit; pEdit = (CEdit *)GetDlgItem(IDC_EDIT1); pEdit->SetWindowText(""); }

前回はダイアログボックスのエジットコントロールから テキストを取得するのはGetDlgItemText関数を使っていました。 今回はまずGetDlgItemでエジットコントロール(子ウィンドウ) へのポインタを取得してGetWindowText関数でテキストを取得しています。

CWnd* GetDlgItem( int nID ) const;

これで指定されたIDへのポインタを取得できます。

int GetWindowText( LPTSTR lpszStringBuf, int nMaxCount ) const; void GetWindowText( CString& rString ) const;

これでコントロールからテキストを取得できます。ウィンドウの場合は タイトルが取得できます。SetWindowTextについてはすでに 第4章で出てきました。

さて、ダイアログボックスで「OK」ボタンが押されたとき どのように親ウィンドウのデータメンバにコントロールのテキストを コピーしているのかというと、実に簡単です。まず親ウィンドウの ポインタを調べます。

CWnd::GetParent CWnd* GetParent( ) const;

これで親のウィンドウのポインタが取得できます。 親ウィンドウのポインタ(pParent)がわかったらpParent->m_data というように親のデータメンバにアクセスできます。 しかし、このポインタを保存しておいてあとから使おうとしてはいけません。 その都度取得する必要があります。

ダイアログボックスの初期化はOnInitDialogで行います。 ここで、前回のデータを初期値としてコントロールに表示します。 ここでは、この関数の最初のところで本来のCDialog::OnInitDialog(); を呼んでいる点に注意してください。CDialog::OnOK()の時とは 呼ぶ順番が逆です。


[MFC Index] [総合Index] [Previous Chapter] [Next Chapter]

Update 06/May/1998 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。