Одной и наиболее сильных сторон среды программирования Delphi является ее открытая архитектура, благодаря которой Delphi допускает своего рода метапрограммирование, позволяя “программировать среду программирования”.
Такой подход переводит Delphi на качественно новый уровень систем разработки приложений и позволяет встраивать в этот продукт дополнительные инструментальные средства, поддерживающие практически все этапы создания прикладных систем.
Столь широкий спектр возможностей открывается благодаря реализованной в Delphi концепции так называемых открытых интерфейсов, являющихся связующим звеном между IDE (Integrated Development Environment) и внешними инструментами. Данная статья посвящена открытым интерфейсам Delphi и представляет собой обзор представляемых ими возможностей.
В Delphi определены шесть открытых интерфейсов: Tool Interface, Design Interface, Expert Interface, File Interface, Edit Interface и Version Control Interface. Вряд ли в рамках данной статьи нам удалось бы детально осветить и проиллюстрировать возможности каждого из них.
Более основательно разобраться в рассматриваемых вопросах вам помогут исходные тексты Delphi, благо разработчики снабдили их развернутыми комментариями. Объявления классов, представляющих открытые интерфейсы, содержатся в соответствующих модулях в каталоге ...DelphiSourceToolsAPI.
Design Interface (модуль DsgnIntf.pas) предоставляет средства для создания редакторов свойств и редакторов компонентов. Редакторы свойств и компонентов – это тема, достойная отдельного разговора, поэтому напомним лишь, что редактор свойства контролирует поведение Инспектора Объектов при попытке изменить значение соответствующего свойства, а редактор компонента активизируется при двойном нажатии левой кнопки мыши на изображении помещенного на форму компонента.
Version Control Interface (модуль VCSIntf.pas) предназначен для создания систем контроля версий. Начиная с версии 2.0, Delphi поддерживает интегрированную систему контроля версий Intersolv PVCS, поэтому в большинстве случаев в разработке собственной системы нет необходимости. По этой причине рассмотрение Version Control Interface мы также опустим.
File Interface (модуль FileIntf.pas) позволяет переопределить рабочую файловую систему IDE, что дает возможность выбора собственного способа хранения файлов (в Memo-полях на сервере БД, например).
Edit Interface (модуль EditIntf.pas) предоставляет доступ к буферу исходных текстов, что позволяет проводить анализ кода и выполнять его генерацию, определять и изменять позицию курсора в окне редактора кода, а также управлять синтаксическим выделением исходного текста.
Специальные классы предоставляют интерфейсы к помещенным на форму компонентам (определение типа компонента, получение ссылок на родительский и дочерние компоненты, доступ к свойствам, передача фокуса, удаление и т.д.), к самой форме и к ресурсному файлу проекта.
Также Edit Interface позволяет идентифицировать так называемые модульные нотификаторы, определяющие реакцию на такие события, как изменение исходного текста модуля, модификация формы, переименование компонента, сохранение, переименование или удаление модуля, изменение ресурсного файла проекта и т. д.
Tool Interface (модуль ToolIntf.pas) предоставляет разработчикам средства для получения общей информации о состоянии IDE и выполнения таких действий, как открытие, сохранение и закрытие проектов и отдельных файлов, создание модуля, получение информации о текущем проекте (число модулей и форм, их имена и т. д.), регистрация файловой системы, организация интерфейсов к отдельным модулям и т.д.
В дополнение к модульным нотификаторам Tool Interface определяет add-in нотификаторы, уведомляющие о таких событиях, как открытие/закрытие файлов и проектов, загрузка и сохранение desktop-файла проекта, добавление/исключение модулей проекта, инсталляция/деинсталляция пакетов, компиляция проекта, причем в отличие от модульных нотификаторов add-in нотификаторы позволяют отменить выполнение некоторых событий.
Кроме того, Tool Interface предоставляет средства доступа к главному меню IDE Delphi, позволяя встраивать в него дополнительные пункты.
Expert Interface (модуль ExptIntf.pas) представляет собой основу для создания экспертов — программных модулей, встраиваемых в IDE c целью расширения ее функциональности. В качестве примера эксперта можно привести входящий в Delphi Database Form Wizard, выполняющий генерацию формы для просмотра и изменения содержимого таблицы БД.
Данная проблема возникает из-за того, что BDE вначале запрашивает базу данных для получения информации о таблице, прежде чем он начнет с ней работать. Как только появляется информация о таблице, она кэшируется и обращение к таблице во время всего сеанса (пока TDatabase.Connection имеет значение True) происходит практически мгновенно.
Для того, чтобы использовать кэшируемую информацию и при последующем запуске приложения, в конфигурации BDE найдите необходимый псевдоним и установите BDE CACHE = TRUE и BDE CACHE DIR = 'C:temp' или любой другой удобный каталог.
ПРИМЕЧАНИЕ:
При любом изменении структуры таблицы Вам придется удалять кэш вручную. Имя файла, в котором хранится кэш, Вы можете узнать, посмотрев в любом текстовом редакторе файл SCache.INI.
Интересно, есть ли технология преобразования Wave-формата в обычный набор звуковых данных? К примеру, мне необходимо удалить заголовок и механизм (метод) сжатия, которые могут компилироваться и сохраняться вместе с Wave-файлами.
Прежде чем работать с графикой, необходимо понять, как именно в Windows реализован принцип перерисовки изображений. Не инструменты рисования являются предметом этого материала, а общий механизм перерисовки окон.
Данный материал посвящен системному сообщению WM_PAINT.
Основной принцип перерисовки: Save and Paint - сохраняй и прорисовывай.
Windows не хранит в памяти нарисованное изображение в виде растрового рисунка. Система перерисовывает ту часть окна , которая в какждый конкретный момент в этом нуждается.
Когда Windows ( или другое приложение) посылает запрос на перерисовку окна или его части, этому окну посылается сообщение WM_PAINT.
Посылка сообщения WM_PAINT окну может быть вызвана как явным обращением к методам Window или RedrawWindow, так и полученим запроса на перерисовку от системы, которое поступает при перемещении окна, изменении его размеров и так далее. Windows посылает это сообщение, когда не имеется никаких других сообщений в очереди сообщений приложения.
Сообщение WM_PAINT относится к сообщениям с низким приоритетом, поэтому оно будет обработано в самую последнюю очередь.
Если будут посланы подряд несколько сообщений WM_PAINT, то обработано будет только одно, так как система не регистрирует следующие сообщения WM_PAINT. Таким образом достигается минимизация затрат на исполнение очень длительной операции - перерисовки окна.
В соответствии с общим подходом, принятым в Windows, перерисовываться будет не все окно, а только та часть, которая в этом нуждается. Так называемая область модификации - Region. К области модификации добавляется только некорректно отображаемая часть - Invalid Area , именна та часть окна, которая нуждается в перерисовке.
Область окна установливается как некорректная (Invalid area) методами Invalidate, InvalidateRect, или InvalidateRgn, а так же после того, как окно передвигают, изменяют его размеры или выполняют любою другою операцию, которая воздействует на клиентскую область окна.
Метод Invalidate объявляет некорректной всю клиентскую область окна.
Метод InvalidateRect ( и InvalidateRgn ) объявляет некорректной клиентскую область внутри данного прямоугольника, добавляя этот прямоугольник к текущей области модификации ( Region).
Удалить некоторую область из Region можно методами ValidateRect или ValidateRgn.
Таким образом, некорректные области накапливаются в Region, пока эта область не будет обработана при следующем сообщении WM_PAINT , или пока она не будет объявлена корректной принудительно, методом ValidateRect или ValidateRgn.
Как уже отмечалось выше, установка непустой области модификации Region не заставляет приложение немедленно перерисоваться. Вместо этого, приложение продолжает получать сообщения из очереди, пока все сообщения не будут обработаны. Затем Windows проверяет область модификации, и если область не пустая, посылает сообщение WM_PAINT окну. При проверке области модификации могут быть посланы так же сообщения WM_NCPAINT и WM_ERASEBKGND, если требуется перерисовать рамку ( неклиентскую часть) окна или необходимо очистить окно.
Например, при увеличении размера окна будут посланы все три сообщения : WM_NCPAINT , WM_ERASEBKGND и WM_PAINT. При уменьшении размеров, окну придет только два сообщения из этой группы, сообщение WM_NCPAINT и WM_ERASEBKGND. По смыслу ситуации это резонно - при уменьшении окна клиентская часть его только урезается, следовательно стереть ее надо, а рисовать, вообще говоря, нечего...
[pagebreak]
Метод Window требует немедленной перерисовки клиентской области в обход общей очереди. Предварительно проверяется состояние области модификации: если область модификации не пустая, окну будет послано сообщение WM_PAINT. Если область модификации пуста сообщение WM_PAINT, наоборот, не будет послано.
Если эта область была помечена для стирания, то окну предварительно будет послано сообщение WM_ERASEBKGND.
Для получения более подробной информации смотрите Help WinAPI по темам:
Все вышеперечисленные методы являются методами класса CWnd, доступного через WinAPI.
Для перерисовки окон в Delphi применяются два метода :
Метод RePaint заключается в объявлении всей области окна как некорректной и немедленного запроса на перерисовавание окна. Достаточно привести реализацию этого метода из модуля Controls.pas, чтобы это увидеть:
Метод Refresh является модификацией метода RePaint. Для класса TWinControl метод Refresh повторяет вызов RePaint.
Таким образом, если Вам необходимо немедленно обновить окно, воспользуйтесь методом RePaint, если в этом нет необходимости и перерисовку нужно запросить, но в порядке общей очереди, лучше использовать метод Invalidate;
Для получения более подробной информации смотрите реализацию методов:
* TWinControl.Invalidate
* TWinControl.
* метод Refresh для разных компонент, наследников от TWinControl.
В этой статье будут рассмотрены некоторые функции для работы с окнами.
Функция FindWindow
Синтаксис function FindWindow(className,WindowName : PChar) : HWND;
Функция возвращает дескриптор окна, удовлетворяющий запросу (0 - если такого окна не найдено).
ClassName - Имя класса, по которому призводится поиск среди ВСЕХ окон системы.
WindowName - Заголовок окна
Один из параметров может быть равен nil, тогда поиск ведется по другому параметру.
Функция GetWindow
Синтаксис function GetWindow(Wnd : HWND; Param) : HWND
Функция возвращает дескриптор окна удовлетворяющий запросу.
Wnd - Дескриптор какого-либо начального окна
Param - Принимает одно из следующих значений-констант:
gw_Owner - Возвращается дескриптор окна-предка (0 - если нет предка).
gwHWNDFirst - Возвращает дескриптор первого окна (относительно Wnd).
gw_HWNDNext - Возвращает дескриптор следующего окна (окна перебираются без повторений, т.е. если вы не меняли параметр Wnd функции, повторно дескрипторы не возвращаются)
gw_Child - Возвращает дескриптор первого дочернего окна.
Функция GetWindowText
Синтаксис function GetWindowText(hWnd: HWND; lpString: PChar; nMaxCount: Integer): Integer;
Функция возвращает текст окна. Для формы это будет заголовок, для кнопки - надпись на кнопке.
hWnd - Дескриптор того окна, текст которого нужно получить.
lpString - Переменная, в которую будет помещен результат
nMaxCount - Максимальная длина текста, если текст длиннее, то он обрезается.
Функция SetWindowText
Синтаксис function SetWindowText(hWnd: HWND; lpString: PChar): BOOL;
Устанавливает текст окна.
hWnd - дескриптор того окна, текст которого нужно установить
X, Y, nWidth, nHeight - Соответственно: новые координаты X,Y; новая ширина, высота.
bRepaint - Булево значение, показывающее будет ли окно перерисовано заново.
Функция IsWindowVisible
Синтаксис function IsWindowVisible(hWnd: HWND): BOOL;
Возвращает True если данное окно видимо.
hWnd - дескриптор окна.
Функция EnableWindow
Синтаксис function EnableWindow(hWnd: HWND; bEnable: BOOL): BOOL;
Устанавливает доступность окна(окно недоступно, если оно не отвечает на события мыши, клавиатуры и т.д.). Аналог в Delphi свойство Enabled компонентов. EnableWindow возвращает True, если всё прошло успешно и False в противном случае.