第199章 リストビューの複数選択項目を知る


さて、前章では新しいスタイルのリストビューについてやりましたが、 実際のプログラミングではチェックされたり、選択されている項目について 知ることが必要になります。この時複数のチェックがあったり、複数のアイテムが 選択されている可能性もあります。



では、どのように選択項目を取得すればよいのでしょうか。

チェックされているかどうかを調べるのはListView_GetCheckStateマクロを使います。

BOOL ListView_GetCheckState( HWND hwndLV, UINT iIndex );

hwndLVはリストビューコントロールのハンドルです。
iIndexはチェック状態を取得するアイテムのインデックスです。
チェックされていると0以外の数値を返します。

ListView_GetNextItemマクロもよく使いますが、これはすでに 第108章で出ています。

int ListView_GetNextItem( HWND hwnd, int iStart, UINT flags );

残念なことにこのマクロではflagsにLVNI_CHECKED というのはありません。 チェックされているかどうかはアイテムを順番に調べていく必要があります。 アイテムの数はListView_GetItemCountマクロで調べることができます。

int ListView_GetItemCount( HWND hwnd );

戻り値がアイテムの数となります。

アイテムからテキストを取得するにはListView_GetItemTextマクロもすでに 第110章で出てきました。

では、プログラムを見てみましょう。

// newlist2.rcの一部 ///////////////////////////////////////////////////////////////////////////// // // Menu // MYMENU MENU DISCARDABLE BEGIN POPUP "ファイル(&F)" BEGIN MENUITEM "終了(&X)", IDM_END END POPUP "データ(&D)" BEGIN MENUITEM "チェックされたデータ(&C)", IDM_CHECK MENUITEM "選択されたアイテム(&S)", IDM_SELECT END END

前章のプログラムにメニューをつけてみました。

// newlist2.cpp #ifndef STRICT #define STRICT #endif #include <windows.h> #include <commctrl.h> #include "resource.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); ATOM InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); HWND MakeMyList(HWND); void InsertMyColumn(HWND); void InsertMyItem(HWND); void CheckMySelect(HWND); void CheckMyCheck(HWND); char szClassName[] = "newlist2"; //ウィンドウクラス HINSTANCE hInst;

前章とほとんど同じですが、いくつかの自作関数が増えました。

int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; hInst = hCurInst; if (!InitApp(hCurInst)) return FALSE; if (!InitInstance(hCurInst, nCmdShow)) return FALSE; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } //ウィンドウ・クラスの登録 ATOM InitApp(HINSTANCE hInst) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; //プロシージャ名 wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst;//インスタンス wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = "MYMENU"; //メニュー名 wc.lpszClassName = (LPCSTR)szClassName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); return (RegisterClassEx(&wc)); } //ウィンドウの生成 BOOL InitInstance(HINSTANCE hInst, int nCmdShow) { HWND hWnd; hWnd = CreateWindow(szClassName, "猫でもわかるListView", //タイトルバーにこの名前が表示されます WS_OVERLAPPEDWINDOW, //ウィンドウの種類 CW_USEDEFAULT, //X座標 CW_USEDEFAULT, //Y座標 CW_USEDEFAULT, //幅 CW_USEDEFAULT, //高さ NULL, //親ウィンドウのハンドル、親を作るときはNULL NULL, //メニューハンドル、クラスメニューを使うときはNULL hInst, //インスタンスハンドル NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; }

前章とほとんど同じですがウィンドウクラスにメニューを設定しました。

//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; INITCOMMONCONTROLSEX ic; static HWND hList; RECT rc; switch (msg) { case WM_CREATE: ic.dwSize = sizeof(INITCOMMONCONTROLSEX); ic.dwICC = ICC_LISTVIEW_CLASSES; InitCommonControlsEx(&ic); hList = MakeMyList(hWnd); InsertMyColumn(hList); InsertMyItem(hList); break; case WM_SIZE: GetClientRect(hWnd, &rc); MoveWindow(hList, 0, 0, rc.right - rc.left, rc.bottom - rc.top, TRUE); break; case WM_COMMAND: switch (LOWORD(wp)) { case IDM_END: SendMessage(hWnd, WM_CLOSE, 0, 0); break; case IDM_SELECT: CheckMySelect(hList); SetFocus(hList); break; case IDM_CHECK: CheckMyCheck(hList); SetFocus(hList); break; } break; case WM_CLOSE: id = MessageBox(hWnd, "終了してもよいですか", "終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { DestroyWindow(hList); DestroyWindow(hWnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }

メニューでIDM_SELECT, IDM_CHECKを選択すると、選択されている項目とか チェックされている項目がメッセージボックスで表示されます。 ここでは、それぞれの目的を達成するための自作関数を呼んでいます。 SetFocus関数でリストビューにフォーカスを戻しておかないと 選択されている項目の色が見えずに、どれが選択されているのか わからなくなります。

HWND MakeMyList(HWND hWnd) { HWND hList; DWORD dwStyle; hList = CreateWindowEx(0, WC_LISTVIEW, "", WS_CHILD | WS_VISIBLE | LVS_REPORT, 0, 0, 0, 0, hWnd, (HMENU)100, hInst, NULL); dwStyle = ListView_GetExtendedListViewStyle(hList); dwStyle |= LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP; ListView_SetExtendedListViewStyle(hList, dwStyle); return hList; } void InsertMyColumn(HWND hList) { LV_COLUMN lvcol; lvcol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; lvcol.fmt = LVCFMT_LEFT; lvcol.cx = 100; lvcol.pszText = "名前"; lvcol.iSubItem = 0; ListView_InsertColumn(hList, 0, &lvcol); lvcol.cx = 50; lvcol.pszText = "性別"; lvcol.iSubItem = 1; ListView_InsertColumn(hList, 1, &lvcol); lvcol.cx = 200; lvcol.pszText = "住所"; lvcol.iSubItem = 2; ListView_InsertColumn(hList, 2, &lvcol); return; } void InsertMyItem(HWND hList) { LV_ITEM item; memset(&item, 0, sizeof(LV_ITEM)); item.mask = LVIF_TEXT; item.pszText = "粂井康孝"; item.iItem = 0; item.iSubItem = 0; ListView_InsertItem(hList, &item); item.pszText = "男"; item.iSubItem = 1; ListView_SetItem(hList, &item); item.pszText = "北海道旭川市"; item.iSubItem = 2; ListView_SetItem(hList, &item); item.pszText = "粂井ひとみ"; item.iItem = 1; item.iSubItem = 0; ListView_InsertItem(hList, &item); item.pszText = "女"; item.iSubItem = 1; ListView_SetItem(hList, &item); item.pszText = "東京都特許許可局"; item.iSubItem = 2; ListView_SetItem(hList, &item); item.pszText = "粂井志麻"; item.iItem = 2; item.iSubItem = 0; ListView_InsertItem(hList, &item); item.pszText = "女"; item.iSubItem = 1; ListView_SetItem(hList, &item); item.pszText = "空知郡妹背牛町"; item.iSubItem = 2; ListView_SetItem(hList, &item); return; }

この3つの関数は前章と全く同じです。

void CheckMySelect(HWND hList) { int nItem = -1; char str[256], name[64], sex[8], address[128]; while ((nItem = ListView_GetNextItem(hList, nItem, LVNI_SELECTED)) != -1) { ListView_GetItemText(hList, nItem, 0, name, sizeof(name)); ListView_GetItemText(hList, nItem, 1, sex, sizeof(sex)); ListView_GetItemText(hList, nItem, 2, address, sizeof(address)); wsprintf(str, "「%s, %s, %s」が選択されています", name, sex, address); MessageBox(hList, str, "OK", MB_OK); } return; }

選択されている項目をメッセージボックスで表示する関数です。
ListView_GetNextItemの使い方は第108章とほぼ同じです。 (このマクロが-1を返すまで繰り返す)

void CheckMyCheck(HWND hList) { int nCount, i; char str[256], name[64], sex[8], address[128]; nCount = ListView_GetItemCount(hList); for (i = 0; i < nCount; i++) { if (ListView_GetCheckState(hList, i) != 0) { ListView_GetItemText(hList, i, 0, name, sizeof(name)); ListView_GetItemText(hList, i, 1, sex, sizeof(sex)); ListView_GetItemText(hList, i, 2, address, sizeof(address)); wsprintf(str, "「%s, %s, %s」にチェックあり", name, sex, address); MessageBox(hList, str, "CHECKED", MB_OK); } } return; }

さて、新しいスタイルのLVS_EX_CHECKBOXESを指定した時、どのアイテムが チェックされているかを知るのにListView_GetNextItemは使えません。 仕方がないので、全アイテム数を調べてそれぞれのアイテムについて ListView_GetCheckStateマクロでチェックされているかどうかを調べています。 アイテム数が少ない場合はこれでよいのかもしれませんが、大量にある時は ちょっと問題です。もっとよい方法が他にあるのかもしれません。あるいは 将来ListView_GetNextItemマクロがバージョンアップされるのかもしれません。

今回もあんまり目新しいことはやりませんでした。


[SDK第2部 Index] [総合Index] [Previous Chapter] [Next Chapter]

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