handle delphi что такое

Delphi: What is Application.Handle?

The Delphi help says:

Provides access to the window handle of the main form (window) of the application.

Description

Use Handle when calling Windows API functions that require a parent window handle. For example, a DLL that displays its own top-level pop-up windows needs a parent window to display its windows in the application. Using the Handle property makes such windows part of the application, so that they are minimized, restored, enabled and disabled with the application.

If i focus on the words «the window handle of the main form of the application«, and i take that to mean the window handle of the main form of the application, then i can compare:

but they are not the same:

Really what i’m asking is: What is the design rationale that makes Application.Handle exist? If i can understand the why, the how should become obvious.

Update Understanding through a game of twenty questions:

This can cause some problems with modal forms shown from secondary forms.

If the user switches away from the app while a modal form is up, and then back to the form that showed it, the modal form may hide beneath the form. It is possible to deal with this by making sure the modal form is parented [sic; he meant owned] to the form that showed it (using params.WndParent as above)

He also talked about using the new Windows extended style that forces a window to appear on the taskbar (when the normal rules of making it un-owned is insufficient, impractical, or undesirable), by adding the WS_EX_APPWINDOW extended style:

But then he cautions:

If you click on a secondary forms taskbar button while another app is active this will still bring all the applications forms to front. If you do not want that there is option

This will add the taskbar button for your form, but there are a few other minor details to handle. Most obviously, your form still receives minimize/maximize that get sent to the parent form (the main form of the application). In order to avoid this, you can install a message handler for WM_SYSCOMMAND by adding a line such as:

Note that this handler goes in the PARENT form of the one you want to behave independantly of > the rest of the application, so as to avoid passing on the minimize message. You can add similar > code for SC_MAXIMIZE, SC_RESTORE, etc.

will remove Application and it’s window Handle from interfering with my form, and Windows should once again send me my mimimize/maximize/restore messages?

Obviously Borland realized the flaw in their initial design. What was their initial design, what problem was it solving, what is the flaw, what was the re-design, and how does it solve the problem?

3 Answers 3

The reason for the application window has a bit of a sordid history. When developing Delphi 1, we knew we wanted to use «SDI» (windows scattered all over the desktop) ui model for the IDE. We also knew that Windows sucked (and still does) at that model. However we also noticed that Visual Basic at that time employed that model and it seemed to work well. Upon further examination, we found that VB used a special «hidden» parking window which was used as the «owner» (Windows blurs the notion of parent and owner at times, but the distinction is similar to VCL) for all the other visible windows.

This is how we solved the «problem» where the windows containing the main menu was rarely ever focused so processing Alt-F for the File menu simply wouldn’t work. By using this central parking window as an intermediary, we could more easily keep track of and route messages to the appropriate windows.

This arrangement also solved another issue where normally multiple top level windows were entirely independent. By making the application handle the «owner» of all these windows, they would all behave in concert. For instance, you may have noticed that when you select any of the application windows, all the application windows move to the front and retain their z-order relative to each other. This would also make the application minimize and restore as a functional grouping.

That is a consequence of using this model. We could have manually done all this work to keep things straight, but the design philosophy was to not re-invent Windows, but to leverage it where we could. That is also why a TButton or a TEdit is really a Windows «User» BUTTON and EDIT window class and style, respectively.

As Windows evolved, that «SDI» model began to fall out of favor. In fact Windows itself began to become «hostile» to that style of application. Starting with Windows Vista and continuing to 7, the user shell doesn’t seem to work well with an application using a parking window. So, we set out to shuffle things around in VCL to eliminate the parking window and move its function into the main form. This presented several «chicken and egg» problems whereby we need to have the parking window available early enough in the application initialization so that other windows can «attach» to it, but the main form itself may not be constructed soon enough. TApplication has to jump through a few hoops to get this to work, and there have been a few subtle edge cases that have caused issue, but most of the problems have been worked out. However, for any application you move forward, it will remain using the older parking window model.

Источник

Handle delphi что такое

Здравствуйте, _silent, Вы писали:

_>Люди, может, подскажете тупому программеру — что такое HANDLE?
_>Уже и встречался и даже работал. Но что это такое, так и не знаю. Странно, да? Вот и я так думаю. Объясните мне, пожалуйста.

идентификатор объекта handle delphi что такое

Здравствуйте, _silent, Вы писали:

_>Люди, может, подскажете тупому программеру — что такое HANDLE?
_>Уже и встречался и даже работал. Но что это такое, так и не знаю. Странно, да? Вот и я так думаю. Объясните мне, пожалуйста.

1) рукоять, рукоятка, черенок, ручка
the handle of wife — рукоятка жены (скалка)
starting handle — кнопка «Старт» в Windows

3) оснащать (что-л.) ручкой, рукоятью; приделывать рукоять (к чему-л.)
to handle — приделать ноги.

4) управлять чем-л., справляться с чем-л. руками
she handled the boyfriend very easily — она с легкостью справлялась с товарищем
handle a wife — управлять женой (фантаст.)

5) хорошо управляться; слушаться (рук, руля и т. п.)
the wife handles well — жена идет/работает очень послушно (фантаст.)

6) обходиться, обращаться; управляться, справляться с кем-л., чем-л.
a wife handles all my affairs — жена занимается всеми моими делами (фантаст.)
handle with care! — осторожно! (надпись на свадебных платьях)

handle delphi что такоеОт: mrhru
Дата:03.12.03 12:26
Оценка: 6 (1)

Здравствуйте, _silent, Вы писали:

_>Люди, может, подскажете тупому программеру — что такое HANDLE?
_>Уже и встречался и даже работал. Но что это такое, так и не знаю. Странно, да? Вот и я так думаю. Объясните мне, пожалуйста.

Handle — идентификатор-указатель объекта. Термин используется в основном в процедурном программировании. Т.е. об объекте неизвестно ничего, а работа с ним осуществляется через методы, в которые этот handle и передаётся. Например, WinAPI. Или в CLX от Borland — используется библиотека Qt, которая возвращает указатели на объекты просто как целые.

handle delphi что такоеОт: Dmitry V.Abramovhttp://imap.ru
Дата:03.12.03 15:03
Оценка: 10 (2)

_>Люди, может, подскажете тупому программеру — что такое HANDLE?
_>Уже и встречался и даже работал. Но что это такое, так и не знаю. Странно, да? Вот и я так думаю. Объясните мне, пожалуйста.

Воспринимай его как универсальную ссылку (pointer) на некую структуру. Что это за структура, создана ли отдельно или является частью другой, — ты не знаешь. Но об этом прекрасно осведомлена та функция WinAPI, которая тебе его предоставила или которой ты его передашь.

При такой аналогии становится понятно, почему хэндлы нужно получать и освобождать. А уж API само разберется — заводить под него память или дать просто адрес, освобождать память при CloseHandle или ну его.

По аналогии — можно воспринимать классы как хэндлы, структура которых тебе известна.

Встречается еще аналогия, что HANDLE — это пароль, который тебе дают в одном месте, чтобы ты его произнес в другом и тебя пустили. Но это не объясняет, почему пароль нужно освобождать (CloseHandle).

handle delphi что такоеОт: Diouzshev
Дата:03.12.03 16:46
Оценка: 6 (1)

Hello, _silent!
You wrote on Wed, 03 Dec 2003 11:44:16 GMT:

s> Люди, может, подскажете тупому программеру — что такое HANDLE?
s> Уже и встречался и даже работал. Но что это такое, так и не знаю.
s> Странно, да? Вот и я так думаю. Объясните мне, пожалуйста.

И я свою лепту внесу handle delphi что такое

With best regards, Alexander Diouzshev-Maltsev.

handle delphi что такоеОт:Аноним
Дата:03.12.03 17:01
Оценка: 9 (1)

Попробую объяснить на пальцах.

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

Такой подход характеризуется полным отсутствием инкапсуляции, т.е.
каждый может получить полный доступ к полям структуры безо
всяких функций и сделать её состояние внутренне противоречивым.

Простейший способ решения этой проблемы —
просто скрыть от пользователя декларацию структуры:

Здесь хэндл — просто указатель.
Так, например, устроен HINSTANCE(HMODULE).

Другая возможная реализация Хэндла — через
индекс в некоторой скрытой от пользователя таблице
(которая вообще говоря может лежать в другом адресном пространстве).

Пример такой реализации:

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

handle delphi что такоеОт: Slicer [Mirkwood]https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата:03.12.03 17:58
Оценка: 6 (1)

Здравствуйте, Dmitry V.Abramov, Вы писали:

_>>Люди, может, подскажете тупому программеру — что такое HANDLE?
_>>Уже и встречался и даже работал. Но что это такое, так и не знаю. Странно, да? Вот и я так думаю. Объясните мне, пожалуйста.

DVA>Воспринимай его как универсальную ссылку (pointer) на некую структуру. Что это за структура, создана ли отдельно или является частью другой, — ты не знаешь. Но об этом прекрасно осведомлена та функция WinAPI, которая тебе его предоставила или которой ты его передашь.
Ты бы людей не путал словами pointer и ссылка — с непривычки еще поймут неправильно. Я бы сказал так: хендл, хотя официально это не регламентировано handle delphi что такое, — это идентификатор некоторой сущности. Одной сущности может соответствовать несколько идентификаторов.

DVA>При такой аналогии становится понятно, почему хэндлы нужно получать и освобождать.
Надо ли освобождать — зависит от сущности, чей идентификатор нас интересует. Если мы всего лишь пользуемся сущностью, созданной кем-то другим, то часто ничего освобождать не надо. Если же сущность находится в нашем владении (т.е. грубо говоря, мы ее создали, например, путем вызова ф-ии ОС, которая вернула хендл). Бывает, что владельцем сущности является ОС — тогда освобождать таки надо, но для того, чтобы ОС уменьшила счетчик ссылок на сущность и при достижении 0 удалила эту больше ненужную сущность (разумеется, некоторые сущности могут в из соображений оптимизации никогда не удаляться, если они используются часто — даже если счетчик достиг 0, можно предположить, что сущность «популярна» и ее скоро снова кто-то захочет поюзать).

handle delphi что такоеОт: Kluge
Дата:03.12.03 23:45
Оценка: 3 (1)

В w2k Handle это смешение относительно начала таблицы Handle-ов процесса, в указанном месте начинается описание объекта ядра. Т.к. объект ядра может лежать и в памяти процесса и в памяти ядра давать на него указатель не разумно handle delphi что такое

Здравствуйте, Slicer [Mirkwood], Вы писали:

SM>Ты бы людей не путал словами pointer и ссылка — с непривычки еще поймут неправильно. Я бы сказал так: хендл, хотя официально это не регламентировано handle delphi что такое, — это идентификатор некоторой сущности. Одной сущности может соответствовать несколько идентификаторов.

Вот. Сразу все стало значительно понятней.

ЗЫ А кто такая сущность?

handle delphi что такоеОт: Leonid Troyanovsky
Дата:04.12.03 07:20
Оценка:

Здравствуйте, All, мы писали:

А>Здравствуйте, Slicer [Mirkwood], Вы писали:

Sorry, это опять я забыл зарегистрироваться handle delphi что такое

Источник

Handle delphi что такое

Одним из важнейших понятий в Windows-программировании является понятие объектного дескриптора (handle). В Windows все объекты — кисти, перья, растры, указатели мыши, контексты устройств, окна, экземпляры программ— идентифицируются 32-разрядным (в Winl6 — 16-разрядным) целым числом, которое называется дескриптором (иногда манипулятором). С каждым дескриптором связывается идентификатор типа, начинающийся с буквы «Н» (в языке Си — с «h» нижнего регистра. В отличие от Pascal, регистр в Си имеет значение). Например, hwnd— это дескриптор окна. Дескрипторы ссылаются на объекты, находящиеся под управлением системы Windows. Работающая операционная система отслеживает все дескрипторы которые служат связующими звеньями между загруженными объектами вызвавшими их приложениями.

Когда мы создаем некоторый объект в Windows, ему присваивается уникальный 32-разрядный дескриптор, который в последующем передается каждой функции, при работе с этим объектом. Это главное различие между функциями Widows API и стандартными методами класса Object Pascal. Вторые связаны с тем экземпляром класса, через который они вызываются, и поэтому не требуют явного указания на объект. Первым необходимо такое указание (что и делается с помощью дескриптора), т. к. они сами по себе никак не связаны ни с одним объектом.

В Delphi для хранения дескриптора объектов определен тип THandle:

type THandle : LongInt;

Кроме типа THandle в Delphi поддерживаются также имена типов, пришедшие из С++, а именно: hwnd, hmenu, hkey и другие имена, начинающиеся с префикса. Н (Handle).

При использовании функций Windows API к объектам Object Pascal следует понимать, что данные функции «не знают» о внутренних механизмах работы Delphi.

Поясним на примере: если скрыть окно не с помощью метода Delphi Hide, а с помощью функции WinAPI showWindow(Handle, sw_Hide), то в Delphi не возникнет событие onHide, потому что оно генерируется упомянутыми внутренними механизмами. Следует об этом помнить.

Но случается такое только когда функциями Windows API дублируется то, что можно сделать с помощью Delphi. Для вызова функций Windows API для объекта, созданного с помощью Delphi, используйте свойство объекта Handle, — в нем хранится дескриптор.

Читайте также

Сообщения операционной системы Windows очень напоминают событийные сообщения Delphi.

Каждое сообщение Windows имеет свой уникальный номер (идентификатор).

(ниже представлена обработка сообщения wm_move.

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

Большая часть функций API уже импортирована в среду Delphi и описана в ее модулях

Подпишись на нашу группу в контакте и будь в курсе обновлений:

Источник

Delphi и Windows API

Одной из наиболее интересных особенностей Delphi является предоставление, наряду с высокоуровневыми функциями VCL, простого доступа к функциям Windows API. Программист в любой момент волен (в зависимости от стоящей перед ним задачи) выбрать для ее решения простые в использовании компоненты либо реализовать алгоритм, требующий компактности и быстродействия при помощи прямых вызовов API. Более того, как правило, можно без прекращения использования компонентов и визуального программирования нанести несколько штрихов при помощи API и добиться максимальной точности решения задачи и быстродействия.

Windows — окна и сообщения

Само название операционной системы Windows говорит о том, что основным ее элементом является окно. Для успешного программирования разработчик должен иметь четкое представление о том, что подразумевается в Windows под этим понятием.

Для начинающих программистов неочевидно, что окнами Windows являются не только главные окна, но и большинство элементов управления в них, таких как поля ввода, списки, кнопки и т.п. Фактически любой элемент интерфейса, способный получать фокус ввода, является окном Windows. Окна могут иметь окно-владельца (Parent window). В этом случае остальные называются дочерними окнами (Child Window) и располагаются на поверхности владельца.

Класс окна

Поведение и внешний вид окна определяются его классом. Класс — это внутренняя структура Windows, описывающая шаблон, на основании которого операционная система создает окна. Перед созданием окна необходимо зарегистрировать его класс при помощи функции:

Рассмотрим ключевые элементы этой структуры подробнее:

StyleБитовая маска, задающая стиль окна. Стиль — это набор флагов, указывающих операционной системе, какие действия надо предпринимать по умолчанию при возникновении тех или иных событий в окне. Стиль класса в основном определяет моменты, связанные с прорисовкой окна
lpfnWndProcАдрес процедуры — обработчика сообщений. Каждый раз, когда в Windows возникает какое-либо событие, относящееся к окну (например, появилась необходимость в перерисовке или переместился курсор мыши над окном), операционная система формирует сообщение, состоящее из идентификатора и двух целочисленных параметров — wParam и lParam, и вызывает эту функцию. Таким образом, функция обработки сообщений и определяет поведение всех окон, созданных с этим стилем
hIconИдентификатор значка. Он будет выводиться в левом верхнем углу окна. Сам значок может быть загружен из ресурса функцией API LoadIcon
lpszMenuNameИмя меню. Это меню должно быть оформлено в виде ресурса. Если имя не задано, окно по умолчанию не будет иметь меню
lpszClassNameИмя класса. В дальнейшем на него можно будет ссылаться при создании новых окон

Как видно из этой структуры, именно на уровне класса окна определяется функция обработки сообщений, которая будет задавать поведение всех окон с этим классом.

Создание окна

После того как класс зарегистрирован, приложение может создавать окна этого класса функцией:

Функция CreateWindowEx позволяет задать конкретный вид окна и уточнить информацию, полученную от класса окна.

Сообщения

Сообщения — это базовый механизм информирования программ о событиях, на которые они должны реагировать. Ядром программы является зарегистрированная в классе окна функция обработки сообщений, вызываемая ядром Windows при появлении событий, на которые программа должна отреагировать. Получение сообщения окном означает вызов его оконной функции с параметрами, описывающими передаваемое сообщение. Например, сразу после своего создания окно получает сообщение WM_CREATE, при нажатии клавиш на клавиатуре — WM_KEYDOWN, WM_KEYUP, при перемещении мыши — WM_MOUSEMOVE и т.п. Без обработки сообщений окно не сможет даже отрисовать себя — рисование выполняется по получении сообщений WM_PAINT, WM_NCPAINT. В программе, написанной с использованием только Windows API, функция обработки сообщений обычно представляет собой оператор case. Альтернативами данного оператора являются различные сообщения, которые эта функция должна обработать.

TWinControl — оболочка окна Windows

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

Базовым классом, инкапсулирующим окно Windows, является TWinControl. Когда создается экземпляр наследника этого класса, VCL автоматически регистрирует соответствующий класс окна Windows и создает окно. Благодаря этому наследники TWinControl могут содержать в себе другие окна и обрабатывать сообщения Windows. Визуальные компоненты, не являющиеся наследниками TWinControl (такие как TLabel, TSpeedButton), не представляют собой окна в понимании Windows. Все их события эмулируются компонентом, в который они помещены.

Свойство Handle

Центральное свойство компонента TWinControl — Handle. Оно представляет собой идентификатор окна Windows, полученного при создании этого компонента. Указанный идентификатор можно использовать с любыми функциями Windows API, работающими с окнами. Например, нижеприведенный код прокручивает текст в TMemo на одну строку вниз:

Метод CreateParams

TWinControl перед созданием окна вызывает виртуальный метод CreateParams, позволяя программисту задать низкоуровневые параметры создаваемого окна. В процедуру передается структура данных:

Наследники TWinControl могут перекрыть CreateParams, создавая окна с требуемыми внешним видом и поведением. Например, необходимо создать форму, не имеющую заголовка, однако позволяющую изменять свои размеры. Delphi не предоставляет возможности задать такое поведение визуальными средствами, однако, перекрыв TForm.CreateParams, мы легко добиваемся нужного эффекта:

В качестве упражнения рекомендуем посмотреть на некоторые фрагменты реализации класса TWinControl, расположенного в модуле Controls.pas. Хорошо видно, что метод CreateWnd сначала вызывает метод CreateParams, заполняющий структуру WndClass с параметрами класса окна и параметры для CreateWindow, а затем регистрирует класс и создает окно. Также очень показателен метод TCustomForm.CreateParams, расположенный в модуле Forms.pas. Можно увидеть, как по свойствам Position, BorderIcons и FormStyle формируется набор флагов стиля окна для функции CreateWindow.

Обработка сообщений

Каждое окно Windows должно обрабатывать сообщения. VCL берет на себя работу по организации цикла сообщений и по их базовой обработке. Для большинства сообщений Windows, которые должны обрабатываться окном, уже предусмотрена обработка по умолчанию. Сообщения, требующие специфической обработки, приводят к вызовам функций —обработчиков событий, например:

WM_MOUSEMOVEOnMouseMove
WM_LBUTTONDOWN, WM_RBUTTONDOWNOnMouseDown
WM_LBUTTONUP, WM_RBUTTONUPOnMouseUp
WM_LBUTTONDBLCLKOnDblClick
WM_KEYDOWNOnKeyDown
WM_KEYUPOnKeyUp
WM_PAINTOnPaint

Показателен в этом смысле метод WndProc класса TWinControl или его наследников. При этом VCL перед вызовом обработчиков производит «упаковку» параметров сообщений в удобный для обработки и анализа вид. Понимание того, какое сообщение Windows вызывает срабатывание того или иного события VCL, очень помогает при программировании обработчиков и совершенно необходимо при написании собственных компонентов. Разумеется, предусматривать отдельные обработчики для каждого из сотен сообщений, которые могут поступить в окно, — значит неоправданно усложнять код VCL. Поэтому для обработки остальных сообщений синтаксис Object Pascal предусматривает создание процедур — обработчиков сообщений. Такие процедуры объявляются как:

В качестве параметра такая функция получает указатель на структуру TMessage, содержащую информацию о сообщении, переданном окну. Для многих часто используемых сообщений в модуле Messages.pas определены структуры, позволяющие более удобно работать с конкретными сообщениями.

Рассмотрим пример окна, обрабатывающего не предусмотренное VCL сообщение, в качестве которого используем WM_HOTKEY. Это сообщение посылается окну посредством зарегистрированной в Windows горячей клавиши, что позволяет программе реагировать на нее, даже не имея фокуса ввода:

Хочется обратить ваше внимание на вызов унаследованного обработчика в методе WMHotKey. Если вы не уверены, что хотите запретить обработку предком подобного сообщения, — всегда вызывайте унаследованный обработчик. В противном случае вы рискуете помешать VCL обрабатывать сообщения. Например, написав свой обработчик WM_PAINT и не вызвав в нем унаследованный, вы полностью заблокируете перерисовку формы средствами VCL.

Свойства Controls и Parent

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

TForm — просто окно

Delphi вводит новую для Windows концепцию — форма. Такого понятия нет в Windows, однако оно довольно часто встречается в высокоуровневых средствах разработки. Форма инкапсулирует окно верхнего уровня (top-level window), которое служит контейнером для остальных визуальных элементов программы. С точки зрения Windows — это такое же окно, как и все остальные, только с соответствующим образом подобранным набором стилей. В частности, на этом уровне реализованы поддержка главного меню, управление дочерними окнами (MDI). Как и любое окно, TForm имеет свойство Handle, которое может быть использовано в вызовах Windows API. Например, приведенный ниже код создает форму в виде пятиконечной звезды:

Концепция форм помогает разработчику в управлении окнами верхнего уровня, однако многие ее понятия (например, главное окно приложения, список окон (Screen.Forms)) не имеют прямых аналогов в Windows API.

Графика

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

Графическая подсистема Windows

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

Типичный сценарий вывода информации в Windows выглядит следующим образом:

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

Класс TCanvas

VCL предлагает элегантное решение проблемы, описанной в предыдущем разделе, — класс TCanvas, инкапсулирующий контекст графического устройства Windows. Вместе с вспомогательными классами TFont, TBrush и т.д., реализующими графические объекты, этот класс берет на себя всю работу, связанную с получением и освобождением контекстов устройства его атрибутов и графических объектов. Когда вы меняете, например, свойства кисти (Canvas.Brush), TCanvas автоматически создаст новую кисть с нужными атрибутами и включит ее в свой контекст, а старую — корректно удалит. Наряду с этим TCanvas реализует ряд методов, позволяющих рисовать на нем без указания контекста устройства. В итоге программист может вообще не знать принципов работы графической подсистемы Windows, а использовать только методы TCanvas. Все классы VCL, допускающие рисование, имеют свойство Canvas, указывающее на автоматически создаваемый экземпляр TCanvas, связанный с ним.

Использование Windows API с TCanvas

Реализовать в TCanvas все функции рисования Windows нереально, поскольку это приведет к резкому усложнению кода VCL. Однако TCanvas имеет свойство Handle, которое представляет собой идентификатор графического контекста Windows, ассоциированного с экземпляром класса. Используя его, мы можем задействовать все многообразие функций API, предназначенных для рисования. При этом всю работу по установке атрибутов и недопущению утечки ресурсов можно выполнить в реализации класса TCanvas.

Рассмотрим наиболее часто употребляемые функции Windows API, которые можно использовать для рисования.

DrawText

Функция DrawText объявлена как:

Эта функция имеет широкие возможности по форматированию текста, задаваемые параметром uFormat. Данный параметр представляет собой набор битовых флагов, задающих способ выравнивания и дополнительные операции над текстом.

Рассмотрим некоторые из этих флагов:

DT_SINGLELINEТекст выводится в одну строку, при этом игнорируются символы перевода строки и возврата каретки. С данным флагом могут комбинироваться DT_TOP, DT_BOTTOM и DT_VCENTER, задающие вертикальное выравнивание текста
DT_WORDBREAKТекст разбивается на строки так, чтобы он поместился по ширине в прямоугольнике lpRect. Символы возврата каретки и перевода строки также приводят к переходу на новую строку
DT_LEFT
DT_CENTER

DT_RIGHT

Выводимый текст выравнивается по левому краю, по центру или по правому краю
DT_END_ELLIPSISЕсли строка не помещается в lpRect, ее конец заменяется на три точки. Это бывает удобно использовать для вывода полей, имеющих значительную длину
DT_PATH_ELLIPSISИспользуется с путями, содержащими символ ‘\’. Если строка не помещается в lpRect, то часть ее из середины заменяется на три точки

Функция DrawText также может использоваться для расчета высоты или ширины области, занимаемой текстом. Для этого к вышеприведенным флагам форматирования надо добавить флаг DT_CALCRECT. Если выводится одна строка текста, то DrawText изменяет lpRect.Right так, чтобы он вместил всю эту строку. Если выводится несколько строк (DT_WORDBREAK), то lpRect.Bottom изменяется так, чтобы полученный прямоугольник вместил весь текст.

Рассмотрим в качестве примера создание списка, содержащего две колонки. Первая из них содержит номер позиции, вторая — сопроводительный текст, высота которого может изменяться. Для создания такого списка разместим на форме TListBox, установив его свойство Style в lbOwnerDrawVariable. После этого создадим следующие обработчики событий:

DrawEdge

Функция DrawEdge бывает очень полезна при написании собственных компонентов. Она автоматизирует задачу рисования трехмерных кнопок, рамок и т.п. Функция объявлена как:

Рамка рисуется в виде комбинации из двух прямоугольников — внутреннего (inner) и внешнего (outer). Каждый из них может быть выпуклым (raised) либо вдавленным (sunken). Тип рамки определяется параметром edge, который представляет собой битовую маску из следующих значений:

BDR_SUNKENINNERЗадают выпуклый либо вдавленный внутренний контурBDR_RAISEDOUTER

BDR_SUNKENOUTERЗадают выпуклый либо вдавленный внешний контур

Также имеются предопределенные флаги:

EDGE_BUMP — выпуклая рамка;

EDGE_ETCHED — вдавленная рамка;

EDGE_RAISED — выпуклая кнопка;

EDGE_SUNKEN — вдавленная кнопка.

Параметр grfFlags определяет тип бордюра. Это набор следующих флагов:

BF_BOTTOM
BF_TOP
BF_LEFT
BF_RIGHT
Рисуется соответствующая сторона рамки
BF_BOTTOMLEFT
BF_BOTTOMRIGHT
BF_TOPLEFT
BF_TOPRIGHT
Рисуется соответствующий угол
BF_RECTРисуется вся рамка
BF_DIAGONAL
BF_DIAGONAL_ENDBOTTOMLEFT
BF_DIAGONAL_ENDBOTTOMRIGHT
BF_DIAGONAL_ENDTOPLEFT
BF_DIAGONAL_ENDTOPRIGHT
Рисует бордюр по диагонали. Используется для создания кнопок, разбитых по диагонали на две секции
BF_FLAT
BF_SOFT
Позволяют получить плоские кнопки для создания интерфейса в стиле Office 97
BF_MONOРисует одномерную рамку
BF_MIDDLEЗаливает внутреннюю область рамки текущей кистью
BF_ADJUSTКорректирует параметр qrc так, что после отрисовки он соответствует внутренней области рамки. Удобно применять для рисования в дальнейшем

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

Резюме

Таким образом, Delphi, позволяя программисту не вдаваться в тонкости реализации Windows API, в то же время не изолирует программиста от него, предоставляя возможность в любой момент взять управление программой в свои руки и добиться от нее именно того поведения, которое необходимо для решения каждой конкретной задачи. Грамотное использование возможностей API позволяет писать более компактные и быстродействующие программы, а зачастую и сократить объем кода, нужного для решения задачи. Для того чтобы иметь такую возможность, программист должен понимать, что означает классы и функции VCL и каким объектам Windows они соответствуют.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *