До сих пор мы рисовали в основном на канве компонента Image. Но канву имеет не только Image. Ее имеют и многие другие компоненты, например, формы. Все, что ранее вы рисовали на канве компонентов типа TImage, вы могли бы рисовать и на форме. Кроме того имеется специальный компонент PaintBox, имеющий канву и позволяющий рисовать на ней. Рисование на PaintBox вместо формы не имеет никаких преимуществ, кроме, может быть, некоторого облегчения в расположении одного или нескольких рисунков в площади окна.
При рисовании на канве формы или PaintBox надо учитывать некоторые осо бенности. Давайте сначала выясним на собственном опыте, о чем идет речь.
Откройте новое приложение, перенесите на него диалог OpenPictureDialog, кнопку и в обработчик щелчка на ней вставьте операторы:
void __fastcall TForml::ButtonlClick(TObject *Sender)
{
if (OpenPictureDialogl->Execute())
{
Graphics::TBitmap *Bitmap = new Graphics::TBitmap;
try
{
Bitmap->LoadFromFile(OpenPictureDialogl->FileName);
Canvas->Draw(0,0,Bitmap);
}
__finally
{
Bitmap->Free ();
}
}
)
Эти операторы обеспечивают загрузку выбранного пользователем графического файла и отображение изображения непосредственно на канве формы (поскольку оператор Canvas->Draw относится к канве формы, можно было бы это уточнить, написав Form1->Canvas->Draw). Запустите приложение, выберите файл и посмотрите результат. А теперь, не закрывая своего приложения, вернитесь в C++Builder и, ничего там не делая, опять перейдите в свое выполняющееся приложение. Если окно Редактора Кода, выступившее на первый план при вашем переходе в C+-t-Builder, целиком перекрыло окно вашего приложения, то вернувшись в него вы увидите, что картинка в окне исчезла. Если же вы опять загрузите в него картинку и сдвинете окно приложения так, чтобы окно Редактора Кода не могло целиком его закрыть, то, повторив эксперимент с переходом в C++Builder и обратно вы, возможно, увидите другой результат.
Вы видите, что если окно какого-то другого приложения перекрывает на время окно вашего приложения, то изображение, нарисованное на канве формы, портится. В компоненте Image этого не происходило, поскольку в классе TImage уже предусмотрены все необходимые действия, осуществляющие перерисовку испорченного изображения. А при рисовании на канве формы или других оконных компонентов эти меры должен принимать сам разработчик приложения.
Если окно было перекрыто и изображение испортилось, операционная система сообщает приложению, что в окружении что-то изменилось и что приложение должно предпринять соответствующие действия. Как только требуется обновление окна, для него генерируется событие OnPaint. В обработчике этого события (в нашем случае события формы) нужно перерисовать изображение.
Перерисовка может производиться разными способами в зависимости от приложения. В нашем примере можно было бы вынести объявление указателя Bitmap за пределы приведенной выше процедуры, т.е. сделать эту переменную глобальной:
Graphics::TBitmap *Bitmap;
Тогда приведенная выше процедура загрузки файла сокращается до
if (OpenPictureDialogl->Execute())
{
Bitmap = new Graphics::TBitmap;
Bitmap->LoadFromFile(OpenPictureDialogl->FileName);
Canvas->Draw(0,0,Bitmap);
}
Оператор Bitmap->Free(), содержавшийся ранее в этой процедуре, переносится в обработчик события формы OnDestroy. Тогда в течение всего времени выполнения вашего приложения вы будете иметь копию картинки в компоненте Bitmap и вам достаточно ввести в обработчик события OnPaint формы всего один оператор:
if (Bitmap != NULL) Canvas->Draw(0,0,Bitmap);
Оператор if используется, чтобы избежать ошибочного обращения к Bitmap, пока графический файл еще не загружался и объект Bitmap не создан.
Сделайте это, и увидите, что изображение на форме не портится при любых перекрытиях окон.
Сделанный вами обработчик перерисовывает все изображение, хотя, может быть, испорчена только часть его. При больших изображениях это может существенно замедлять перерисовку и вызывать неприятные зрительные эффекты. Перерисовку можно существенно ускорить, если перерисовывать только испорченную область канвы. У канвы есть свойство ClipRect типа TRect, которое в момент обработки события OnPaint указывает область, которая подлежит перерисовке. Поэтому более экономным будет обработчик:
if (Bitmap != NULL) Canvas->CopyRect (Canvas->ClipRect,Bitmap->Canvas, Canvas->ClipRect);
Он перерисовывает только область ClipRect, которая испорчена.
КОНТРОЛЬНЫЕ ВОПРОСЫ:
1. Форматы графических файлов
2. Создание файла изображения в Image Editor
3. Создание пиктограммы для кнопки
4. Рисование с помощью пера Pen
5. Brush-кисть
6. Режимы пера
7. Режимы копирования и рисования канвы.
8. События OnPaint.
ИНДИВИДУАЛЬНЫЕ ЗАДАНИЯ:
1. Создать пиктограмму для кнопок SpeedButton и BitBtn, соответствующую 4 состояниям (цветовая дифференциация – черный, синий, красный, белый). Кнопкой Btn осуществить переключение свойства доступности кнопок.
2. Для индивидуального задания ЛБ-2 создайте новый курсор в виде
3. Для индивидуального задания ЛБ-4 создайте пиктограмму созданного компонента в виде
4. Для индивидуального задания ЛБ-2 создайте новую иконку для файла ресурсов проекта в виде
5. Используя метод рисования с помощью пера Pen, нарисуйте
6. Используя метод рисования с помощью пера Pen, нарисуйте
7. Для компонента BitBtn создайте пиктограмму
8. Для индивидуального задания ЛБ-2 создайте новый курсор в виде
