在Delphi中有效地填充组合框

siw*_*mas 4 delphi combobox delphi-xe3

需要在TComboBox中添加许多项目(超过10k)(我知道TComboBox不应该包含很多项目,但不能由我来改变它)而不添加重复项.所以我需要在添加之前搜索完整列表.我想避免使用TComboBox.items.indexof,因为我需要二进制搜索,但二进制查找在TStrings中不可用.

所以我创建了一个临时的Tstringlist,设置排序为true并使用find.但现在将临时Tstringlist分配回TComboBox.Items

(myCB.Items.AddStrings(myList)) 
Run Code Online (Sandbox Code Playgroud)

复制整个列表真的很慢.有没有办法移动列表而不是复制它?或者以其他方式高效填充我的TComboBox?

Rob*_*edy 6

没有办法将列表"移动"到组合框中,因为组合框的存储属于内部Windows控件实现.它不知道任何直接使用Delphi TStringList对象的方法.它提供的所有功能都是将一个项目添加到列表中的命令,TComboBox然后用于将每个项目从字符串列表中逐个复制到系统控件中.避免将数千个项目复制到组合框中的唯一方法是完全避免此问题,例如使用不同类型的控件或减少需要添加的项目数.

列表视图具有"虚拟"模式,您只需告诉它应该拥有多少项,然后当需要知道屏幕上可见内容的详细信息时,它会回调您的程序.不可见的项目不会占用列表视图实现中的任何空间,因此您可以避免复制.但是,系统组合框没有"虚拟"模式.您可能能够找到一些提供该功能的第三方控件.

减少需要放入组合框中的项目数量是您的下一个最佳选择,但只有您和您的同事具备必要的领域知识才能找到最佳方法.


ven*_*eis 4

正如 Rudy Velthuis 在评论中已经提到的那样,假设您正在使用CB_INITSTORAGE 消息VCL,那么CB_INITSTORAGE消息可能是一个选项:

SendMessage(myCB, CB_INITSTORAGE, myList.Count, 20 * myList.Count*sizeof(Integer));
Run Code Online (Sandbox Code Playgroud)

其中20是平均字符串长度。

结果(在 i5-7200U 和 20K 项目上,随机长度在 1 到 50 个字符之间):

  • CB_INITSTORAGE:~ 265ms
  • CB_INITSTORAGE:~215ms

因此,虽然您可以通过预分配内存来加快速度,但更大的问题似乎是糟糕的用户体验。用户如何在包含如此多项目的组合框中找到正确的元素?