環境:WinXP,VB6
ファイルを一覧表示するリストビューで更新日時ソートが出来るように
なりましたが、リストビュー内にはチェックボックスを設けておりチェック
したファイルを隣のリストビューにコピーできます。
が、しかし!!!
降順ソートするとチェックものとは違うファイルがコピーされてしまいます。
例)一番下のファイルをチェックしてコピーすると一番上のファイルがコピー
チェックボックスが付いてきていないと言うことですよね。
何故でしょうか????
チェックしたファイルの判断はどうやってますか?
その判断方法が間違っていると思うんですが・・・
「何故でしょうか????」といわれても、ソースをみてみないと
これ以上は、なんとも言えません。
、
レスありがとうございます。
以下のソースで検索リストから選択リストにファイル名をコピーしています。
Dim i As Integer
Dim j As Integer
Dim checkflag As Integer
Dim itmX As ListItem
For i = 1 To 検索リスト.ListItems.Count
If 検索リスト.ListItems(i).Checked = True Then
If intAddCount = 100 Then
MsgBox ("選択可能なファイル数は100件までです。")
Exit Sub
End If
'/// 重複してコピーしないように
checkflag = 0
For j = 1 To 選択リスト.ListItems.Count
If 選択リスト.ListItems(j) = 検索リスト.ListItems(i) Then
checkflag = 1
Exit For
End If
Next j
'/// コピーを実行
If checkflag = 0 Then
Set itmX = 選択リスト.ListItems.Add(, , 検索リスト.ListItems(i))
itmX.SubItems(1) = FileDateTime(strOpenFilePath & 検索リスト.ListItems(i))
intAddCount = intAddCount + 1
'/// 結合ファイル名をプリセット
If intAddCount = 1 Then
Text1.Text = 検索リスト.ListItems(検索リスト.ListItems.Count)
End If
'/// 選択ファイル数を表示
If intAddCount > 0 Then
AddCounter.Caption = intAddCount & "件"
End If
End If
End If
Next i
降順にした時はループを逆に回さなくてはいけないのでしょうか????
すみません。何だか良くわからないことを書いてしまって。
自分でも頭がパニックで現象が良く分からなかったので。
検証した結果、日付でソートするとファイル名が不定になる事が分かりました。
ファイル名とチェックボックスの位置が画面上と内部では違うという事かな。
検索していたら、ファイル名でソートしてから日付でソートと2回
ソートすれば大丈夫とありましたが、実行しても駄目でした。
ファイル名でソートは文字列をテキストとして比較しています。
こんな感じです。
Dim strText1 As String 'ファイル名1
Dim strText2 As String 'ファイル名2
strText1 = GetTextFromlParam(hwnd, lParam1, GetProp(hwnd, PROP_SORT_KEY))
strText2 = GetTextFromlParam(hwnd, lParam2, GetProp(hwnd, PROP_SORT_KEY))
If GetProp(hwnd, PROP_SORT_ORDER) = 0 Then
If strText1 < strText2 Then
CompareFuncByText = 0
ElseIf strText1 = strText2 Then
CompareFuncByText = 1
Else
CompareFuncByText = 2
End If
Else
If strText1 < strText2 Then
CompareFuncByText = 2
ElseIf strText1 = strText2 Then
CompareFuncByText = 1
Else
CompareFuncByText = 0
End If
End If
Windowsのエクスプローラとは違う結果になるので比較の方法が違うのかな。
何故ファイル名がめちゃくちゃになるのでしょうか???
> strText1 = GetTextFromlParam(hwnd, lParam1, GetProp(hwnd, PROP_SORT_KEY))
もしかして、APIでソートしてます?
コントロールの標準機能だけでソートしているのなら、
ListItem経由で取れますけど、APIでソートしているなら、
項目の読み取りもAPIで行わないと。
>>strText1 = GetTextFromlParam(hwnd, lParam1, GetProp(hwnd, PROP_SORT_KEY))
>もしかして、APIでソートしてます?
strText1,strText2にはリストビュー上に表示されている日付が入ってきます。
なのでソート自体はAPIでは行っていないと思うのですが。
すみません自分で作った訳ではないのです。
ソースをいただいたところです。
http://www.mitene.or.jp/~sugisita/api_comct.html
「リストアイテムを数値型、日付型でソートする」をいただきました。
ほとんどカスタマイズは行っていません。
昇順降順にする機能が動作しなかったので呼び出しの時に指定して
昇順降順を可能にしました。
以下は呼び出し時-------
Private Sub 検索リスト_ColumnClick(ByVal ColumnHeader As MSComctlLib.ColumnHeader)
Static TextSortOrder As String
Static DateSortOrder As String
Select Case ColumnHeader.Index
Case 1 ' テキストでソート
Select Case TextSortOrder
Case "ASC"
TextSortOrder = "DESC"
Call ListView_SortItems(検索リスト, ColumnHeader.Index, lvwSortText, lvwSortDescending)
Case Else
TextSortOrder = "ASC"
Call ListView_SortItems(検索リスト, ColumnHeader.Index, lvwSortText, lvwSortAscending)
End Select
DateSortOrder = ""
Case 2 ' 日付でソート
Select Case DateSortOrder
Case "ASC"
DateSortOrder = "DESC"
Call ListView_SortItems(検索リスト, ColumnHeader.Index, lvwSortDate, lvwSortDescending)
Case Else
DateSortOrder = "ASC"
Call ListView_SortItems(検索リスト, ColumnHeader.Index, lvwSortDate, lvwSortAscending)
End Select
TextSortOrder = ""
End Select
検索リスト.Refresh
End Sub
どうか宜しくお願いします。
> なのでソート自体はAPIでは行っていないと思うのですが。
うそつきー。
サンプル見たら、思いっきり LVM_SORTITEMS が使われてるじゃないですか。
> http://www.mitene.or.jp/~sugisita/api_comct.html
> 「リストアイテムを数値型、日付型でソートする」をいただきました。
ここを見ると、
「大小比較を自前のコールバック関数に置き換えることで実現」
としっかり書いてありますねぇ。APIへコールバックしてますよって。
ベースはこれですかね。
http://support.microsoft.com/kb/170884/
チェックボックスの確認を、ListItem経由で行っているようですけど、
ここを、ListView_GetCheckStateマクロ……というか、
LVM_GETITEMSTATEメッセージ操作に置き換えて試してみてはどうかな。
でも、うまくいくかどうかは、試して無いので保証不可能なり。
すみません。
VB初めて・・・というかプログラムを本格的に始めて2週間。。
良く分からないのですが何とかしなくては。
下記のようなものを見つけました。
こういうことですよね。
Option Explicit
Private Declare Function SendMessage Lib "user32" _
Alias "SendMessageA" _
(ByVal hwnd As Long, ByVal wMsg As Long, _
ByVal wParam As Long, lParam As Any) As Long
Private Const LVM_FIRST = &H1000
Private Const LVM_GETITEMSTATE = (LVM_FIRST + 44)
Private Const LVIS_STATEIMAGEMASK = &HF000
'リストビューチェックボックスのチェック状態を取得する関数
Private Function LvwGetCheckState(lvwCTRL As ListView, _
lngIndex As Long) As Boolean
'lvwCTRL : リストビュー , lngIndex : アイテムのIndex
'戻り値 : BOOL値(True:チェックON, False:チェックOFF)
Dim lngState As Long
lngState = SendMessage(lvwCTRL.hwnd, LVM_GETITEMSTATE, _
lngIndex, ByVal LVIS_STATEIMAGEMASK)
LvwGetCheckState = (lngState And &H2000)
End Function
んで以下を修正。
If 検索リスト.ListItems(i).Checked = True Then
→If LvwGetCheckState(検索リスト, 検索リスト.ListItems(i).Index) = True Then
でも、上手くいかない。。
→If LvwGetCheckState(検索リスト, 検索リスト.ListItems(i).Index) = True Then
項目の読み取りもAPIで試してねって言ってるのにのにのに。
ListItemは使わずに試してくださいませ。
APIでソートしちゃったので、ListItemが保持しているIndexと、
実際の位置がずれているんじゃ無いかなーと想像してます。
外してたらごめんなさい。
>APIでソートしちゃったので、ListItemが保持しているIndexと、
>実際の位置がずれているんじゃ無いかなーと想像してます。
>外してたらごめんなさい
なるほどです。
Listitemを使用しないでIndexを取得しなくてはならないと言う事ですよね。
と言う事は以下で良いのでしょうか?
→If LvwGetCheckState(検索リスト, CLng(i)) = True Then
んー。上手くいかない。
難しいです。。
> Listitemを使用しないでIndexを取得しなくてはならないと言う事ですよね。
ListItemsコレクションのプロパティは、Indexだけじゃないでしょう。
検索リスト.ListItems(i).Text も使ってますよね。
それと、APIの場合、項目のIndexは、0から(VBは1から)始まるので注意。
http://support.microsoft.com/kb/170884/
をよく読んでいれば、APIでソートした場合、ListItemsコレクションが
ソートされないことや、その対処法として、ListView_GetListItem()関数
で項目のテキスト取得ができることが解かったはずだが。
ツイート | ![]() |