Создание Combobox с одним или несколькими элементами разделителя?

StackOverflow https://stackoverflow.com/questions/4354891

Вопрос

Я использую Delphi7, и я хотел бы иметь Combobox с предметами разделителя (как в всплывающих меню).

Я видел это красиво реализовано в Mozilla Sunbird (я знаю, это не Delphi ...) следующим образом:

  1. Предмет сепаратора - это простая серая линия, нарисованная в центре элемента

  2. Если вы наведите курсор на разделитель с помощью мыши, выбор не появляется

  3. Если пользователь нажимает на сепаратор, он также не выбран, и Combobox не крупный план.

№ 1 может быть реализован с помощью DrawItem. Я мог бы жить без № 2, потому что я понятия не имею об этом.

На нет 3, я прошу вашу помощь. Я понял, что прямо после закрытия сообщения CBN_CLOSEUP отправляется в Combobox.

Я подумал о подключении Window Proc, и если CBN_CLOSEUP отправляется на определенный Combobox, а затем противодействовать ему. Но я не уверен, если это лучшее решение, или, возможно, есть другие, более элегантные способы?

Каким бы ни было решение, я бы хотел иметь стандартное Combobox, которое правильно поддерживает тематику WinXP / Vista / 7.

Спасибо!


Редактировать: Для рабочего компонента, пожалуйста, смотрите эту тему:

Можете ли вы помочь перевести этот очень маленький компонент C ++ в Delphi?

Это было полезно?

Решение

То, что вы хотите, это совокупный совокупность. Видеть это: http://delphi.about.com/od/vclusing/a/drawincombobox.htm.

Кроме того, это, кажется, решает, что делает элемент не знакомый:http://borland.newsgroups.Archived.at/public.delphi.vcl.components.using.win32/200708/0708225320.html.

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

Бог благословил

Другие советы

Я играл с помощью непонятных элементов разделителя (как описано в Этот ответ) и столкнулся с несколькими глюками UI. Проблема в том, что комбо коробки имеют несколько аспектов их поведения, которые могут быть трудно получить точно:

  • Нажатие клавиш со стрелками вверх и вниз навидует список, пока список удаляется.
  • Нажатие ENTER закрывает выпавший список, выбирающий текущий элемент.
  • Нажатие Escape закрывает выпавший список, выбирая текущий элемент (если текущий элемент был выбран с помощью клавиш со стрелками вверх и вниз) или последним выбранным элементом.
  • Если в поле Combo имеет фокус, затем нажимая клавиши со стрелками вверх и вниз, чтобы изменить текущий выбор, не отображая список.
  • Если в поле «комбинированное поле» имеет фокус, то набрав все, что выбирает элемент Combo Box, соответствующий тем, что печатает.
  • Если в поле Combo имеет фокус, то нажатие F4 выпадает в списке поле Combo, который затем может управляться клавиатурой или мышью.

Обеспечение того, чтобы предметы отключенных сепараторов не отвечают на Любые Из этих событий (плюс любые другие события, которые мне не хватает, например, считыватели экрана?) Кажется, чреватой ошибкой.

Вместо этого подход, который я использую, - это нарисовать сепаратор как часть элемента:

  1. Используйте владелец переменных высоты.
  2. Добавьте 3 пикселей на высоту для любых предметов, которые нуждаются в разделителях.
  3. Нарисуйте горизонтальную линию в верхней части каждого элемента, нуждающегося в разделитель.

Вот несколько C ++ Code Code для достижения этого; Перевод его в 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;
  }
}

Если вы хотите, чтобы ваши контроли были хорошо использовать бесплатный SPTBXLIB. Отказ Он поддерживает компоненты Combo Style, которые всплывают всплывающее меню с линиями.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top