【问题标题】:How to get the sort order in Delphi as in Windows Explorer?如何像在 Windows 资源管理器中一样在 Delphi 中获取排序顺序?
【发布时间】:2011-07-05 07:37:19
【问题描述】:

总结:

  1. 我使用过的术语 寻找似乎是“自然的 排序”。
  2. 对于操作系统中的行为:

    • 对于 Windows(版本 >= XP),Windows 资源管理器利用自然 排序。
    • 对于 Linux 终端:使用“ls -v”而不是普通的“ls”来获得自然 排序。
  3. 对于在 Delphi 中编程,使用 StrCmpLogicalW Windows API 来获得自然排序。

  4. 对于在 Delphi & Kylix & Lazarus 中编程,使用手工制作的函数来获取 自然排序:

===========================

以下文件名将在 Windows 资源管理器中按如下顺序排列:

test_1_test.txt

test_2_test.txt

test_11_test.txt

test_12_test.txt

test_21_test.txt

test_22_test.txt

例如,如果我把它们放在一个 TStringList 实例中并调用 Sort,排序顺序如下:

test_1_test.txt

test_11_test.txt

test_12_test.txt

test_2_test.txt

test_21_test.txt

test_22_test.txt

为了记录,上述文件名将在Cygwin的rxvt终端或Linux发行版如CentOS的xterm终端中排序,如下所示:

test_11_test.txt

test_12_test.txt

test_1_test.txt

test_21_test.txt

test_22_test.txt

test_2_test.txt

您能帮忙评论一下如何理解排序行为的这种差异吗?此外,是否可以获得与 Windows 资源管理器中相同的顺序?任何建议表示赞赏!

PS:我的 Windows 区域设置为中文,但我认为英文区域设置相同。

【问题讨论】:

  • 我之前注意到了这一点。 AFAICS,较新的 Windows 版本识别文件名中的数字,并将数字排序为数字而不是文本。
  • @ax:非常感谢您提供的信息!我现在就读!
  • 名称中包含数字的文件和文件夹的排序顺序:support.microsoft.com/kb/319827
  • @Jørn E. Angeltveit:谢谢,但这是猜测还是来自官方消息?

标签: windows sorting delphi collation


【解决方案1】:

StrCmpLogicalW 可以处理数字,另一种选择是CompareString

【讨论】:

  • 非常感谢您的建议!
  • 您能否帮忙评论一下在 Kylix(Kylix 编译的应用程序在 Linux 中运行)中实现相同功能的最佳实践是什么?
  • @Xichen Li:如果linux/posix没有类似的功能你就得自己写了...
  • 我明白了!谢谢你的建议!
【解决方案2】:

感谢 Anders - 答案是 StrCmpLogicalW;我在 Delphi 2009 源代码中没有找到它的声明,所以我在下面的测试中自己声明了它:

type
  TMyStringList = class(TStringList)
  protected
    function CompareStrings(const S1, S2: string): Integer; override;
  end;

function StrCmpLogicalW(P1, P2: PWideChar): Integer;  stdcall; external 'Shlwapi.dll';

function TMyStringList.CompareStrings(const S1, S2: string): Integer;
begin
  Result:= StrCmpLogicalW(PChar(S1), PChar(S2));
end;

procedure TForm11.Button2Click(Sender: TObject);
var
  SL: TMyStringList;

begin
  SL:= TMyStringList.Create;
  try
    SL.Add('test_1_test.txt');
    SL.Add('test_11_test.txt');
    SL.Add('test_12_test.txt');
    SL.Add('test_2_test.txt');
    SL.Add('test_21_test.txt');
    SL.Add('test_22_test.txt');
    SL.Sort;
    Memo1.Lines:= SL;
  finally
    SL.Free;
  end;
end;

【讨论】:

  • 非常感谢您的宝贵时间和热心帮助!您的示例代码很有帮助!
  • [错误] Test.pas(264):不兼容的类型:“Char”和“WideChar”。如何修复 (D7)?
  • @NGLN 由于不存在StrCmpLogicalA 版本,您应该在调用StrCmpLogicalW 之前将字符串转换为unicode,如果您有国家字符,可能使用MultiByteToWideChar 函数-msdn.microsoft.com/en-us/library/windows/desktop/…
猜你喜欢
  • 2014-06-05
  • 2013-02-24
  • 1970-01-01
  • 1970-01-01
  • 2012-08-01
  • 2016-12-20
  • 2023-03-21
  • 2014-05-16
相关资源
最近更新 更多