Главная » Delphi » Примеры разработки компонентов

0

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

Расширение возможностей компонентов оболочек для классов Win32

В некоторых случаях может  потребоваться расширение функциональных возмож ностей существующих  компонентов, особенно компонентов, инкапсулирующих клас сы элементов управления Win32. Рассмотрим, как этого  можно  добиться на примере расширения функций элементов управления TMemo и TListBox.

Компонент TddgExtendedMemo — расширение компонента TMemo

Несмотря на известную гибкость, компонент TMemo не дает возможности реализо вать некоторые полезные функции. В частности, он не позволяет управлять положе нием  курсора  вставки  с точки  зрения строк  и столбцов. Поэтому  расширим компо нент TMemo дополнительными открытыми свойствами.

Кроме того, иногда может понадобиться выполнять определенные действия вся

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

Исходный код компонента TddgExtendedMemo приведен в листинге 11.10.

Листинг 11.10. ExtMemo.pas — исходный  код компонента TddgExtendedMemo

unit ExtMemo;

interface uses

Windows, Messages, Classes, StdCtrls;

type

TddgExtendedMemo = class(TMemo)

private

FRow: Longint;

FColumn: Longint;

FOnHScroll: TNotifyEvent;

FOnVScroll: TNotifyEvent;

procedure WMHScroll(var Msg: TWMHScroll); message WM_HSCROLL;

procedure WMVScroll(var Msg: TWMVScroll); message WM_VSCROLL;

procedure SetRow(Value: Longint);

procedure SetColumn(Value: Longint);

function GetRow: Longint;

function GetColumn: Longint;

protected

// Методы диспетчеризации событий

procedure HScroll; dynamic;

procedure VScroll; dynamic;

publicproperty Row: Longint read GetRow write SetRow;

property Column: Longint read GetColumn write SetColumn;

published

property OnHScroll: TNotifyEvent read FOnHScroll

write FOnHScroll;

property OnVScroll: TNotifyEvent read FOnVScroll

write FOnVScroll;

end;

implementation

procedure TddgExtendedMemo.WMHScroll(var Msg: TWMHScroll);

begin

inherited;

HScroll;

end;

procedure TddgExtendedMemo.WMVScroll(var Msg: TWMVScroll);

begin

inherited;

VScroll;

end;

procedure TddgExtendedMemo.HScroll;

{ Это метод диспетчеризации события OnHScroll. Он проверяет, связан

ли обработчик с событием OnHScroll, и если да, вызывает его. }

begin

if Assigned(FOnHScroll) then

FOnHScroll(self);

end;

procedure TddgExtendedMemo.VScroll;

{ Это метод диспетчеризации события OnVScroll. Он проверяет, связан

ли обработчик с событием OnVScroll, и если да, вызывает его. }

begin

if Assigned(FOnVScroll) then

FOnVScroll(self);

end;

procedure TddgExtendedMemo.SetRow(Value: Longint);

{ Сообщение EM_LINEINDEX возвращает позицию первого символа строки,

заданной параметром wParam. В этом экземпляре в качестве wParam

используется параметр Value. Установка возвращаемого значения

SelStart устанавливает позицию курсора вставки в строке, заданной

параметром Value. }

begin

SelStart := Perform(EM_LINEINDEX, Value, 0);

FRow := SelStart;

end;

function TddgExtendedMemo.GetRow: Longint;

{ Сообщение EM_LINEFROMCHAR возвращает строку, в которой находится

символ, определяемый значением wParam. Если в качестве wParamпередается -1, то возвращается номер строки, в которой находится курсор вставки. }

begin

Result := Perform(EM_LINEFROMCHAR, -1, 0);

end;

procedure TddgExtendedMemo.SetColumn(Value: Longint);

{ Получает длину текущей строки с помощью сообщения EM_LINELENGTH.

Это сообщение принимает позицию символа как параметр WParam.

Возвращается длина строки, в которой находится этот символ. }

begin

FColumn := Perform(EM_LINELENGTH,

Perform(EM_LINEINDEX, GetRow, 0), 0);

{ Если значение FColumn больше значения, переданного в

процедуру, то это значение присваивается переменной FColumn. }

if FColumn > Value then FColumn := Value;

// SelStart получает значение найденной позиции

SelStart := Perform(EM_LINEINDEX, GetRow, 0) + FColumn;

end;

function TddgExtendedMemo.GetColumn: Longint;

{ Сообщение EM_LINEINDEX возвращает индекс строки символа,

переданного в качестве параметра wParam. Если wParam равен -1, то

возвращается индекс текущей строки. Отнимая это значение от

SelStart, получаем положение столбца. }

begin

Result := SelStart – Perform(EM_LINEINDEX, -1, 0);

end;

end.

Прежде всего рассмотрим добавленную в компонент TddgExtendedMemo информа цию о строках и столбцах. Обратите внимание, что  в этот  компонент было  добавлено два закрытых поля: FRow и FColumn. Данные поля предназначены для хранения значе ний строки и столбца курсора  вставки. Заметьте также,  что определены открытые свой ства Row и Column. Эти свойства объявлены в разделе public, так как во время  разра ботки  они  не нужны.  Оба  они  обладают  методами доступа —  как для записи, так и для чтения. В качестве методов доступа  к свойству  Row используются методы  GetRow() и SetRow(), а к свойству  Column —  методы  GetColumn() и SetColumn(). На  практике можно  было бы обойтись без полей  FRow и FColumn, так как доступ к свойствам Row и Column осуществляется с помощью соответствующих методов доступа; но мы оставили их, чтобы иметь возможность для дальнейшего расширения компонента.

Четыре упомянутых  выше  метода  доступа  используют различные сообщения EM_XXXX. Комментарии в коде поясняют, что  происходит в каждом  методе  и как эти сообщения  используются для  обеспечения компонента информацией  о  значениях Row и Column. Компонент TddgExtendedMemo вводит  также два события: OnHScroll и OnVScroll. Событие OnHScroll происходит, когда пользователь щелкает  на гори зонтальной полосе  прокрутки, а событие OnVScroll — когда пользователь щелкает  на вертикальной полосе  прокрутки. Для  обнаружения  этих  событий необходимо пере хватить  сообщения  Win32   WM_HSCROLL и  WM_VSCROLL,  передаваемые  в  элементуправления, когда пользователь щелкает  на одной  из его полос  прокрутки. Для этого созданы  два обработчика сообщений — WMHScroll() и WMVScroll(), — которые вы зывают  методы  диспетчеризации событий HScroll() и VScroll(), а те, в свою оче редь,  проверяют, назначил ли пользователь компонента обработчики событиям OnHScroll и OnVScroll, а затем вызывают их. Если вас удивляет,  почему эта провер ка не выполняется в обработчиках сообщений, то объяснение заключается в обеспе чении возможности вызывать обработчик событий в результате выполнения других действий, например изменения пользователем позиции курсора вставки.

Теперь компонент TddgExtendedMemo можно  установить и использовать в любом приложении. Можно  также подумать о расширении этого  компонента (к примеру, ко гда пользователь изменяет позицию курсора  вставки, владельцу  элемента посылается сообщение WM_COMMAND). Функция  HiWord(wParam) содержит уведомляющий код, подтверждающий выполнение определенного действия. Данный код мог бы иметь значение EN_CHANGE, наличие которого говорило бы об изменении сообщения, свя занного с редактируемым элементом. Затем  можно  сделать  подкласс  данного компо нента  родительским и перехватывать это сообщение в родительской процедуре окна, которая автоматически обновит поля  FRow и FColumn. Подклассы —  еще  одна  слож ная тема, обсуждение которой еще предстоит.

Источник: Тейксейра, Стив, Пачеко, Ксавье.   Borland Delphi 6. Руководство разработчика. : Пер.  с англ. — М. : Издательский дом “Вильямс”, 2002. —  1120 с. : ил. — Парал. тит. англ.

По теме:

  • Комментарии