親ウィンドウのクライアント領域を左クリックすると
左の図のようなダイアログボックスが出現します。
エジットフィールドには前回入力した文字列が表示されます。
全部消去して新たに入力し直すときは「クリア」ボタンを
押します。
前回までは、親ウィンドウとダイアログボックスの両方に
データメンバを持たせていました。今回は親だけに持たせます。
ダイアログボックスの法からもこのデータを見たり、書いたりするので
当然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
ダイアログボックスに入力されたテキストはCMyWindowのstrです。 また、今回は自作の「クリア」ボタンが押されたときの処理 をするOnClear()関数を記述するので、CMyDlgクラスにも DECLARE_MESSAGE_MAP()が必要です。さらに、ダイアログボックスの 初期化関数もオーバーライドします。// 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() };
これは、いつもと同じです。// 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; }
ダイアログボックスで「OK」ボタンが押されたときはInvalidate()関数を 実行しているだけです。ダイアログボックス側でデータ処理をしています。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(); }
前回はダイアログボックスのエジットコントロールから テキストを取得するのはGetDlgItemText関数を使っていました。 今回はまずGetDlgItemでエジットコントロール(子ウィンドウ) へのポインタを取得してGetWindowText関数でテキストを取得しています。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(""); }
これで指定されたIDへのポインタを取得できます。CWnd* GetDlgItem( int nID ) const;
これでコントロールからテキストを取得できます。ウィンドウの場合は タイトルが取得できます。SetWindowTextについてはすでに 第4章で出てきました。int GetWindowText( LPTSTR lpszStringBuf, int nMaxCount ) const; void GetWindowText( CString& rString ) const;
さて、ダイアログボックスで「OK」ボタンが押されたとき どのように親ウィンドウのデータメンバにコントロールのテキストを コピーしているのかというと、実に簡単です。まず親ウィンドウの ポインタを調べます。
これで親のウィンドウのポインタが取得できます。 親ウィンドウのポインタ(pParent)がわかったらpParent->m_data というように親のデータメンバにアクセスできます。 しかし、このポインタを保存しておいてあとから使おうとしてはいけません。 その都度取得する必要があります。CWnd::GetParent CWnd* GetParent( ) const;
ダイアログボックスの初期化はOnInitDialogで行います。 ここで、前回のデータを初期値としてコントロールに表示します。 ここでは、この関数の最初のところで本来のCDialog::OnInitDialog(); を呼んでいる点に注意してください。CDialog::OnOK()の時とは 呼ぶ順番が逆です。
Update 06/May/1998 By Y.Kumei