Function Reference

GUICtrlRegisterListViewSort

リストビュー内部のソートコールバック関数にユーザー定義関数を登録します。

GUICtrlRegisterListViewSort ( controlID, "function" )

 

パラメータ

controlID ユーザー関数が処理するリストビューのコントロールID。
function ソートコールバック実行時に呼ばれるユーザー関数名。

 

返し値

成功 1
失敗 0

 

注意

!!! ユーザー関数を正常に動作させるためには最大で4つの関数パラメータを定義しなければいけません。パラメータの定義が不適切な場合、関数は呼び出されません !!!
例:
Func MySortFunction($nListViewID, $LParam1, $LParam2, $nColumn)
...
EndFunc

または

Func MySortFunction($nListViewID, $LParam1, $LParam2)
...
EndFunc

ユーザー関数が呼び出し時、これら4つのパラメータは次の値を持ちます。
位置 パラメータ 意味
1 controlID コールバック関数が使用されるリストビューコントロールのコントロールID。
2 lParam1 1番目のアイテムのlParam値(デフォルトではアイテムのコントロールID)。
3 lParam2 2番目のアイテムのlParam値(デフォルトではアイテムのコントロールID)。
4 column ソートのためにクリックされた列(1番目の列の番号は0)。

ソートコールバックの動作を変更するために次の値が返されなければなりません
返し値 意味
-1 1番目のアイテムが2番目のアイテムの前にくる。
0 変更なし。
1 2番目のアイテムが1番目のアイテムの前にくる。

例にある自作のGUIリストビューアイテムのソートも参照してください。

 

関連

GUICtrlCreateListView

 


#include <GUIConstantsEx.au3>
#include <ListViewConstants.au3>

Opt('MustDeclareVars', 1)

Global $nCurCol = -1
Global $nSortDir = 1
Global $bSet = 0
Global $nCol = -1

Example1()
Example2()

; *******************************************************
; 例 1 - 3列毎のソート
; *******************************************************
Func Example1()
    Local $hGUI, $lv, $lvi1, $lvi2, $lvi3, $msg

    $hGUI = GUICreate("Test", 300, 200)

    $lv = GUICtrlCreateListView("Column1|Col2|Col3", 10, 10, 280, 180)
    GUICtrlRegisterListViewSort(-1, "LVSort") ; ソートのコールバック用に関数"SortLV"を登録

    $lvi1 = GUICtrlCreateListViewItem("ABC|666|10.05.2004", $lv)
    GUICtrlSetImage(-1, "shell32.dll", 7)
    $lvi2 = GUICtrlCreateListViewItem("DEF|444|11.05.2005", $lv)
    GUICtrlSetImage(-1, "shell32.dll", 12)
    $lvi3 = GUICtrlCreateListViewItem("CDE|444|12.05.2004", $lv)
    GUICtrlSetImage(-1, "shell32.dll", 3)

    GUISetState()

    While 1
        $msg = GUIGetMsg()
        Switch $msg
            Case $GUI_EVENT_CLOSE
                ExitLoop
               
            Case $lv
                $bSet = 0
                $nCurCol = $nCol
                GUICtrlSendMsg($lv, $LVM_SETSELECTEDCOLUMN, GUICtrlGetState($lv), 0)
                DllCall("user32.dll", "int", "InvalidateRect", "hwnd", GUICtrlGetHandle($lv), "int", 0, "int", 1)
        EndSwitch
    WEnd

    GUIDelete()
EndFunc   ;==>example1

; 自前のソートコールバック関数
Func LVSort($hWnd, $nItem1, $nItem2, $nColumn)
    Local $nSort, $val1, $val2, $nResult
   
    ; ソート方向を切り替え
    If $nColumn = $nCurCol Then
        If Not $bSet Then
            $nSortDir = $nSortDir * - 1
            $bSet = 1
        EndIf
    Else
        $nSortDir = 1
    EndIf
    $nCol = $nColumn
   
    $val1 = GetSubItemText($hWnd, $nItem1, $nColumn)
    $val2 = GetSubItemText($hWnd, $nItem2, $nColumn)
   
    ; 3列目(列は0始まり)の場合、日付を比較
    If $nColumn = 2 Then
        $val1 = StringRight($val1, 4) & StringMid($val1, 4, 2) & StringLeft($val1, 2)
        $val2 = StringRight($val2, 4) & StringMid($val2, 4, 2) & StringLeft($val2, 2)
    EndIf
   
    $nResult = 0    ; アイテム1、アイテム2の位置に変更なし
   
    If $val1 < $val2 Then
        $nResult = -1   ; アイテム2をアイテム1の前に置く
    ElseIf $val1 > $val2 Then
        $nResult = 1    ; アイテム2をアイテム1の後ろに置く
    EndIf

    $nResult = $nResult * $nSortDir
   
    Return $nResult
EndFunc   ;==>LVSort


; 指定した列のリストビューアイテムのテキストを取得
Func GetSubItemText($nCtrlID, $nItemID, $nColumn)
    Local $stLvfi = DllStructCreate("uint;ptr;int;int[2];int")
    Local $nIndex, $stBuffer, $stLvi, $sItemText
   
    DllStructSetData($stLvfi, 1, $LVFI_PARAM)
    DllStructSetData($stLvfi, 3, $nItemID)

    $stBuffer = DllStructCreate("char[260]")
   
    $nIndex = GUICtrlSendMsg($nCtrlID, $LVM_FINDITEM, -1, DllStructGetPtr($stLvfi));
   
    $stLvi = DllStructCreate("uint;int;int;uint;uint;ptr;int;int;int;int")
   
    DllStructSetData($stLvi, 1, $LVIF_TEXT)
    DllStructSetData($stLvi, 2, $nIndex)
    DllStructSetData($stLvi, 3, $nColumn)
    DllStructSetData($stLvi, 6, DllStructGetPtr($stBuffer))
    DllStructSetData($stLvi, 7, 260)

    GUICtrlSendMsg($nCtrlID, $LVM_GETITEMA, 0, DllStructGetPtr($stLvi));

    $sItemText = DllStructGetData($stBuffer, 1)

    $stLvi = 0
    $stLvfi = 0
    $stBuffer = 0
   
    Return $sItemText
EndFunc   ;==>GetSubItemText


; *******************************************************
; 例2 - DllCallによる自作アイテムのソート
; *******************************************************
Func Example2()
    Local $hGUI, $lv, $msg

    $nCurCol = -1
    $nSortDir = 1
    $bSet = 0
    $nCol = -1

    $hGUI = GUICreate("Test", 300, 200)

    $lv = GUICtrlCreateListView("Column1|Col2|Col3", 10, 10, 280, 180)
    GUICtrlRegisterListViewSort(-1, "LVSort2") ; ソートのコールバック用に関数"SortLV"を登録

    MyGUICtrlCreateListViewItem("ABC|666|10.05.2004", $lv, -1)
    MyGUICtrlCreateListViewItem("DEF|444|11.05.2005", $lv, -1)
    MyGUICtrlCreateListViewItem("CDE|444|12.05.2004", $lv, -1)

    GUISetState()

    While 1
        $msg = GUIGetMsg()
        Switch $msg
            Case $GUI_EVENT_CLOSE
                ExitLoop
               
            Case $lv
                $bSet = 0
                $nCurCol = $nCol
                GUICtrlSendMsg($lv, $LVM_SETSELECTEDCOLUMN, GUICtrlGetState($lv), 0)
                DllCall("user32.dll", "int", "InvalidateRect", "hwnd", ControlGetHandle($hGUI, "", $lv), "int", 0, "int", 1)
        EndSwitch
    WEnd
EndFunc   ;==>Example2

; 自前のソートコールバック関数
Func LVSort2($hWnd, $nItem1, $nItem2, $nColumn)
    Local $nSort, $val1, $val2, $nResult
   
    ; ソート方向を切り替え
    If $nColumn = $nCurCol Then
        If Not $bSet Then
            $nSortDir = $nSortDir * - 1
            $bSet = 1
        EndIf
    Else
        $nSortDir = 1
    EndIf
    $nCol = $nColumn
   
    $val1 = GetSubItemText($hWnd, $nItem1, $nColumn)
    $val2 = GetSubItemText($hWnd, $nItem2, $nColumn)

    ; 3列目(列は0始まり)の場合、日付を比較
    If $nColumn = 2 Then
        $val1 = StringRight($val1, 4) & StringMid($val1, 4, 2) & StringLeft($val1, 2)
        $val2 = StringRight($val2, 4) & StringMid($val2, 4, 2) & StringLeft($val2, 2)
    EndIf
   
    $nResult = 0    ; アイテム1、アイテム2の位置に変更なし
   
    If $val1 < $val2 Then
        $nResult = -1   ; アイテム2をアイテム1の前に置く
    ElseIf $val1 > $val2 Then
        $nResult = 1    ; アイテム2をアイテム1の後ろに置く
    EndIf

    $nResult = $nResult * $nSortDir
   
    Return $nResult
EndFunc   ;==>LVSort2


; 指定した列のリストビューアイテムのテキストを取得
Func GetSubItemText2($nCtrlID, $nItemID, $nColumn)
    Local $stLvfi = DllStructCreate("uint;ptr;int;int[2];int")
    Local $stBuffer, $nIndex, $stLvi, $sItemText
   
    DllStructSetData($stLvfi, 1, $LVFI_PARAM) ; 保存したインデックスからアイテムを検索
    DllStructSetData($stLvfi, 3, $nItemID)
   
    $stBuffer = DllStructCreate("char[260]")
   
    $nIndex = GUICtrlSendMsg($nCtrlID, $LVM_FINDITEM, -1, DllStructGetPtr($stLvfi));

    $stLvi = DllStructCreate("uint;int;int;uint;uint;ptr;int;int;int;int")
   
    DllStructSetData($stLvi, 1, $LVIF_TEXT)
    DllStructSetData($stLvi, 2, $nIndex)
    DllStructSetData($stLvi, 3, $nColumn)
    DllStructSetData($stLvi, 6, DllStructGetPtr($stBuffer))
    DllStructSetData($stLvi, 7, 260)

    GUICtrlSendMsg($nCtrlID, $LVM_GETITEMA, 0, DllStructGetPtr($stLvi));

    $sItemText = DllStructGetData($stBuffer, 1)

    $stLvi = 0
    $stLvfi = 0
    $stBuffer = 0
   
    Return $sItemText
EndFunc   ;==>GetSubItemText2


; アイテムを作成し、リスビューに直接挿入
Func MyGUICtrlCreateListViewItem($sText, $nCtrlID, $nIndex)
    Local $stLvItem = DllStructCreate("uint;int;int;uint;uint;ptr;int;int;int;int;")
    Local $stText = DllStructCreate("char[260]")
    Local $arText = StringSplit($sText, "|")
   
    If $nIndex = -1 Then $nIndex = GUICtrlSendMsg($nCtrlID, $LVM_GETITEMCOUNT, 0, 0)
   
    DllStructSetData($stText, 1, $arText[1]) ; アイテムテキストを構造体に保存
   
    DllStructSetData($stLvItem, 1, BitOR($LVIF_TEXT, $LVIF_PARAM))
    DllStructSetData($stLvItem, 2, $nIndex)
    DllStructSetData($stLvItem, 6, DllStructGetPtr($stText))
    ; 構造体のlParamを行インデックス(リストビュー内でユニーク)に設定
    DllStructSetData($stLvItem, 9, $nIndex)
   
    $nIndex = GUICtrlSendMsg($nCtrlID, $LVM_INSERTITEMA, 0, DllStructGetPtr($stLvItem))

    If $nIndex > -1 Then
        ; 現在の列テキストの残りを挿入
        For $i = 2 To $arText[0]
            DllStructSetData($stText, 1, $arText[$i])
            DllStructSetData($stLvItem, 3, $i - 1) ; サブアイテムのインデックスを保存
           
            GUICtrlSendMsg($nCtrlID, $LVM_SETITEMTEXTA, $nIndex, DllStructGetPtr($stLvItem))
        Next
    EndIf

    $stText = 0
    $stLvItem = 0

    ; アイテムテキストにあわせて列の幅を変更
    For $i = 0 To 2
        GUICtrlSendMsg($nCtrlID, $LVM_SETCOLUMNWIDTH, $i, -1)
        GUICtrlSendMsg($nCtrlID, $LVM_SETCOLUMNWIDTH, $i, -2)
    Next
EndFunc   ;==>MyGUICtrlCreateListViewItem