Учись программированию на C++ Builder бесплатно!

Все, что можно рисовать на канве с помощью компонента TImage, можно рисовать и на форме. Кроме того, имеется специальный компонент PaintBox, имеющий канву и позволяющий рисовать на ней. Рисование на PaintBox вместо формы не имеет никаких преимуществ, кроме может быть некоторого облегчения в расположении одного или нескольких рисунков в площади окна. При рисовании на канве формы или PaintBox надо учитывать некоторые особенности.

Откройте новое приложение, перенесите на него диалог OpenPictureDialog, кнопку и в обработчик щелчка на ней вставьте операторы:

if (OpenPictureDialog1->Execute()}
{
Graphics::TBitmap *Bitmap = new Graphics::TBitmap;
try
{
	Bitmap->LoadFromFile(OpenPictureDialog1->FileName);
	Canvas->Draw(0, 0, Bitmap);
}
__finally
{
	Bitmap->Free();
}
}

Эти операторы обеспечивают загрузку выбранного пользователем графического файла и отображение изображения непосредственно на канве формы (поскольку оператор Canvas->Draw относится к канве формы, можно было бы это уточнить, написав Form1->Canvas->Draw). Запустите приложение, выберите файл. А теперь, не закрывая своего приложения, вернитесь в C++Builder и, ничего там не делая, опять перейдите в свое выполняющееся приложение. Если окно Редактора Кода, выступившее на первый план при вашем переходе в C++Builder, целиком перекрыло окно вашего приложения, то вернувшись в него вы увидите, что картинка в окне исчезла. Если же вы опять загрузите в него картинку и сдвинете окно приложения так, чтобы окно Редактора Кода не могло целиком его закрыть, то, повторив эксперимент с переходом в C++Builder и обратно вы, возможно, увидите уже иной результат.

Если окно какого-то другого приложения перекрывает на время окно вашего приложения, то изображение, нарисованное на канве формы, портится. В компоненте Image этого не происходило, поскольку в классе TImage уже предусмотрены все необходимые действия, осуществляющие перерисовку испорченного изображения. А при рисовании на канве формы или других оконных компонентов эти меры должен принимать сам разработчик приложения.

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

Перерисовка может производиться разными способами в зависимости от приложения. В нашем примере можно было бы вынести объявление указателя Bitmap за пределы приведенной выше процедуры, т.е. сделать эту переменную глобальной:

Graphics::TBitmap*Bitmap;

Тогда приведенная выше процедура загрузки файла сокращается на следующий код:

if (OpenPictureDialog1->Execute())
{
	Bitmap = new Graphics::TBitmap;
	Bitmap->LoadFromFile(OpenPictureDialog1->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, которая испорчена.


Поиск по сайту