![]() |
![]() ![]() ![]() ![]() |
|
Создание компонентов для KOL и MCK - Часть 1 - Создание невизуального KOL компонентаDelphi , Технологии , KOL и MCKВведение: Дорога из желтого кирпича С появлением KOL, а после и MCK в программировании под Delphi началась новая эпоха - стало возможно создавать быстро, быстрый и легкий код, не отказываясь от любимого языка. Но среди достоинств этого, на данной стадии развития - есть и недостатки, нехватка компонентов, сравнимая почти с нехваткой воздуха, и что самое главное, нехватка людей, которые могут их написать. Данная статья ставит себе целью изменить ситуацию и перевести написание компонентов для KOL и MCK из разряда "для избранных" в разряд "для всех". При этом она не в коей мере не ставит себе целью обучением вас Delphi, KOL, MCK считается, что эти знания у вас уже есть. Материал преподносится в форме "от простого к сложному", и так начнем. Создание не визуального KOL компонента: Шапка невидимка
TNewKOLUnVisual = object(TObj)
private
public
end;
Заметьте, что когда я сказал объект, я имел в виду именно объект, а не класс! Такова особенность модели наследования KOL, к ней придется привыкнуть. Данный переход на "устаревшую" модель обусловлен ее эффективностью и спецификой внутренней реализации, что дало возможность построить на ее основе KOL. Далее, чтобы наше повествование не было некой абстракцией, давайте перейдем на построение компонента, я взял за пример постройку AboutDialog. unit KOLMHAboutDialog;
interface
uses
KOL;
type
PMHAboutDialog =^TMHAboutDialog;
TKOLMHAboutDialog = PMHAboutDialog;
TMHAboutDialog = object(TObj)
private
public
end;
implementation
end.
Как можно заметить модуль называется, как и файл, знакомьтесь это шаблон компонента. После беглого просмотра можно увидеть две строки значение коих еще не объяснялось: PMHAboutDialog =^TMHAboutDialog; TKOLMHAboutDialog = PMHAboutDialog; Эти строки также результат специфики KOL, поскольку мы в KOL работаем не с самими объектами, а с указателями на них. Потому мы и написали первую строку. Вторая нужна для психологического успокоения нас и компилятора, поскольку механизм MCK, как мы увидим позже, использует именно этот тип. unit KOLMHAboutDialog;
interface
uses
KOL, Windows, ShellAPI;
type
TIconType = (itShell, itApplication, itCustom);
PMHAboutDialog =^TMHAboutDialog;
TKOLMHAboutDialog = PMHAboutDialog;
TMHAboutDialog = object(TObj)
private
FTitle: String;
FCopyRight: String;
FText: String;
FIcon: HIcon;
FIconType: TIconType;
public
property Title: String read FTitle write FTitle;
property CopyRight: String read FCopyRight write FCopyRight;
property Text: String read FText write FText;
property Icon: HIcon read FIcon write FIcon;
property IconType: TIconType read FIconType write FIconType;
end;
implementation
end.
Думаю, что никто для себя ничего нового не нашел. Но мог возникнуть вопрос, зачем все вынесено в свойства, когда в этом нет необходимости (чтение и запись идут напрямую), отвечу - как пример, и поскольку необходимости в этом действительно нет, мы переделаем код: unit KOLMHAboutDialog; interface uses KOL, Windows, ShellAPI; type TIconType = (itShell, itApplication, itCustom); PMHAboutDialog = ^TMHAboutDialog; TKOLMHAboutDialog = PMHAboutDialog; TMHAboutDialog = object(TObj) private public Title: String; CopyRight: String; Text: String; Icon: String; IconType: TIconType; end; implementation end. Если посмотреть размер, после этих несложных манипуляций уменьшился почти в 2 раза. Да, если кого удивило появление модулей Windows и ShellAPI, не пугайтесь, они понадобиться чуть позже. Ну что же пора вносить работоспособность в компонент, сделаем это добавив два метода Destroy и Execute: unit KOLMHAboutDialog;
interface
uses
KOL, Windows, ShellAPI;
type
TIconType = (itShell,itApplication,itCustom);
PMHAboutDialog = ^TMHAboutDialog;
TKOLMHAboutDialog = PMHAboutDialog;
TMHAboutDialog = object(TObj)
private
public
Title: String;
CopyRight: String;
Text: String;
Icon: HIcon;
IconType: TIconType;
destructor Destroy; virtual;
procedure Execute;
end;
implementation
destructor TMHAboutDialog.Destroy;
begin
DestroyIcon(Icon);
inherited;
end;
procedure TMHAboutDialog.Execute;
var
HWndOwner: THandle;
TMPIcon: HIcon;
begin
if Assigned(Applet) then
HWndOwner := Applet.Handle
else
HWndOwner := 0;
case IconType of
itShell: TMPIcon := 0;
itApplication: TMPIcon := Applet.Icon;
itCustom: TMPIcon := Icon;
end;//case
ShellAbout(HWndOwner, PChar(Title + '#' + Text), PChar(CopyRight), TMPIcon);
end;
end.
Начнем разбираться, Destroy (не забывайте virtual, а то компилятор не пустит). Фактически в нем идет освобождение ресурса иконки (Проверку на наличие иконки делать не надо, поскольку мы используем функцию DestroyIcon - если иконку уничтожить нельзя она вернет не нуль, но программа будет работать корректно), а далее выполнения Destroy предка. Метод Execute не должен вызывать испуга у людей знакомых с API. Вопрос может возникнуть только по поводу переменной Applet - это глобальная переменная из KOL типа PControl, аналог Application из Delphi. У наблюдательных читателей, возможно, возник вопрос: Destroy есть, а где Create? Будет, вот он: unit KOLMHAboutDialog;
interface
uses
KOL, Windows, ShellAPI;
type
TIconType = (itShell, itApplication, itCustom);
PMHAboutDialog = ^TMHAboutDialog;
TKOLMHAboutDialog = PMHAboutDialog;
TMHAboutDialog = object(TObj)
private
public
Title: String;
CopyRight: String;
Text: String;
Icon: HIcon;
IconType: TIconType;
destructor Destroy; virtual;
procedure Execute;
end;
function NewMHAboutDialog: PMHAboutDialog;
implementation
function NewMHAboutDialog:PMHAboutDialog;
begin
New(Result, Create);
end;
destructor TMHAboutDialog.Destroy;
begin
DestroyIcon(Icon);
inherited;
end;
procedure TMHAboutDialog.Execute;
var
HWndOwner: THandle;
TMPIcon: HIcon;
begin
if Assigned(Applet) then
HWndOwner := Applet.Handle
else
HWndOwner := 0;
case IconType of
itShell: TMPIcon := 0;
itApplication: TMPIcon := Applet.Icon;
itCustom: TMPIcon := Icon;
end;//case
ShellAbout(HWndOwner, PChar(Title + '#' + Text), PChar(CopyRight), TMPIcon);
end;
end.
Те кто задавали этот вопрос, наверное, ждали нечто иное чем внешнюю функцию NewMHAboutDialog, но ничего не поделаешь KOL. Помните, я говорил, что нам придется работать с указателями, да и ООП модель у нас на базе объектов, а не классов. Сама функция как мы видим, выделяет память для объекта. uses … {$ENDIF}, KOLMHAboutDialog; …
var
TMP: TKOLMHAboutDialog;
begin
TMP := NewMHAboutDialog;
TMP.Execute;
TMP.Free;
end;
Запустили, посмотрели - работает. var TMP: TKOLMHAboutDialog; begin TMP := NewMHAboutDialog(0); TMP.Execute; TMP.Free; end; Замечаете, мы фактически задаем ненужный параметр, да к тому же сама функция New потолстела (правда несильно). Тут мы выигрываем не много (байты), но это принципиальный момент. Много помалу - много! В этой статье описывается создание компонента для KOL и MCK, начиная с невизуального KOL-компонента. Автор объясняет принципы работы с указателями на объекты в КОЛ, а также показывает пример создания компонента AboutDialog. Он подчеркивает важность исполь Комментарии и вопросыПолучайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш
|
||||
©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007 | ||||