ListViewのサイズカラムでソートするには?


たま  2003-11-25 03:08:10  No: 5731

プログラミング勉強中です。

ListViewで、ファイルサイズのカラムをクリックしたとき、
サイズの大小でソートせず、文字列の順番としてソートされてしまいます。
具体的には次のとおり。

(ソート前)
カラム1    サイズ
aaaaaa     1234 KB
bbbbbb     555 KB
cccccc     1280 KB

(昇順ソート後)
カラム1    サイズ
aaaaaa     1234 KB
cccccc     1280 KB
bbbbbb     555 KB

(こうなってほしい)
カラム1    サイズ
bbbbbb     555 KB
aaaaaa     1234 KB
cccccc     1280 KB

どのようにしたら、よろしいでしょうか。
よろしくお願いいたします。

環境
Delphi 6 personal + Windows2000


にしの  2003-11-25 04:49:55  No: 5732

TListViewって、カラムを押すと自動でソートしましたっけ?
SortTypeを設定して試してみましたがソートされませんでした
# D7Pro

自動でできるかどうかはさておき。
ソートする場合、AlphaSortかCustomSortを使用するかと思いますが、AlphaSortであれば、SortTypeをstNone以外にしておき、OnCompareイベントで比較してやればよいかと思います。
CustomSortであれば、比較用プロシージャを用意する必要があるので、各カラムごとにプロシージャを用意するなり、プロシージャ内で切り分けるなりすればできます。


Po  2003-12-01 09:03:31  No: 5733

Format使って桁指定して数字出力すればいいんじゃないでしょうか?


にしの  2003-12-01 17:59:21  No: 5734

Poさんへ。
数値をB, KB, MBにするのは、Formatでは無理では?Ifで、どの単位にするか切り分ける必要がありそうです。

APIを使えば1発変換ですね。

定義で、
{$EXTERNALSYM StrFormatByteSize64}
function StrFormatByteSize64(
    qdw: int64;
    pszBuf: PCHAR;
    uiBufSize: UINT
):PCHAR; stdcall;export;
{$EXTERNALSYM StrFormatByteSize64A}
function StrFormatByteSize64A(
    qdw: int64;
    pszBuf: PAnsiChar;
    uiBufSize: UINT
):PAnsiChar; stdcall;export;
{$EXTERNALSYM StrFormatByteSize64W}
function StrFormatByteSize64W(
    qdw: int64;
    pszBuf: PWideChar;
    uiBufSize: UINT
):PWideChar; stdcall;export;
として、実体を
function StrFormatByteSize64; external 'shlwapi.dll' name 'StrFormatByteSize64A';
function StrFormatByteSize64A; external 'shlwapi.dll' name 'StrFormatByteSize64A';
function StrFormatByteSize64W; external 'shlwapi.dll' name 'StrFormatByteSize64W';
としておき、

var
  buf: array[0..512] of char;
begin
  Memo1.Lines.Add(StrFormatByteSize64(532, @buf[0], 511));
  Memo1.Lines.Add(StrFormatByteSize64(1340, @buf[0], 511));
  Memo1.Lines.Add(StrFormatByteSize64(23506, @buf[0], 511));
  Memo1.Lines.Add(StrFormatByteSize64(2400016, @buf[0], 511));
  Memo1.Lines.Add(StrFormatByteSize64(2400000000, @buf[0], 511));
end;

とすれば、
532 バイト
1.30 KB
22.9 KB
2.28 MB
2.23 GB
と出来ます。

IE5.0以降で使用できるAPIですので、使えないときもあります。


にしの  2003-12-01 18:00:09  No: 5735

書き忘れました。

StrFormatByteSize64に関する情報
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/shlwapi/string/strformatbytesize64.asp


Po  2003-12-02 09:43:44  No: 5736

すみません。単位変換のほうの説明は省略してました。
この辺りは自分でなんとかやってくれるだろうと思ってましたので(^^;
私が答えたのは
>サイズの大小でソートせず、文字列の順番としてソートされてしまいます。
の部分です。
このことから、たまさんは既に文字列のソートはできるのだと解釈します。Formatを使ってListViewに出力すれば、文字列の順番としてソートしていただければ
たまさんのご希望通りの動作になってくれると思います。

ヘルプより
>d  10進数。指定された桁数より少ないときは,結果の文字列の左側にゼロが埋め込まれる
実際にはゼロは表示には現れませんがソートには働いてくれますんで。
うろ覚えですが
var Size: Integer;
SubItems.Add(Format('%5d, [Size]));
こんな感じに出力すれば[00120]のようになると思います。
#実際には左側のゼロは見えません。

便利そうなAPIですねぇ
ソートもちゃんとなってくれそうですね(?
ところで、単位違ってもソートできるんでしょうかね


Po  2003-12-02 09:48:41  No: 5737

またまたすみません。
Size: Integer;
ではおそらくダメです。
Size: Extended;
とでもしておいてください。


にしの  2003-12-02 18:00:42  No: 5738

なるほど、例えば、20, 1000という数値を、
'   20'
' 1000'
とすると言うことでしょうか。
そうすると、ListViewのカラム幅を小さくしたとき、
 20
1..
となってほしいのに、
 ..
1..
となってしまいますよ。
# ..は省略された部分
OnCompareで、直接数値を比較してやった方がスマートだと思いますが、どうでしょう。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加