2016-07-27 3 views
0

Я работаю над проектом, где мне нужно постоянно получать растровые изображения и рисовать их на картинке.C# пользовательский контроль изображения

Идея состоит в том, чтобы нарисовать первую начальную растровую карту, затем извлечь оставшуюся часть растрового изображения и нарисовать их над начальным. (Первый, который все еще отображается в окне изображения, поэтому я хочу нарисовать их на первом растровом изображении).

Я попытался создать пользовательский элемент управления, чтобы реализовать событие OnPaint, но во второй раз, когда событие запущено, оно рисует второй block и полностью скрывает изображение, которое было нарисовано ранее.

public class RapidPictureBox: PictureBox 
{ 
    public pictureBox1Control() 
    { 
     SetStyle(
      ControlStyles.AllPaintingInWmPaint | 
      ControlStyles.OptimizedDoubleBuffer | 
      ControlStyles.UserPaint | 
      ControlStyles.ResizeRedraw, true); 
    } 

    public Bitmap block = null; 
    public int x = 0, y = 0; 
    protected override void OnPaint(PaintEventArgs e) 
    { 
     e.Graphics.DrawImage(block, x, y); 
    } 
} 

private void Form1_Load(object sender, EventArgs e) 
{ 
    RapidPictureBox pictureBox1 = new RapidPictureBox(); 
    pictureBox1.Dock = DockStyle.Fill; 
    Controls.Add(pictureBox1); 

    pictureBox1.block = new Bitmap("3.png"); //first initial image 

    pictureBox1.block = new Bitmap("2.png"); //draw on the initial one. 
} 

Я не уверен, что не так в коде. Я использую EventArgs e для рисования нового блока каждый раз, когда мне нужно, но кажется, что новый чертеж полностью скрывает предыдущее растровое изображение.

+1

Вы отметили 'Shlomi's' ответ в качестве принятого ответа. Как это устраняет вашу проблему? Любое изображение, которое вы рисуете с помощью графического объекта, вы получаете с помощью pictureBox1.CreateGraphics() будет немедленно очищен, не перерисовывая его снова в переопределенном методе OnPaint. –

+0

@ user12572 no, без пользовательского элемента управления, если я просто использую picturebox и создаю из него графический объект, он будет рисовать поверх текущего изображения. Вы можете видеть сами. По крайней мере, здесь я всего лишь рисую один блок каждый раз а не весь образ. – Slashy

+0

Получил! Поэтому вам нужно рисовать второе изображение повторно, но не нужно рисовать первое изображение. Nice :) –

ответ

2

вы можете создать графический объект из PictureBox, а затем перерисовывать его на текущем изображении

initial =new Bitmap("test.png"); 
pictureBox1.Image = initial; 
var graphics = pictureBox1.CreateGraphics(); //create a graphic objec 
graphics.DrawImage(block, x,y);//that's the second method 
0

Проблема с кодом заключается в том, что вы не добавляете изображения в элемент управления, который вы заменяете.

Side Примечание: С кодом у вас есть вы не расправившись с Bitmap объектов, установленных в PictureBox эс изображения и таким образом, это может вызвать утечку памяти.

Вы можете создать аналогичный элемент управления LayeredPictureBox. Это позволит получить все изображения и нарисовать их поверх друг друга. Это будет иметь низкую производительность и изображения должны иметь прозрачность, чтобы выглядеть слоистые, но вы получите идею:

public class LayeredPictureBox : PictureBox 
{ 
    public LayeredPictureBox() 
    { 
     SetStyle(
      ControlStyles.AllPaintingInWmPaint | 
      ControlStyles.OptimizedDoubleBuffer | 
      ControlStyles.UserPaint | 
      ControlStyles.ResizeRedraw, true); 
    } 

    public List<Bitmap> blocks = new List<Bitmap>(); 
    public int x = 0, y = 0; 
    protected override void OnPaint(PaintEventArgs e) 
    { 
     foreach (Bitmap block in blocks) 
     { 
      e.Graphics.DrawImage(block, x, y); 
     } 
    } 
} 

private void Form1_Load(object sender, EventArgs e) 
{ 
    RapidPictureBox pictureBox1 = new RapidPictureBox(); 
    pictureBox1.Dock = DockStyle.Fill; 
    Controls.Add(pictureBox1); 

    pictureBox1.blocks.Add(new Bitmap("3.png")); //first initial image 

    pictureBox1.blocks.Add(new Bitmap("2.png")); //draw on the initial one. 
} 

Другой вариант заключается в объединении всех изображений вместе, добавив их, а затем просто рисунок, что изображение в PictureBox.

+0

На самом деле, что вы наведете, что при каждом обновлении элемент управления будет рисовать весь список ... это определенно плохо. я расскажу здесь короткую идею: это для проекта совместного использования экрана, где я получаю полный растровый файл deksopt из сокета, а затем я извлекаю много маленьких растровых блоков из сокета и должен обновлять их в ящике с картинками, что обеспечит обновленное изображение рабочего стола. - – Slashy

+0

@Slashy Я знаю, что это плохо, я сказал, что это очень простая идея того, чего вы хотите достичь. Я не буду писать код для вас, просто укажу вам в правильном направлении, чтобы прийти к решению самостоятельно. И это должно объединить изображения, прежде чем рисовать их на PictureBox. – TheLethalCoder

+0

@ TheLethalCoder посмотреть обновленный комментарий :). теперь я знаю, что могу создать объект «Graphics» из окна с картинками и рисовать каждый блок, который я получаю, не создавая пользовательский элемент управления, но «Picturebox.CreateGraphics» вызвал некоторые проблемы с рисованием. Я предпочитаю использовать событие «OnPaint» /// – Slashy

1

Что вы должны сделать, это наложить новое изображение на предыдущее изображение. Предположим, что есть основное изображение (первое изображение), и вы хотите напечатать следующее изображение (перекрывающееся изображение) на том же основном изображении. Используйте следующий метод для этого.

private Bitmap GetOvelappedImages(Bitmap primaryImage, Bitmap overlappingImage) 
{ 
//create graphics from main image 
using (Graphics g = Graphics.FromImage(primaryImage)) 
{ 
    //draw other image on top of main Image 
    g.DrawImage(overlappingImage, new Point(0, 0)); 
} 
return primaryImage; 
} 

затем установите это новое изображение в изображениеBox1.block.

private void Form1_Load(object sender, EventArgs e) 
{ 
    RapidPictureBox pictureBox1 = new RapidPictureBox(); 
    pictureBox1.Dock = DockStyle.Fill; 
    Controls.Add(pictureBox1); 

    pictureBox1.block = GetOverlappedImages(new Bitmap("3.png"),new Bitmap("2.png")); //draw on the initial one. 
} 

Это должно сработать для вас.

Примечание: Вы должны располагать изображения после их использования.

Update: Вам нужно перерисовывать все изображение, потому что, OnPaint вызывается только тогда, когда текущее изображение, показанное на картинке поле необходимо перерисовать. Метод OnPaint переопределяется, чтобы перерисовать изображение каждый раз, когда форма нарисована; иначе изображение будет сохраняться только до следующей перекраски. Читайте документацию для OnPaint here

+0

Приятно, это, по сути, код базовой формы идеи в нижней части моего ответа – TheLethalCoder

+0

@ user12572 Мне не нужно такое решение вроде этого ... он собирается разорвать мою производительность :(Я получаю что-то вроде 60 ~ 70 маленьких блоков в секунду, перерисовка 60 ~ 70 раз, полная битмап будет просто ... черт возьми. – Slashy

Смежные вопросы