リストビュー内部のソートコールバック関数にユーザー定義関数を登録します。
GUICtrlRegisterListViewSort ( controlID, "function" )
パラメータ
controlID | ユーザー関数が処理するリストビューのコントロールID。 |
function | ソートコールバック実行時に呼ばれるユーザー関数名。 |
返し値
成功 | 1 |
失敗 | 0 |
注意
!!! ユーザー関数を正常に動作させるためには最大で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番目のアイテムの前にくる。 |
関連
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