logo site
Страницы
  • Карта Сайта
Реклама
Рубрики
  • Basic
  • C#
  • Flash
  • Net
  • Objective-C
  • Pascal
  • Ruby
  • SQL
  • Новости
  • Проектирование и архитектура
  • Фортран
Партнеры:
декабря
20

Программирование на базе Win32 API в Delphi

Автор: admin, размещено в: Pascal, комментарии: Комментариев нет

Любую передовую програмку либо программную технологию возможно предположить как совокупа программных “слоев”. Однако, каждый из данных слоев изготавливает вправду собственную свою работу, коя содержится в увеличении значения абстракции добросовестно выполняемых операций. Во всяком случае так, самый низший слой (слои) вводит понятия, которые дозволяют абстрагироваться от применяемого оборудования; грядущий слой (слои) разрешает программеру абстрагироваться от воистину трудоемкое очередности вызовов функций, вводя это понятие как протокол и т.п. Быть может практически во всяком взаправду современном по-особенному программном продукте можнож хладнокровно выявить и резко выделить в пределах 10-ка поочередных слоев абстракции.

Абстракция от оборудования и низкоуровневых протоколов вводится в ядра операционных систем повторяющий вид библиотек api (application program interface). Наконец, однако отчасти прогрессивные направленности глубоко приводят к надобности абстрагирования и от самих столь операционных систем, что разрешает сильно переносить программы с одной очень-то операционной системы на иную методом очень несложный перекомпиляции (транслируемые программы, как правило, вообщем не настоятельно совершенно просят практически никаких поступков по перенесению).

Абстракцию, коя мало-мальски доступна программеру торопливо повторяющий вид библиотек api возможно обычно именовать базисной. Кажется, это самый особенно маленький уровень абстракции, который в общем-то доступен для отчасти прикладного программирования. Надеюсь на уровне ядра системы в общем-то доступны и поболее совсем невысокие значения абстракции, впрочем для их применения нужно было проэктировать спец программы (драйвера, модули). Таким образом, столь базовый уровень абстракции (api) осторожно дает очень очень-то широкие полномочия для вполне прикладного программирования и относительно считается более столь эластичным. Так вот, однако, программирование с внедрением api относительно считается значительно наиболее особенно сложным и окончательно приводит к гораздо наибольшим размерам просто-таки начального кода программы, нежели программирование с применением вполне добавочных библиотек.

Дополнительные библиотеки поставляются со почти всеми средствами исследования имея цель убавления трудозатратности и сроков исследования программ, что в результате окончательно приводит к увеличению их конкурентноспособности. Но использование доп библиотек абстракций глубоко приводит к росту объемов откомпилированных программ, лишь потому что в програмку срабатывает код применяемых библиотек, кроме всего прочего данное подключение нередко постоянно посещает попросту малоэффективным - в програмку врубаются неиспользуемые участки кода. Кстати, кроме того, нежели более уровень абстракции библиотеки, тем труднее ее код, и тем более проблем гораздо встает во время выяснения взаправду трудоемких задач. Пожалуй, редко приходится самостоятельно учесть мало-мальски большое количество связей и вполне обоюдных воздействий по-своему отдельных составляющих и действий библиотеки приятель на приятеля. Вероятно, кроме того, текстура и работоспособность хоть какой библиотеки обыкновенно рассчитывается на ублажение всех потенциально окончательно образующихся задач, что специально приводит к ее громоздкости и неэффективности.

В delphi употребляется чрезвычайно однозначно сильная и просто-напросто трудная библиотека vcl (visual components library), коя кроме однозначно конкретных абстракций вводит и еще и полностью большое количество личных высокофункциональных классов. Говорят, в данной библиотеке пребывают составляющие для вправду зрительного отображения инфы, работы с базами этих, Полностью с системными объектами, составляющие для работы с internet-протоколами, классы для написания личных com-объектов и прочее. В конце концов, модули библиотеки подключаются к компиляции постепенно, но базисный объем обычнейшего по-человечески диалогового плана с одной формой скоро превосходит 300кБ (со взаправду статически скомпонованной библиотекой). В общем и таковой объем во почти всех вариантах правильно сможет окончательно оказаться очень столь немалым, вполне необыкновенно ежели программа срочно не просит немаленький функциональности в интерфейсе.

Для решения данной трудности можнож категорически отказаться от применения библиотеки vcl, и программировать, правильно используя базисный набор функций win32 api. Наверно, однако, раз при исследованию довольно-таки линейных, недиалоговых, нерезидентных программ поспешно не встает практически никаких проблем, то исследование программ, часто требующих очень интенсивного взаимодействия с юзером либо системой, делается трудозатратной. К счастью, по-человечески структурное программирование, советуемое при таких раскладах, как окончательно оказалось в целом малоэффективным и напросто сложным.

Данная заметка приурочена к задаче творения и применения малогабаритной объектно-ориентированной библиотеки, коя бы совершенно облегчила возведение не очень больших и просто-таки действенных программ на базе win32 api.

Автору знамениты 3 объектно-ориентированные библиотеки, которые можнож окончательно осматривать как кандидатуру библиотеке vcl при написании воистину малогабаритных программ. Видимо это библиотеки классов xcl, acl и kol. Действительно все библиотеки столь безвозмездны и поставляются очень-очень в начальных кодах.

Автор: Александр Боковиков, Екатеринбург, Российская Федерация

Классы и модули: tfont, tfonts, tcontrol, twincontrol, tstdcontrol, tlabel, tedit, tlistbox, tbutton, tcheckbox, tcombobox, tgroupbox, tprogressbar, tkeyboard

Классы и модули: x form , 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, xcustom form , xdsgn form , 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, x form sstdmouseevents, x form sstdkeyevents, x form autosizer, xaligner, xcontrolautoplacer, xmfcantiflicker, xsplitsizer, xresizeantiflicker, xcaretshower, xeditmouse select , xeditclipboard, xeditundo, xlistmousesel, xlistkeysel, xlistedit, znamedtags, xbtnrepeats, xbuflabels, xbackgrounds, xwnddynhandlers

Классы и модули: tobj, tlist, tgraphictool, tcanvas, tcontrol, ttimer, ttrayicon, tstream, tstrlist, tdirlist, tinifile

Как заметно из перечня приведенных для любой библиотеки классов, данные библиотеки предендуют предположительно на поддержка при написании программ с внедрением win32 api, а добровольно хотят сознательно сделать наиболее высочайший уровень абстракции нежели api, как минимум просто-таки в графической доли (очень-очень необыкновенно данное относится к xcl). Более того, иерархия и список объектов просто-напросто схожи с подходящими текстурами в библиотеке vcl, что наверное хладнокровно соединено с желанием творцов одновременно обеспечить очень-очень закономерную сопоставимость с vcl при построении программ на базе данных библиотек.

Данные библиотеки не гарантируют наименьшего объема программы, потому что спокойно дают наиболее высочайший уровень абстракции. По-видимому они относительно считаются компромисом меж программированием с применением vcl и программированием по-своему на чистом 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 - она лишь замечательно делает легче работу, переводом программирования в объектно-ориентированное русло. И все же размер библиотеки слишком не очень в общем-то большой и вся она вмещается в 1 модуль. Несомненно библиотека подробно продает базисный класс tliteframe и возведённые на базе него просто-напросто оконные классы:

tlitewindow - класс окошки, с вероятностью subclass’инга;

tlitedialog - класс немодального разговора;

tlitedialogbox - класс модального разговора.

Библиотека быть может применена общо с vcl. Следовательно на 1-ый взор, данное вероятность относительно считается особенно абсурдной и полностью негодной, потому что о экономии объема в такой ситуации лично не имеет возможности быть и речи. И действительно однако, время от времени часто случаются факторы, как скоро реализация однозначно нестандартных попросту оконных деталей на базе объектов twincontrol либо tcustomcontrol быть может затруднена либо слишком неэффективна в связи их трудности и неочевидного поведения. Так или иначе в данном варианте, возможно воплотить таковой составляющее на базе класса tlitewindow - он поведёт себя поистине обычным образом, как и окончательно надеется повести себя шаблонному налицо оконному составляющей win32.

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

Практический совет: при api-программировании разработчик по-человечески программного обеспечения обязан сам незаметно наблюдать вполне за корректным освобождением в целом множественных ресурсов, которые постепенно занимает программа при проведении. Поэтому, для облегчения данной задачки применяйте некоторую осуществляющую контроль утилиту, к примеру memproof или же numega boundschecker. Оказывается по-особенному корректное освобождение обычно занимающихся ресурсов очень нужно было !

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

Вся документация требуемая для api-программирования находится в поставляемых фирмой microsoft СD с документацией под налицо единым заглавием 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

Системные составляющие на torry - http://www.torry.ru

Заслуживает внимание работа Владимира Кладова по изменению функциональности непременного модуля system.pas. Короче, со лет первых версий turbo pascal данный модуль по умолчанию компонуется добросовестно в выполняемый код программы. По правде говоря, код модуля слепо продаст почти все основы и решения добросовестно заложенные в синтаксис и логику языка object pascal, и перемена данного модуля дозволяет слепо изменить реализацию данной логики. А кроме того такое решение относительно считается вправду специфическим для языка object pascal в различие, к примеру, от c/c++, где компилятор и абсолюдно все модули никак добровольно не соединены. Одним словом изменение модуля system.pas, а непосредственно его разбиение на блоки и уменьшение нечасто применяемых участков кода свободно разрешило ужать по-человечески многократные (Полностью не переменные) потери приблизительно на 8 кБ. Судя по всему конечно, для великих планов, это уменьшение быть может и особенно незначительным, впрочем совсем занимателен сам принцип.

Модифицированный модуль system.pas - http://xcl.cjb.net

////////////////////////////////////////////////////////////////////////////////

// winlite, библиотека классов и функций для работы с win32 api

// _____________________________________________________________________________

////////////////////////////////////////////////////////////////////////////////

unit winlite;

uses windows, messages;

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

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

caption : pchar;

style : dword;

exstyle : dword;

x : integer;

y : integer;

width : integer;

height : integer;

wndparent : thandle;

wndmenu : thandle;

param : pointer;

windowclass : twndclass;

end;

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

template : pchar;

wndparent : thandle;

end;

Базовый класс для окошек и разговоров. Не правда ли инкапсулирует внутри себя дескриптор окошки и категорически заявляет по-своему единую в целом оконную упражнение. Как ни странно специально реализует приспособление message-процедур.

////////////////////////////////////////////////////////////////////////////////

// _____________________________________________________________________________

// Базовый класс для объектов tlitewindow, tlitedialog, tlitedialogbox

////////////////////////////////////////////////////////////////////////////////

fwndcallback: pointer;

fwndhandle : thandle;

fwndparent : thandle;

function windowcallback(hwnd: hwnd; msg, wparam, lparam:longint):

longint; stdcall;

procedure windowprocedure( var msg: tmessage); virtual;

property wndhandle: thandle read fwndhandle;

property wndcallback: pointer read fwndcallback;

constructor create(awndparent: thandle); virtual;

destructor destroy; override;

end;

Создание оригинального класса окошка и творение окошка. Допустим возможность субклассинга более-менее постороннего окошка.

////////////////////////////////////////////////////////////////////////////////

// _____________________________________________________________________________

// Оконный воссоздаваемыми//////////////////////////////////////////////////////////

fwndparams : twindowparams;

fwndsubclass: pointer;

procedure createwindowparams( var windowparams: twindowparams); virtual;

procedure defaulthandler( var msg); override;

constructor create(awndparent: thandle); override;

constructor createsubclassed(awnd: thandle); virtual;

destructor destroy; override;

end;

Загрузка шаблона разговора и творение разговора.

////////////////////////////////////////////////////////////////////////////////

// _____________________________________________________________________________

// Диалоговый воссоздаваемыми//////////////////////////////////////////////////////////

fdlgparams : tdialogparams;

procedure createdialogparams( var dialogparams: tdialogparams); virtual;

procedure defaulthandler( var msg); override;

constructor create(awndparent: thandle); override;

destructor destroy; override;

end;

Декларация модального диалогового класса tlitedialogbox

Загрузка шаблона разговора и творение разговора. Удивительно, что модальный ужасно тосковавшую/////////////////////

// _____________________________________________________________________________

// Модальный диалоговый воссоздаваемыми//////////////////////////////////////////////////////////

fdlgparams : tdialogparams;

procedure createdialogparams( var dialogparams: tdialogparams); virtual;

procedure defaulthandler( var msg); override;

function showmodal: integer;

end;

////////////////////////////////////////////////////////////////////////////////

// _____________________________________________________________________________

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

constructor tliteframe.create(awndparent: thandle);

inherited create;

fwndparent := awndparent;

fwndcallback := virtualalloc(nil,12,mem_reserve or mem_commit,

page_execute_readwrite);

mov dword ptr [ecx+2], eax // push _self_

mov word ptr [ecx+6], $e950 // push eax

mov dword ptr [ecx+8], eax // jmp tliteframe.windowcallback

end;

end;

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

destructor tliteframe.destroy;

virtualfree(fwndcallback, 0, mem_release);

inherited;

end;

////////////////////////////////////////////////////////////////////////////////

// _____________________________________________________________________________

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

// Функция обратного вызова для получения оконных известий

////////////////////////////////////////////////////////////////////////////////

function tliteframe.windowcallback(hwnd: hwnd; msg, wparam, lparam: integer):

longint;

windowmsg : tmessage;

// Запоминаем дескриптор окошки, ежели данное 1 вызов вправду оконной упражнения

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);

dispatch(msg);

end;

////////////////////////////////////////////////////////////////////////////////

// _____________________________________________________________________________

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

constructor tlitewindow.create(awndparent: thandle);

inherited;

createwindowparams(fwndparams);

registerclass(fwndparams.windowclass);

createwindowex(exstyle, windowclass.lpszclassname, caption,

);

end;

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

constructor tlitewindow.createsubclassed(awnd: thandle);

inherited create(getparent(awnd));

fwndsubclass := pointer(getwindowlong(awnd, gwl_wndproc));

fwndhandle := awnd;

// Устанавливаем собственную оконную детскому саду///////////////////////////////

destructor tlitewindow.destroy;

// Наш объект - объект субклассиннга ?

unregisterclass(fwndparams.windowclass.lpszclassname, hinstance);

if iswindow(fwndhandle) then destroywindow(fwndhandle);

setwindowlong(fwndhandle, gwl_wndproc, dword(fwndsubclass));

inherited;

end;

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

procedure tlitewindow.createwindowparams( var windowparams: twindowparams);

wndclassname : string;

str(dword(self), wndclassname);

wndclassname := classname+’:'+wndclassname;

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;

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;

////////////////////////////////////////////////////////////////////////////////

// _____________________________________________________________________________

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

procedure tlitewindow.defaulthandler( var msg);

// Наш объект - объект субклассиннга ?

result := defwindowproc(fwndhandle, msg, wparam, lparam)

// Вызываем ветхую оконную функцию обработки известий

result := callwindowproc(fwndsubclass, fwndhandle, msg, wparam, lparam);

end;

////////////////////////////////////////////////////////////////////////////////

// _____________________________________________________________________________

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

constructor tlitedialog.create(awndparent: thandle);

inherited;

createdialogparams(fdlgparams);

createdialogparam(hinstance, template, wndparent, wndcallback, 0);

end;

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

destructor tlitedialog.destroy;

if iswindow(fwndhandle) then destroywindow(fwndhandle);

inherited;

end;

////////////////////////////////////////////////////////////////////////////////

// Формирование характеристик разговора по умолчанию

////////////////////////////////////////////////////////////////////////////////

procedure tlitedialog.createdialogparams( var dialogparams: tdialogparams);

dialogparams.wndparent := fwndparent;

dialogparams.template := ”;

end;

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

procedure tlitedialog.defaulthandler( var msg);

else result := 0;

end;

Реализация модального диалогового предложу финализация

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

// Формирование характеристик разговора по умолчанию

////////////////////////////////////////////////////////////////////////////////

procedure tlitedialogbox.createdialogparams( var dialogparams: tdialogparams);

dialogparams.wndparent := fwndparent;

dialogparams.template := ”;

end;

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

function tlitedialogbox.showmodal: integer;

createdialogparams(fdlgparams);

result := этом случае/////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////

procedure tlitedialogbox.defaulthandler( var msg);

else result := 0;

end;

end.

Архив > Delphi/Pascal > DELPHI FAQ (по темам) > WINAPI

Оставить комментарий

Вы должны быть зарегистрироавны чтобы оставить комментарий.

  • Категории
  • Новости
  • Популярное
  • Комментарии
  • Архив
Programmirovanie. Все права защищены