概要

コンボボックスのサンプルです。
コンボボックスの選択状態が変化するとリアルタイムにラベルに反映されます。
OKボタンをクリックするとコンボボックスで選択されている文字列をメッセージボックスを表示し、メッセージボックスのOKをクリックするとプログラムが終了します。
キャンセルボタンをクリックするとプログラムが終了します。
ダイアログボックスはリソースファイル(resource.rc)で定義しています。
コンボボックスは、ダイアログボックスの子ウィンドウです。

コンボボックスの属性はリソースファイルで定義しております。

 CONTROL "", IDC_COMBOBOX, "COMBOBOX", WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_DROPDOWNLIST, 7, 7, 115, 100
コンボボックスは、エディットボックスとリストボックスで構成されています。
コンボボックスの根幹にかかわるスタイルですが、以下の3つがあります。CBS_DROPDOWNとCBS_DROPDOWNLISTの違いは、CBS_DROPDOWNLISTはエディットボックスで文字列の編集が不可能な点です。
CBS_SIMPLE CBS_DROPDOWN CBS_DROPDOWNLIST

    ↓

    ↓
上記の他に以下の属性が使用可能です。複数の属性を適用するにはOR演算子 | を使用します。

CBS_SORT アイテムを自動ソート

コンボボックスへのメッセージ

コンボボックスへのメッセージは以下のようなものがあります。
hWndはコンボボックスのハンドル

アイテムを末尾に追加する。(ソートは指定してはいけない)

SendMessage(hWnd, CB_ADDSTRING, 0, _TEXT("文字列"));

アイテムをインデックスを指定して追加

SendMessage(hWnd, CB_INSERTSTRING, index, _TEXT("文字列"));

インデックスで指定されるアイテムを削除

SendMessage(hWnd, CB_DELETESTRING, index, 0);

アイテム数を取得

SendMessage(hWnd, CB_GETCOUNT, 0, 0);

選択されているアイテムのインデックスを取得 選択されていないときはCB_ERRを返す

SendMessage(hWnd, CB_GETCURSEL, 0, 0);
アイテムが編集されているときはエラーが返る。

インデックスを指定してアイテムを選択 -1を指定すると非選択状態にできる

SendMessage(hWnd, CB_SETCURSEL, index, 0);

インデックスを指定してアイテムの文字数を取得する

SendMessage(hWnd, CB_GETLBTEXTLEN, index, 0);
編集されている文字列や選択されている文字列を取得するには単純にGetWindowText APIが使える。

インデックスを指定してアイテムの文字列を取得

SendMessage(hWnd, CB_GETLBTEXT, index,(LPARAM) buf);

ドロップダウンリストを表示する

SendMessage(hWnd, CB_SHOWDROPDOWN, 0, 0);

テスト環境

コンパイラ

Visual C++ 2008 Standard 32/64bit
Visual C++ 2013 Express 32/64bit

実行環境

Windows 8.1 Enterprise 64bit
Windows 7 EnterPrise Service Pack 1 64bit
Windows Vista Ultimate Service Pack 2 32bit
Windows XP Professional Service Pack 3 32bit

プログラムソースの概要

editbox.cpp

_tWinMain

DialogBox APIを呼び出してモーダルダイアログボックスを表示します。

DlgProc1(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)

ダイアログボックスプロシージャーです。
必要な時にWindowsから呼び出されます。
第2引数にメッセージの種類が格納されていますので、switchステートメントによりメッセージごとの処理を振り分けます。
コントロールダイアログボックスに張り付けられているコンボボックスやプッシュボタン等 コントロールと呼ぶ)を操作するには、コントロールのハンドルが必要です。 ダイアログボックスのコントロール(子ウィンドウ)のハンドルを取得するには、 GetDlgItem APIを呼び出し、ダイアログボックスのハンドルとコントロールのID番号よりハンドルを取得します。
自分で処理しないメッセージは、ダイアログボックスプロシージャー終了時にFALSEを渡せば、Windowsが標準的な処理を行ってくれます。
case WM_INITDIALOG:
ダイアログボックスの初期化時に発生するメッセージです。
ここでは、コンボボックスのアイテムを設定します。
SendMessage APIを呼び出しCB_INSERTSTRINGメッセージによりアイテムを追加します。
case WM_COMMAND:
ダイアログボックスの子ウィンドウ(ダイアログボックスに張り付けられているコントロールボックスやプッシュボタン等)から発生したメッセージが届きます。
ダイアログボックスプロシージャーの第3引数であるWPARAMの下位16bitがコントロールのID番号、その上位16bitには通知内容が格納されています。
LOWORDマクロによりWPARAMの下位16bitを取り出し、switchステートメントによりコントロールごとに処理を振り分けます。
case IDC_COMBOBOX:
コンボボックスのID番号がIDC_COMBOBOXです。
コンボボックスからのメッセージが届きます。
ここではコンボボックスの選択項目が変更したときに発生するCBN_SELCHANGEメッセージを処理します。
他に以下のようなメッセージがあります。

CBN_DROPDOWN  ドロップダウンリストが開いた 
CBN_CLOSEUP  ドロップダウンリストが閉じられた 
CBN_SELCHANGE  選択項目が変更された 
CBN_EDITUPDATE  直接入力で内容が変更された 変更内容が表示される前に呼ばれる
CBN_EDITCHANGE  直接入力で内容が変更された 変更内容が表示された後に呼ばれる
HIWORDマクロによりWPARAMの31~16bitの値を取り出し、ifステートメントによりCBN_SELCHANGEの時 SendMessage APIを呼び出し、CB_GETCURSELメッセージにより選択されているアイテムのインデックスを取得します。
インデックスを元に配列より文字列を取り出しSetWindowText APIによりラベルに表示します。
case IDOK:
OKプッシュボタンのID番号がIDOKです。
OKプッシュボタンをクリックするとこのメッセージが発生します。
SendMessage APIを呼び出し、CB_GETCURSELメッセージにより選択されているアイテムのインデックスを取得します。
先ほどは、配列より文字列を取り出しましたが、ここでは、コンボボックス自身から取得します。アイテムを自動ソートしていないので結果は同じです。
SendMessage APIを呼び出し、CB_GETLETEXTLENメッセージによりインデックスで指定するアイテムの文字数を取得します。
文字数が格納する配列を大きさを超えていないか確認し、 SendMessage APIを呼び出し、CB_GETLETEXTメッセージによりインデックスで指定するアイテムの文字列を取得します。
もし文字数が配列の大きさを超えている場合は、動的にメモリを確保する必要があります。
MessageBox APIを呼び出し、取得した文字列を表示します。
EndDialog APIを呼び出し、ダイアログボックスを終了させます。 このAPIの第2引数は、ダイアログボックスが終了し、DialogBox APIが返す値となります。
case IDCANCEL:
キャンセルプッシュボタンのID番号がIDCANCELKです。
キャンセルプッシュボタンをクリックするとこのメッセージが発生します。
EndDialog APIを呼び出し、ダイアログボックスを終了させます。 このAPIの第2引数は、ダイアログボックスが終了し、DialogBox APIが返す値となります。

resource.h

ダイアログボックスで使用する各コントロールのID値をマクロで定義しています。

resource.rc

ダイアログボックスやコントロールの定義をしています。

プログラムソース

editbox.cpp


//      コンボボックスサンプル
//      Visual C++ 2013 32/64bit

#include <windows.h>
#include <commctrl.h>
#include <tchar.h>
#include "resource.h"


TCHAR* str[]={ TEXT("ロシアンブルー"),TEXT("アメリカンハースキー"),  TEXT("三毛"),0 };

//      ダイアログボックスプロシージャー
LRESULT CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);

int WINAPI _tWinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, TCHAR* lpsCmdLine, int nCmdShow){
        DialogBox(hCurInst, TEXT("DLG1"), 0, (DLGPROC)DlgProc);
        return (int)0;
}


//      ダイアログボックスプロシージャー

LRESULT CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam){
        TCHAR buf[32],buf2[32];
        int num,len;
    switch (msg) {
        case WM_INITDIALOG:
                        num=0;
                        while(str[num]){
                                SendMessage(GetDlgItem(hDlg,IDC_COMBOBOX),CB_INSERTSTRING,num,(LPARAM)str[num]);        //コンボボックスにアイテムの設定
                                ++num;
                        }
                        SendMessage(GetDlgItem(hDlg,IDC_COMBOBOX),CB_SETCURSEL,0,(LPARAM)0);    //      初期時に選択されるアイテムを選択
                        return TRUE;
        case WM_COMMAND:
            switch (LOWORD(wParam)) {
                                case IDC_COMBOBOX:
                                        if (HIWORD(wParam) == CBN_SELCHANGE){   //      コンボボックスのアイテムが選択されたときに呼び出される
                                                num = (int)SendMessage(GetDlgItem(hDlg, IDC_COMBOBOX), CB_GETCURSEL, 0, 0);     //      カーソル位置のアイテムを取得
                                                _stprintf_s(buf, sizeof(buf) / sizeof(TCHAR), TEXT("%i番目[%s]"), num, str[num]);
                                                SetWindowText(GetDlgItem(hDlg, IDC_LABEL), buf);
                                        }
                                        break;
                                case IDOK:
                                        num=(int)SendMessage(GetDlgItem(hDlg,IDC_COMBOBOX),CB_GETCURSEL,0,0);   //      カーソル位置のアイテムを取得
                                        len = (int)SendMessage(GetDlgItem(hDlg, IDC_COMBOBOX), CB_GETLBTEXTLEN, num,0);
                                        if (len < sizeof(buf) / sizeof(TCHAR)){
                                                SendMessage(GetDlgItem(hDlg, IDC_COMBOBOX), CB_GETLBTEXT, num,(LPARAM)buf2);
                                                _stprintf_s(buf, sizeof(buf) / sizeof(TCHAR), TEXT("%i番目[%s]"), num,buf2);
                                                MessageBox(hDlg, buf, TEXT("選ばれたアイテム"), MB_OK);
                                        }
                                        EndDialog(hDlg, TRUE);
                                        return TRUE;
                                case IDCANCEL:
                                        EndDialog(hDlg,FALSE);
                                        return FALSE;
                                default:
                                        return FALSE;
                        }
                        default:
                                return FALSE;
        }
        return TRUE;
}

resource.h


#define IDC_COMBOBOX 100
#define IDC_LABEL       110

resource.rc


#include <windows.h>
#include "resource.h"

DLG1 DIALOG DISCARDABLE 0, 0, 129, 85
EXSTYLE WS_EX_DLGMODALFRAME
STYLE WS_POPUP  | WS_CAPTION | WS_SYSMENU |  DS_SETFONT
CAPTION "コンボボックス"
FONT 9, "MS Shell Dlg"
{
 CONTROL "", IDC_COMBOBOX, "COMBOBOX", WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_DROPDOWNLIST, 7, 7, 115, 100
 LTEXT                  "", IDC_LABEL, 7, 50, 115, 14

 CONTROL "OK", IDOK, "BUTTON", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 7, 64, 54, 14
 CONTROL "キャンセル", IDCANCEL, "BUTTON", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 68, 64, 54, 14
}

ソースファイルと実行ファイルのダウンロード

ダウンロード combobox.zip(40.9kByte)

ZIPファイルに含まれるファイル

combobox.cpp
combobox.exe
resource.h
resource.rc