MFC/C++ ComboBox:禁用下拉列表关闭和打开(UI 冻结)的绘制



我刚刚将一个项目过滤器功能添加到一个名为CComboBox派生类ComboBoxFbp旧的 MFC 应用程序中。

BOOL CComboBoxFbp::OnEditChange()
{
CString csText;
if (m_wFbpMode & _FbpMode_UserTextFiltersList) {
GetWindowText(csText);
// This makes the DropDown "flicker"
// ShowDropDown(false);
// Just insert items that match
FilterItems(csText);
// Open DropDown (does nothing if already open)
ShowDropDown(true);
}
return FALSE;   // Notification weiterleiten
}
void CComboBoxFbp::FilterItems(CString csFilterText)
{
CString csCurText;
int nCurItem;
DWORD wCurCursor;
// Text/selection/cursos restore
GetWindowText(csCurText);
nCurItem = GetCurSel();
if (nCurItem != CB_ERR && nCurItem >= 0 && nCurItem < GetCount()) {
CString csCurItemText;
GetLBText(nCurItem, csCurItemText);
if (csCurItemText == csCurText)     csCurText = csCurItemText;
else                                nCurItem = CB_ERR;
} else {
nCurItem = CB_ERR;
}
wCurCursor = GetEditSel();
// Delete all items
ResetContent();
csFilterText.MakeLower();
// Add just the items (from the vector of all possibles) that fit
for (auto item : m_vItems)
{
CString csItemText = item.first;
csItemText.MakeLower();
if (!csFilterText.IsEmpty() && csItemText.Find(csFilterText) < 0)
continue;
const int i = AddString(item.first);
SetItemData(i, item.second);
}
// Text/selection/cursos restore
if (nCurItem != CB_ERR)     SelectString(-1, csCurText);
else                        SetWindowText(csCurText);
SetEditSel(LOWORD(wCurCursor), HIWORD(wCurCursor));
}

因此,当用户键入时,下拉列表中的长项目列表将相应地进行过滤。到目前为止一切都很好。

列表框/下拉列表的大小/高度在打开后不会更改。当模具下拉列表打开时,它确实会相应地更改。这意味着如果只有 2 个项目,则下拉列表只有 2 个项目高。

我的问题

当用户输入仅一个项目适合的文本时,下拉列表的高度仅为 1 个项目(某些用户工作流会发生这种情况,即用户手动关闭并打开下拉列表(。

现在,当用户现在更改文本以使多个项目适合高度时,高度保持 1 个项目,看起来很奇怪,因为即使滚动条看起来也不正确,因为它不适合。

到目前为止我尝试过什么

  1. 我不能使用CComboBox::SetMinVisibleItems(或其背后的MSG(,因为它只能在Unicode CharacterSet(我无法在此旧应用程序中更改(和WinVista(应用程序在WinXP上运行(中工作。
  2. 唯一的其他选择是关闭并打开下拉列表,以便以正确的高度正确重绘它(请参阅//这使得下拉列表在上面的源代码中"闪烁">(。

现在使用选项 2,我不希望用户在他按下每个键后看到 DropDown 的关闭和打开("闪烁"(。

为了防止这种情况,我尝试了几种解决方案,但没有一种适用于我使用ComboBox-DropDown。这是我在ShowDropDown(false)之前和ShowDropDown(true)之后放置的方法列表。

  1. 启用窗口(假/真(;
  2. (取消(LockWindowUpdate((;
  3. 发送消息(WM_SETREDRAW, 假/真, 0(

在所有三个调用中,我仍然看到下拉菜单关闭/打开。

你们还有其他想法吗,我可以防止这种闪烁?

提前致谢 索科

这是一个XY问题。

使用以下方法来调整组合框的高度应该更容易

  1. 使用GetComboBoxInfo获取列表控件的句柄。
  2. 使用OnChildNotifyON_CONTROL_REFLECT并捕获CBN_DROPDOWN
  3. 在消息的处理程序中,根据需要调整窗口大小 使用SetWindowPos,只需更改大小。

最新更新