クリックできないセパレーター項目を作成してみました (この回答で説明されています)。いくつかの UI の不具合に遭遇しました。問題は、コンボ ボックスの動作にいくつかの側面があり、正確に正しく表示するのが難しい場合があることです。
- リストがドロップダウンされている間、上矢印キーと下矢印キーを押すと、リスト内を移動します。
- Enter を押すとドロップダウン リストが閉じ、現在の項目が選択されます。
- Escape を押すとドロップダウン リストが閉じ、現在の項目 (現在の項目が上下矢印キーで選択されている場合) または最後に選択された項目が選択されます。
- コンボ ボックスにフォーカスがある場合、上下の矢印キーを押すと、リストを表示せずに現在の選択が変更されます。
- コンボ ボックスにフォーカスがある場合、何かを入力すると、入力内容に一致するコンボ ボックス項目が選択されます。
- コンボ ボックスにフォーカスがある場合、F4 キーを押すとコンボ ボックス リストがドロップダウンし、キーボードまたはマウスで制御できます。
無効化された区切り項目がこれらのイベントのいずれにも応答しないようにする (スクリーン リーダーなど、見逃している可能性のあるその他のイベントはありますか?) と、エラーが発生するようです。
代わりに、私が使用しているアプローチは、セパレーターをアイテムの一部として描画することです。
- 可変高のオーナー描画コンボ ボックスを使用します。
- セパレーターが必要なアイテムの高さに 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;
}
}