以下の過去ログを参考にしました。
http://www.activebasic.com/forum/viewtopic.php?t=576
三日ぐらい悩んで完成させたのですが、基本的な事なのになぜか過去ログに載ってない様なので、私の苦労が皆様のお役に立てばと思い、投稿します。
詳しい解説は、私が書くより以下のページへ。言語は違うけど、やってる事は同じなので分かると思います。
http://www.kumei.ne.jp/c_lang/sdk2/sdk_110.htm
■私の環境
OS WinXP Home SP
AB 4.13
■準備
RADでリストビューを貼り付ける。
プロパティで、表示をレポートにする。
リストビューのイベントコードでカラムの1つがクリックされたときを選択。
■コード
コード: 全て選択
Dim hLV As HWND			'リストビューハンドル
Dim SortLV =1 As Long		'昇/降順判定
hLV = GetDlgItem(hMainWnd,ListView1)
Sub MainWnd_ListView1_ColumnClick(ByRef nmListView As NMLISTVIEW)	'リストソート カラムクリック
	If SortLV > 0 Then
		SortLV = -1
	Else
		SortLV = 1
	End If
	SendMessage(hLV, LVM_SORTITEMS, nmListView.iSubItem, AddressOf(CompareProc) As LPARAM)
End Sub
Function CompareProc(lp1 As Long, lp2 As Long, lpSort As Long) As Long
	Dim nItem1 As Long				'比較のためのコールバック関数
	Dim nItem2 As Long
	Dim bBuf1[MAX_PATH] As Byte
	Dim bBuf2[MAX_PATH] As Byte
	Dim lvf As LVFINDINFO
	lvf.flags = LVFI_PARAM
	lvf.lParam = lp1
	nItem1 = SendMessage(hLV, LVM_FINDITEM, -1, VarPtr(lvf) As LPARAM)
	lvf.lParam = lp2
	nItem2 = SendMessage(hLV, LVM_FINDITEM, -1, VarPtr(lvf) As LPARAM)
	GetLVText(nItem1, lpSort, bBuf1)
	GetLVText(nItem2, lpSort, bBuf2)
	If lpSort = 0 or lpSort = 3 Then		'カラム(列)が0.3の時は数値で比較
		nItem1 = Val(bBuf1) As Long
		nItem2 = Val(bBuf2) As Long
		If nItem1 = nItem2 Then
			CompareProc = 0
		ElseIf nItem1 > nItem2 Then
			CompareProc = 1
		Else
			CompareProc = -1
		End If
	Else
		CompareProc = lstrcmp(bBuf1, bBuf2)
	End If
	If SortLV < 0 Then CompareProc = CompareProc * -1	'降順 -1を掛ける。昇順はそのまま。
End Function
Sub GetLVText(ByRef iItem As Long, ByRef iSubItem As Long, ByRef pszText[MAX_PATH] As Byte)
	Dim lvi As LVITEM
	With lvi
		.mask = LVIF_TEXT
		.iItem = iItem
		.iSubItem = iSubItem
		.cchTextMax = MAX_PATH
		.pszText = pszText
	End With
	SendMessage(hLV, LVM_GETITEM, 0, VarPtr(lvi) As LPARAM)
End Sub
Sub SetLVText(ByRef iItem As Long, ByRef iSubItem As Long, ByRef pszText As String)
	Dim lvi As LVITEM
	With lvi
		.iItem = iItem
		.iSubItem = iSubItem
		.cchTextMax = MAX_PATH
		.pszText = StrPtr(pszText)
		If .iSubItem = 0 Then
			.mask = LVIF_TEXT or LVIF_PARAM
			.lParam = iItem
			SendMessage(hLV,LVM_INSERTITEM,0,VarPtr(lvi) As LPARAM)		'0 = インサート
		Else
			.mask = LVIF_TEXT
			SendMessage(hLV,LVM_SETITEM,0,VarPtr(lvi) As LPARAM)		'0 <> セット
		End If
	End With
End Subまずリストビューにアイテムを入れるのにはSetLVTextを使います。
サブアイテムが0の時にインサートし、その時にLVIF_PARAMを追加します。(これをやらないとソートできない)
ここでは、行(横のライン)の値をそのまま使ってます。
カラムクリックでNMLISTVIEW構造体にどのカラムがクリックされたか入るのでそれを利用します。
昇順/降順はクリックするたびに替わります。
CompareProcの最後の所は
コード: 全て選択
CompareProc = lstrcmp(bBuf1, bBuf2) 
If SortLV < 0 Then CompareProc = CompareProc * -1そこでlpSortにはクリックされたカラムが入ってますので、ここでは1番目と4番目の時は数値にして比較してます。
しかし、文字と数が混ざっている場合は不可能です。ここら辺良いやり方を知っていたら教えて欲しいです。
注意点は、扱える文字列の長さがMAX_PATHですので変えたい場合は、関数を弄ったりして下さい。
setLVText、getLVTextとも引数がByRefになってるので気をつけてください。
リストビューから文字列を得るのにはGetLVTextを使いますが
過去ログの所ではLVM_GETITEMTEXTで文字列をリストビューから取得していて、
それだと設定したlParamの値が取得できないらしく、これに気づくまでに相当無意味な時間を過ごしました。
文字列がByte配列だったり、String型だったりしてますが、それは大目に見てください。
(ここら辺が未だに4.13を使ってる理由になってると思います・汗)
こうした方が速いとか、簡単だとか、上記の数値が順番どおりに並ぶ方法とかあったら教えて下さい。