MFC / C ++ ComboBox:禁用下拉菜单关闭和打开的图形绘制(UI冻结)

时间:2018-09-20 06:45:45

标签: c++ winapi combobox mfc ccombobox

我刚刚在名为CComboBox的派生类中添加了 Item-Filter-Feature 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));
}

因此,当用户键入内容时,DropDown中的长项列表将得到相应的过滤。到目前为止一切都很好。

ListBox / DropDown的大小/高度一旦打开就不会改变。 DropDown打开时,它会相应地更改。这意味着如果只有2个项目,则DropDown高度只有2个项目。

我的问题

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

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

到目前为止我尝试过的事情

  1. 我不能使用CComboBox::SetMinVisibleItems(或它后面的MSG),因为它只能在Unicode字符集(在旧应用程序中无法更改)和从WinVista开始(在WinXP上运行的应用程序)中工作。
  2. 唯一的其他选择是关闭并打开DropDown,以便以正确的高度正确地重绘它(请参见 //这将使DropDown在屏幕上的源代码中“闪烁” )。

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

为避免这种情况,我尝试了一些找到的解决方案,但在ComboBox-DropDown情况下都无法解决。这是我在ShowDropDown(false)之前和ShowDropDown(true)之后放置的方法的列表。

  1. EnableWindow(false / true);
  2. (Un)LockWindowUpdate();
  3. SendMessage(WM_SETREDRAW,FALSE / TRUE,0)

在所有三个呼叫中,我仍然看到DropDown的关闭/打开。

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

预先感谢 索科

1 个答案:

答案 0 :(得分:1)

这是一个XY问题。

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

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