Как сделать калькулятор в Delphi?

Delphi - объектно-ориентированный язык программирования, разработанный компанией Borland в 1995 году. Он основан на языке программирования Pascal, но имеет более расширенные возможности и добавлены новые функции.

Как Delphi реализует многоплатформенную разработку?

Delphi является интегрированной средой разработки (IDE), которая позволяет разрабатывать программное обеспечение для различных платформ, включая Windows, macOS, Android и iOS. Delphi достигает многоплатформенности с помощью...

Окна - такие разные:круглые, треугольные, звездообразные...

Статьи » Формы и окна » Окна - такие разные:круглые, треугольные, звездообразные...

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

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

Об окнах нестандартной формы знают многие программисты - сам автор статьи впервые узнал о них из материалов одной эхо-конференции. Почему же тогда разработчики так мало используют эту привлекательную возможность?

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

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

Понятие региона окна и функций региона
Любое окно в Windows можно представить как прямоугольную систему координат, с точкой отсчета в левом верхнем углу. Точки экранного изображения окна описываются координатами (X, Y), где X - порядковый номер точки по горизонтальной оси, а Y - по вертикальной.

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

Имена функций региона соответствуют геометрической форме создаваемого региона: CreateEllipticRgn() - эллипс, CreateRectRgn() - прямоугольник, CreateRoundRectRgn() - прямоугольник со скругленными углами, CreatePolygonRgn() - произвольный многоугольник. Функции создают регион (т.е. описывающую его структуру в памяти) и возвращают дескриптор созданного региона (region handle).

Для одного окна можно определить любое количество разных регионов; есть также функция CombineRgn(), позволяющая получить составной регион, представляющий собой пересечение, объединение, разность или симметрическую разность нескольких регионов.

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

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

Далее, в Windows API имеется функция SetWindowRgn(), вызов которой позволяет ограничить область окна на экране определенным, созданным заранее регионом. Определив регион необычной формы, мы можем с помощью этой функции усечь прямоугольное экранное окно до его фрагмента - "куска" эллиптической, полигональной и т.п. формы.

Итак, резюмируя изложенные выше общие сведения, можно определить следующий порядок создания окна с нестандартными очертаниями:

  1. Создать набор элементарных регионов, составляющих нужную форму окна, вызывая соответствующие функции создания региона и запоминая дескрипторы созданных регионов;
  2. Если регионов больше одного, то скомбинировать созданные регионы при помощи функции CombineRgn(), получив регион с требуемыми очертаниями;
  3. Отобразить окно в очертаниях региона, вызвав функцию SetWindowRgn().

Описание основных функций региона
Всего существует примерно два с половиной десятка функций региона. Здесь мы ограничимся описанием прототипов важнейших из них (все побробности можно узнать из любого help’а по WinAPI - например, достаточно неплохого руководства 95guide.hlp).

Прототипы функций приведены в соответствии с синтаксисом языка 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

Другое по теме:

Категории

Статьи

Советы

Copyright © 2024 - All Rights Reserved - www.delphirus.com