リストデータの取得

リストビュー1 リストビュー2

今回は、リストビューをダブルクリック(もしくは、リストを選択)すると、そのデータを取得して、 ダイアログを表示するようにします。

リストビュー1 - インコのWindowsSDK で作成したソースを修正します。

流れ

WM_NOTIFY

WM_NOTIFYメッセージを取得します。

項目を選択したときに発生する LVN_ITEMCHANGEDメッセージか、 項目をダブルクリックしたときに発生する NM_DBLCLKメッセージ を取得します。

1.GetCursorPos()マウスカーソルの位置を取得

BOOL GetCursorPos(
    LPPOINT lpPoint   // カーソルの位置
);

LV_HITTESTINFO構造体のメンバptにカーソルの位置が格納されています。

typedef struct tagLVHITTESTINFO{
    POINT pt;       // カーソルの位置
    UINT flags;
    int iItem;      // アイテム
    int iSubItem;   // サブアイテム
} LVHITTESTINFO, FAR* LPLVHITTESTINFO;


flagsデータを取得できる場所
LVHT_ONITEMICONリストビューアイコンの上
LVHT_ONITEMLABELリストビュー文字列の上
LVHT_ONITEMSTATEICONリストビューイメージの上
LVHT_ONITEM(LVHT_ONITEMICON | LVHT_ONITEMLABEL | LVHT_ONITEMSTATEICON)

2.ScreenToClient()で、スクリーン座標から、指定されたウィンドウのクライアント座標に変換します。

BOOL ScreenToClient(
    HWND   hwnd,       // ウィンドウハンドル
    PPOINT ppt         // スクリーン座標
);

3.ListView_SetImageList()で、リストビューのアイテムを取得

HIMAGELIST ListView_SetImageList(
    HWND hwnd,       // リストビューのハンドル
    HIMAGELIST himl, // リストビューに関連付けるイメージリストのハンドル
    int iImageList   // LV_HITTESTINFO構造体のポインタ
);

ListView_SetImageList()の代わりに、LVM_HITTESTメッセージでも、リストビューのアイテムを取得することができます。

lResult = SendMessage(
   (HWND) hWndControl, // リストビューのハンドル
   (UINT) LVM_HITTEST,
   0,                  // 0固定
   (LPARAM) lParam     // LV_HITTESTINFO構造体のポインタ
);

4.クリックされた場所が、指定された場所(ここでは、LVHT_ONITEM)ならば、 LVITEM構造体から データを取得。

5.ListView_GetItem()で、リストビューのデータを取得

BOOL ListView_GetItem( 
    HWND hwnd,         // リストビューのハンドル
    LVITEM FAR* pitem  // LV_HITTESTINFO構造体のポインタ
);

ソースコードの入力

ソースコードは下記のように入れてください。

test.cpp
#include <windows.h>
#include <commctrl.h>
#include "resource.h"

#pragma comment(lib, "comctl32.lib")
#define T_BUFFER 128   // リストビューのテキストバッファ

LPTSTR strItem0[] = { TEXT("TILTE1"), TEXT("TILTE2") };
int CX[] = { 80, 160 };
LPTSTR strItem1[] =
         { TEXT("LIST11"), TEXT("LIST12") };
LPTSTR strItem2[] =
         { TEXT("LIST21"), TEXT("LIST22") };

// このコード モジュールに含まれる関数の宣言を転送します:
BOOL CALLBACK DialogProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
          PSTR lpCmdLine, int nCmdShow )
{
    DialogBox(hInstance, TEXT("DIALOG_BOX"), NULL, DialogProc);
    return 0;
}

BOOL CALLBACK DialogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    LVCOLUMN lvcol;
    LVITEM item;
    UINT i;
    static HWND hList;
    LV_HITTESTINFO lvinfo;
    TCHAR buf[T_BUFFER];
    switch (msg)
    {
        case WM_INITDIALOG:
            InitCommonControls();
            hList = GetDlgItem(hWnd, IDC_LIST1);

            lvcol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
            lvcol.fmt = LVCFMT_LEFT;
            for(i = 0; i < 2; i++)
            {
                lvcol.cx = CX[i];             // 表示位置
                lvcol.pszText = strItem0[i];  // 見出し
                lvcol.iSubItem = i;           // サブアイテムの番号
                ListView_InsertColumn(hList, i, &lvcol);
            }

            item.mask = LVIF_TEXT;
            for(i = 0; i < 2; i++)
            {
                item.pszText = strItem1[i];   // テキスト
                item.iItem = i;               // 番号
                item.iSubItem = 0;            // サブアイテムの番号
                ListView_InsertItem(hList, &item);
                item.pszText = strItem2[i];   // テキスト
                item.iItem = i;               // 番号
                item.iSubItem = 1;            // サブアイテムの番号
                ListView_SetItem(hList, &item);
            }
            break;

        case WM_NOTIFY:
            switch(((LPNMHDR)lParam)->idFrom)
            {
                case IDC_LIST1:
                    switch (((LPNMLISTVIEW)lParam)->hdr.code)
                    {
                        // case LVN_ITEMCHANGED: // 項目を選択
                        case NM_DBLCLK:  // 項目をダブルクリック
                            GetCursorPos((LPPOINT)&lvinfo.pt);
                            ScreenToClient(((LPNMLISTVIEW)lParam)->hdr.hwndFrom, &lvinfo.pt);
                            ListView_HitTest(((LPNMLISTVIEW)lParam)->hdr.hwndFrom, &lvinfo);
                            if ((lvinfo.flags & LVHT_ONITEM) != 0)
                            {
                                item.mask = TVIF_HANDLE | TVIF_TEXT;
                                item.iItem = lvinfo.iItem;
                                item.iSubItem = 0;          //取得するサブアイテムの番号
                                item.pszText = buf;         //格納するテキストバッファ
                                item.cchTextMax = T_BUFFER; //バッファ容量
                                ListView_GetItem(((LPNMLISTVIEW)lParam)->hdr.hwndFrom, &item);
                                MessageBox(hWnd, buf, TEXT("選択したデータ"), MB_OK);
                            }
                            break;
                    }
                    break;
                default:
                    break;
                }
                break;
        case WM_CLOSE:
            EndDialog(hWnd, IDOK);
            break;
        default:
            break;
    }
    return FALSE;
}

resource.h
#define IDC_LIST1 400
#ifndef IDC_STATIC
#define IDC_STATIC -1
#endif

Reseditで作成した場合は、これとは異なるソースコードになります。
上記の太線で示している箇所のみ追加です。

test.rc
#include <windows.h>
#include <commctrl.h>
#include "resource.h"

/////////////////////////////////////////////////////////////////////////////
//
// ダイアログ
//

DIALOG_BOX DIALOG 0, 0, 170, 62
FONT 9, "MS UI Gothic"
CAPTION "ダイアログ"
BEGIN
     CONTROL         "", IDC_LIST1,
                    WC_LISTVIEW, WS_TABSTOP | WS_BORDER | LVS_REPORT | LVS_ICON,
                    2, 2, 166, 58
END

Reseditで作成した場合は、これとは異なるソースコードになります。
上記の太線で示している箇所のみ追加です。