2016-07-27 13 views
0

Ich arbeite an einem Projekt, wo ich ständig Bitmaps bekommen und sie auf einer Picturebox zeichnen muss.C# benutzerdefinierte Picturebox Kontrolle

Die Idee besteht darin, eine erste anfängliche Bitmap zu zeichnen, dann den Rest der Bitmap abzurufen und sie über die ursprüngliche zu zeichnen. (Die erste wird immer noch in der Bildbox angezeigt, also möchte ich sie auf die erste Bitmap zeichnen).

Ich habe versucht, ein benutzerdefiniertes Steuerelement zu entwerfen, das OnPaint Ereignis zu implementieren, aber das zweite Mal das Ereignis ausgelöst wird, zeichnet es die zweite block und verbirgt vollständig das Bild, das zuvor gezeichnet wurde.

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. 
} 

Ich bin mir nicht sicher, was im Code falsch ist. Ich benutze die e EventArgs, um einen neuen Block zu zeichnen, wann immer ich brauche, aber es scheint, dass die neue Zeichnung die vorherige Bitmap vollständig verbirgt.

+1

Sie markiert haben 'Shlomi's' als akzeptierte Antwort beantworten. Wie behebt das dein Problem? Jedes Bild, das Sie mit einem Grafikobjekt zeichnen, erhalten Sie mit pictureBox1.CreateGraphics() wird sofort gelöscht, ohne es erneut in der überschriebenen OnPaint-Methode neu zu zeichnen. –

+0

@ user12572 nein, ohne ein benutzerdefiniertes Steuerelement, wenn ich nur Picturebox verwenden und ein Grafikobjekt daraus erstellen würde, würde es auf dem aktuellen Bild zeichnen.Sie können für sich selbst sehen, am wenigsten hier zeichne ich nur einen Block jedes Mal und nicht das ganze Bild. – Slashy

+0

Verstanden! Sie müssen also das zweite Bild wiederholt zeichnen, aber nicht das erste Bild zeichnen. Nice :) –

Antwort

2

Sie ein Grafik-Objekt aus dem picturebox erstellen, neu zu zeichnen sie dann über das aktuelle Bild

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

Das Problem mit Ihrem Code besteht darin, dass Sie dem Steuerelement, das Sie ersetzen, keine Bilder hinzufügen.

Side Hinweis: Mit dem Code, den Sie haben Sie nicht von den in dem PictureBox es Bild gesetzt Bitmap Objekte entsorgen und so könnte diese Speicherlecks verursachen.

Sie können ein ähnliches Steuerelement LayeredPictureBox erstellen. Dadurch werden alle Bilder erhalten und übereinander gezeichnet. Es wird eine schlechte Leistung haben und die Bilder müssen Transparenz haben geschichtet zu sehen, aber Sie bekommen die Idee:

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. 
} 

Eine weitere Möglichkeit alle Bilder zusammen, um sie zu verschmelzen ist zum Hinzufügen und dann nur das Bild in der Zeichnung Bilderkiste.

+0

eigentlich was du nicht ist, dass auf jeder Aktualisierung die Kontrolle wird die gesamte Liste zeichnen ... das ist definitely schlecht. ich werde hier die kurze idee sagen: es ist für ein bildschirm-sharing-projekt, wo ich eine vollständige deksopt-bitmap von einem sockel bekomme, und dann ich viele kleine bitmap-blöcke aus dem sockel abrufen und sie in einer picturebox aktualisieren müssen-was bereitstellen würde ein aktualisiertes Desktop-Image. - – Slashy

+0

@Slashy Ich weiß, dass es schlecht ist, sagte ich, das ist eine sehr grundlegende Idee für das, was du erreichen willst. Ich werde den Code für Sie nicht einfach nur in die richtige Richtung zeigen, um selbst zur Lösung zu kommen. Und das ist, die Bilder vor dem Zeichnen auf der PictureBox zusammenzuführen. – TheLethalCoder

+0

@ TheLethalCoder sehen Sie den aktualisierten Kommentar :). jetzt weiß ich, dass ich 'Graphics' Objekt aus der Picturebox erstellen und jeden Block zeichnen konnte, ohne das Benutzersteuerelement zu erstellen - aber die' Picturebox.CreateGraphics' verursachte einige Zeichnungsprobleme..so ich bevorzugte das 'OnPaint'-Ereignis /// – Slashy

1

Was Sie tun sollten, ist das neue Bild auf dem vorherigen Bild zu überlagern. Nehmen wir an, es gibt ein primäres Bild (erstes Bild) und Sie möchten das nächste Bild (überlappendes Bild) auf demselben primären Bild drucken. Verwenden Sie die folgende Methode, um das zu tun.

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; 
} 

dann legen Sie dieses neue Bild auf pictureBox1.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. 
} 

Das sollte für Sie arbeiten.

Hinweis: Sie sollten Bilder nach der Verwendung entsorgen.

Update: Sie müssen ganzes Bild neu zu zeichnen, weil OnPaint nur aufgerufen wird, wenn aktuelles Bild auf Bildfeld neu gezeichnet werden muss, gezeigt. Die OnPaint-Methode wird überschrieben, um das Bild jedes Mal neu zu streichen, wenn das Formular gemalt wird. ansonsten würde das Bild nur bis zum nächsten Neuanstrich bestehen bleiben. lesen Dokumentation für OnPaint here

+0

Schön, das ist im Wesentlichen der Code für die Grundform der Idee am Ende meiner Antwort – TheLethalCoder

+0

@ user12572 Ich wollte nicht eine solche Lösung wie diese ... es wird meine Leistung reißen :(Ich bekomme etwas wie 60 ~ 70 kleine Blöcke pro Sekunde, 60-70 Mal das komplette Bitmap neu zeichnen würde nur ... verdammt. – Slashy