begin
AboutBox.Close; {или просто Close}
end;
end.
Остановимся более подробно на имени процедуры: TAboutBox — это имя класса, в котором происходит событие, OKButton — это имя кнопки, а OKButtonClick — это событие, возникающее при нажатии кнопки.
Для того чтобы из модуля первой формы была доступна вторая форма, необходимо подключить этот модуль, тогда весь список подключаемых модулей будет иметь вид:
uses Windows, SysUtils, Classes, Graphics, Forms, Controls, StdCtrls, Buttons, ExtCtrls, Unit2 ;
На главной форме разместим дополнительную кнопку с именем About (свойство Name). Именно при нажатии на эту кнопку выводится дополнительная форма, тогда процедура обработки события будет иметь вид:
procedure TForm1.AboutClick(Sender: TObject);
begin
AboutBox.Show;
end;
Задания:
1. Проверьте все примеры из лабораторной работы.
2. В примере 3 выведите дополнительную форму в модальном виде.
3. Сделайте так, чтобы при закрытии окна текстового редактора, если данные не были сохранены, выводилось сообщение.
4. Сделайте так, чтобы при нажатии на кнопку сообщение появлялось в левом верхнем углу, при втором нажатии — в правом верхнем и т. д. (сообщения разные: каждое соответствует своему углу).
Лабораторная работа 7. Графические компоненты
Цель: изучить основные графические возможности.
Многие компоненты Delphi, включая саму форму, имеют средства рисования. Однако есть специальные средства, предназначенные либо непосредственно для рисования, либо для отображения уже готовых рисунков, либо для того и другого. Для рисования компоненты могут включать свойства определенного класса: TPen, TBrush, TCanvas и класс, который определяет цвет. Рассмотрим их более подробно.
Класс TColor позволяет выбирать цвет из таблицы стандартных цветов Windows (clWhite, clRed, …). Однако могут использоваться и нестандартные цвета. В этом случае учитывая, что свойство данного типа хранит четырехбайтовое значение, каждый байт которого (нумерация байтов происходит слева направо) имеет следующее значение:
1 — указатель формата цвета;
2, 3, 4 — интенсивность, соответственно, синей, зеленой и красной
составляющей.
Старший байт указывает, каким способом будут использоваться
остальные байты значения. Если он равен 0, то оставшиеся байты определяют RGB — цвет. Например, значение $00000000 задает черный цвет,
а $00FF0000 — чисто синий цвет, $00FFFFFF — белый цвет. Если старший байт равен 1, то два последних байта определяют один из 65536 возможных логических палитр. Наконец, если старший байт равен 2, то оставшиеся байты задают относительный цвет. Выбор цвета также можно осуществлять посредством диалога. В этом случае используется компонент ColorDialog со страницы Dialogs, который возвращает выбранный из палитры цвет в свойстве Color.
Пример 1
Создать приложение, в котором выбор цвета можно осуществлять как посредством диалога, так и вводом шестнадцатеричного значения цвета.
Поместим на форму компоненты ColorDialog, Panel, Label и Button. При нажатии на кнопку будет вызываться диалоговое окно, после закрытия которого, данным цветом будет закрашиваться компонент Panel, а в компоненте Label будет выдаваться шестнадцатеричное представление данного цвета. Компонент Panel со стандартной панели инструментов используется просто для демонстрации. Никакими дополнительными свойствами, кроме возможности объединять другие компоненты, он не обладает. Для нас интересно только то, что имеется свойство Color и может менять цвет. В этом случае процедура обработки нажатия на кнопку вызывает диалоговое окно выбора цвета и окрашивает компонент Panel
в выбранный цвет, при этом также отображается шестнадцатеричное представление данного цвета.
procedure TForm1.Button1Click(Sender: TObject);
begin
if ColorDialog1.Execute then
begin
Panel1.Color:=ColorDialog1.Color;
Label1.Caption:=IntToHex(ColorDialog1.Color,8)
end;
end;
Теперь рассмотрим обратную задачу, а именно будем задавать самостоятельно шестнадцатеричное представление цвета. Поскольку нет стандартной функции, переводящей символьное представление шестнадцатеричной константы в число, создадим функцию HexStrToHex, которая будет выполнять данную работу. Программа будет иметь вид:
function HexStrToInt(s:string):integer;
function hex(c:char):integer ;
begin
case c of
'0'..'9':Result:=ord(c)-ord('0');
'A'..'F':Result:=ord(c)-ord('A')+10;
end;
end;
Var i:integer;
begin
result:=0;
if s[1]='$' then delete(s,1,1);
For i:=1 to length(s) do
Result:=result*16+hex(s[i]);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Panel2.Color:=HexStrToInt(Edit1.Text);
end;
Класс TPen задает характеристики карандаша, с помощью которого изображаются различные линии. У этого класса есть свойства Color — для задания цвета линии, Mode — для задания стиля рисования, который заключается в выборе одного или нескольких цветов рисования линии, Style — свойство, определяющее стили рисования (штриховая, пунктирная, штрихпунктирная), Width — свойство целого типа, определяющее толщину линии.
Класс TBrush задает характеристики кисти, которой закрашивается поверхность изображения. Свойство Bitmap задает собственное заполнение раскрашиваемой поверхности и представляет собой изображение 8×8 пикселей, Style — свойство, определяющее орнамент кисти (горизонтальные, вертикальные или диагональные линии).
Данные классы не могут использоваться самостоятельно, а являются составными частями других, более сложных, классов.
TCanvas представляет собой наиболее сложный класс и является поверхностью, на которой размещается созданное изображение. К свойствам данного класса относятся свойство Pen класса Tpen, свойство Brush класса TBrush. Большое количество методов предназначено для отображения геометрических фигур. При отображении фигур контур изображается карандашом Pen с установленными в нем характеристиками. Если фигура является замкнутой и необходимо произвести ее закраску, то будут использоваться значения свойства класса Brush. Для доступа к каждой точке имеется свойство Pixel, которое является двухмерным массивом, содержащим цвет каждой точки.
В данном классе имеется ряд методов, которые позволяют строить
линию — LineTo, эллипс — Ellipse, дугу — Arc, многоугольника — PolyLine.
Методы для вывода картинок на канву — Draw и StretchDraw. В качестве параметров указываются прямоугольник и графический объект для вывода (это может быть TBitmap, TIcon или TMetafile). StretchDraw отличается тем, что растягивает или сжимает картинку так, чтобы она заполнила весь указанный прямоугольник.
Методы для вывода текста — TextOut и TextRect. При выводе текста используется шрифт (Font) канвы. При использовании TextRect текст выводится только внутри указанного прямоугольника. Длину и высоту текста можно узнать с помощью функций TextWidth и TextHeight.
У объектов из библиотеки визуальных компонентов TBitmap, TComboBox, TDrawGrid, TForm, TImage, TPaintBox, TStringGrid есть свойство Canvas (канва), которое предоставляет простой путь для рисования на них.
На странице System палитры компонентов есть объект TPaintBox, который можно использовать для построения приложений типа графического редактора. Никаких ключевых свойств, кроме Canvas, данный компонент не имеет, собственно, этот объект является просто канвой для рисования.
Рассмотрим некоторые примеры использования графических компонентов и возможности рисования.
Пример 2
При перемещении курсора мыши по форме все пиксели формы закрашиваются в красный цвет. Поскольку пиксели необходимо закрашивать при перемещении мыши, можно использовать событие MouseMove.
В процедуре необходимо просто закрашивать точки формы.
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
Form1.Canvas.Pixels[x,y]:=clRed;
end;
Пример 3
Строятся части прямых линий, которые задаются при перемещении мыши. При первом событии происходит смещение в точки, при следующем эта линия строится. Для решения никаких дополнительных компонентов помещать не будем, поскольку само построение происходит на форме. Необходимо только ввести новую переменную и считать количество нажатий на кнопку. Программа будет иметь следующий вид:
var i:Integer;
procedure TForm1.FormCreate(Sender: TObject);
begin
i:=1;
end;
procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
i:=i+1;
if odd(i) then
Form1.Canvas.LineTo(x,y)
else
Form1.Canvas.MoveTo(x,y);
end;
Эту задачу можно решить и другим способом. Обрабатывать отдельно нажатие на кнопку мыши и ее отпускание. В одном случае осуществлять перемещение, а во втором — строить данную линию.
Var x1,y1:integer;
procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Form1.Canvas.LineTo(x,y);
end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Form1.Canvas.MoveTo(x,y);
end;
Построение линии подобным образом выглядит не совсем красиво, поскольку она появляется только один раз и остается на этом же месте. При работе с современными графическими редакторами процесс построения линии, да и любого другого объекта, несколько иной. А именно — после фиксации начального положения можно перемещать мышь, при этом появляется динамический характер данного объекта. И только после отпускания кнопки мыши объект фиксируется. Данный эффект принято называть «резиновой линией». Для подобных построений необходимо использовать внутренние функции Windows, т. е. функции API. Изложение данных функций выходит за пределы пособия, однако хочется надеяться, что познавательный интерес возьмет верх и позволит вам разобраться в программе.
Пример 4. Построение «резиновой линии».
type
TForm1 = class(TForm)
procedure FormMouseDown(Sender:TObject;Button:TMouseButton; Shift: TShiftState;X,Y:Integer);
procedure FormMouseMove (Sender:TObject; Shift:TShiftState; X,Y: Integer);
procedure FormMouseUp (Sender:TObject;Button:TMouseButton;Shift: TShiftState; X,Y:Integer);