winapi — MFC / C ++ ComboBox: отключить отрисовку закрытия Dropdown & amp; открытие (заморозка пользовательского интерфейса)

Я только что добавил Пункт-Filter-Feature к 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));
}

Поэтому, когда пользователь печатает, длинный список элементов в DropDown фильтруется соответствующим образом. Пока все хорошо.

Размер / высота ListBox / DropDown не изменяется после его открытия. Это делает измените соответственно, когда открывается DropDown. Это означает, что если есть только 2 предмета, то DropDown имеет высоту только 2 предмета.

Моя проблема

Когда пользователь вводит текст, в который помещается только один элемент, DropDown высотой всего 1 элемент (это происходит с некоторыми рабочими процессами пользователя, то есть пользователь закрывает вручную & открывает DropDown).

Теперь, когда пользователь изменяет текст так, чтобы подгонять несколько элементов, высота остается на 1 элемент, и это выглядит странно, поскольку даже полоса прокрутки выглядит неправильно, поскольку она не помещается.

Что я пробовал до сих пор

  1. Я не могу использовать CComboBox::SetMinVisibleItems (или MSG за ним), так как он работает только в Unicode CharacterSet (который я не могу изменить в этом старом приложении) и начиная с WinVista (приложение работает на WinXP).
  2. Единственный другой вариант — закрыть и открыть DropDown, чтобы он правильно перерисовывался с правильной высотой (см. // Это делает DropDown «мерцающим» в исходном коде выше).

Теперь перейдя к варианту 2, я не хочу, чтобы пользователь видел закрытие и открывание («мерцание») DropDown после каждой нажатой клавиши.

Чтобы предотвратить это, я попробовал пару решений, которые нашел, но ни одно из них не работает в моем случае с ComboBox-DropDown. Вот список методов, которые я поставил перед ShowDropDown(false) и сразу после ShowDropDown(true),

  1. EnableWindow (ложь / истина);
  2. (Un) LockWindowUpdate ();
  3. SendMessage (WM_SETREDRAW, FALSE / TRUE, 0)

Со всеми тремя вызовами я все еще вижу закрытие / открытие DropDown.

У вас есть другие идеи, как я могу предотвратить это мерцание?

заранее спасибо
Соко

1

Решение

Это вопрос XY.

Должно быть проще использовать следующий подход для регулировки высоты ComboBox

  1. использование GetComboBoxInfo чтобы получить ручку управления списком.
  2. использование OnChildNotify или же ON_CONTROL_REFLECT и захватить CBN_DROPDOWN,
  3. В обработчике сообщения измените размер окна по мере необходимости. SetWindowPos и просто измените размер.
1

Другие решения

Других решений пока нет …