
今回は、コモンコントロールの1つであるリストビューコントロールを作成してみることにしましょう。
リストビューとは右の図のようなコントロールです。いろいろなアプリケーションで使われていて、よく見かけると思います。また、もっとも身近なリストビューは、エクスプローラの右側のウィンドウです。「表示」メニューには「大きいアイコン」「小さいアイコン」「一覧表示」「詳細表示」があります。「詳細表示」にすると、右に示したコントロールと同じものが表示されると思います。
今回作成するリストビューはアイコンはありませんが、いわゆる「詳細表示」のリストビューを作ります。
リストビューを作成する手順は、以下のようになります。
まず最初に InitCommonControls 関数を呼び出します。これはすべてのコモンコントロールについて共通です。
リストビューを作成するには、 CreateWindowEx 関数を呼び出すときに、ウィンドウクラス名を "SysListView32" とします。このとき、ウィンドウスタイルとして WS_CHILD (0x40000000) および WS_VISIBLE (0x10000000) を指定します。その他に、今回は LVS_REPORT (0x0001) を指定します。このスタイルは、エクスプローラで「詳細表示」を選択したときと同じリストビューを作成するためのものです。
以上の操作で作成されたリストビューには、まだ何も表示されていません。ここにまず、カラム(列)を追加していく必要があります。カラムを追加するには、まず LVCOLUMN 構造体に必要な情報を格納しておいてから、その構造体のアドレスをパラメータとしてリストビューに LVM_INSERTCOLUMN メッセージを送信します。
LVCOLUMN 構造体は以下のように定義されています。
typedef struct _LVCOLUMN {
UINT mask; // 有効メンバを示すフラグ
int fmt; // 列の配置
int cx; // カラムの幅
LPTSTR pszText; // カラムのヘッダの文字列
int cchTextMax; // pszTextのサイズ
int iSubItem; // カラムのサブアイテムインデックス
} LVCOLUMN, FAR *LPLVCOLUMN;
mask メンバには有効なメンバを表すフラグを指定します。ここでは、すべてのメンバを有効にするために、 0x0001 (LVCF_FMT)、 0x0002 (LVCF_WIDTH)、 0x0004 (LVCF_TEXT)、 0x0008 (LVCF_SUBITEM) を組み合わせた値を指定します。
fmt メンバには、そのカラムに表示される文字列の表示位置を指定します。 0x0000 (LVCFMT_LEFT) を指定すると、左に表示されます。 0x0001 (LVCFMT_RIGHT) を指定すると、右に表示されます。 0x0002 (LVCFMT_CENTER) を指定すると、中央に表示されます。
cx メンバには、カラムの幅をピクセル単位で指定します。
pszText メンバには、ヘッダに表示する文字列のアドレスを指定します。
cchTextMax はここでは無視されます。 0 にしておきましょう。
iSubItem はこのカラムに関連付けられるサブアイテムのインデックスを指定します。後でアイテムを追加して各カラムに文字列を設定するときにこの値を指定すれば、このカラムに表示されます。
LVCOLUMN 構造体に情報を入れたら、 LVM_INSERTCOLUMN メッセージを送信します。
#define LVM_INSERTCOLUMN 0x101B
LVM_INSERTCOLUMN
wParam = iCol;
lParam = pcol;
iCol パラメータには、新しいカラムを挿入する位置のインデックスを指定します。ここで指定した位置にカラムが追加されます。このインデックスは 0 から始まる値で、最も左のカラムが 0 に、その右隣のカラムが 1 になります。
pcol パラメータには、先ほど情報を入れた LVCOLUMN 構造体のアドレスを指定します。カラムが作成されると、戻り値として作成されたカラムのインデックスが返ります。作成に失敗すると -1 が返ります。
さて、これでカラムができたので、次はアイテムを追加していきます。アイテムを追加するには LVITEM 構造体に情報を格納してから LVM_INSERTITEM メッセージを送信します。
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) を指定しておきます。
iItem メンバには、新しいアイテムを追加する位置のインデックスを指定します。このインデックスは 0 から始まる値で、最も上のアイテムが 0 に、その1つ下のアイテムが 1 になります。
iSubItem メンバには 0 を指定します。
pszText メンバには表示する文字列を入れた文字列変数のアドレスを指定します。
他のメンバはここでは関係ないので、どんな値が入っていても無視されます。(今回はとりあえず 0 にしておきます。)
LVITEM 構造体に情報を入れたら、リストビューに LVM_INSERTITEM メッセージを送ります。
#define LVM_INSERTITEM 0x1007
LVM_INSERTITEM
wParam = 0;
lParam = pitem
pitem パラメータには、新しいアイテムの情報を格納した LVITEM 構造体のアドレスを指定します。アイテムが追加されると、戻り値として作成されたアイテムのインデックスが返ります。失敗すると、戻り値として -1 が返ります。
アイテムが追加できたので、次はこのアイテムが持つサブアイテムを設定します。サブアイテムというのは、簡単に言えば、そのアイテムの2列目以降に表示されている文字列のことです。
サブアイテムを設定するには LVITEM 構造体に情報を格納してから LVM_SETITEM メッセージを送ります。
LVITEM 構造体についてはアイテム追加時とほとんど変わりませんが、ここでは iSubItem メンバにサブアイテムのインデックスを指定する必要があります。このインデックスは 1 から始まる値で、リストビューの2列目がインデックス1にあたります。ちなみに、ここで iSubItem メンバに 0 を指定すると、先ほど追加されたアイテムの文字列が変更されます。
LVITEM 構造体に情報を入れたら、リストビューに LVM_SETITEM メッセージを送ります。
#define LVM_SETITEM 0x1006
LVM_SETITEM
wParam = 0;
lParam = pitem;
pitem パラメータは、サブアイテムの情報を格納した LVITEM 構造体のアドレスを指定します。設定に成功すると、戻り値として 0 以外の値が、失敗すると 0 が返ります。
さて、実際にスクリプトを書いてみます。今回は、それぞれの機能ごとにモジュール命令を定義してみます。
リストビューの作成には、 CreateWindowEx 関数を呼び出すのに、LLMODモジュールの _makewnd 命令を使用しています。
#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
#global ;================= モジュール終わり =====================
CreateListView 0, 0, winx, winy
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
次回はアイテムの情報取得や削除などです。