Суббота
16.12.2017
21:38


Форма входа

Приветствую Вас Гость | RSS
Borland Delphi 7
Главная Регистрация Вход
Главная » 2009 » Август » 19 » Программирование на основе Win32 API в Delphi
Программирование на основе Win32 API в Delphi
08:54
Программирование на основе Win32 API в Delphi
Источник: www.codenet.ru
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.

Категория: Статьи участников клуба | Просмотров: 6288 | Добавил: delphi | Рейтинг: 0.0/0 |
Всего комментариев: 3
3  
Новейшая уникальная программа «Стройное тело» была разработана ведущими российскими экспертами-диетологами и эндокринологами (РАМН). Программа составит индивидуальную диету и разработает методику похудения исходя из Ваших личных параметров. При соблюдении данной диеты Вы похудеете больше чем на 10 кг в месяц. В первую неделю вы гарантированно потеряете 3-5кг лишнего веса.
http://tinyurl.com/d5pxa2m

2  
Нужна помощь Трифонов Александр
http://svkris.ru/help-me/63-trifonov-alexander.html - Трифонов Александр, 2010, г. Белгород, Россия
Диагноз: резидуально-органическое поражение центральной нервной системы, миотононический синдром с левосторонним гемисиндромом, мозжечковая недостаточность, задержка психоречевого развития, сколиоз 2 степени. Необходимо: курс лечения в клинике в Трускавце стоимостью 141 372 рублей.
Подробнее на сайте http://www.svkris.ru/help-me.html - Красноярский благотворительный фонд "Святая Кристина"

Need help Alexander Trifonov
http://svkris.ru/help-me/63-trifonov-alexander.html - Alexander Trifonov, 2010, Belgorod, Russia
Diagnosis: residual-organic lesion of the central nervous system, miotononichesky syndrome with left gemisindromom, cerebellar failure, delay psychoverbal development, scoliosis 2 degrees. You need: a course of treatment in a clinic in Truskavets worth 3366 euros.
Read more: http://www.svkris.ru/help-me.html - Krasnoyarsk charity "Holy Kristina"

1  
http://mamont-creative.ru/stat/417-venecianskiy-karnaval-prazdnik-izyskannosti-i-bogatstva-ili-pochemu-ya-vlyubi las-v-gorod-kazanovy-.html - Венецианский карнавал - праздник изысканности и богатства, или Почему я влюбилась в город Казановы ...

Имя *:
Email *:
Код *:
Меню сайта

Разделы новостей
Программные обеспечения [6]
Учебники и справочники Delphi [15]
Лабораторные работы [2]
Статьи участников клуба [36]
Советы и трюки [1]

Календарь новостей
«  Август 2009  »
ПнВтСрЧтПтСбВс
     12
3456789
10111213141516
17181920212223
24252627282930
31

Поиск

Друзья сайта

Мини-чат

Наш опрос
Оцените мой сайт
Всего ответов: 71

Статистика

Copyright MyCorp © 2017