如何像在 Windows 资源管理器中一样在 Delphi 中获取排序顺序?

Posted

技术标签:

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

总结:

    我使用过的术语 寻找似乎是“自然的 排序”。

    对于操作系统中的行为:

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

    对于在 Delphi 中编程,使用 StrCmpLogicalW Windows API 来获得自然排序。

    对于在 Delphi & Kylix & Lazarus 中编程,使用手工制作的函数来获取 自然排序: (1) Martin Pool 用于自然顺序字符串比较的 Delphi 包装器。http://irsoft.de/web/strnatcmp-and-natsort-for-delphi (2) 来自davekeolle网站的其他语言的字母排序算法代码。http://www.davekoelle.com/alphanum.html (3) 其他知识页面:http://www.codinghorror.com/blog/2007/12/sorting-for-humans-natural-sort-order.htmlhttp://objectmix.com/delphi/722211-natural-sorting-optimizing-working-solution.htmlhttp://groups.google.com/group/borland.public.delphi.language.delphi.general/browse_thread/thread/1141d49f8bbba577http://objectmix.com/delphi/401713-alphanumeric-sort-routine-delphi.html

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

以下文件名将在 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 区域设置为中文,但我认为英文区域设置相同。

【问题讨论】:

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

以上是关于如何像在 Windows 资源管理器中一样在 Delphi 中获取排序顺序?的主要内容,如果未能解决你的问题,请参考以下文章

如何获得完整的 unicode 支持,包括 VCL 控件中的中文字符或 XP 上的 Windows 通用控件,就像在 Win7 中一样

如何在 Windows 资源管理器中添加“在此处打开 git-bash ...”上下文菜单?

如何在 Windows 资源管理器中刷新文件的缩略图?

如何在 Windows 11 的 Windows 资源管理器中添加“Git Bash Here”上下文菜单选项?

如何像 Windows 任务管理器中显示的那样获得可用的物理内存

windoes任务管理器中的“句柄数”是啥意思!