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. Пользовательский элемент управления действует как холст - код здесь

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 объект! Вы можете передать его подпрограммам, чтобы сделать код более структурированным, но не пытайтесь его кэшировать; это должно быть актуальным!

Другие вопросы по тегам