Вторник, 08.07.2025, 10:59
Главная
Регистрация
Вход
Мир софта!
Приветствую Вас Гость | RSS
Меню сайта
Категории каталога
Мои статьи [0]
WWW [42]
все про WWW технологии
Delphi и Pascal [23]
Delphi и Pascal
Программирование баз данных [0]
Программирование баз данных
JavaScript и DHTML [0]
JavaScript и DHTML
Perl [0]
Perl
Python [0]
Python
Active Server Pages [0]
Active Server Pages
Наш опрос
Какое радио ты любиш?
Всего ответов: 29
Главная » Статьи » Delphi и Pascal

Программирование на основе Win32 API в 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)
Автор: Александр Боковиков, Екатеринбург, Россия
Страничка: http://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)
Страничка: http://xcl.cjb.net/
E-Mail: http://www.infocity.kiev.ua/prog/delphi/content/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)
Страничка: http://xcl.cjb.net/
E-Mail: http://www.infocity.kiev.ua/prog/delphi/content/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 и построенные на основе него оконные классы:

  • TLiteWindow - класс окна, с возможностью subclass'инга;
  • TLiteDialog - класс немодального диалога;
  • TLiteDialogBox - класс модального диалога.

Библиотека может быть использована совместно с VCL. На первый взгляд, это возможность является абсурдной и ненужной, так как об экономии размера в этом случае не может быть и речи. Однако, иногда бывают моменты, когда реализация специфических оконных элементов на основе объектов TWinControl или TCustomControl может быть затруднена или неэффективна из-за их сложности и неочевидного поведения. В этом случае, можно реализовать такой элемент на базе класса TLiteWindow - он будет вести себя стандартным образом, как и полагается вести себя стандартному оконному элементу Win32.

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

Практический совет: при API-программировании программист должен сам следить за корректным освобождением многочисленных ресурсов, которые занимает программа во время выполнения. Поэтому, для облегчения этой задачи используйте какую-либо контролирующую утилиту, например MemProof или Numega BoundsChecker. Корректное освобождение занятых ресурсов крайне необходимо !

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

Вся документация необходимая для API-программирования содержится в поставляемых компанией Microsoft компакт-дисках с документацией под общим названием MSDN (Microsoft Developer's Network). Существует online-версия документации по адресу http://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

Базовый класс для окон и диалогов. Инкапсулирует в себе дескриптор окна и объявляет общую оконную процедуру. Реализует механизм 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


В прилагаемом примере, построенном на основе разработанной автором библиотеки API-программирования WinLite, рассматриваются следующие проблемы:

  • создание и показ окон;
  • создание и показ диалогов;
  • загрузка ресурсов;
  • работа с трэем;
  • активизация приложения по нажатию глобальной "горячей" клавиши;
  • "прилипание" окна к границам рабочей области экрана;
  • реализация графики OpenGL;
  • субклассинг стандартных элементов управления;
  • буферизация вывода в окно для устранения мерцания;
  • создание дополнительного потока и передача сообщений между потоками;
  • установка таймера.
Категория: Delphi и Pascal | Добавил: mirsoft (03.02.2008) | Автор: максим
Просмотров: 983 | Рейтинг: 0.0/0 |
Всего комментариев: 0
Имя *:
Email *:
Код *:
Форма входа
Поиск
Друзья сайта
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

| Copyright MyCorp © 2025 | Используются технологии uCoz |