第14章 リストボックスとコンボボックス


今回は、前回やらなかったリストボックスとコンボボックスに ついてやります。基本的なことは全く同じです。
一番上がエジットコントロール、次がコンボボックス、一番下がリストボックスです。 前回入力があればその入力が表示されます。 「OK」ボタンを押すと今入力した事項が親ウィンドウに表示されます。


では、早速プログラムを見てみます。

// dlg04.rcの一部 ///////////////////////////////////////////////////////////////////////////// // // Dialog // MYDLG DIALOG DISCARDABLE 0, 0, 215, 93 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "入力用ダイアログ" FONT 9, "MS Pゴシック" BEGIN EDITTEXT IDC_EDIT1,55,7,97,17,ES_AUTOHSCROLL COMBOBOX IDC_COMBO1,55,33,97,53,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP LISTBOX IDC_LIST1,55,55,97,31,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP DEFPUSHBUTTON "OK",IDOK,158,7,50,14 PUSHBUTTON "キャンセル",IDCANCEL,158,28,50,14 PUSHBUTTON "氏名欄クリア",IDC_CLEAR,158,49,50,14 LTEXT "氏名:",IDC_STATIC,15,7,18,8 LTEXT "本籍地:",IDC_STATIC,15,33,25,8 LTEXT "ペット:",IDC_STATIC,15,57,20,8 END ///////////////////////////////////////////////////////////////////////////// // // Menu // MYMENU MENU DISCARDABLE BEGIN POPUP "ファイル(&F)" BEGIN MENUITEM "終了(&X)", IDM_END END POPUP "オプション(&O)" BEGIN MENUITEM "ダイアログ(&D)", IDM_DLG END END

これは、普通のリソース・スクリプトです。

// dlg04.h class CMyApp : public CWinApp { public: virtual BOOL InitInstance(); }; class CMyWindow : public CFrameWnd { public: CMyWindow(); CString str; CString ListStr; CString ComboStr; protected: afx_msg void OnPaint(); afx_msg void OnClose(); afx_msg void OnEnd(); afx_msg void OnDlg(); 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, ListStr, ComboStrなどの 表示用メンバを持たせます。前回同様CMyDlgクラスにはこのような メンバはありません。

// dlg04.cpp #include <afxwin.h> #include "dlg04.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_COMMAND(IDM_END, OnEnd) ON_COMMAND(IDM_DLG, OnDlg) END_MESSAGE_MAP() CMyWindow::CMyWindow() { Create(NULL, "猫でもわかるダイアログ", WS_OVERLAPPEDWINDOW, CRect(100, 100, 100 + 222, 100 + 106), NULL, "MYMENU"); }

222*106の大きさで親ウィンドウを作ります。 また、"MYMENU"メニューを付けます。

void CMyWindow::OnEnd() { SendMessage(WM_CLOSE); }

メニューから「終了」が選択されたときの処理です。

void CMyWindow::OnDlg() { CMyDlg dlg(this); if(dlg.DoModal() == IDOK) Invalidate(); }

メニューの「ダイアログ」が選択されたときの処理です。 ダイアログボックスを表示します。

void CMyWindow::OnPaint() { CPaintDC dc(this); CString MyStr; MyStr.Format("氏 名=%s", str); dc.TextOut(0, 0, MyStr); MyStr.Format("本籍地=%s", ComboStr); dc.TextOut(0, 20, MyStr); MyStr.Format("ペット=%s", ListStr); dc.TextOut(0, 40, MyStr); }

WM_PAINメッセージが来たときの処理です。 Format()については第12章を参照してください。

void CMyWindow::OnClose() { int id; id = MessageBox("終了しますか", "終了の確認", MB_OKCANCEL | MB_ICONQUESTION); if (id == IDOK) CWnd::OnClose(); }

WM_CLOSEメッセージが来たときの処理です。 CWnd::OnClose()をオーバーライドしているので最後に本家本元の OnClose()を呼んでいることに注意してください。

BEGIN_MESSAGE_MAP(CMyDlg, CDialog) ON_COMMAND(IDC_CLEAR, OnClear) END_MESSAGE_MAP() BOOL CMyDlg::OnInitDialog() { CDialog::OnInitDialog(); CMyWindow *pParent; CEdit *pEdit; CComboBox *pCombo; CListBox *pList; pCombo = (CComboBox *)GetDlgItem(IDC_COMBO1); pCombo->AddString("北海道"); pCombo->AddString("本州"); pCombo->AddString("四国"); pCombo->AddString("九州"); pList = (CListBox *)GetDlgItem(IDC_LIST1); pList->AddString("猫"); pList->AddString("犬"); pList->AddString("ネズミ"); pList->AddString("鳥"); pList->AddString("ウサギ"); //前回の入力や設定を再現 pParent = (CMyWindow *)GetParent(); pEdit = (CEdit *)GetDlgItem(IDC_EDIT1); pEdit->SetWindowText(pParent->str); pCombo->SetCurSel(pCombo->FindStringExact(0, pParent->ComboStr)); pList->SetCurSel(pList->FindStringExact(0, pParent->ListStr)); return TRUE; }

ダイアログボックスの初期設定です。単にリストボックスやらコンボボックスを 作っても項目は何も表示されません。ここでAddString()で文字列を追加します。

CComboBox::AddString int AddString( LPCTSTR lpszString );

コンボボックスに文字列を追加します。

CListBox::AddString int AddString( LPCTSTR lpszItem );

リストボックスに文字列を追加します。 戻り値はどちらもリスト内での0から始まるインデックスを返します。

さて、文字列を追加したら前回の入力を表示した方が 親切です。前回の表示はCMyWindowのstr, ComboStr, ListStrに格納されて いるので、これを使います。 エジットコントロールの場合はそのまま使えばよいのですが リストボックスやコンボボックスの場合はその文字列のインデックスを 知らないといけないのでFindStringExact関数で調べています。 そして、インデックスがわかったらSetCurSel関数で表示します。

CComboBox::FindStringExact int FindStringExact( int nIndexStart, LPCTSTR lpszFind ) const;

lpszFindに見つけたい文字列を指定します。
nInsexStartは何番のインデックスから調べるかを指定します。 最初から調べたいのなら0を指定します。
戻り値は検索の結果(インデックス番号)です。

CListBox::FindStringExact int FindStringExact( int nIndexStart, LPCTSTR lpszFind ) const;

これも使い方は全く同じです。

CComboBox::SetCurSel int SetCurSel( int nSelect );

nSelectに選択させたいインデックス番号を指定します。 CListBox::SetCurSel()も同じです。

void CMyDlg::OnOK() { CEdit *pStr; CMyWindow *pParent; CListBox *pList; CComboBox *pCombo; int index; pParent = (CMyWindow *)GetParent(); pStr = (CEdit *)GetDlgItem(IDC_EDIT1); pStr->GetWindowText(pParent->str); pList = (CListBox *)GetDlgItem(IDC_LIST1); index = pList->GetCurSel(); pList->GetText(index, pParent->ListStr); pCombo = (CComboBox *)GetDlgItem(IDC_COMBO1); index = pCombo->GetCurSel(); pCombo->GetLBText(index, pParent->ComboStr); CDialog::OnOK(); }

ダイアログボックスで「OK」ボタンが押されたときの処理です。 まず親のウィンドウのポインタを取得しておきます。これは、 親のメンバに直接文字列をコピーするので必要です。

CComboBox::GetCurSel int GetCurSel( ) const;

コンボボックスの現在選択されている項目のインデックスを 返します。

CListBox::GetCurSel int GetCurSel( ) const;

リストボックスで現在選択されている項目のインデックスを 返します。

CListBox::GetText int GetText( int nIndex, LPTSTR lpszBuffer ) const; void GetText( int nIndex, CString& rString ) const;

リストボックスのnIndexで指定された文字列を取得します。 Cstringオブジェクトでも受け取ることができます。

注意すべき点はCComboBox::GetTextというのはないという点です。 かわりに、

CComboBox::GetLBText int GetLBText( int nIndex, LPTSTR lpszText ) const; void GetLBText( int nIndex, CString& rString ) const;

を使います。使い方はリストボックスの時と同じです。

最後に本家本元のCDialog::OnOK()を呼んでダイアログボックスを 閉じます。

void CMyDlg::OnClear() { CEdit *pEdit; pEdit = (CEdit *)GetDlgItem(IDC_EDIT1); pEdit->SetWindowText(""); }

「指名欄クリア」ボタンを押したときの処理です。
[MFC Index] [総合Index] [Previous Chapter]

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