ООП IDE Borland C++ Builder Лекции 16. Проектирование

advertisement
ООП
IDE Borland C++ Builder
Лекции 16.
Проектирование
графических
приложений
1
Содержание
1. Построение графических изображений компонент Image
2. Канва - холст для рисования
3. Режимы рисования
4. События OnPaint
2
Вопрос 1
Построение графических изображений компонент Image
3
Компонент Image
• Потребность вставить в приложение
графические объекты:
• графическая заставка, являющаяся
логотипом приложения - компонент
Image (Additional)
• графические объекты при разработке
приложения, работающего с базой
данных –DBImage -DBImage.
4
Компонент Image
Свойства компонента Image.
• Picture - свойство, может содержать картинку
• AutoSize - позволяет подгонять компонент под
размер рисунка.
• True -размер компонента Image будет
автоматически подгоняться под размер
помещенной в него картинки
• False -изображение может не поместиться в
компонент или, наоборот, площадь
компонента может оказаться много больше
площади изображения
• Stretch позволяет подгонять рисунок под размер
компонента
5
Компонент Image
Свойства компонента Image.
• Установить AutoSize = false, растянуть или сжать
размер компонента Image и установить Stretch в
true.
• Рисунок займет всю площадь компонента, но
изображение может исказиться.
• Устанавливать Stretch в true может иметь смысл
только для каких-то узоров, но не для картинок.
• Stretch не действует на изображения пиктограмм,
которые не могут изменять своих размеров.
6
Компонент Image
•
•
•
•
•
•
•
Свойства компонента Image.
Center=true центрирует изображение на площади Image,
если размер компонента больше размера рисунка.
Transparent (прозрачность) = true - изображение в
Image становится прозрачным - можно использовать для
наложения изображений друг на друга.
Поместить на форму второй компонент Image и загрузить
в него мало заполненную, контурную картинку.
Передвинуть Image так, чтобы они перекрывали друг
друга, и в верхнем компоненте установить Transparent
равным true.
Верхняя картинка перестанет заслонять нижнюю.
Возможное применение Transparent - наложение на
картинку надписей, выполненных в виде битовой матрицы.
Свойство Transparent действует только на битовые
матрицы
7
Компонент Image - пример
• Поместим на форму компонент Image.
• Кнопка с … свойства Picture или двойной щелчок на
Image, откроется окно Picture Editor, позволяющее
загрузить в свойство Picture графический файл
(кнопка Load), а также сохранить открытый файл под
новым именем или в новой папке.
• Щелкнуть на Load - откроется окно Load Picture.
• По мере перемещения курсора в списке по графическим
файлам в правом окне отображаются содержащиеся в
них изображения.
• В окне загрузки графического файла можно просмотреть
изображение, и увидеть размер изображения.
• После щелчка на ОК в компоненте Image отобразится
выбранный объект.
8
Компонент Image - пример
• При загрузке в процессе проектирования картинки из
файла в Image, он не просто отображает ее, но и
сохраняет в приложении.
• Это дает возможность поставлять приложение без
отдельного графического файла.
• В Image можно загружать и внешние графические
файлы в процессе выполнения приложения.
• Рассмотрим пример, чтобы пользователь смог
просматривать и загружать любые графические файлы.
• Поместим на форму компонент ОреnPictureDialog и
кнопку Button и в обработчике щелчка на кнопке
введем код:
if (OpenPictureDialog1->Execute())
Image1->Picture->LoadFromFile
(OpenPictureDialog1->FileName);
9
Компонент Image - пример
• Недостаток приложения - изображения могут быть разных
размеров и их положение на форме или будет
несимметричным, или они не будут помещаться в окне.
• Чтобы форма автоматически настраиваться на размеры
изображения, установим в Image1 свойство AutoSize
равным true, и сделать следующие изменения:
if (OpenPictureDialog1->Execute () )
{
Image1->Picture->LoadFromFile(OpenPictureDialog1>FileName);
Form1->ClientHeight = Image1->Height + 10;
Image1->Top=Form1->ClientRect.Top + (Form1>ClientHeight - Image1->Height)/2;
Form1->ClientWidth = Image1->Width + 10;
Image1->Left=Form1->ClientRect.Left + (Form1>ClientWidth - Image1->Width)/2; }
10
Вопрос 2
Канва - холст для рисования
11
Канва - холст для рисования. Канва и пикселы
• Многие компоненты в C++Builder (формы,
графические компоненты Image, PaintBox,
Bitmap и др.) имеют свойство Canvas (канва,
холст)
• Канва – это область компонента, на которой можно
рисовать или отображать готовые изображения.
• Канва содержит свойства и методы, существенно
упрощающие графику C++Builder.
• Все сложные взаимодействия с системой
спрятаны для пользователя.
• Каждая точка канвы имеет координаты X и Y.
• Система координат канвы имеет началом левый
верхний угол канвы.
• X возрастает при перемещении слева направо, а Y при перемещении сверху вниз.
12
Канва - холст для рисования. Канва и пикселы
• Координаты измеряются в пикселах.
• Пиксел - это наименьший элемент поверхности рисунка,
с которым можно манипулировать.
• Важнейшее свойство пиксела - его цвет.
• Для описания цвета используется тип TCoIor.
• Для графики иногда этих предопределенных констант не
хватает, т.е. могут понадобиться такие оттенки, которых
нет в стандартных палитрах.
• В этом случае можно задавать цвет 4-байтовым
шестнадцатеричным числом.
• Например:
• $00FF0000 - чистый синий цвет,
• $0000FF00 - чистый зеленый,
• $000000FF - чистый красный
• $00000000 - черный цвет, $00FFFFFF - белый.
13
•
•
•
•
•
•
Рисование по пикселам
Рисовать на канве можно разными способами.
1 первый вариант - рисование по пикселам.
Для этого используется свойство канвы Pixels представляет собой двумерный массив Canvas>Pixels[int X][int Y], который отвечает за цвета
канвы.
Canvas->Pixels[10][20] соответствует цвету
пиксела, 10-го слева и 20-го сверху.
С массивом пикселов можно обращаться как с
любым свойством: изменять цвет, задавая пикселу
новое значение, или определять его цвет по
хранящемуся в нем значению.
Например, Canvas->Pixels[10][20] = clBlack это задание пикселу черного цвета.
14
Рисование по пикселам
• Пример: нарисовать график функции F(X) на канве
компонента Image1, если известен диапазон ее
изменения Ymax и Ymin и диапазон изменения
аргумента Xmin и Хmах.
• Это можно сделать такой процедурой:
float x,y; // координаты функции
int Px, Py; // координаты пикселов
for (Рx = 0; Рx <= Image1->Width; Px++)
{
//х - координата, соответствующая пикселу с координатой Рх
x = Xmin + Рx * (Xmax - Xmin)/ Image1->Width;
y = F(x) ;
//Pу - координата пиксела, соответствующая координате у
Py = Image1->Height - (y - Ymin)*Image1->Height/(YmaxYmin); //Устанавливается черный цвет выбранного пиксела
Image1->Canvas->Pixels[Px] [Py] = clBlack; }
15
•
•
•
•
•
•
Рисование по пикселам
Вводятся переменные x и y, являющиеся
значениями аргумента и функции, а также
переменные Рx и Py, являющиеся координатами
пикселов, соответствующими x и y.
Функция состоит из цикла по всем значениям
горизонтальной координаты пикселов Рx
компонента Image1.
Сначала выбранное значение Рx пересчитывается в
соответствующее значение x.
Затем производится вызов функции и определяется
ее значение y.
Это значение пересчитывается в вертикальную
координату пиксела Py.
И в заключение цвет пиксела с координатами (Рx,
Py) устанавливается черным.
16
Рисование по пикселам
• Пример приложения построения графика функции sin(x), для
которой Xmin=0, Хmах=4π, Ymin=-1, Ymax=1.
• Поместим на форму компонент Image и кнопку с надписью
«Нарисовать», в обработчик события OnClick запишем
следующий код:
const double Pi =3.14159
float x, y;
// координаты функции sin(x)
int Px, Py;
// координаты пикселов
for (Рx = 0; Рx <- Image1->Width; Px++)
{ //x - координата, соответствующая пикселу с коорд. Рx
x = Рx * 4 * Pi/Image1->Width;
y = sin(x) ; //Py - координата пиксела, соответствующая
координате y
Py = Image1->Height - (y+1) * Image1->Height /2;
Image1->Canvas->Pixels[Px][Py] = clBlack; }
17
Рисование с помощью пера Реn
•
•
•
•
•
2 вариант рисования на канве – с помощью пера Pen.
У канвы есть свойство Реn - перо.
Это объект, в свою очередь имеет ряд свойств.
Свойство Color - цвет, которым наносится рисунок.
Свойство - Width (ширина линии) - задается в пикселах, по
умолчанию равна 1.
• Свойство Style определяет вид линии, может принимать
следующие значения:
psSolid
Сплошная линия.
psDash
Штриховая линия.
psDot
Пунктирная линия.
psDashDot
Штрихпунктирная линия.
psDashDotDot
Линия, чередующая штрих и два пунктира.
psClear
Отсутствие линии.
psInsideFrame
Сплошная линия, но при Width > 1 допускающая
цвета, отличные от палитры Windows.
18
Рисование с помощью пера Реn
• Все стили со штрихами и пунктирами доступны только при
Width=1.
• В противном случае линии этих стилей рисуются как
сплошные.
• Стиль psInsideFrame - единственный, который допускает
произвольные цвета.
• Цвет линии при остальных стилях округляется до ближайшего
из палитры Windows.
• Свойство канвы PenPos определяет в координатах канвы
текущую позицию пера.
• Перемещение пера без прорисовки линии, т.е. изменение
PenPos, производится методом канвы MoveTo(x,y) (где (x,y)
- координаты точки, в которую перемещается перо).
• Эта текущая точка становится исходной, от которой методом
LineTo(x,y) можно провести линию в точку с координатами
(x,y).
• При этом текущая точка перемещается в конечную точку
линии и новый вызов LineTo будет проводить точку из этой
19
новой текущей точки.
Рисование с помощью пера Реn
• Рассмотрим рисование пером графика синуса.
• Добавим на форму еще один компонент Image.
• Размеры обоих компонентов Image должны быть
абсолютно одинаковы.
• Сделать размеры компонентов абсолютно
одинаковыми легко, выделив их оба и
воспользовавшись командой всплывающего меню
Size.
• Затем в обработчике щелчка на кнопке сделаем
соответствующие изменения:
20
Рисование с помощью пера Реn
const double Pi = 3.14159;
float x, y;
// координаты функции sin(x)
int Px, Py;
// координаты пикселов
Image2->Canvas->MoveTo(0,Image2->Height / 2) ;
for (Рx = 0; Рx < Image1->Width; Px++)
{
x = Рx * 4 * Pi / Image1->Width;
y = sin(x) ;
Py = Image1->Height - (y+l) * Imagel->Height /2;
Image1->Canvas->Pixels[Px][Py] = clBlack;
Image2->Canvas->LineTo(Px,Py); // Проводится
линия на втором графике
}
21
Рисование с помощью пера Реn
• Оба графика абсолютно одинакового размера
• пересчет координат достаточно провести для одного из
них, затем воспользоваться ими для рисования обоих
графиков.
• Качество двух одинаковых графиков сильно
различается.
• В левом на крутых участках сплошной линии нет - она
распадается на - пикселы.
• А правый график весь сплошной.
• Это показывает, что при прочих равных условиях
рисовать лучше пером.
• Еще одно свойство компонента Image и его канвы.
Можно задавать координаты пикселов, выходящие за
пределы размеров канвы
• Это позволяет не заботиться о том, какая часть рисунка
попадает в рамку Image, а какая нет.
22
Рисование с помощью пера Реn
• легко проверить это, увеличив, например, вдвое
размах синусоиды.
• Для этого достаточно изменить оператор, задающий
значение y, на следующий:
Y = 2 * sin(x) ;
• Изобразится только та часть рисунка, которая
помещается в рамку канвы.
• Это позволяет легко осуществлять приложения, в
которых пользователю предоставляется
возможность увеличивать и просматривать в
деталях какие-то фрагменты графиков.
23
Рисование с помощью пера Реn
• Перо может рисовать не только прямые линии, но и
фигуры.
• Методы канвы, использующие перо для рисования
фигур:
Arc
Рисует дугу окружности или эллипса.
Chord
Ellipse
Рисует замкнутую фигуру, ограниченную дугой
окружности или эллипса и хордой.
Рисует окружность или эллипс.
Pie
Рисует сектор окружности или эллипса.
Polygon
Polyline
Рисует замкнутую фигуру с кусочно-линейной
границей.
Рисует кусочно-линейную кривую.
Rectangle
Рисует прямоугольник.
RoundRect
Рисует прямоугольник со скругленными углами.
24
Рисование с помощью пера Реn
Код, который рисует различные фигуры.
Image1->Canvas->Font->Style << fsBold;
Image1->Canvas->Arc(10,10,90,90, 90, 50,10,50) ;
Image1->Canvas->TextOut (40, 60, "Arc") ;
Image1->Canvas->Chord(110,10,190,90,190,50,110, 50) ;
Image1->Canvas->TextOut(135,60,"Chord");
Image1->Canvas->Ellipse(210,10,290, 50) ;
Image1->Canvas->TextOut(230,60,"Ellipse") ;
Image1->Canvas->Pie(310,10,390,90,390,30,310,30);
Image1->Canvas->TextOut(340,60,"Pie") ;
TPoint points[5];
points[0] = Point(30,150) ;
points[1] = Point(40,130);
points[2] = Point(50,140);
points[3] = Point(60,130) ;
points[4] = Point(70,150) ;
25
Рисование с помощью пера Реn
Код, который рисует различные фигуры.
Image1->Canvas->Polygon(points,4);
Image1->Canvas->TextOut(30,170,"Polygon");
points[0].x += 100;
points[1].x += 100;
points[2].x += 100;
points[3].x += 100;
points[4].x += 100;
Image1->Canvas->Polyline(points, 4) ;
Image1->Canvas->TextOut(130,170,"Polyline");
Image1->Canvas->Rectangle(230,120,280,160) ;
Image1->Canvas->TextOut(230,170,"Rectangle") ;
Image1->Canvas->RoundRect(330,120,380,160,20,20) ;
Image1->Canvas->TextOut(325,170,"RoundRect") ;
26
Рисование с помощью пера Реn
• Свойство канвы Brush - кисть определяет фон и
заполнение замкнутых фигур на канве.
• Brush - это объект, имеющий в свою очередь ряд
свойств.
• Свойство Color определяет цвет заполнения.
• Свойство Style определяет шаблон заполнения
(штриховку).
• Свойство Bitmap является указателем на объект типа
TBitmap и определяет нестандартное заполнение
заданным шаблоном.
• Шаблон задается битовой матрицей размером 8x8.
• Если для кисти задан шаблон Bitmap, то заполнение
производится именно этим шаблоном, независимо от
значения свойства Style.
• Шаблон Bitmap может создаваться в процессе
выполнения приложения или, например, загружаться из
27
файла.
Рисование с помощью пера Реn
• Метод канвы FillRect (TRect SRect) заполняет заданным
стилем или шаблоном прямоугольную область, заданную
параметром Rect.
• Для его задания проще всего использовать функцию
Rect(x1,y1,x2,y2), возвращающую структуру Rect с
координатами углов, заданных параметрами (x1, y1) и
(x2, y2).
• Функцию FillRect удобно, в частности, использовать для
стирания изображения. Например, оператор
Image1->Canvas->FillRect(Rect(0,0, Image1>Width,Image1->Height)); очищает всю площадь
канвы компонента Image1.
• Кисть участвует в заполнении фигур не только с
помощью этой функции.
• Все перечисленные ранее методы рисования замкнутых
фигур тоже заполняют их с помощью кисти.
• Это относится к методам Chord, Ellipse, Pie, Polygon28и
Рисование с помощью пера Реn
• Метод FloodFill - заполняет замкнутую область на
канве.
• Определен следующим образом:
FloodFill(int x, int y, TColor Color, TFillstyle
FillStyle);
• Точка с координатами x и y является произвольной
внутренней точкой заполняемой области, которая
может иметь произвольную форму.
• Граница этой области определяется сочетанием
параметров Color и FillStyle.
• Параметр Color указывает цвет, который
используется при определении границы заполняемой
области, а параметр FillStyle определяет, как
именно по этому цвету определяется граница.
29
Рисование с помощью пера Реn
• Параметр FillStyle может принимать одно из двух
следующих значений:
• fsSurface
• fsBorder.
• Если FillStyle = fsSurface, то заполняется область,
окрашенная цветом Color, а на других цветах метод
останавливается.
• Если FillStyle = fsBorder, то наоборот, заполняется
область окрашенная любыми цветами, не равными
Color, a на цвете Color метод останавливается.
• Для определения области закрашивания можно
использовать координаты и цвет одного из пикселов,
расположенных внутри области (если FillStyle =
fsSurface) или снаружи ее (если FillStyle = fsBorder).
30
Вопрос 3
Режимы рисования
31
Режимы рисования пера Реn
• У пера Реn имеется еще одно свойство - Mode (режим).
• По умолчанию значение Mode = pmCopy.
• Это означает, что линии проводятся цветом, заданным в
свойстве Color.
• Но возможны и другие режимы, в которых учитывается
не только цвет Color, но и цвет соответствующих
пикселов фона.
• Наиболее интересным из этих режимов является режим
pmNotХоr - сложение с фоном по инверсному
исключающему ИЛИ.
• Операция инверсного исключающего ИЛИ анализирует
по битам два своих операнда.
• Результирующий бит равен "0", если соответствующие
биты двух операндов не равны друг другу, а при
равенстве битов операндов результирующий бит равен
"1".
32
Режимы рисования пера Реn
• Каждый пиксел хранит цвет как набор битов.
• Пусть фоновый пиксел имеет значение 0110011, а
цвет пера установлен в 1111000.
• Применение, операции pmNotXor к этим двум
числам даст цвет со значением 0110100.
• Этот цвет перо задаст данному пикселу.
• А теперь посмотрим, что получится, если перо
повторно пройдет по тому же пикселу.
• В этом случае опять будет выполнена операция
pmNotXor по отношению к цвету пера 1111000 и
текущему цвету пиксела, который стал равен
0110100.
• Применение pmNotXor к этим числам даст в
результате 0110011, т.е. первоначальный цвет
пиксела.
33
Режимы рисования пера Реn
• Если нарисовать на фоне какую-то фигуру один
раз, а затем нарисовать ту же фигуру повторно, то
нарисованная фигура исчезнет и каждый пиксел
вернется к своему первоначальному цвету.
• Эту особенность режима pmNotXor, свойственную
также режиму ртХог - сложение с фоном по
исключающему ИЛИ, можно использовать для
создания простенькой анимации.
• Достаточно нарисовать нечто, затем стереть
нарисованное, перерисовать немного измененным и рисунок будет представляться ожившим.
34
Режимы копирования и рисования канвы
• Метод копирования канвы CopyRect позволяет копировать
прямоуг. область источника изображения в прямоуг. область
данной канвы.
• Метод определен следующим образом:
CopyRect(TRect &Dest, TCanvas * Canvas, TRect
&Source);
• Параметр Dest определяет прямоугольную область канвы, в
которую производится копирование.
• Параметр Canvas указывает источник, из которого копируется
изображение.
• Это может быть канва любого компонента: типа TImage, типа
TBitmap и др.
• В частном случае источником может быть и канва того же
компонента, в который производится копирование.
• Параметр Source определяет прямоугольную область в
источнике изображения, которая копируется в область Dest.
• Обе прямоугольные области и в источнике, и в приемнике
35
имеют тип Trect.
Режимы копирования и рисования канвы
• Копирование - это не просто перенос изображения, а
сложное взаимодействие копируемого изображения и того,
которое было до этого в области, куда производится
копирование.
• Характер этого взаимодействия определяется параметром
CopyMode (режим копирования) той канвы, в которую
производится копирование.
• По умолчанию значение CopyMode равно cmSrcCopy.
• Это единственный режим, при котором производится
действительное копирование: изображение в Dest
стирается и заменяется скопированным.
• Есть два значения - cmWhiteness и cmBlackness, при
которых собственно никакое копирование не
производится: просто область закрашивается
соответственно белым или черным цветом.
• А все остальные режимы определяют сложное
взаимодействие копируемого изображения с тем, которое
36
было в Dest.
Режимы копирования и рисования канвы
• Особый интерес представляет режим cmScrInvert,
при котором изображения канвы и источника
комбинируются, используя булеву операцию XOR.
• Так же, как и для пера, повторное копирование в
подобном режиме восстанавливает прежнее
изображение на канве.
• Интересен также режим cmSrcAnd.
• Если копируемое изображение представляет собой
контурный черный рисунок на белом фоне, то этот
рисунок наложится на прежнее изображение канвы,
а белый фон будет прозрачным, так что под ним
будет видно первоначальное изображение.
• В режиме cmSrcPaint аналогичный эффект будет,
если копируемое изображение представляет собой
белый контурный рисунок на черном фоне.
37
Режимы копирования и рисования канвы
Примеры копирования в различных режимах.
Image1->Canvas->CopyMode = cmSrcCopy;
Image1->Canvas->
CopyRect(Rect(0,0,200,200),Image2->Canvas, Rect
(0,0,200,200));
• обеспечивают копирование изображения фрагмента
канвы компонента Image2 в указанную область
канвы компонента Image1.
• Изображение, которое ранее было на канве
компонента Image1 в пределах области с
координатами углов (0, 0) и (200, 200), просто
заменяется новым.
38
Режимы копирования и рисования канвы
Примеры копирования в различных режимах.
Image1->Canvas->CopyMode = cmSrcInvert;
Image1->Canvas>CopyRect(Rect(0,0,200,200),Image2->Canvas,
Rect(0,0,200,200)) ;
Image1->Canvas->CopyRect (Rect (0, 0, 200, 200)
,lmage2->Canvas,Rect (0,0,200,200));
• обеспечивают копирование изображения фрагмента
канвы компонента Image2 в указанную область
канвы компонента Image1 в режиме cmSrcInvert.
• После выполнения функции CopyRect в первый раз
изображения в компонентах Image1 и Image2
налагаются друг на друга, а в результате
выполнения функции CopyRect во второй раз
исходное изображение на канве компонента
39
Image1 восстанавливается.
Режимы копирования и рисования канвы
Примеры копирования в различных режимах.
Image1->Canvas->CopyMode = cmWhiteness;
Image1->Canvas>CopyRect(Rect(0,0,200,200),Image2->Canvas,
Rect(0,0,200,200)) ;
• просто очищают указанную область канвы
компонента Image1, закрашивая ее белым цветом.
• При этом изображение в компоненте Image2 никак
не участвует в операциях копирования.
40
Режимы копирования и рисования канвы
• Помимо методов копирования свойство CopyMode
используется также методом рисования на канве
Draw:
void _fastcall Draw(int x, int y, TGraphic*
Graphic);
• Метод Draw рисует изображение, содержащееся в
объекте, указанном параметром Graphic, сохраняя
исходный размер изображения в его источнике и
перенося изображение в область канвы объекта,
верхний левый угол которой определяется
параметрами x и y.
• Источник изображения может быть битовой
матрицей, пиктограммой или метафайлом.
• Если источник - объект типа TBitmap, то перенос
изображения производится в режиме,
установленном свойством канвы CopyMode.
41
Режимы копирования и рисования канвы
•
•
•
•
•
Оператор Image1->Canvas->Draw(10,10,Bitmap1);
рисует на канве компонента Image1 изображение
из компонента Bitmap1 в область с координатами
левого верхнего угла (10, 10).
Метод рисования – DrawFocusRect - рисует
изображение прямоугольника в виде, используемом
для отображения рамки фокуса, операцией XOR.
Функция DrawFocusRect объявлена следующим
образом:
void _fastcall DrawFocusRect(const
Windows::TRect *Rect);
где Rect - прямоугольная область.
Поскольку при рисовании используется операция
XOR, то повторный вызов этого метода с тем же
значением Rect удаляет изображение
42
прямоугольника.
Вопрос 4
События OnPaint
43
События OnPaint
• Канву имеют многие компоненты, например,
формы.
• Все, что ранее рисовали на канве компонента
Image, можно рисовать и на форме.
• Кроме того, имеется специальный компонент
PaintBox, имеющий канву и позволяющий рисовать
на ней.
• При рисовании на канве формы или PaintBox надо
учитывать некоторые особенности.
• Сначала выясним, о чем идет речь.
• Откроем новое приложение, перенесем на него
диалог OpenPictureDialog, кнопку и в обработчик
щелчка на ней вставим операторы:
44
События OnPaint
void _fastcall TForm1::ButtonlClick(TObject *Sender)
{
if (OpenPictureDialog1->Execute ())
{
Graphics::TBitmap *Bitmap = new Graphics::TBitmap;
try
{
Bitmap->LoadFromFile(OpenPictureDialog1->FileName);
Form1->Canvas->Draw(0,0,Bitmap);
}
finally
{
Bitmap->Free();
}
}
}
• .
45
События OnPaint
• Эти операторы обеспечивают загрузку выбранного
пользователем графического файла и отображение
изображения непосредственно на канве формы.
• Запустим приложение, выберем файл.
• А теперь, не закрывая приложение, вернемся в
C++Builder и, ничего там не делая, опять перейдем
в приложение.
• Если окно Редактора Кода, выступившее на первый
план при переходе в C++Builder, целиком
перекрыло окно приложения, то, вернувшись в него
увидим, что картинка в окне исчезла.
• Если же опять загрузим в него картинку и сдвинем
окно приложения так, чтобы окно Редактора Кода
не могло целиком его закрыть, то, повторив
эксперимент с переходом в C++Builder и обратно
увидим результат.
46
События OnPaint
• Если окно какого-то другого приложения перекрывает
на время окно приложения, то изображение,
нарисованное на канве формы, портится.
• В компоненте Image этого не происходило, поскольку в
классе TImage уже предусмотрены все необходимые
действия, осуществляющие перерисовку испорченного
изображения.
• А при рисовании на канве формы или других оконных
компонентов эти меры должен принимать разработчик
приложения.
• Если окно было перекрыто и изображение испортилось,
операционная система сообщает приложению, что в
окружении что-то изменилось и что приложение должно
предпринять соответствующие действия.
• Как только требуется обновление окна, для него
генерируется событие OnPaint.
• В обработчике этого события нужно перерисовать
47
изображение.
События OnPaint
• Перерисовка может производиться разными
способами в зависимости от приложения.
• В примере можно было бы вынести объявление
указателя Bitmap за пределы приведенной выше
процедуры, т.е. сделать эту переменную глобальной:
Graphics::TBitmap *Bitmap;
• Тогда приведенная выше процедура загрузки файла
примет вид:
if (OpenPictureDialog1->Execute())
{
Bitmap = new Graphics::TBitmap;
Bitmap->LoadFromFile(OpenPictureDialog1>FileName);
Canvas->Draw(0,0,Bitmap);
}
48
•
•
•
•
События OnPaint
Оператор Bitmap->Free() нужно перенести в
обработчик события формы OnDestroy.
Тогда в течение всего времени выполнения
приложения будете иметь копию картинки в
компоненте Bitmap и достаточно ввести в
обработчик события OnPaint формы всего один
оператор:
if (Bitmap != NULL)
Canvas->Draw(0,0,Bitmap);
Оператор if используется, чтобы избежать
ошибочного обращения к Bitmap, пока
графический файл еще не загружался и объект
Bitmap не создан.
Теперь изображение на форме не портится при
любых перекрытиях окон.
49
События OnPaint
• Написанный обработчик перерисовывает все
изображение.
• При больших изображениях это может существенно
замедлять перерисовку и вызывать неприятные
зрительные эффекты.
• Перерисовку можно существенно ускорить, если
перерисовывать только испорченную область канвы.
• У канвы есть свойство ClipRect типа TRect, которое в
момент обработки события OnPaint указывает
область, которая подлежит перерисовке.
• Поэтому более экономным будет обработчик:
if (Bitmap != NULL)
Canvas->CopyRect (Canvas->ClipRect, Bitmap>Canvas, Canvas->ClipRect);
• Он перерисовывает только область ClipRect,
50
которая испорчена.
Download