Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Визуальное программирование / Визуальное_программирование_лекция_16.doc
Скачиваний:
40
Добавлен:
07.06.2015
Размер:
75.26 Кб
Скачать

Лекция № 16 визуальное программирование (конспекты лекций)

Win api функции в Delphi. Работа с регионами (областями)

  1. Использование win api функций в Delphi

Современные программы можно представлять как совокупность программных уровней, каждый из которых проводит собственную работу, заключающуюся в повышении уровня производимых операций. Низший уровень вводит инструменты, помогающие работать с оборудованием; следующий уровень помогает определять сложные последовательности вызова функций. Практически в каждом современном программном продукте Delphi есть около десятка последовательных уровней абстракции.

Абстракция оборудования и различных протоколов вводится в виде библиотек API (Application Program Interface), такую абстракцию называют базовой. Она является самым низким уровнем, доступным для прикладного программирования. Доступны и более низкие уровни, находящиеся на уровне ядра системы, однако для их использования нужны специализированные программы: драйвера и модули.

Win API – это набор функций, предоставляемых операционной системой каждой программе. Эти функции находятся в стандартных динамически компонуемых библиотеках (Dynamic Linked Library, DLL), таких как kernel32.dll, user32.dll, gdi32.dll. Эти файлы находятся в директории Window\System. Каждая программа самостоятельно заботится о том, чтобы подключить эти библиотеки. DLL могут подключаться к программе статически и динамически. В первом случае программа «освобождает» DLL только при завершении, во втором освобождение может произойти в любой момент. Если после освобождения DLL оказывается, что её больше не использует ни одна программа, она выгружается из памяти. Так как стандартные библиотеки используются самой системой, они всегда находятся в памяти, и поэтому использование динамического подключения бессмысленно.

Обычно программа использует довольно большое число функций Win API. Декларировать их все довольно утомительно. К счастью, Delphi избавляет программиста от этой работы: все эти функции уже описаны в соответствующих модулях, достаточно упомянуть их имена в разделе uses.

В Delphi используется не только очень мощная, но и довольно сложная библиотека VCL (Visual Components Library). В данной библиотеке представлены компоненты для отображения информации, работы с системными объектами, с базами данных, компоненты для организации работы с Интернет-протоколами, классы для написания COM-объектов и т.д. Каждый из стандартных модулей Delphi подключаются только по необходимости к компиляции, однако базовый размер самого простого диалогового проекта составляет более 300 Кб. Для решения данной проблемы можно не использовать библиотеку VCL, а программировать только с использованием базового набора функций Win32 API. Хотя создание многих программ в этом случае становится достаточно трудоемким.

  1. Изменение стандартной экранной формы. Работа с регионами

При создании программ средствами Delphi (да и иными средствами программирования) мы привыкаем к экранным формам стандартной экранной формы. В плане функциональности такой вид действительно самый удобный, но бывают ситуации, когда возникает необходимость или просто прихоть использовать экранные формы иного внешнего вида.

В класс TCanvas Delphi не входит интересный графический объект Windows – область (Region). Область формируется из простейших геометрических фигур, таких как эллипс, многоугольник и т.п. С помощью областей можно значительно разнообразить графическое оформление своих программ.

В Microsoft Windows регионом называется прямоугольник, полигон или эллипс (либо комбинация двух или более этих фигур), которые могут быть заполнены, нарисованы, инвертированы, обрамлены и могут использоваться для определения местонахождения курсора (имеется в виду, что есть стандартная функция, определяющая входит ли точка (X,Y) в наш регион).

С точки зрения Windows, регион является обыкновенным объектом GDI (Graphics Device Interface – интерфейс, который Windows использует для рисования 2D графики), задаваемым дескриптором HRGN.

Программируя в Delphi, мы быстро привыкаем к тому, что каждый объект реализуется экземпляром соответствующего класса. Например, кнопка реализуется экземпляром класса TButton, контекст устройства – классом TCanvas. Но когда создавались первые версии Windows, объектно-ориентированный метод программирования ещё не был общепризнанным, поэтому он не был реализован. Современные версии Windows частично унаследовали этот недостаток, DLL могут экспортировать только функции, но не классы.

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

При работе с Win API не следует полностью отказываться от классов Delphi. Эти методы прекрасно работают вместе.

Регион позволяет задать на канве область определенной формы.

procedure TForm1.RebuildWindowRgn;

var

MyRgn, OldRgn : HRGN;

begin

MyRgn := CreateEllipticRgn(1, 1, 50, 50);

// Запомнили старый регион

OldRgn:=SelectObject(Canvas.handle, MyRgn);

Canvas.Rectangle(4, 4, 150, 150);

//------ рисуем ... ---------

// Восстановили исходный регион

SelectObject(Canvas.handle,OldRgn);

end;

Регион создается одной из функций API:

function CreateRectRgn(X1, Y1, X2, Y2: Integer): HRGN;

function CreateRectRgnIndirect(const p1: TRect): HRGN;

Функция CreateRectRgn создает регион прямоугольной формы (параметры задают координаты для верхнего левого и нижнего правого угла прямоугольника, задающего регион. Функция CreateRectRgnIndirect аналогична функции CreateRectRgn – разница в том, что вместо четырех координат функция получает структуру типа TRect .

function CreateRoundRectRgn(X1, Y1, X2, Y2, H, W: Integer): HRGN;

Функция CreateRoundRectRgn аналогична функции CreateRectRgn, но создаваемая прямоугольная область имеет скругленные углы. X1, Y1 – координаты верхнего левого угла, X2, Y2 – координаты нижнего правого, H, W – высота и ширина эллипса, применяемого для скругления углов

function CreatePolygonRgn(const Points; Count, FillMode: Integer): HRGN;

Функция CreatePolygonRgn создает регион, ограниченный многоугольником, вершины которого заданы в массиве Points (элемент массива – пара координат x, y). Параметр Count указывает количество точек в массиве, FillMode определяет, какие точки будут принадлежать региону (возможно два режима – ALTERNATE и WINDING) .

function CreatePolyPolygonRgn (const pPtStructs; const pIntArray; p3, p4: Integer): HRGN;

Функция CreatePolyPolygonRgn создает регион, состоящий из нескольких регионов. Параметр pPtStructs является массивом массивов точек (что-то типа двумерного массива), pIntArray является массивом, содержащем количество точек (вершин) для каждого из регионов, p3 – количество регионов, p4 – режим заполнения.

function CreateEllipticRgn(X1, Y1, X2, Y2: Integer): HRGN;

function CreateEllipticRgnIndirect(const p1: TRect): HRGN;

Данные функции создают эллиптический регион (эллипс вписан в прямоугольник, заданный в первом случае координатами верхнего левого и нижнего правого углов, во втором - структурой p1: TRect с такими же координатами).

Дополнительные функции для работы с регионами.

function CombineRgn(DestRgn, Rgn1, Rgn2: Cardinal; CombineMode: Ineger): Integer;

Объединяет две области в одну.

DestRgn – дескриптор результирующей области;

Rgn1, Rgn2 – дескрипторы объединяемых областей;

CombineMode – параметр, указывающий способ объединения.

Параметр CombineMode может иметь следующие значения:

RGN_AND- включает в результат общие части областей;

RGN_COPY- копирует область Rgn1 в DestRgn;

RGN_DIFF- исключает из Rgn1 часть, принадлежащую Rgn2;

RGN_OR- объединяет области;

RGN_XOR- включает в результат только те части областей, которые не принадлежат им одновременно.

До применения функции область DestRgn уже должна существовать и иметь размеры, достаточные для размещения объединенной области.

function EqualRgn(Rgn1,Rgn2: Cardinal): Bool;

Проверяет эквивалентность двух областей. Rgn1, Rgn2 - дескрипторы сравниваемых областей.

function FillRgn(DC, Rgn,Brush: Cardinal): Bool;

Закрашивает область кистью.

DC – дескриптор канвы окна;

Rgn – дескриптор области;

Brush – дескриптор кисти.

function FrameRgn(DC, Rgn,Brush: Cardinal; Width,Height: Integer): Bool;

Обводит область кистью высотой Height и шириной Width пикселей.

DC – дескриптор канвы окна;

Rgn – дескриптор области;

Brush – дескриптор кисти.

Function InvertRgn(DC, Rgn:Cardinal): Bool;

Инвертирует цвет всех точек внутри области.

DC – дескриптор канвы окна;

Rgn – дескриптор области.

function OffsetRgn(DC, Rgn:Cardinal; dX, dY: Integer):Integer;

Смещает область на dX по горизонтали и на dY по вертикали. DC - дескриптор канвы окна;

Rgn - дескриптор области.

function PaintRgn(DC, Rgn:Cardinal): Bool;

Rgn - дескриптор области.

function PtInRegion(Rgn:Cardinal; X, Y: Integer):Bool;

Проверяет принадлежность точки (X,Y) области с дескриптором Rgn.

function RectInRegion(Rgn:Cardinal; Rect: TRect):Bool;

Проверяет принадлежность прямоугольника Rect области с дескриптором Rgn.

Назначение региона окну производится при помощи процедуры:

Procedure SetWindowRgn(

HWND hWnd, // дескриптор окна

HRGN hRgn, // дескриптор региона

BOOL bRedraw // флаг, управляющий перерисовкой окна после назначения региона

);

Пример работы с данной процедурой:

procedure TForm1.RebuildWindowRgn;

var

Rgn, Rgn1 : HRGN; // Регионы

begin

// Настройка размеров окна

Height := 400;

Width := 600;

// Создание эллиптического региона размером с окно

Rgn := CreateEllipticRgn(0, 0, width, height);

// Создание прямоугольного региона

Rgn1 := CreateRectRgn(50, 50, 100, 100);

// Комбинирование регионов по RGN_XOR (сумма за вычетом пересечения)

CombineRgn (Rgn, Rgn, Rgn1, RGN_XOR);

// Создание региона

Rgn1 := CreateRectRgn(250, 250, 100, 100);

// Комбинирование регионов по RGN_DIFF (Rgn - Rgn1)

CombineRgn(Rgn, Rgn, Rgn1, RGN_DIFF);

// Назначение региона текущему окну

SetWindowRgn(Handle, Rgn, true);

end;

В результате окно становится эллиптическим, внутри окна есть прозрачная прямоугольная и "дырка", в левом углу к нему добавлена прямоугольная область (хорошо видна работа CombineRgn в режиме RGN_XOR).

Если экранная форма, будет с изменяемыми размерами, то достаточно добавить:

procedure TForm1.Resize;

begin

inherited; // вызов унаследованного обработчика

RebuildWindowRgn; // строим новый регион

end;

Еще один штрих - произвольное перемещение формы, а не за строку заголовка (Title Bar). Достаточно одной процедуры.

type

TForm1 = class(TForm)

. . .

private

procedure WMNCHitTest(var M: TWMNCHitTest);

message wm_NCHitTest;

. . .

end;

. . .

procedure TForm1.WMNCHitTest(var M: TWMNCHitTest);

begin

inherited; //вызов унаследованного обработчика события

//если событие произошло в клиентской области,

if M.Result = htClient then M.Result := htCaption;

//то пусть Windows думает, что это произошло на Caption

end;

В этом случае недоступны некоторые события связанные с мышью (например, OnClick).

6