リストボックス

リストボックスコントロールは、多数のデータをリスト形式で一覧表示できるコントロールです。

コントロールの作成の基本的なことはボタンコントロールの項を参照してください。

リストボックスの作成

リストボックスはLISTBOXクラスで作成します。


#include <windows.h>

//ウィンドウの生成等は省略

#define IDC_LIST1 1000

//ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	HWND hList;

	//リストボックスに表示するアイテム
	static const WCHAR* items[] = {
		L"dog",
		L"cat",
		L"rabbit",
		L"fox",
		L"monkey",
		L"hamster"
	};

	switch (message)
	{
	case WM_CREATE: //ウィンドウ作成
		//リストボックスの作成
		hList = CreateWindowEx(
			WS_EX_CLIENTEDGE,
			L"LISTBOX", NULL,
			WS_CHILD | WS_VISIBLE | WS_VSCROLL,
			10, 10, 280, 100,
			hWnd, (HMENU)IDC_LIST1, hInst, NULL);

		//リストボックスにアイテムを追加
		for (int i = 0; i < sizeof(items) / sizeof(items[0]); i++)
		{
			SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)items[i]);
		}
		break;

	case WM_DESTROY: //ウィンドウの破棄
		PostQuitMessage(0);
		break;

	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

リストボックスを作成しただけでは中身が空っぽなので、項目(アイテムと呼ぶ)を追加しています。
表示された項目をクリックすると選択状態になります。
リストボックスの作成

ウィンドウスタイルにはWS_VSCROLLを指定して垂直スクロールバーを表示しています。
また、拡張スタイルを使用して立体的な枠線(WS_EX_CLIENTEDGE)を表示しています。
(→CreateWindowEx関数)
ただの平面な枠線でも良い場合はWS_BORDERスタイルを使用します。

リストボックスの操作

リストボックスの操作はSendMessage関数で行います。
メッセージはたくさんありますが、まずは基本的な操作を説明します。

アイテムの追加

アイテムの追加はLB_ADDSTRINGメッセージを使用します。

WPARAMは使用しません。
LPARAMは追加したい文字列を指定します。
戻り値は追加された位置を示す整数値です。
エラーが発生した場合はLB_ERR(-1)、またはLB_ERRSPACE(-2)が返されます。
(0未満ならエラー)

リストボックスのアイテムは上から順に0から始まるインデックス(位置情報)を持っています。
一番上の項目のインデックスは0、次の項目は1…といった具合です。
このインデックスを使用して操作対象のアイテムを選択します。

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

LB_ADDSTRINGメッセージはリストボックスの末尾にアイテムを追加しますが、任意の位置に追加(挿入)したい場合はLB_INSERTSTRINGメッセージを使用します。

WPARAMは追加したい位置を示すインデックスです。
LPARAMは追加したい文字列を指定します。
戻り値は追加された位置を示す整数値です。

インデックスに-1を指定すると末尾に追加されます。

選択中のアイテムのインデックス取得

現在選択中のアイテムのインデックスを取得するにはLB_GETCURSELメッセージを使用します。

WPARAMLPARAMは共に使用しません。
戻り値は選択中のアイテムのインデックスです。
選択中のアイテムがない場合はLB_ERRが返されます。

インデックスでアイテムを選択

インデックスを指定してアイテムを選択するにはLB_SETCURSELメッセージを使用します。

WPARAMは選択するアイテムのインデックスを指定します。
LPARAMは使用しません。
戻り値は選択アイテムのインデックスです。
存在しないインデックスを指定した場合はLB_ERRが返されます。

WPARAMに-1を指定すると全ての選択状態が解除されます。
この時の戻り値はLB_ERRです。

インデックスでアイテムを削除

インデックスを指定してアイテムを削除するにはLB_DELETESTRINGメッセージを使用します。

WPARAMは削除するアイテムのインデックスを指定します。
LPARAMは使用しません。
戻り値はリストに残っているアイテムの数です。
存在しないインデックスを指定した場合はLB_ERRが返されます。

リストをクリア

アイテムをすべて削除するにはLB_RESETCONTENTメッセージを使用します。

WPARAMLPARAM共に使用しません。
戻り値はありません。

アイテム数の取得

アイテム数を取得するにはLB_GETCOUNTメッセージを使用します。

WPARAMLPARAM共に使用しません。
戻り値はアイテム数です。
エラーが発生した場合はLB_ERRが返されます。

サンプルコード

ここまでのメッセージを使用したサンプルコードです。


#include <windows.h>

//ウィンドウの生成等は省略

#define IDC_LIST1 1000
#define IDC_EDIT1 100
#define IDC_BUTTON_ADD 200
#define IDC_BUTTON_INS 201
#define IDC_BUTTON_DEL 202
#define IDC_BUTTON_CLR 203
#define IDC_BUTTON_DESEL 204

#define STR_LENGTH 256

//ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static HWND hList, hEdit;
	WCHAR buf[STR_LENGTH];
	int index;

	switch (message)
	{
	case WM_CREATE: //ウィンドウ作成
		//リストボックスの作成
		hList = CreateWindowEx(
			WS_EX_CLIENTEDGE,
			L"LISTBOX", NULL,
			WS_CHILD | WS_VISIBLE | WS_VSCROLL,
			10, 10, 280, 100,
			hWnd, (HMENU)IDC_LIST1, hInst, NULL);

		hEdit = CreateWindowEx(
			WS_EX_CLIENTEDGE,
			L"EDIT", NULL,
			WS_CHILD | WS_VISIBLE,
			10, 115, 280, 25,
			hWnd, (HMENU)IDC_EDIT1, hInst, NULL);

		CreateWindow(
			L"BUTTON", L"Add",
			WS_CHILD | WS_VISIBLE,
			10, 140, 70, 25,
			hWnd, (HMENU)IDC_BUTTON_ADD, hInst, NULL);
		CreateWindow(
			L"BUTTON", L"Insert",
			WS_CHILD | WS_VISIBLE,
			80, 140, 70, 25,
			hWnd, (HMENU)IDC_BUTTON_INS, hInst, NULL);
		CreateWindow(
			L"BUTTON", L"Delete",
			WS_CHILD | WS_VISIBLE,
			150, 140, 70, 25,
			hWnd, (HMENU)IDC_BUTTON_DEL, hInst, NULL);
		CreateWindow(
			L"BUTTON", L"Clear",
			WS_CHILD | WS_VISIBLE,
			220, 140, 70, 25,
			hWnd, (HMENU)IDC_BUTTON_CLR, hInst, NULL);
		break;

	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case IDC_BUTTON_ADD: //アイテムを末尾に追加
			SendMessage(hEdit, WM_GETTEXT, STR_LENGTH, (LPARAM)buf);
			if (lstrlen(buf) == 0) //空文字は無視
				break;
			SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)buf);
			break;
		case IDC_BUTTON_INS: //アイテムを選択中のアイテムの次に追加
			SendMessage(hEdit, WM_GETTEXT, STR_LENGTH, (LPARAM)buf);
			if (lstrlen(buf) == 0) //空文字は無視
				break;
			index = SendMessage(hList, LB_GETCURSEL, 0, 0);
			if (index < 0) {
				SendMessage(hList, LB_INSERTSTRING, index, (LPARAM)buf);
				index = SendMessage(hList, LB_GETCOUNT, 0, 0);
				SendMessage(hList, LB_SETCURSEL, index - 1, 0);
			}				
			else {
				SendMessage(hList, LB_INSERTSTRING, index + 1, (LPARAM)buf);
				SendMessage(hList, LB_SETCURSEL, index + 1, 0);
			}
			break;
		case IDC_BUTTON_DEL: //選択アイテムを削除
			index = SendMessage(hList, LB_GETCURSEL, 0, 0);
			if (index < 0)
				break;
			if (SendMessage(hList, LB_DELETESTRING, index, 0) > 0) {
				//アイテムが残っている場合は次のアイテムを選択
				SendMessage(hList, LB_SETCURSEL, index, 0);
			}
			break;
		case IDC_BUTTON_CLR: //アイテムを全てクリア
			SendMessage(hList, LB_RESETCONTENT, 0, (LPARAM)buf);
			break;
		}
		break;

	case WM_DESTROY: //ウィンドウの破棄
		PostQuitMessage(0);
		break;

	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

このコードはエディットコントロールに入力した文字列をリストボックスのアイテムに追加できます。
選択位置の次に挿入、削除、クリアの機能もあります。
リストボックスのサンプル