В этой статье приводится усовершенствованный 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.
Все! Теперь Вы можете создать новое приложение и использовать компонент.
Author, Daniel
|