Создание компонентов для KOL и MCK - Часть 2 - Создание невизуальных MCK объектов
Ведущий раздела KOL и MCK: Анатолий aka XVeL
Автор: Жаров Дмитрий aka Gandalf
WEB-сайт: http://kol.mastak.ru
Полную версию библиотеки KOL и MCK можно скачать здесь
Создание невизуальных MCK объектов: Нечего на Mirror пенять коль…
Возможно, после завершения прошлой главы у вас осталось двоякое
чувство, с одной стороны мы сделали KOL компонент, с другой не на йоту не
пододвинулись к MCK и компонентом в палитре пока и не пахнет. Для того,
что понять, как делать MCK компоненты, разберемся что это. Итак, если
посмотреть на код нашего проекта (KOL и MCK ) мы увидим строку: {$I
Unit1_1.inc} Посмотрев же сам файл, мы в нем увидим код, который
фактически создает компоненты и настраивает их свойства и подобное в
соответствии с нашими действиями во время разработки. Т.е. фактически MCK
компонент это инструмент, который позволяет изменять свои свойства
(аналогичные свойствам KOL компонента) и генерирует необходимые строки в
выше указанном файле. Возможно, самые шустрые уже все поняли и побежали
реализовать данный механизм вручную, но не торопитесь! Автор добавил в MCK
базовые классы, которые, переопределив часть методов, позволят нам
осуществлять этот механизм довольно просто. Приступим. Создадим файл
MCKMHAboutDialog.pas:
unit MCKMHAboutDialog;
interface
uses
KOL, KOLMHAboutDialog, Mirror, MCKObjs, Classes, Graphics;
type
TKOLMHAboutDialog = class(TKOLObj)
private
FTitle: String;
FCopyRight: String;
FText: String;
FIcon: TIcon;
FIconType: TIconType;
procedure SetTitle(const Value: String);
procedure SetCopyRight(const Value: String);
procedure SetText(const Value: String);
procedure SetIcon(const Value: TIcon);
procedure SetIconType(const Value: TIconType);
protected
function AdditionalUnits: string; override;
procedure SetupFirst(SL: TStringList; const AName,AParent, Prefix: String); override;
function SetupParams(const AName, AParent: String): String;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property Title: String read FTitle write SetTitle;
property CopyRight: String read FCopyRight write SetCopyRight;
property Text: String read FText write SetText;
property Icon: TIcon read FIcon write SetIcon;
property IconType: TIconType read FIconType write SetIconType;
end;
procedure Register;
implementation
constructor TKOLMHAboutDialog.Create(AOwner: TComponent);
begin
inherited;
FTitle := 'О программе "Программа"';
FCopyRight := 'CopyRight 1984-2001 Ваша Фирма';
FText := 'Программа';
FIcon := TIcon.Create;
FIconType := itApplication;
end;
destructor TKOLMHAboutDialog.Destroy;
begin
FIcon.Free;
inherited;
end;
function TKOLMHAboutDialog.AdditionalUnits;
begin
Result := ', KOLMHAboutDialog';
end;
procedure TKOLMHAboutDialog.SetupFirst(SL: TStringList; const AName, AParent, Prefix: String);
const
IconType2Str: array [TIconType] of String = ('itShell', 'itApplication', 'itCustom');
var
RsrcName, RsrcFile: String;
begin
inherited;
SL.Add(Prefix + AName + '.Title:=' + String2PascalStrExpr(Title) + ';');
SL.Add(Prefix + AName + '.CopyRight:=' + String2PascalStrExpr(CopyRight) + ';');
SL.Add(Prefix + AName + '.Text:=' + String2PascalStrExpr(Text) + ';');
if Icon.Empty then
SL.Add(Prefix + AName + '.Icon:=0;')
else
begin
RsrcName := UpperCase(ParentKOLForm.FormName + '_' + Name);
RsrcFile := ParentKOLForm.FormName + '_' + Name;
SL.Add(Prefix + AName + '.Icon:=LoadIcon(hInstance,' +
String2PascalStrExpr(RsrcName) + ')' + ';');
SL.Add(Prefix + ' {$R ' + RsrcFile + '.RES}');
GenerateIconResource(Icon, RsrcName, RsrcFile, fUpdated);
end;
SL.Add(Prefix + AName + '.IconType:=' + IconType2Str[IconType] + ';');
end;
function TKOLMHAboutDialog.SetupParams(const AName, AParent: String): String;
begin
Result := '';
end;
procedure TKOLMHAboutDialog.SetTitle(const Value: String);
begin
FTitle := Value;
Change;
end;
procedure TKOLMHAboutDialog.SetCopyRight(const Value: String);
begin
FCopyRight := Value;
Change;
end;
procedure TKOLMHAboutDialog.SetText(const Value: String);
begin
FText := Value;
Change;
end;
procedure TKOLMHAboutDialog.SetIcon(const Value: TIcon);
begin
FIcon.Assign(Value);
Change;
end;
procedure TKOLMHAboutDialog.SetIconType(const Value: TIconType);
begin
FIconType := Value;
Change;
end;
procedure Register;
begin
RegisterComponents('KOL Dialogs', [TKOLMHAboutDialog]);
end;
end.
Обратите внимания на названия файла, но более на название нашего класса
(TKOLMHAboutDialog) оно должно соответствовать тому, что объявляли в KOL
компоненте. Теперь поясним код. Наследуемся мы от класса TKOLObj, он
создан специально для создания не визуальных MCK компонентов - хотя ни кто
не мешает делать по-другому, но думаю, ваш путь станет
сложнее. Обращаю ваше внимание на то, что ни одна строка кода их MCK
части не попадет в исполняемый файл, то есть не гонитесь за оптимизацией -
это ничего не даст, не ловите байты - это никому не нужно, и уж конечно не
используйте ассемблер. Поймите, вы ни чем не улучшите ситуацию, а здоровье
не вернешь. Так же забудь о классическом (для VCL) обороте:
procedure TKOLMHAboutDialog.SetIconType(const Value: TIconType);
begin
if Value<>FiconType then
FIconType:=Value;
…
В MCK компоненте это не нужно, поскольку незаметно отражается на
быстродействии, в KOL это не нужно тоже, кто-то может сказать, как же так,
а вот так, довольно редко бывает так, чтобы эта проверка срабатывала, а
код увеличивается, чуть ли не в двое, если уж у вас такая ситуация, что вы
часто присваиваете одинаковые значения - вставьте проверку в код вашей
программы перед присваиванием. Я думаю, секции private и published
вас не смущают, поэтому на них останавливаться не будем. Перейдем к
процедурам из разделов protected и public. Первое что вам следует
запомнить - не забывайте ставить override в описании методов, иначе у вас
вряд ли что будет работать. Create и Destroy не получили нового смысла, в
Create вы можете указать значения компонента по умолчанию, что я и сделал.
Далее обратим взор к разделу protected. AdditionalUnits - этот метод
возвращает строку с названиями тех модулей, которые необходимы для работы
KOL компонента (тут только - KOLMHAboutDialog). Не забывайте запятые перед
модулями, но в конце запятую ставить не надо. Идем дальше SetupParams -
возвращает строку с параметрами функции New, но поскольку у нас, их нет,
мы вернули пустую строку. Если бы они были, нам надо было вернуть строку
вида ' Param1, Param2 …,ParamN ' запятой в конце также нет. SetupFirst
- вызывается раньше всех предшествующих функций, в ней добавляем,
необходимы строки, фактически устанавливаем значения свойств, которые мы
установили во время разработки. Здесь мы использовали inherited, чтобы
вызвать метод определенный у предка - он создаст вызов New функции, правда
уже с нашими новыми параметрами, ведь мы переопределили метод SetupParams.
Последний возможно непонятный момент:
if Icon.Empty then
SL.Add(Prefix + AName + '.Icon:=0;')
else
begin
RsrcName := UpperCase(ParentKOLForm.FormName + '_' + Name);
RsrcFile := ParentKOLForm.FormName + '_' + Name;
SL.Add(Prefix + AName + '.Icon:=LoadIcon(hInstance,' + String2PascalStrExpr(RsrcName) + ')' + ';');
SL.Add(Prefix + ' {$R ' + RsrcFile + '.RES}');
GenerateIconResource(Icon, RsrcName, RsrcFile, fUpdated);
end;
Но тут нет ничего страшного, просто создается файл ресурсов с
иконкой, GenerateIconResource стандартная функция KOL и MCK специально для
этого и созданная, она генерирует скрипт файл и компилирует ресурс.
Главное это сделать уникальное имя файла, мы поступаем просто, создаем его
из имени формы и имени компонента - уникальная комбинация. Ну что же,
добавим ресурс для иконки компонента, откомпилируем и получаем новый
компонент уже KOL и MCK . Работает!
|