DrawToBitmap возвращает пустое изображение
У меня проблема с созданием растрового изображения из моего приложения winform.
Ситуация:
у меня есть UserControl
названный какCanvasControl
"который принимает OnPaint
метод, действующий как холст для моего приложения Draw Pad. Внутри этого пользовательского элемента управления у меня есть функция "PrintCanvas()
"Это создаст скриншот изображения UserControl
в файл PNG. Ниже PrintCanvas()
функция:
public void PrintCanvas(string filename = "sample.png")
{
Graphics g = this.CreateGraphics();
//new bitmap object to save the image
Bitmap bmp = new Bitmap(this.Width, this.Height);
//Drawing control to the bitmap
this.DrawToBitmap(bmp, new Rectangle(0, 0, this.Width, this.Height));
bmp.Save(Application.StartupPath +
@"\ExperimentFiles\Experiment1" + filename, ImageFormat.Png);
bmp.Dispose();
}
Этот пользовательский элемент управления (CanvasControl
) вызывается внутри моей основной формы, где пользователь будет что-то рисовать и затем иметь возможность сохранить с помощью кнопки сохранения. Кнопка сохранения вызоветPrintCanvas()
"Функция UserControl
,
Я получаю выходной файл изображения, как и ожидалось, но проблема в том, что это было пустое изображение.
Что я уже пробовал:
Чтобы проверить, что это не проблема синтаксиса, я попытался передать PrintCanvas()
функции в мою основную форму, и на удивление я получаю изображение всей основной формы в файле, но UserControl
там не видно
Есть ли другие настройки, которые я пропустил, чтобы сделать winform UserControl
можно напечатать?
ОБНОВЛЕНИЕ: (РИСУНКИ РИСУНКА)
- Пользовательский элемент управления действует как холст - код здесь
1 ответ
Код в вопросе дал первую подсказку, но код в ссылке показал источник проблемы: вы используете "неправильный" экземпляр Graphics
объект для рисования:
protected override void OnPaint(PaintEventArgs e)
{
// If there is an image and it has a location,
// paint it when the Form is repainted.
Graphics graphics = this.CreateGraphics();
..
Это одна из самых распространенных ошибок с графикой winforms! Никогда не используйте CreateGrphics! Вы всегда должны рисовать на управляющей поверхности с помощью объекта Graphics в событии Paint или DrawXXX. Эти события имеют параметр e.Graphics
который является единственным, который может рисовать постоянную графику.
Постоянный означает, что он будет обновляться всегда, когда это необходимо, а не только при запуске. Это неприятная ошибка, потому что кажется, что все работает, пока вы не столкнетесь с ситуацией, когда внешнее событие делает необходимым перерисовку:
- Минимизация, а затем максимизация формы
- Перемещаем его с экрана и обратно
- призвание
DrawToBitmap
- ...
..все будет работать только при использовании действующего и текущего Graphics
объект из PaintEventArgs e
параметр.
Итак, решение простое:
protected override void OnPaint(PaintEventArgs e)
{
// If there is an image and it has a location,
// paint it when the Form is repainted.
Graphics graphics = e.Graphics(); // << === !!
..
Но что это CreateGraphics
хорош для? Это хорошо только для того, чтобы заманить новичков в эту ошибку??
Не совсем; Вот несколько вариантов использования:
- Рисование непостоянной графики, например, прямоугольника с резинкой или специального курсора мыши
- Измерение размеров текста без фактического рисования
TextRenderer
илиMeasureString
метод - Опрос экрана или
Bitmap
разрешение сGraphics.DpiX/Y
и, вероятно, некоторые другие, о которых я не могу думать в настоящее время..
Так что для нормального рисования на элементы управления всегда используйте e.Grapahics
объект! Вы можете передать его подпрограммам, чтобы сделать код более структурированным, но не пытайтесь его кэшировать; это должно быть актуальным!