【问题标题】:How to load a large array of strings in to an MFC combobox control fast as possible?如何尽可能快地将大量字符串加载到 MFC 组合框控件中?
【发布时间】:2010-09-18 18:25:22
【问题描述】:

我有一个包含 1000 个字符串的数组要加载到组合框中。将字符串数组加载到组合框中的最快方法是什么?

除了遍历字符串列表,一次一个地将每个字符串放入组合框之外,还有其他方法吗?

以及如何将加载后的组合框数据复制到其他大约 10 个组合框?

【问题讨论】:

    标签: visual-c++ mfc combobox arrays


    【解决方案1】:

    如果您在 10 个组合框中重复了 1,000 个字符串,您可能需要考虑使用所有者绘制的组合框,它根据数组中的索引动态绘制字符串,而不是将它们存储在组合框中。速度更快,内存效率更高。查看在线帮助中的 DrawItem 方法和 DRAWITEMSTRUCT 结构。基本上,您会使用 InitStorageInsertString(如 NuSonic 所述)在您的组合框中创建 1000 个空白项,并覆盖 DrawItem 根据需要绘制的索引提取和绘制所需的字符串。

    【讨论】:

    • 这很痛苦,但这是快速的方法...... +1
    • 它将完成工作..我不会想到这一点。太棒了
    • 我遇到了同样的问题 - 我有 256 个组合框,我需要用 10 个项目填充每个组合框。每个组合框需要 2-3 毫秒来填充。我正在做上面建议的所有事情 - 将 16 个空项目插入组合框真的需要 2-3 毫秒吗?
    • 不确定需要多长时间,但大部分 MFC 的性能可能非常糟糕。一种可能的解决方法是扩大 256 个组合框的范围,使它们要么是全局的,要么是持续时间更长的类的一部分,因此它们不会经常被初始化和删除。
    • 旧线程(双关语),但如果您要加载 256 个独特的组合框,那么如果您有线程安全的代码库,线程可能会有所帮助。
    【解决方案2】:

    我不知道以原子方式加载多个字符串的任何方法,但是您可以采取一些措施来提高该过程的效率:

    • 在添加项目以预分配内存之前调用 CComboBox::InitStorage
    • 使用 InsertString 而不是 AddString 以防止在每次添加时触发排序(假设启用了 CBS_SORT 样式)

    【讨论】:

      【解决方案3】:

      owner data CListCtrl 可能比带有 DrawItem 的 CComboBox 更快。 这也有助于您将项目的子集复制到其他列表中,因为可以使用通用数据源。

      我建议这样做是因为包含 1000 个项目的 CComboBox 不会很有用。

      【讨论】:

        【解决方案4】:

        我会考虑使用选择列表而不是组合框来提高性能。

        在 UI 列表中插入许多项目时提高性能的一般经验法则是在插入之前调用并在插入之后将其设置回 true。

        这是正确的语法

        #define NB_ITEM 1000
        #define ITEM_LENGTH 10
        
        void CMFCComboDlg::InitMyCombo()
        {
            CString _strData;
            m_cbMyCombo.SetRedraw( FALSE );
        
            m_cbMyCombo.Clear();
        
            m_cbMyCombo.InitStorage(NB_ITEM, ITEM_LENGTH); 
        
            for( int i = 0; i < NB_ITEM; i++ )
            {
                _strData.Format( L"Test %ld", i );
                m_cbMyCombo.InsertString( i, _strData );
            }
        
            m_cbMyCombo.SetCurSel(0);
        
            m_cbMyCombo.SetRedraw( TRUE );
        }
        

        编辑:改进解决方案以包含 smacl 建议

        【讨论】:

        • 这个问题特指MFC,没有这个机制。
        • @nusonic - 是的,CWnd::SetRedraw(或 WM_SETREDRAW)。这实际上是一个很好的建议。太糟糕了,合气道说的是与 Win32/MFC 不同的语言(无论如何,检查是什么“选择列表”?)
        • 选择列表是一种经过优化的搜索对话框,可快速获取您想要的数据。浏览一千多条记录真的没有效果。
        • @Hapkido,改进上述代码的简单模式是添加一个 m_cbMyCombo.InitStorage(1000,10000);在 SetRedraw 之后,同意 1000 个项目对于 Combo 框来说太大了,并且替代 UI 将是一个好主意。
        • InitStorage 是一个很好的建议,我将它包含在我的解决方案中。但是,语法是 int InitStorage(int nNbItems, UINT nBytesPerItem );
        【解决方案5】:

        我遇到了这个问题并通过两种方式解决了它,具体取决于 # 个项目。设置为不绘制和初始化存储对我来说没有任何区别。让所有者绘制一个也是可行的,但我有大量的组合框。假设每个组合框都有一个固定列表,不改变内容,列表设置一次。

        非常大 # 项: 使用 SetWindowText 将组合框设置为 Simple/Disabled 以设置初始字符串,并在它旁边的一个小按钮打开一个对话框,让您在报告模式下的列表控件中选择组合中的数据项框(可以在对话框中完成任何操作)。

        中等#项目: 制作了一个自定义派生组合框类,该类覆盖 AddString、SelectString 并处理 OnDropDown。当您添加项目时,它会将它们放入一个临时向量中,然后在 SelectString 上(也可以执行 SetCurSel 覆盖),它会添加它找到并选择的一个项目。下拉时,它会重置组合框并添加所有项目并选择当前选定的项目。删除组合框的速度略有下降,但在项目数量较少时并不明显。

        它使我的对话框加载速度更快,并且在没有所有者绘制的情况下仍然可以正常工作。

        【讨论】:

          猜你喜欢
          • 2016-06-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-16
          • 2016-08-11
          • 2018-12-23
          • 1970-01-01
          相关资源
          最近更新 更多