【问题标题】:CComboBox not selecting CurSel when dropped downCComboBox 下拉时未选择 CurSel
【发布时间】:2016-07-29 21:39:57
【问题描述】:

我在对话框中有一个按字母顺序排序的组合框。此组合包含多个字符串,但有些字符串因大小写不同而重复。即我们有一个“开”和一个“开”,一个“关”和一个“关”。这似乎是多余的,但这是有原因的,尽管目前这并不重要。

重复项显然一个接一个地出现在列表中,大写的字符串在前。即:

关闭

关闭

开启

开启

当用户选择“开”(小写)时,正确的索引设置为CurSel,并显示正确的字符串。但是,当我单击组合框的箭头下拉列表时,它并没有突出显示CurSel,而是突出显示它之前的一个大写字符串。见下图。

这是在下拉列表中选择的:

这是展开下拉列表时在组合框中选择的内容。

我已经捕获了ON_CBN_DROPDOWN 消息,并检查了curcel 值,它与我预期的一样。

我也已经对这个组合框进行了子类化,以便我可以在此列表中以区分大小写的方式搜索字符串,因为我知道它没有正常实现,所以它可能是导致我的问题的原因。

但我不明白为什么在这个阶段字符串会覆盖curcel 值? CurSel 值不应该是用于选择相关项目的值吗?

任何关于如何解决此问题的想法将不胜感激。

编辑: 我试图通过覆盖OnWndMsg 来捕获CBN_DROPDOWN 消息。出现此消息时,我会在下拉菜单之前获得当前选定的项目(这是正确的项目)。然后我放下菜单,调用SetCurSel 来获取我之前检索到的内容。

BOOL CMyComboBox::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam,    LRESULT *pResult)
{
    if(message == CBN_DROPDOWN)
    {
        int nCurSel = GetCurSel();
        if(nCurSel != CB_ERR)
        {
            ShowDropDown();
            SetCurSel(nCurSel);
            return TRUE;
        }

    }
    return CComboBox::OnWndMsg(message, wParam, lParam, pResult);
}

这种 有效,但是当我取消焦点或再次单击下拉箭头以隐藏下拉菜单时,文本框中会显示错误的项目。这是一种有效的方法,还是我完全不在这儿? 折叠下拉菜单时会发送什么消息?

编辑 2: 我已经从code project 实现了区分大小写的组合框,效果很好。

【问题讨论】:

  • 你能用标准的非子类组合框重现这种行为吗?你能用其他完全非冗余的字符串来重现这种行为吗? “Apple”、“Pie”、“Foo”、“Bar”?我怀疑这个问题与你的子类化有关。
  • @MichaelWalz 是的,我可以使用非子类组合框来重现它。抱歉,问题的那部分措辞不清楚。我的意思是说,由于在列表中查找和选择字符串的功能仅以不区分大小写的方式完成,也许这就是导致我的问题的原因。并不是说组合框的子类化是原因。
  • 我也可以使用一个新生成的基于对话框的应用程序和一个包含“OFF”、“Off”、“ON”、“On”的排序组合框来重现它。看起来像一个 MSBug。但仅限于“下拉”类型。使用“droplist”类型,行为符合预期。
  • 最近我发现选择条目的内部机制不是使用FindStringExact。它使用 SelectString ,这意味着它将选择第一个条目。因此,与其做 updatedata 等,不如使用: FindStringExact 和带有该索引的 SetCurSel。见:stackoverflow.com/questions/36016759/…

标签: c++ winapi combobox mfc ccombobox


【解决方案1】:

进一步我的评论。我想你会发现,当它是 dropdown 样式时,内部机制正在使用 SelectString 来设置索引。

副作用是它可能无法从列表中为您选择正确的条目。因此,鉴于组合内容的性质,请尝试以下操作:

int iIndex = m_cbData.FindStringExact(-1, "On");
m_cbData.SetCurSel(iIndex);

或者

int iIndex = m_cbData.FindStringExact(-1, "OFF");
m_cbData.SetCurSel(iIndex);

但是,请注意,FindStringExact 的文档说搜索不区分大小写。但是SelectString(默认行为)更糟糕。

可以解决所有这些问题的另一种方法是使用 SetWindowText 并这样做。这样,列表框组件中的内容无关紧要。例如:

m_cbData.SetWindowText("On");
m_cbData.SetWindowText("ON");

并通过映射到字符串或直接使用 GetWindowText 来获取变量的值。

更新:有人已经完成了这项工作!这是一个区分大小写的 ComboBox 类:

http://www.codeproject.com/Articles/1363/Case-sensitive-ComboBox

【讨论】:

  • 很高兴知道这一点,并解释了为什么我看到了自己。我知道 FindStringExact 不区分大小写,并且我已经在我的自定义组合框类中重写了这个函数,所以它是。它为我传入的字符串返回正确的索引。但我的问题是,当我下拉列表时,选择了错误的项目(由于 SelectString 不区分大小写),但放在编辑框中的是基于此正确。是否会覆盖 SelectString 以使其区分大小写?不过,这可能会导致其他问题。
  • 是的,我倾向于让现有方法像宣传的那样有效。
  • 我想优雅的解决方案是从列表框派生,然后覆盖某些事件处理程序,但现在它已经超出了我的范围......
  • 效果很好。再次感谢安德鲁。我会将您的答案标记为解决方案。
猜你喜欢
  • 2018-09-17
  • 2021-09-16
  • 2016-08-03
  • 2011-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-01
相关资源
最近更新 更多