Внешний вид сайта:

Заполнение в ComboBox (компонент)

В этой статье приводится усовершенствованный ComboBox, который заполняет текстовую область, в зависимости от ввода пользователя (автозаполнение), с возможными опциями.

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

В нашем случае, мы собираемся расширить компонент TComboBox непосредственно. Мы могли бы выбрать TCustomComboBox, но у него имеются различные published свойства в разных версиях Delphi.

Delphi делает эту задачу простой, предлагая маленький мастер. Из меню File -> New... выберите Component на первой вкладке New.

Появится простой мастер. Заполните соответственно:

  • Ancestor Type: TComboBox
  • Class Name: TFillComboBox
  • Palette Page: Samples (или любая другая, например "Standard")
  • Unit File Name: Выберите папку и файл для сохранения Вашей работы

Нажмите OK. Мы установим его позже.

Мастер создаст основной компонент, включая подпрограмму установки:

procedure Register;
begin
  RegisterComponents('Standard', [TFillComboBox]);
end;

Эта подпрограмма будет вызвана Delphi, когда Вы выберите установку пакета, включая этот файл.

Первый параметр RegisterComponents называет страницу палитры, где компонент будет установлен, второй - массив компонентов, которые будут установлены.

Добавление нового свойства

К нашему новому компоненту, мы добавим новой свойство AutomaticFillIn. Когда он установлен в True, мы будем искать элемент, соответствующий вводу пользователя и добавлять остаток к текстовому полю.

Поэтому мы должны объявить одну частную переменную, которая будет хранить знечение переключателя.

Поместив переменную в Published секцию, мы позволим пользователю изменять ее значение в Инспекторе Объектов.

private
  FAutomaticFillin: Boolean; 
  

procedure
 SetAutomaticFillin(const Value: Boolean);
published
  property AutomaticFillin: Boolean
    read FAutomaticFillin
    write SetAutomaticFillin
    default True;

procedure TFillComboBox.SetAutomaticFillin(
      const Value: Boolean);
begin
  FAutomaticFillin := Value;
end;

Обработка изменения текста пользователем

Чтобы узнать, когда пользователь изменяет текст в текстовом поле, мы должны отменить заданный по умолчанию обработчик сообщения для ComboBox.

protected
  procedure ComboWndProc(
    var Message: TMessage; ComboWnd: HWnd; ComboProc: Pointer
  ); override;

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

Напишите код модуля и сохраните файл:

unit FillComboBox;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, 
  Controls, Forms, Dialogs, StdCtrls;

type
  TFillComboBox = class(TComboBox)
  private
    FAutomaticFillin: Boolean;
    procedure SetAutomaticFillin(const Value: Boolean);
  protected
    procedure ComboWndProc(
      var Message: TMessage; ComboWnd: HWnd; 
          ComboProc: Pointer
    ); override;
  public
  published
    constructor Create(AOwner: TComponent); override;
    property AutomaticFillin: Boolean
      read FAutomaticFillin 
      write SetAutomaticFillin
      default True;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Standard', [TFillComboBox]);
end;

{ TFillComboBox }

procedure TFillComboBox.ComboWndProc(
  var Message: TMessage; ComboWnd: HWnd; ComboProc: Pointer
);
var
  I: Integer;
  CurrentText: String;
begin
  inherited ComboWndProc(Message, ComboWnd, ComboProc);
  // пропускаем обработку, если отключено
  if not FAutomaticFillin then
    Exit;
  // сначала проверим, была ли нажата клавиша BackSpace,
  // в этом случае не заполняем!
  if Message.Msg = WM_CHAR then
  begin
    // ищем все символы от 32 (Пробел) до 127 (Upper ANSI)
    if TWMChar(Message).CharCode in [$20..$7F] then
    begin
      // заполняем остальную часть текста
      // сохраняем текущий текст, который напечатал пользователь
      CurrentText := Text;
      // получаем первую строк, которая соответствует части текста
      I := SendMessage(Handle, CB_FINDSTRING, -1, LongInt(PChar(CurrentText))); 
      if I >= 0 then
      begin
        // найдено соответствие!
        // загружаем соответствие, и в позицию этой строки
        Text := Items.Strings[I];
        // выделим текст, который не был напечатан
        SelStart := Length(CurrentText);
        SelLength := Length(Text) - Length(CurrentText);
      end;
    end;
  end;
end;

constructor TFillComboBox.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FAutomaticFillin := True;
end;

procedure TFillComboBox.SetAutomaticFillin(const Value: Boolean);
begin
  FAutomaticFillin := Value;
end;

end.

Инсталляция компонента

Теперь нужно установить компонент, который Вы только что создали.

В меню Component -> Install Component... выберите свой FillComboBox.pas в поле Unit file name и нажмите OK.

Все! Теперь Вы можете создать новое приложение и использовать компонент.

Комментарии

Нет комментариев. Ваш будет первым!