Я поиграл с созданием неприкасаемых элементов-разделителей (как описано в этот ответ ) и столкнулся с несколькими сбоями пользовательского интерфейса.Проблема состоит в том, что в комбинированных полях есть несколько аспектов их поведения, которые может быть трудно понять точно:
- Нажатие клавиш со стрелками вверх и вниз перемещает список, пока список выпадает.
- Нажатие Enter закрывает выпадающий список, выбирая текущий элемент.
- Нажатие Escape закрывает выпадающий список, выбирая текущий элемент (если текущий элемент был выбран с помощью клавиш со стрелками вверх и вниз) илипоследний выбранный элемент.
- Если поле со списком имеет фокус, то нажатие клавиш со стрелками вверх и вниз изменяет текущий выбор без отображения списка.
- Если поле со списком имеет фокусзатем ввод чего-либо выбирает элемент комбинированного списка, совпадающий с тем, что печатается.
- Если поле комбинированного списка имеет фокус, то нажатие клавиши F4 приводит к раскрытию списка комбинированного списка, которым можно управлять с помощью клавиатуры или мыши.
Обеспечение того, чтобы отключенные элементы-разделители не реагировали на любые этих событий (pluЛюбые другие события, которые я могу пропустить, например, программы чтения с экрана?) кажутся чреваты ошибками.
Вместо этого я использую подход, чтобы нарисовать разделитель как часть элемента:
- Используйте комбинированное окно рисования владельца переменной высоты.
- Добавьте 3 пикселя к высоте для любых элементов, для которых требуется разделитель.
- Нарисуйте горизонтальную линию вверху каждого элемента, нуждающегося в этомразделитель.
Вот код C ++ Builder для этого;перевести его на Delphi должно быть достаточно просто.
void __fastcall TForm1::ComboBox1DrawItem(TWinControl *Control,
int Index, TRect &Rect, TOwnerDrawState State)
{
bool draw_separator = NeedsSeparator(Index) &&
!State.Contains(odComboBoxEdit);
TCanvas *canvas = dynamic_cast<TCustomCombo*>(Control)->Canvas;
canvas->FillRect(Rect);
TRect text_rect = Rect;
// Add space for separator if needed.
if (draw_separator) {
text_rect.Top += 3;
}
canvas->TextOut(text_rect.Left + 3,
(text_rect.Top + text_rect.Bottom) / 2 -
canvas->TextHeight(ComboBox1->Items->Strings[Index]) / 2),
ComboBox1->Items->Strings[Index]);
// Draw a separator line above the item if needed.
if (draw_separator) {
canvas->Pen->Color = canvas->Font->Color;
canvas->MoveTo(Rect.Left, Rect.Top + 1);
canvas->LineTo(Rect.Right, Rect.Top + 1);
}
}
void __fastcall TForm1::ComboBox1MeasureItem(
TWinControl * /* Control */, int Index, int &Height)
{
Height = ComboBox1->ItemHeight;
// Add space for the separator if needed.
if (Index != -1 && NeedsSeparator(Index)) {
Height += 3;
}
}