Как сохранить в файле примитивы с объекта типа Graphics?

Создал проект Приложение Windows Forms. На форме разместил pictureBox1. На нем создал объект g : Graphics. Применяя к нему метод DrawLine, рисую мышью.

implementation
var g : Graphics;   // инкапсуляция поверхности рисования
var x, y : integer;                 // координаты мыши
var p := new Pen(Color.Black);      // перо черного цвета

procedure Form1.pictureBox1_Paint(sender: Object; e: PaintEventArgs);
begin
  g := Graphics.FromHwnd(pictureBox1.Handle);
  //g := pictureBox1.CreateGraphics;
end;

procedure Form1.pictureBox1_MouseDown(sender: Object; e: MouseEventArgs);
begin
  (x, y) := (e.X, e.Y);
end;

procedure Form1.pictureBox1_MouseMove(sender: Object; e: MouseEventArgs);
begin
  if e.Button = System.Windows.Forms.MouseButtons.Left then 
  begin
    g.DrawLine(p, x, y, e.x, e.y);
    (x, y) := (e.X, e.Y);    
  end;
end;

Как сохранить нарисованное в файле? Так понимаю, у объекта g должен быть какой-то метод, - но я не нашел, какой.

Знаю, вот так можно сохранить изображение Image: pictureBox1.Image.Save(‘2.png’);

  • это если предварительно выполнили загрузку, например так: pictureBox1.load(‘1.png’);

А нарисованное как сохранить?

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

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

Painting.rar (234.8 КБ) Через контекстное меню пытаюсь сохранить нарисованное. В результате приложение прекращает работу и файл не создается. Однако, если предварительно открыть какой-то файл, а потом сохранить - пожалуйста, сохраняется, - но только без нарисовнного поверх него. Посмотрите, пожалуйста. Спасибо!

В первую очередь обновитесь и запускайте с помощью простого F9 из редактора. Потому что программа должна не прекращать работу, а показывать что было кинуто NullReferenceException.

Ну, получилось кое-как заставить работать:

var lines_to_draw := new List<array of integer>;

Добавляет в него линии вместо того чтобы их рисовать в MouseMove:

    lines_to_draw += |x, y, e.x, e.y|; // Создавать целый массив это костыль, лучше объявить свою запись для этого
    pictureBox1.Invalidate; // Вызывает перерисовку
    (x, y) := (e.X, e.Y);

Затем в обработчике .Paint:

  g := e.Graphics; // Берём поданый нам специальный объект Graphics вместо создания нового
  foreach var (x1,y1, x2,y2) in lines_to_draw do
    g.DrawLine(p, x1,y1, x2,y2);

Обратите внимание - lines_to_draw нельзя очищать, все линии надо заново рисовать при каждой перерисовке. Ну, мне не хватило терпения достаточно долго рисовать чтобы это привело к лагам.

Наверное, чтобы сделать по-нормальному - придётся рисовать на отдельно созданном битмапе, а в Paint копировать содержимое этого битмапа на PictureBox.

P.S. А, ещё должно быть возможно сохранить такой промежуточный битмап в свойство .Image, чтобы его рисовало автоматически. А обработчик Paint тогда надо удалить. Но .Invalidate всё равно надо будет вызывать.

Спасибо! Вы мне в который раз уже хорошо помогаете! Чувствую, как расту ))

1 лайк

Попробуйте SaveWindow(‘файл.jpg’’) или Window.Save(‘файл.jpg’)

@ahtam вы не понимаете разницу между графическими модулями (/библиотеками и т.п.)?

Возможно ошибся.