Базы данныхИнтернетКомпьютерыОперационные системыПрограммированиеСетиСвязьРазное
Поиск по сайту:
Подпишись на рассылку:

Назад в раздел

Программирование на основе Win32 API в Delphi.

eManual - электронная документация
ПрограммыЖелезоДрайверыХостингЭнциклопедия рекламы

Программирование на основе Win32 API в Delphi
Оглавление
Введение Существующие решения Принципы построения API-библиотеки Библиотека WinLite Пример программы на основе библиотеки WinLite

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: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: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), так и многие сторонние - естественно, что размер вашей программы при этом увеличится. Невизуальные классы библиотеки ACL - http://a-press.ur.ru/pc/bokovikov Невизуальные классы библиотеки XCL - http://xcl.cjb.net JEDI Code Library - http://www.delphi-jedi.com Системные компоненты на Torry - http://www.torry.ru Заслуживает внимание работа Владимира Кладова по изменению функциональности обязательного модуля system.pas. Со времен первых версий Turbo Pascal этот модуль по умолчанию компонуется в исполняемый код программы. Код модуля реализует многие принципы и решения заложенные в синтаксис и логику языка Object Pascal, и изменение этого модуля позволяет модифицировать реализацию этой логики. Такое решение является специфичным для языка Object Pascal в отличие, например, от C/C++, где компилятор и абсолюдно все модули никак не связаны. Изменение модуля system.pas, а именно его разбиение на блоки и сокращение редко используемых участков кода позволило сократить постоянные (не переменные) издержки примерно на 8 кБ. Конечно, для больших проектов, такое сокращение может быть и незаметным, однако интересен сам принцип. Модифицированный модуль system.pas - http://xcl.cjb.net

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; субклассинг стандартных элементов управления; буферизация вывода в окно для устранения мерцания; создание дополнительного потока и передача сообщений между потоками; установка таймера.


  • Главная
  • Новости
  • Новинки
  • Скрипты
  • Форум
  • Ссылки
  • О сайте




  • Emanual.ru – это сайт, посвящённый всем значимым событиям в IT-индустрии: новейшие разработки, уникальные методы и горячие новости! Тонны информации, полезной как для обычных пользователей, так и для самых продвинутых программистов! Интересные обсуждения на актуальные темы и огромная аудитория, которая может быть интересна широкому кругу рекламодателей. У нас вы узнаете всё о компьютерах, базах данных, операционных системах, сетях, инфраструктурах, связях и программированию на популярных языках!
     Copyright © 2001-2024
    Реклама на сайте