
前回はリストビューの作成と、アイテムの追加についてを説明しました。今回は、作成されたリストビューからアイテムの内容を取得して、それを表示できるようにしてみましょう。また、アイテムの削除についてや、アイテムを検索する方法についてもやってみます。
リストビューのアイテムの内容を取得するには、 LVITEM 構造体に必要な情報を格納しておいてから、その構造体のアドレスをパラメータとしてリストビューに LVM_GETITEM メッセージを送信します。
前回も示しましたが、 LVITEM 構造体は以下のように定義されています。
typedef struct _LVITEM {
UINT mask; // 有効メンバを示すフラグ
int iItem; // アイテムのインデックス
int iSubItem; // サブアイテムインデックス
UINT state; // アイテムの状態・イメージ
UINT stateMask; // state のフラグ
LPTSTR pszText; // アイテムの文字列
int cchTextMax; // pszTextのサイズ
int iImage; // イメージのインデックス
LPARAM lParam; // アイテムの持つ32ビット値
} LVITEM, FAR *LPLVITEM;
mask メンバは、この構造体の有効メンバを示すフラグです。アイテム(またはサブアイテム)の文字列を取得したい場合は 0x0001 (LVIF_TEXT) を指定しておきます。 0x0008 (LVIF_STATE) を指定すると、アイテムの状態を取得することもできます。これらのフラグは値を組み合わせて指定します。
iItem メンバには、状態を取得したいアイテムの位置のインデックスを指定します。
iSubItem メンバには、アイテムの文字列(1列目のカラムの文字列)や状態を取得する場合には 0 を指定します。また、サブアイテムの文字列(2列目以降のカラムの文字列)を取得したい場合には、 1 以降のサブアイテムのインデックスを指定します。
mask メンバで 0x0001 (LVIF_TEXT) を指定した場合は、pszText メンバに取得した文字列を格納するバッファのアドレスを、 cchTextMax メンバにはそのバッファのサイズを格納しておかなければなりません。
LVITEM 構造体に必要な情報を格納したら、リストビューに LVM_GETITEM メッセージを送信します。
#define LVM_GETITEM 0x1005
LVM_GETITEM
wParam = 0;
lParam = pitem;
pitem パラメータには、情報を格納した LVITEM 構造体のアドレスを指定します。情報の取得が成功すると、 LVITEM 構造体のそれぞれのメンバに情報が格納され、戻り値として 0 以外の値が返ります。情報の取得に失敗した場合は 0 が返ります。
次は、アイテムを削除する方法です。
アイテムを削除するには、リストビューに LVM_DELETEITEM メッセージを送信します。
#define LVM_DELETEITEM 0x1008
LVM_DELETEITEM
wParam = iItem;
lParam = 0;
iItem パラメータには、削除するアイテムのインデックスを指定します。削除に成功すると、戻り値として 0 以外の値が、失敗すると 0 が返ります。
最後に、アイテムを検索する方法です。
アイテムを検索するのには2つのタイプがあり、それによって検索の方法も異なってきます。
まず、特殊な状態を持つアイテムを検索する場合についてです。
特殊な状態を持つアイテムを検索するには、リストビューに LVM_GETNEXTITEM メッセージを送ります。
#define LVM_GETNEXTITEM 0x100C
LVM_GETNEXTITEM
wParam = iStart;
lParam = flags;
iStart パラメータには、検索を開始するアイテムのインデックスを指定します。指定されたアイテム自身は検索の対象にはなりません。リストの最初から検索をする場合には -1 を指定します。
flags パラメータには、検索する方向と、どの状態のアイテムを検索するのかを示すフラグを指定します。これは以下の値になります。
| 値 | 意味 |
|---|---|
| 0x0000 (LVNI_ALL) | 指定されたアイテムの後に続くアイテムを検索します。(デフォルト) |
| 0x0001 (LVNI_FOCUSED) | フォーカスを持つアイテムを検索します。 |
| 0x0002 (LVNI_SELECTED) | 選択されているアイテムを検索します。 |
| 0x0004 (LVNI_CUT) | カット・アンド・ペーストの対象としてマークされているアイテムを検索します。 |
| 0x0008 (LVNI_DROPHILITED) | ドラッグ・アンド・ドロップのターゲットとしてハイライト表示されているアイテムを検索します。 |
| 0x0100 (LVNI_ABOVE) | 指定されたアイテムの上にあるアイテムを検索します。 |
| 0x0200 (LVNI_BELOW) | 指定されたアイテムの下にあるアイテムを検索します。 |
| 0x0400 (LVNI_TOLEFT) | 指定されたアイテムの左にあるアイテムを検索します。 |
| 0x0800 (LVNI_TORIGHT) | 指定されたアイテムの右にあるアイテムを検索します。 |
該当するアイテムがあった場合、戻り値としてそのアイテムのインデックスが返ります。該当するアイテムがなかった場合は、-1 が返ります。
次に、指定された文字列を持つアイテムなどを検索する場合についてです。
この場合、 LVFINDINFO 構造体に検索のための情報を格納した上で、その構造体のアドレスをパラメータとして、リストビューに LVM_FINDITEM メッセージを送ります。
typedef struct tagLVFINDINFO {
UINT flags; // 検索のタイプを示すフラグ
LPCTSTR psz; // 文字列のアドレス
LPRARAM lParam; // アイテムの持つ32ビット値
POINT pt; // アイテムの位置
UINT vkDirection; // 検索方向を示す仮想キーコード
} LVFINDINFO, FAR* LPFINDINFO;
この構造体についての説明はここでは省きます。
#define LVM_FINDITEM 0x100D
LVM_FINDITEM
wParam = iStart;
lParam = plvfi;
iStart パラメータには、検索を開始するアイテムのインデックスを指定します。指定されたアイテム自身は検索の対象にはなりません。リストの最初から検索をする場合には -1 を指定します。
plvfi パラメータには、検索に必要な情報を格納した LVFINDINFO 構造体のアドレスを指定します。
該当するアイテムが見つかった場合、戻り値としてそのアイテムのインデックスが返ります。該当するアイテムが見つからなかった場合は、-1 が返ります。
さて、実際にスクリプトを書いてみることにしましょう。
前回のスクリプトに、アイテム文字列取得・アイテム削除・選択アイテム取得のためのモジュール命令が追加されています。
このスクリプトでは、マウスクリックなどによって選択されたアイテムの情報表示や削除を行なっています。[Alt]キーや[Shift]キーなどを押しながら選ぶことによって複数のアイテムが同時に選択された場合でも対応できるようにしてあります。
#include "llmod.as"
#module ;============= リストビュー操作モジュール ===============
;----------------------------------------------------------------
; CreateListView リストビュー作成
;----------------------------------------------------------------
#deffunc CreateListView int, int, int, int
mref cx, 0 ; x座標
mref cy, 1 ; y座標
mref sx, 2 ; 幅
mref sy, 3 ; 高さ
mref bmscr, 67 ; 描画中ウィンドウのBMSCR構造体
mref stt, 64 ; stat
; コモンコントロールライブラリ初期化
dllproc "InitCommonControls", pm, 0, D_COMCTL@
; リストビューコントロールの作成
pm.0 = cx, cy, sx, sy ; 座標、サイズ
pm.4 = 0x50000001 ; WS_VISIBLE | WS_CHILD | LVS_REPORT
pm.5 = 0 ; 親ウィンドウ(0のとき描画中ウィンドウ)
pm.6 = 0 ; 拡張スタイル
_makewnd pm, "SysListView32"
stt = pm.0 ; stat にリストビューのハンドルを格納
return
;----------------------------------------------------------------
; AddListColumn リストビューにカラムを追加
;----------------------------------------------------------------
#deffunc AddListColumn str, int, int, int, int
mref setText, 32 ; ヘッダ文字列
mref hList, 1 ; リストビューのハンドル
mref index, 2 ; カラムのインデックス
mref alm, 3 ; 配置(0:左 1:右 2:中央)
mref wid, 4 ; カラムの幅
sdim szText, 256
szText = setText ; いったん別の変数に移しておく
; LVCOLUMN 構造体
lvcolumn.0 = 0x000F ; LVCF_FMT | LVCF_WIDTH | LVCF_TEXT
; | LVCF_SUBITEM
lvcolumn.1 = alm
lvcolumn.2 = wid
getptr lvcolumn.3, szText
lvcolumn.4 = 0
lvcolumn.5 = index
; LVM_INSERTCOLUMN メッセージ送信
pm = hList, 0x101B, index
getptr pm.3, lvcolumn
sendmsg pm
return
;----------------------------------------------------------------
; AddListItem リストビューにアイテム追加
;----------------------------------------------------------------
#deffunc AddListItem str, int, int
mref setText, 32 ; 文字列
mref hList, 1 ; リストビューのハンドル
mref index, 2 ; アイテムのインデックス
sdim szText, 256
szText = setText ; いったん別の変数に移しておく
; LVITEM 構造体
lvitem.0 = 0x0001 ; LVIF_TEXT
lvitem.1 = index ; インデックス
lvitem.2 = 0
getptr lvitem.5, szText
; LVM_INSERTITEM メッセージ送信
pm = hList, 0x1007, 0
getptr pm.3, lvitem
sendmsg pm
return
;----------------------------------------------------------------
; SetListItem リストビューのサブアイテム設定
;----------------------------------------------------------------
#deffunc SetListItem str, int, int, int
mref setText, 32 ; サブアイテム文字列
mref hList, 1 ; リストビューのハンドル
mref index, 2 ; アイテムのインデックス
mref indexsub, 3 ; サブアイテムのインデックス
sdim szText, 256
szText = setText ; いったん別の変数に移しておく
; LVITEM 構造体
lvitem.0 = 0x0001 ; LVIF_TEXT
lvitem.1 = index ; インデックス
lvitem.2 = indexsub
getptr lvitem.5, szText
; LVM_SETITEM メッセージ送信
pm = hList, 0x1006, 0
getptr pm.3, lvitem
sendmsg pm
return
;================================================================
; GetListItem リストビューアイテムの文字列取得
;================================================================
#deffunc GetListItem val, int, int, int, int
mref retText, 24 ; 取得文字列を格納する文字列変数
mref hList, 1 ; リストビューのハンドル
mref index, 2 ; アイテムのインデックス
mref indexsub, 3 ; サブアイテムのインデックス
mref cch, 4 ; バッファサイズ
; LVITEM 構造体
lvitem.0 = 0x0001 ; LVIF_TEXT
lvitem.1 = index ; アイテムのインデックス
lvitem.2 = indexsub ; サブアイテムインデックス
getptr lvitem.5, retText ; バッファのアドレス
lvitem.6 = cch ; バッファのサイズ
; LVM_GETITEM メッセージ送信
pm = hList, 0x1005, 0
getptr pm.3, lvitem
sendmsg pm
return
;================================================================
; DelListItem リストビューアイテムの削除
;================================================================
#deffunc DelListItem int, int
mref hList, 0 ; リストビューのハンドル
mref index, 1 ; アイテムのインデックス
; LVM_DELETEITEM メッセージ送信
pm = hList, 0x1008, index, 0
sendmsg pm
return
;================================================================
; GetSelListItem 選択されているリストアイテムの取得
;================================================================
#deffunc FindSelListItem int, int
mref hList, 0 ; リストビューのハンドル
mref index, 1 ; アイテムのインデックス
; LVM_GETNEXTITEM メッセージ送信
pm = hList, 0x100C
pm.2 = index ; 検索開始インデックス
pm.3 = 0x0002 ; LVNI_ALL | LVNI_SELECTED
sendmsg pm
return
#global ;================= モジュール終わり =====================
objsize winx/2, 25 : objmode 1
pos 0, 0 : button "選択アイテムの情報表示", *lb_mesitem
pos winx/2, 0 : button "選択アイテム削除", *lb_delitem
CreateListView 0, 25, winx, winy-25
hList = stat
AddListColumn "名前", hList, 0, 0, 100
AddListColumn "読み", hList, 1, 0, 100
AddListItem "在原業平", hList, 0
SetListItem "ありわらのなりひら", hList, 0, 1
AddListItem "僧正遍昭", hList, 1
SetListItem "そうじょうへんじょう", hList, 1, 1
AddListItem "喜撰法師", hList, 2
SetListItem "きせんほうし", hList, 2, 1
AddListItem "大伴黒主", hList, 3
SetListItem "おおとものくろぬし", hList, 3, 1
AddListItem "文屋康秀", hList, 4
SetListItem "ふんやのやすひで", hList, 4, 1
AddListItem "小野小町", hList, 5
SetListItem "おののこまち", hList, 5, 1
stop
*lb_mesitem
; 選択されているアイテムの情報を表示
sdim buf1, 256 ; アイテムの文字列を格納する変数
sdim buf2, 256 ; サブアイテムの文字列を格納する変数
; 複数のアイテムが選択されている場合に対応
idx = -1
repeat
FindSelListItem hList, idx
idx = stat
if idx == -1 : break
GetListItem buf1, hList, idx, 0, 128
GetListItem buf2, hList, idx, 1, 128
buf1 += "\n"+buf2
dialog buf1, 0, "情報表示"
loop
stop
*lb_delitem
; 選択されているアイテムをリストビューから削除
; 複数のアイテムが選択されている場合に対応
idx = -1
repeat
FindSelListItem hList, idx
idx = stat
if idx == -1 : break
DelListItem hList, idx
idx-- ; アイテム削除によるインデックスのずれを補正
loop
stop