第2章-7 ListBoxの使い方(3)

今回はサンプルとしては次のようなものを作ります。
何か、Finderみたいで格好いいですね^^;。
こういうのを階層化されているリストと呼びます。みてくれが格好いいと多少、 使い方はややこしくなってきます。では。

list3-1

まず、Window上にListBoxを配置します。特に難しいことはありませんが、綺麗に見えるように 配置します。....そんなことはど−でも良いのですが、ひとつ、プロパティの設定で注意するこ とがあります。上の図でリストの項目名の左に青い三角形が表示されています。日頃、使い慣れ ているものですが(ディスクロージャトライアングルというらしいですね)、これを表示させる為には 下の様にHierarchical(よ、読めない...。)をチェックします

list3-2

次に、コードです。(2)までよりは難しくなってます。
まず、初期化ですが、openイベントに書きました。ListBoxのopenイベントでも良いと思います。

rootには項目のフィールドを書いています。三角形のつく最初から表示されるやつです。 itemには最初は隠されていて、項目が展開されると表示されるフィールドを書いています。 rootのフィールドが","で区切っていて、itemのフィールドが";"で区切られています。itemの場合 各、フィールド内の要素は","で区切られています。

filedNumにはrootのフィールド数を格納します。これが、最初に表示される項目の数になります。 CountFields()関数を使います。この関数の意味は、例えばCountFields(root,",")の場合はrootの中で ","で区切られたフィールドがいくつあるか数えるということです。

次に、For〜Nextループの中で、rootの内容のセットと表示、itemのセットを行います。このとき、item の内容については隠しセルにセットされるためまだ表示されません。
NthFiled(item, ";", counter)はitemの中で";"で区切られたcounter番目のフィールドという意味 です。AddFolderメソッド、Cellメッドについては(2)までを参照して下さい。以上で初期化は終わりです。


Sub open()
    Dim counter As Integer
    Dim fieldNum As integer
    Dim root As String
    Dim item As String

    ' 初期値
    root ="仮面の忍者,仮面ライダー"
    item ="赤影,青影,白影,おいおい;1号,2号,V3,もちとましな例はないのかよ"

    ' rootのフィールド数をカウント
    fieldNum = CountFields(root,",")

    For counter = 1 To fieldNum
        ' itemの中のcounter番目のフィールド
        If NthField(item,";",counter) <> "" Then

            ListBox1.AddFolder ""

            ' この時点ではまだ見えない
            ListBox1.cell(counter-1,1) = NthField(item,";",counter)
        End If

        ' rootのcounter番目を表示
        ListBox1.cell(counter-1,0) = NthField(root,",",counter)
    Next
End Sub
			

次に、リストボックスが操作されたときの処理を書きます。操作というと、

1.ディスクロージャトライアングルがクリックされた時
2.項目がダブルクリックされた時

の2パターンがあります。処理としては、どちらも項目を展開する、元に戻すの2種類に なります。

まず、項目がダブルクリックされた場合ですが、ListBox1のイベントの中のDoubleClick に次のように書きます。


Sub DoubleClick()
    '
    '項目がダブルクリックされた場合の処理
    '

    'すでに展開されていた場合は元に戻し、
    'まだ展開されていない場合は展開する。
    'Me.listindex : 選択されている項目
    'Meexpanded : 展開状態

    Me.expanded(Me.listindex)=Not Me.expanded(Me.listindex)
End Sub
			

Meはこのコントロールのポインタを示します。
この処理は、選択された項目のexpandedプロパティを反転させています。つまり、展開されて いればもとに戻し、展開されていなければ展開するということになります。このexpandedプロパティ を操作すると、
項目を展開する場合はExpandRow
元に戻す場合はCollapseRow
というイベントが発生します。次に、これらのイベント用のコードを書きます。まず、項目を展開する イベントのコードです。ListBox1のExpandRowイベントに次のように書きます。


Sub ExpandRow(Row As Integer)

    '項目がダブルクリックされたときダブルクリックの
    'イベントハンドラを実行したあとに、展開するときだけここに来る
    'ディスクロージャトライアングルがクリックされたときもここに来る

    Dim item as string
    Dim counter As Integer
    Dim fieldNum As integer

    '選択された行(項目)の中のリストをitemに取得する
    item = Me.Cell(row,1)

    'itemの個数を取得する
    fieldNum = CountFields(item,",")

    'item の個数分繰り返す
    For counter = 1 To fieldNum
        '行を追加する
        Me.Addrow ""

        '追加された行にitemの内容をセットし表示する
        Me.cell(Me.lastIndex,0)=NthField(item,",",counter)
    Next
End Sub
			

ExpandRowには選択された行の番号が渡されます。これを使って、Addrowメッソッドで その下に行をひとつずつ追加しながら、今まで隠されていたitemの要素を表示していきます。 これが、For〜Nextループの中の処理です。

次に、展開された項目を元に戻すイベントのコードです。ListBox1のCollapseRowイベントに次のように 書きます。
展開するときと逆のことをやっています。Rowで渡される行番号の項目を元に戻す為に、その下 から何行展開されているかをCountFields()関数で取得し、一番下から上に向かって1行ずつ行そのもの を削除していきます。Removeメソッドを使います。


Sub CollapseRow(Row As Integer)

    'すでに展開されている行のディスクロージャトライアングルをクリックした場合
    'と、すでに展開されている項目をダブルクリックした場合、ここに来る
    '
    '展開されている項目を元に戻す

    Dim counter As Integer
    Dim fieldNum As Integer
    Dim endOfremove As Integer

    '展開されているitemのシールド数を取得する
    fieldNum = CountFields(Me.Cell(row,1),",")

    '削除する行の最終行番号
    endOfremove = row + 1

    '展開されている行を削除する(下から上に向かって)
    For counter = row + fieldNum DownTo endOfremove
        Me.RemoveRow counter
    Next
End Sub
			

以上で終わりです。ここまで、項目がダブルクリックされた時をもとにコードを書いてきましたが、 これだけで、ディスクロージャトライアングルがクリックしたときの対応もできています。
ディスクロージャトライアングルがクリックされたときはexpandedプロパティを操作しなくても直接、 ExpandRowイベントとCollapseRowイベントが発生するからです。

目次に戻る