Програмування на основі Win32 API в Delphi, Delphi, Програмування, статті

1. Введення


Будь-яку сучасну програму або програмну технологію можна представити як сукупність програмних “шарів”. Кожен з цих шарів виробляє свою власну роботу, яка полягає у підвищенні рівня абстракції вироблюваних операцій. Так, самий нижчий шар (шари) вводить поняття, які дозволяють абстрагуватися від використовуваного обладнання; наступний шар (шари) дозволяє програмістові абстрагуватися від складної послідовності викликів функцій, вводячи таке поняття як протокол і т.д. Практично в будь-якому сучасному програмному продукті можна знайти й виділити близько десятка послідовних шарів абстракції.

Абстракція від устаткування і низькорівневих протоколів вводиться в ядра операційних систем у вигляді бібліотек API (Application Program Interface). Однак сучасні тенденції призводять до необхідності абстрагування і від самих операційних систем, що дозволяє переносити програми з однієї операційної системи на іншу шляхом простої перекомпіляції (трансльовані програми, в основному, взагалі не вимагають ніяких дій з перенесення).

Абстракцію, яка доступна програмістові у вигляді бібліотек API можна назвати базовою. Це найнижчий рівень абстракції, який доступний для прикладного програмування. На рівні ядра системи доступні і більш низькі рівні абстракції, проте для їх використання необхідно розробляти спеціалізовані програми (драйвера, модулі). Базовий рівень абстракції (API) надає максимально широкі можливості для прикладного програмування і є найбільш гнучким. Однак, програмування з використанням API є набагато більш трудомістким і приводить до значно більших обсягів вихідного коду програми, ніж програмування з використанням додаткових бібліотек.

Додаткові бібліотеки поставляються з багатьма засобами розробки з метою зменшення трудомісткості і термінів розробки програм, що в підсумку призводить до підвищення їх конкурентоспроможності. Але застосування додаткових бібліотек абстракцій приводить до різкого збільшення розмірів компільованих програм, через те що в програму включається код використовуваних бібліотек, до того ж це включення часто буває неефективним – в програму включаються невживані ділянки коду. Крім того, чим більше рівень абстракції бібліотеки, тим складніше її код, і тим більше труднощів виникає при вирішенні складних задач. Доводиться враховувати безліч взаємозв’язків і взаємних впливів окремих елементів і процесів бібліотеки один на одного. Крім того, структура і функціональність будь-якої бібліотеки зазвичай розраховується на задоволення всіх потенційно виникаючих завдань, що призводить до її громіздкості і неефективності.

В Delphiвикористовується дуже потужна і складна бібліотека VCL (Visual Components Library), яка крім безпосередніх абстракцій вводить також і безліч своїх функціональних класів. У цій бібліотеці знаходяться компоненти для візуального відображення інформації, роботи з базами даних, з системними об’єктами, компоненти для роботи з Internet-протоколами, класи для написання своїх COM-об’єктів та багато іншого. Модулі бібліотеки підключаються до компіляції в міру необхідності, проте базовий розмір простого діалогового проекту з однією формою перевищує 300кб (із статично скомпонованою бібліотекою). І такий розмір в багатьох випадках може виявитися занадто великим, особливо якщо програма не вимагає великої функціональності в інтерфейсі.

Для вирішення цієї проблеми можна відмовитися від використання бібліотеки VCL, і програмувати, використовуючи базовий набір функцій Win32 API. Однак, якщо при розробці лінійних, недіалогових, нерезидентних програм не виникає ніяких труднощів, то розробка програм, що вимагають активної взаємодії з користувачем або системою, стає трудомісткою. Структурне програмування, що рекомендується в таких випадках, виявляється неефективним і трудомістким.

Дана стаття присвячена проблемі створення і використання компактної об’єктно-орієнтованої бібліотеки, яка б полегшила побудову невеликих і ефективних програм на основі Win32 API.


2. Існуючі рішення


Автору відомі три об’єктно-орієнтовані бібліотеки, які можна розглядати як альтернативу бібліотеці VCL при написанні компактних програм. Це бібліотеки класів XCL, ACL і KOL. Всі бібліотеки безкоштовні і поставляються у вихідних кодах.


















Бібліотека ACL (API control library)
Автор: Олександр Боковиков, Єкатеринбург, Росія
Сторінка: a-press.ur.ru/pc/bokovikov 
E-Mail: abb@adx.ru 
Класи і модулі: TFont, TFonts, TControl, TWinControl, TStdControl, TLabel, TEdit, TListBox, TButton, TCheckBox, TComboBox, TGroupBox, TProgressBar, TKeyboard


















Бібліотека XCL (Extreme class library)
Автор: Vladimir Kladov (Mr.Bonanzas)
Сторінка: xcl.cjb.net 
E-Mail: bonanzas@xcl.cjb.net 
Класи і модулі: XForm, XApplet, XCanvas, XPen, XBrush, XFont, ZDDB, ZHiBmp, ZDIBitmap, ZBitmap, ZIcon, ZGifDecoder, ZGif, ZJpeg, XLabel, XButton, XBevel, XPanel, XSplitPanel, XStatus, XGrep, XGroup, XCheckBox, XRadioBox, XPaint, XScroller, XScrollBox, XScrollBoxEx, XEdit, XNumEdit, XCombo, XGrid, XListView, XMultiList, XNotebook, XTabs, XTabbedNotebook, XCalendar, XGauge, XGaugePercents, XHysto, XHystoEx, XImageList, XImgButton, XTooltip, XCustomForm, XDsgnForm, XDsgnNonvisual, CLabel, CPaint, CButton, CEdit, CMemo, CCheckBox, CRadioBox, CListBox, CComboBox, ZList, ZMenu, ZPopup, ZMainMenu, ZPopupMenu, ZTimer, ZStrings, ZStringList, ZIniFile, ZThread, ZQueue, ZFileChange, ZDirChange, ZOpenSaveDialog, ZOpenDirDialog, ZTree, ZDirList, ZDirListEx, ZRegistry, ZStream, ZFileStream, ZMemoryStream, XStrUtils, XDateUtils, XFileUtils, XWindowUtils, XPrintUtils, XShellLinks, XJustOne, XJustOneNotify, XPascalUnit, XSysIcons, XCanvasObjectsManager, XRotateFonts, XFocusPainter, XFormsStdMouseEvents, XFormsStdKeyEvents, XFormAutoSizer, XAligner, XControlAutoPlacer, XMfcAntiFlicker, XSplitSizer, XResizeAntiFlicker, XCaretShower, XEditMouseSelect, XEditClipboard, XEditUndo, XListMouseSel, XListKeySel, XListEdit, ZNamedTags, XBtnRepeats, XBufLabels, XBackgrounds, XWndDynHandlers


















Бібліотека KOL (Key object library)
Автор: Vladimir Kladov (Mr.Bonanzas)
Сторінка: xcl.cjb.net 
E-Mail: bonanzas@xcl.cjb.net 
Класи і модулі: TObj, TList, TGraphicTool, TCanvas, TControl, TTimer, TTrayIcon, TStream, TStrList, TDirList, TIniFile

Як видно зі списку наведених для кожної бібліотеки класів, ці бібліотеки предендуют скоріше не на допомогу при написанні програм з використанням Win32 API, а намагаються створити більш високий рівень абстракції ніж API, по крайней мере в графічної частини (особливо це відноситься до XCL). Більше того, ієрархія і перелік об’єктів співпадають з відповідними структурами в бібліотеці VCL, що швидше за все пов’язано з бажанням авторів забезпечити логічну сумісність з VCL при побудові програм на основі цих бібліотек.

Дані бібліотеки не забезпечують мінімального розміру програми, за рахунок того що надають вищий рівень абстракції. Вони є компромісом між програмуванням з використанням VCL і програмуванням на чистому API.


3. Принципи побудови API-бібліотеки


тандартного видом API-програмування є структурне програмування. Приклади такого програмування на Win32 API є практично в будь-якій книжці по Borland Pascal, Borland C + +, Microsoft Visual C + + і інших систем розробки. Безліч прикладів API-програмування на С міститься в постачанні Microsoft Visual C + +.

Структурне програмування з віконними функціями, процедурами обробки команд, не в змозі забезпечити швидку і ефективну розробку програм. У сучасній ситуації більшість програмістів звикло до об’єктно-орієнтованого методу, з можливістю інкапсуляції, успадкування та перевизначення методів об’єктів. Таке програмування виявляється найбільш ефективним.

Крім того, для побудови ефективної API-бібліотеки перш за все потрібно з’ясувати, які завдання при роботі з Win32 API є найбільш трудомісткими. Практика показує, що найбільш незручним і трудомістким елементом є реалізація основного диспетчера логіки програми – віконній функції. Реалізація цієї функції в якості методу класу, а не простий глобальній функції, дозволила б поліпшити структуру коду і полегшити програмування шляхом інкапсулювання всіх змінних усередині віконного класу.

Програмування може бути ще більш полегшено, є возпользоваться механізмом message-процедур мови Object Pascal. Виклик цих процедур повністю лежить на компіляторі і кореневому об’єкті TObject і включає в себе методи Dispatch, DefaultHandler, а також всі методи, оголошені з директивою message. Таке решенієе дозволить повністю відмовитися від громіздкого оператора case у віконній функції.

Враховуючи все вищеперелічене автором була створена компактна бібліотека віконних класів WinLite. Ця бібліотека є мінімальною, вона не вводить вищих рівнів абстракції чим існують в Win32 API – вона тільки полегшує роботу, перекладом програмування в об’єктно-орієнтоване русло. Розмір бібліотеки дуже невеликий і вся вона поміщається в один модуль. Бібліотека реалізує базовий клас TLiteFrame і побудовані на основі нього віконні класи:


Бібліотека може бути використана спільно з VCL. На перший погляд, це можливість є абсурдною і непотрібною, оскільки про економію розміру в цьому випадку не може бути й мови. Проте, іноді бувають моменти, коли реалізація специфічних віконних елементів на основі об’єктів TWinControl або TCustomControl може бути утруднена або неефективна через їх складності та неочевидного поведінки. В цьому випадку, можна реалізувати такий елемент на базі класу TLiteWindow – він буде вести себе стандартним чином, як і годиться поводитися стандартному віконному елементу Win32.

Завдяки своїй простий архітектурі бібліотека може бути використана в многопоточной програмі. Звичайно, ви не зможете викликати методи класів одного потоку з іншого потоку без відповідної синхронізації. Проте, ви можете безперешкодно створювати віконні класи в різних потоках без блокування і синхронізації, а також посилати повідомлення віконних класів в іншому потоці.

Практична порада: при API-програмуванні програміст повинен сам слідкувати за коректним звільненням численних ресурсів, які займає програма під час виконання. Тому, для полегшення цієї завдання використовуйте будь-яку контролюючу утиліту, наприклад MemProof або Numega BoundsChecker. Коректне звільнення зайнятих ресурсів вкрай необхідно!

Для редагування шаблонів діалогів можна використовувати будь-який редактор ресурсів, наприклад Borland Resource WorkShop, правда він декілька незручний, а остаточний результат все одно доводиться коректувати вручну.

Вся документація необхідна для API-програмування міститься в поставляються компанією Microsoft компакт-дисках з документацією під загальною назвою MSDN (Microsoft Developer “s Network). Існує online-версія документації за адресою msdn.microsoft.com. Урізана версія MSDN, що містить основні файли допомоги, поставляється з Delphi.

Перш ніж ви вирішите працювати над своїм проектом в руслі Win32 API, подумайте, а навіщо вам це потрібно? У переважній кількості випадків розмір програми не має ніякого значення. Я не хочу сказати, що API-програмування складніше ніж VCL-програмування. У багатьох випадках легше вивчити і написати 10 викликів API з купою аргументів і розуміти, що відбувається, ніж написати 1 виклик простій, на перший погляд, VCL-інструкції і потім довго досліджувати нетрі VCL в пошуках відповіді. Просто API-програмування – це інша культура, до якої ви, можливо, не звикли. І первісна робота може викликати у вас сильне розчарування. API-програмування вимагає скрупульозності, ретельності і уважного вивчення документації.

Ті ж, хто наважився програмувати на API, поряд з бібліотекою WinLite можуть спільно використовувати невізуальні класи як зі складу VCL (модулі SysUtils, Classes), так і багато сторонніх – природно, що розмір вашої програми при цьому збільшиться.


Заслуговує на увагу робота Володимира Кладова по зміні функціональності обов’язкового модуля system.pas. З часів перших версій Turbo Pascal цей модуль за умовчанням компонується у виконуваний код програми. Код модуля реалізує багато принципів і рішення закладені в синтаксис і логіку мови Object Pascal, і зміна цього модуля дозволяє модифікувати реалізацію цієї логіки. Таке рішення є специфічним для мови Object Pascal на відміну, наприклад, від C / C + +, де компілятор і абсолюдно всі модулі ніяк не пов’язані. Зміна модуля system.pas, а саме його розбиття на блоки і скорочення рідко використовуваних ділянок коду дозволило скоротити постійні (не змінні) витрати приблизно на 8 кБ. Звичайно, для великих проектів, таке скорочення може бути і непомітним, проте цікавий сам принцип.



4. Бібліотека WinLite

//////////////////////////////////////////////////////////////////////////////// / / WinLite, бібліотека класів і функцій для роботи з Win32 API / / (C) Микола Мазуркін, 1999-2000
// _____________________________________________________________________________ / / Віконні класи
////////////////////////////////////////////////////////////////////////////////
unit WinLite;
interface
uses Windows, Messages;


Ініціалізацій структури


Оголошення структур, які використовуються для формування параметрів новостворюваних вікон і діалогів відповідно.

//////////////////////////////////////////////////////////////////////////////// / / Параметри для створення вікна
////////////////////////////////////////////////////////////////////////////////
type
TWindowParams = record
Caption : PChar;
Style : DWord;
ExStyle : DWord;
X : Integer;
Y : Integer;
Width : Integer;
Height : Integer;
WndParent : THandle;
WndMenu : THandle;
Param : Pointer;
WindowClass : TWndClass;
end;
//////////////////////////////////////////////////////////////////////////////// / / Параметри для створення діалогу
////////////////////////////////////////////////////////////////////////////////
type
TDialogParams = record
Template : PChar;
WndParent : THandle;
end;


Декларація базового класу TLiteFrame


Базовий клас для вікон і діалогів в Delphi. Інкапсулює в собі дескриптор вікна і оголошує загальну віконну процедуру. Реалізує механізм message-процедур.

////////////////////////////////////////////////////////////////////////////////
// TLiteFrame
// _____________________________________________________________________________ / / Базовий клас для об’єктів TLiteWindow, TLiteDialog, TLiteDialogBox
////////////////////////////////////////////////////////////////////////////////
type
TLiteFrame = class(TObject)
private
FWndCallback: Pointer;
FWndHandle : THandle;
FWndParent : THandle;
function WindowCallback(hWnd: HWnd; Msg, WParam, LParam:Longint):
Longint; stdcall;
protected
procedure WindowProcedure(var Msg: TMessage); virtual;
public
property WndHandle: THandle read FWndHandle;
property WndCallback: Pointer read FWndCallback;
public
constructor Create(AWndParent: THandle); virtual;
destructor Destroy; override;
end;


Декларація віконного класу TLiteWindow


Створення унікального класу вікна і створення вікна. Можливість субклассинга стороннього вікна.

////////////////////////////////////////////////////////////////////////////////
// TLiteWindow
// _____________________________________________________________________________ / / Віконний клас
////////////////////////////////////////////////////////////////////////////////
type
TLiteWindow = class(TLiteFrame)
private
FWndParams : TWindowParams;
FWndSubclass: Pointer;
protected
procedure CreateWindowParams(var WindowParams: TWindowParams); virtual;
public
procedure DefaultHandler(var Msg); override;
constructor Create(AWndParent: THandle); override;
constructor CreateSubclassed(AWnd: THandle); virtual;
destructor Destroy; override;
end;


Декларація діалогового класу TLiteDialog


Завантаження шаблону діалогу і створення діалогу.

////////////////////////////////////////////////////////////////////////////////
// TLiteDialog
// _____________________________________________________________________________ / / Діалоговий клас
////////////////////////////////////////////////////////////////////////////////
type
TLiteDialog = class(TLiteFrame)
private
FDlgParams : TDialogParams;
protected
procedure CreateDialogParams(var DialogParams: TDialogParams); virtual;
public
procedure DefaultHandler(var Msg); override;
constructor Create(AWndParent: THandle); override;
destructor Destroy; override;
end;


Декларація модального діалогового класу TLiteDialogBox


Завантаження шаблону діалогу і створення діалогу. Модальний показ діалогу.

////////////////////////////////////////////////////////////////////////////////
// TLiteDialogBox
// _____________________________________________________________________________ / / Модальний діалоговий клас
////////////////////////////////////////////////////////////////////////////////
type
TLiteDialogBox = class(TLiteFrame)
private
FDlgParams : TDialogParams;
protected
procedure CreateDialogParams(var DialogParams: TDialogParams); virtual;
public
procedure DefaultHandler(var Msg); override;
public
function ShowModal: Integer;
end;


Реалізація базового класу TLiteFrame

implementation
////////////////////////////////////////////////////////////////////////////////
// TLiteFrame
// _____________________________________________________________________________ / / Ініціалізація / фіналізація
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// / / Конструктор
////////////////////////////////////////////////////////////////////////////////
constructor TLiteFrame.Create(AWndParent: THandle);
begin
inherited Create; / / Запам’ятовуємо дескриптор батьківського вікна
FWndParent := AWndParent; / / Створюємо місце під блок зворотного виклику
FWndCallback := VirtualAlloc(nil,12,MEM_RESERVE or MEM_COMMIT,
PAGE_EXECUTE_READWRITE); / / Формуємо блок зворотного виклику
asm
mov EAX, Self
mov ECX, [EAX].TLiteFrame.FWndCallback
mov word ptr [ECX+0], $6858 // pop EAX
mov dword ptr [ECX+2], EAX // push _Self_
mov word ptr [ECX+6], $E950 // push EAX
mov EAX, OFFSET(TLiteFrame.WindowCallback)
sub EAX, ECX
sub EAX, 12
mov dword ptr [ECX+8], EAX // jmp TLiteFrame.WindowCallback
end;
end;
//////////////////////////////////////////////////////////////////////////////// / / Деструктор
////////////////////////////////////////////////////////////////////////////////
destructor TLiteFrame.Destroy;
begin / / Знищуємо структуру блоку зворотного виклику
VirtualFree(FWndCallback, 0, MEM_RELEASE); / / Знищення за умовчанням
inherited;
end;
////////////////////////////////////////////////////////////////////////////////
// TLiteFrame
// _____________________________________________________________________________ / / Функції обробки повідомлень
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// / / Функція зворотного виклику для отримання віконних повідомлень
////////////////////////////////////////////////////////////////////////////////
function TLiteFrame.WindowCallback(hWnd: HWnd; Msg, WParam, LParam: Integer):
Longint;
var
WindowMsg : TMessage;
begin / / Запам’ятовуємо дескриптор вікна, якщо це перший виклик віконної процедури
if FWndHandle = 0 then FWndHandle := hWnd; / / Формуємо повідомлення
WindowMsg.Msg := Msg;
WindowMsg.WParam := WParam;
WindowMsg.LParam := LParam; / / Обробляємо його
WindowProcedure(WindowMsg); / / Повертаємо результат назад системі
Result := WindowMsg.Result;
end;
//////////////////////////////////////////////////////////////////////////////// / / Віртуальна функція для обробки віконних повідомлень
////////////////////////////////////////////////////////////////////////////////
procedure TLiteFrame.WindowProcedure(var Msg: TMessage);
begin / / Розподіляємо повідомлення по обробникам
Dispatch(Msg);
end;


Реалізація віконного класу TLiteWindow

////////////////////////////////////////////////////////////////////////////////
// TLiteWindow
// _____________________________________________________________________________ / / Ініціалізація / фіналізація
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// / / Конструктор
////////////////////////////////////////////////////////////////////////////////
constructor TLiteWindow.Create(AWndParent: THandle);
begin
inherited; / / Формуємо параметри вікна
CreateWindowParams(FWndParams); / / Реєструємо клас вікна
RegisterClass(FWndParams.WindowClass); / / Створюємо вікно
with FWndParams do
CreateWindowEx(ExStyle, WindowClass.lpszClassName, Caption,
Style, X, Y, Width, Height,
WndParent, WndMenu, hInstance, Param
);
end;
//////////////////////////////////////////////////////////////////////////////// / / Конструктор елементу з субклассинга
////////////////////////////////////////////////////////////////////////////////
constructor TLiteWindow.CreateSubclassed(AWnd: THandle);
begin
inherited Create(GetParent(AWnd)); / / Зберігаємо віконну функцію
FWndSubclass := Pointer(GetWindowLong(AWnd, GWL_WNDPROC)); / / Зберігаємо дескриптор вікна
FWndHandle := AWnd; / / Встановлюємо свою віконну функцію
SetWindowLong(FWndHandle, GWL_WNDPROC, DWord(WndCallback));
end;
//////////////////////////////////////////////////////////////////////////////// / / Деструктор
////////////////////////////////////////////////////////////////////////////////
destructor TLiteWindow.Destroy;
begin / / Наш об’єкт – об’єкт субклассиннга?
if FWndSubclass = nil then
begin / / Знищуємо клас вікна
UnregisterClass(FWndParams.WindowClass.lpszClassName, hInstance); / / Знищуємо вікно
if IsWindow(FWndHandle) then DestroyWindow(FWndHandle);
end
else / / Відновлюємо стару віконну функцію
SetWindowLong(FWndHandle, GWL_WNDPROC, DWord(FWndSubclass)); / / Знищення за умовчанням
inherited;
end;
//////////////////////////////////////////////////////////////////////////////// / / Формування параметрів вікна за замовчуванням
////////////////////////////////////////////////////////////////////////////////
procedure TLiteWindow.CreateWindowParams(var WindowParams: TWindowParams);
var
WndClassName : string;
begin / / Формуємо ім’я класу
Str(DWord(Self), WndClassName);
WndClassName := ClassName+”:”+WndClassName; / / Заповнюємо інформацію про клас вікна
with FWndParams.WindowClass do
begin
style := CS_DBLCLKS;
lpfnWndProc := WndCallback;
cbClsExtra := 0;
cbWndExtra := 0;
lpszClassName := PChar(WndClassName);
hInstance := hInstance;
hIcon := LoadIcon(0, IDI_APPLICATION);
hCursor := LoadCursor(0, IDC_ARROW);
hbrBackground := COLOR_BTNFACE + 1;
lpszMenuName := “”;
end; / / Заповнюємо інформацію про вікно
with FWndParams do
begin
WndParent := FWndParent;
Caption := “Lite Window”;
Style := WS_OVERLAPPEDWINDOW or WS_VISIBLE;
ExStyle := 0;
X := Integer(CW_USEDEFAULT);
Y := Integer(CW_USEDEFAULT);
Width := Integer(CW_USEDEFAULT);
Height := Integer(CW_USEDEFAULT);
WndMenu := 0;
Param := nil;
end;
end;
////////////////////////////////////////////////////////////////////////////////
// TLiteWindow
// _____________________________________________________________________________ / / Функції обробки повідомлень
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// / / Оброблювач повідомлень за замовчуванням
////////////////////////////////////////////////////////////////////////////////
procedure TLiteWindow.DefaultHandler(var Msg);
begin / / Наш об’єкт – об’єкт субклассиннга?
if FWndSubclass = nil then / / Викликаємо системну функцію обробки повідомлень
with TMessage(Msg) do
Result := DefWindowProc(FWndHandle, Msg, WParam, LParam)
else / / Викликаємо стару віконну функцію обробки повідомлень
with TMessage(Msg) do
Result := CallWindowProc(FWndSubclass, FWndHandle, Msg, WParam, LParam);
end;


Реалізація діалогового класу TLiteDialog

////////////////////////////////////////////////////////////////////////////////
// TLiteDialog
// _____________________________________________________________________________ / / Ініціалізація / фіналізація
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// / / Конструктор
////////////////////////////////////////////////////////////////////////////////
constructor TLiteDialog.Create(AWndParent: THandle);
begin
inherited; / / Формуємо параметри діалогу
CreateDialogParams(FDlgParams); / / Створюємо діалог
with FDlgParams do
CreateDialogParam(hInstance, Template, WndParent, WndCallback, 0);
end;
//////////////////////////////////////////////////////////////////////////////// / / Деструктор
////////////////////////////////////////////////////////////////////////////////
destructor TLiteDialog.Destroy;
begin / / Знищуємо діалог
if IsWindow(FWndHandle) then DestroyWindow(FWndHandle); / / Знищення за умовчанням
inherited;
end;
//////////////////////////////////////////////////////////////////////////////// / / Формування параметрів діалогу за умовчанням
////////////////////////////////////////////////////////////////////////////////
procedure TLiteDialog.CreateDialogParams(var DialogParams: TDialogParams);
begin
DialogParams.WndParent := FWndParent;
DialogParams.Template := “”;
end;
//////////////////////////////////////////////////////////////////////////////// / / Обробка повідомлень за умовчанням
////////////////////////////////////////////////////////////////////////////////
procedure TLiteDialog.DefaultHandler(var Msg);
begin / / Значення, що повертаються за замовчуванням
with TMessage(Msg) do
if Msg = WM_INITDIALOG then Result := 1
else Result := 0;
end;


Реалізація модального діалогового класу TLiteDialogBox

////////////////////////////////////////////////////////////////////////////////
// TLiteDialogBox
// _____________________________________________________________________________ / / Ініціалізація / фіналізація
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// / / Формування параметрів діалогу за умовчанням
////////////////////////////////////////////////////////////////////////////////
procedure TLiteDialogBox.CreateDialogParams(var DialogParams: TDialogParams);
begin
DialogParams.WndParent := FWndParent;
DialogParams.Template := “”;
end;
//////////////////////////////////////////////////////////////////////////////// / / Активізація модального діалогу
////////////////////////////////////////////////////////////////////////////////
function TLiteDialogBox.ShowModal: Integer;
begin / / Формуємо параметри діалогу
CreateDialogParams(FDlgParams); / / Показуємо діалог
with FDlgParams do
Result := DialogBoxParam(hInstance, Template, WndParent, WndCallback, 0);
end;
//////////////////////////////////////////////////////////////////////////////// / / Обробка повідомлень за умовчанням
////////////////////////////////////////////////////////////////////////////////
procedure TLiteDialogBox.DefaultHandler(var Msg);
begin / / Значення, що повертаються за замовчуванням
with TMessage(Msg) do
if Msg = WM_INITDIALOG then Result := 1
else Result := 0;
end;
end.


5. Приклад програми на основі бібліотеки WinLite в Delphi  


У доданому прикладі, побудованому на основі розробленої автором бібліотеки API-програмування WinLite, розглядаються такі проблеми:

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*