Delphi - объектно-ориентированный язык программирования, разработанный компанией Borland в 1995 году. Он основан на языке программирования Pascal, но имеет более расширенные возможности и добавлены новые функции.
Delphi является интегрированной средой разработки (IDE), которая позволяет разрабатывать программное обеспечение для различных платформ, включая Windows, macOS, Android и iOS. Delphi достигает многоплатформенности с помощью...
Основной критерий качества ПО - его функциональность. Но в наше время разработчики коммерческого софта должны думать и о том, что принято называть "товарным видом продукции. Как говорится, по одежке встречают, по уму провожают" - здесь в роли "одежки" выступают красивая коробка, качественно изданная документация - и, конечно же, броский и удобный интерфейс программы.
Тем, кто хочет создать яркий и нетривиальный дизайн для своего приложения, наверное, будет интересно использовать возможность создания окон непрямоугольной формы - круглых, овальных, многоугольных, звездчатых
Об окнах нестандартной формы знают многие программисты - сам автор статьи впервые узнал о них из материалов одной эхо-конференции. Почему же тогда разработчики так мало используют эту привлекательную возможность?
Попробуем дать конструктивный ответ на этот вопрос - то есть предложим технологию создания нестандартных окон.
Но сначала нужно рассказать, как получаются нестандартные окна, и какие механизмы Windows API для этого существуют. Если вы знакомы с концепцией региона окна и API-функциями региона, переходите сразу к последнему разделу статьи...
В WinAPI имеются функции для задания подмножества точек окна, путем определения координат и размеров геометрической фигуры (эллипса, многоугольника и т.п.), внутри которой эти точки расположены. Подмножество точек окна, которое эти функции умеют определять, называется регионом окна, а сами функции - функциями региона.
Имена функций региона соответствуют геометрической форме создаваемого региона: CreateEllipticRgn() - эллипс, CreateRectRgn() - прямоугольник, CreateRoundRectRgn() - прямоугольник со скругленными углами, CreatePolygonRgn() - произвольный многоугольник. Функции создают регион (т.е. описывающую его структуру в памяти) и возвращают дескриптор созданного региона (region handle).
Для одного окна можно определить любое количество разных регионов; есть также функция CombineRgn(), позволяющая получить составной регион, представляющий собой пересечение, объединение, разность или симметрическую разность нескольких регионов.
Если мы создали для нашего окна, к примеру, два региона (а значит, имеем их дескрипторы), то, запросив у этой функции операцию объединения регионов - получим новый регион, состоящий из точек, принадлежащих обоим нашим регионам - и тому, и другому (и обоим вместе, если они пересекаются).
Так, скомбинировав круглый и треугольный регионы, можно получить на экране фрагмент окна, по форме напоминающий голову в треугольной шляпе. А полученная посредством функции CombineRgn() разность двух регионов позволяет отобразить на экране фрагмент окна с самой настоящей "дырой", сквозь которую можно будет увидеть элементы заднего плана экрана, и даже пощелкать по ним мышью!
Далее, в Windows API имеется функция SetWindowRgn(), вызов которой позволяет ограничить область окна на экране определенным, созданным заранее регионом. Определив регион необычной формы, мы можем с помощью этой функции усечь прямоугольное экранное окно до его фрагмента - "куска" эллиптической, полигональной и т.п. формы.
Итак, резюмируя изложенные выше общие сведения, можно определить следующий порядок создания окна с нестандартными очертаниями:
Прототипы функций приведены в соответствии с синтаксисом языка C++ (как в файле справки). Координаты задаются в пикселах относительно левого верхнего угла окна, также в пикселах задаются требуемые размеры. Все функции, для которых указан тип HRGN, возвращают дескриптор созданного региона.
Функция создания прямоугольного региона:
HRGN CreateRectRgn(int nLeftRect,
// X-координата верхнего левого угла прямоугольникаint nTopRect,
// Y-координата верхнего левого угла прямоугольникаint nRightRect,
// X-координата нижнего правого угла прямоугольникаint nBottomRect
// Y-координата нижнего правого угла прямоугольника)Для описания прямоугольника достаточно указать координаты его левой верхней и правой нижней вершин. Функция создания эллиптического региона:
HRGN CreateEllipticRgn(int nLeftRect,int nTopRect,int nRightRect,int nBottomRect);Здесь задаются координаты прямоугольника, в который вписывается требуемый эллипс. Функция создания региона - произвольного многоугольника:
HRGN CreatePolygonRgn(CONST POINT *lppt,
// указатель на массив координат вершинint cPoints,
// число элементов массива вершинint fnPolyFillMode
// режим заполнения многоугольника);Прежде чем вызывать эту функцию, нужно создать и заполнить массив координат вершин многоугольника. Элементы этого массива - структуры типа POINT:
typedef struct tagPOINT {LONG X,LONG Y,} POINT;Указатель на такой массив передается в функцию первым параметром. Вторым параметром передается число вершин многоугольника. Третий параметр особого значения не имеет; может, например, всегда задаваться константой WINDING. Функция создания региона - прямоугольника со скругленными углами:
HRGN CreateRoundRectRgn(int nLeftRect,
// координаты прямоугольникаint nTopRect,
// ...int nRightRect,
// ...int nBottomRect,
// ...int nWidthEllipse,
// ширина скругляющего эллипсаint nHeightEllipse
// высота скругляющего эллипса);Здесь, кроме координат прямоугольника, нужно задать размеры осей эллипса, который будет применяться для закругления углов. Функция комбинирования регионов:
int CombineRgn(HRGN hrgnDest,
// дескриптор результирующего регионаHRGN hrgnSrc1,
// дескриптор первого региона-операндаHRGN hrgnSrc2,
// дескриптор второго региона-операндаint fnCombineMode
// комбинирующая операция);Эта функция создает регион путем выполнения указанной теоретико-множественной операции над множествами точек двух регионов-операндов. Переменная hrgnDest, в которую будет помещен дескриптор нового региона, должна быть описана в программе заранее. Возможны следующие операции (задаваемые соответствующими константами):
RGN_AND: пересечение двух регионов
RGN_COPY: копия региона, заданного переменной
hrgnSrc1RGN_DIFF: разность двух регионов
RGN_OR: объединение двух регионов
RGN_XOR: симметрическая разность двух регионовФункция возвращает код результата, который представляет собой одну из следующих констант:
NULLREGION: результирующий регион пуст
SIMPLEREGION: результирующий регион есть прямоугольник
COMPLEXREGION: результирующий регион есть сложная фигура
ERROR: результирующий регион не был созданФункция задания региона окна:
int SetWindowRgn(HWND hWnd,
// дескриптор окнаHRGN hRgn,
// дескриптор регионаBOOL bRedraw
// флаг перерисовки);Функция устанавливает для окна, заданного первым параметром, регион, заданный вторым параметром. Логический параметр bRedraw указывает, должно ли окно быть перерисовано немедленно в очертаниях нового региона.
Этих шести функций достаточно для создания сложных регионов и вывода на на экран окон с соответствующими силуэтами. Из функций управления внешним видом региона можно выделить следующие две. Функция закраски региона:
BOOL FillRgn(HDC hdc,
// дескриптор контекста устройстваHRGN hrgn,
// дескриптор регионаHBRUSH hbr
// дескриптор кисти);Функция закрашивает заданный регион, пользуясь параметрами заданной "кисти" (объекта brush). Если все получилось - функция возвращает True, иначе - False. Функция обрамления региона:
BOOL FrameRgn(HDC hdc,
// дескриптор контекста устройстваHRGN hrgn,
// дескриптор регионаHBRUSH hbr,
// дескриптор кистиint nWidth,
// ширина обрамленияint nHeight
// высота обрамления);Функция окаймляет регион "бордюром" заданной ширины и высоты, в соответствии с параметрами кисти.
В Delphi для доступа к функциям регионов и связанных с ними типам и константам необходимо подключить модуль Windows (uses Windows;). Ниже приводится пример метода - обработчика события создания формы для Delphi, которой выполняет установку нестандартного региона для окна формы. При запуске приложения на экране появляется не обычное прямоугольное окно, а неправильный четырехугольник с круглым отверстием посередине:
procedure TForm1.FormCreate(Sender: TObject);
varrgn1,rgn2:HRGN;v:array [1..4] of TPoint; // массив вершин
beginv[1].X:=40; v[1].Y:=0;v[2].X:=200; v[2].Y:=20;v[3].X:=300;
v[3].Y:=150;v[4].X:=10; v[4].Y:=180;
rgn1:=CreatePolygonRgn(v,4,WINDING);
rgn2:=CreateEllipticRgn(100,60,150,110);
CombineRgn(rgn1,rgn1,rgn2,RGN_DIFF);
SetWindowRgn(Handle,rgn1,True);
DeleteObject(rgn1); // (ОсвобождаемDeleteObject(rgn2); // ресурсы)
end;
Но как это сделать? Ведь нужно определить координаты и размеры многочисленных "прямоугольников", "эллипсов" и "многоугольников", из которых в совокупности состоит силуэт нашей картинки, чтобы затем создать соответствующие им регионы и скомбинировать их... Наверное, именно поэтому разработчики редко используют нестандартные окна...
На мой взгляд, единственное практичное решение - создать программу,автоматизирующую создание региона по контурурисунка; позволяющей использовать визуальную технику (подобно графическим редакторам) для наложения нажелаемый рисунок графических примитивов.
Николай Больсунов
Источник - http://delphiclub.ru