Создание ComboBox с одним или несколькими разделителями? - PullRequest
3 голосов
/ 04 декабря 2010

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

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

  1. Разделителем является простая серая линия нарисовано в центре предмета

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

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

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

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

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

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

Спасибо!


Редактировать: Работающий компонент см. В этой теме:

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

Ответы [ 3 ]

1 голос
/ 04 декабря 2010

То, что вы хотите, это нарисованный владельцем комбобокс. Смотрите это: http://delphi.about.com/od/vclusing/a/drawincombobox.htm

Кроме того, это, кажется, решает проблему отсутствия предмета у предмета: http://borland.newsgroups.archived.at/public.delphi.vcl.components.using.win32/200708/0708225320.html

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

Боже, благослови

1 голос
/ 03 февраля 2011

Я поиграл с созданием неприкасаемых элементов-разделителей (как описано в этот ответ ) и столкнулся с несколькими сбоями пользовательского интерфейса.Проблема состоит в том, что в комбинированных полях есть несколько аспектов их поведения, которые может быть трудно понять точно:

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

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

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

  1. Используйте комбинированное окно рисования владельца переменной высоты.
  2. Добавьте 3 пикселя к высоте для любых элементов, для которых требуется разделитель.
  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;
  }
}
0 голосов
/ 04 декабря 2010

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

...