2016-07-27 169 views
0

我在一個項目中工作,我需要不斷地獲取位圖並在一個圖片框上繪製它們。C#自定義圖片框控件

這個想法是繪製第一個初始位圖,然後回顧位圖的其餘部分,並將它們繪製在初始位圖之上。 (第一個仍然顯示在picturebox中,所以我想在第一個位圖上繪製它們)。

我試圖設計一個自定義控件來實現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. 
} 

我不確定代碼中出了什麼問題。我使用e EventArgs在我需要的時候繪製一個新塊,但看起來新的繪圖很難隱藏以前的位圖。

+1

。那怎麼解決你的問題?您使用pictureBox1使用圖形對象繪製的任何圖像。CreateGraphics()將立即被擦除,而不會在OnPaint重寫方法中再次重繪。 –

+0

@ user12572不,沒有自定義控件,如果我只是使用picturebox並從它創建一個圖形對象,它會繪製在當前圖像的頂部。你可以看到自己。至少在這裏,我只繪製一個塊每日而不是整個圖像。 – Slashy

+0

Got it!因此,您需要重複繪製第二張圖像,但不需要繪製第一張圖像。很好:) –

回答

2

您可以創建一個圖形文檔閱讀從PictureBox的對象,然後重繪在您標記`Shlomi's`回答,因爲你接受的答案當前圖像

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

您的代碼存在的問題是您沒有將圖片添加到要替換它們的控件中。

旁註:隨着代碼你有沒有配置在PictureBox ES圖像設置Bitmap對象,因此這可能會導致內存泄漏。您可以創建一個類似的控件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. 
} 

另一種選擇是要合併所有的圖像一起加入他們,然後只是繪製圖像進圖片框。

+0

實際上,你在每次刷新時都會控制整個列表......這就是definetley不好的。我會在這裏告訴你一個簡單的想法:它用於屏幕共享項目,我從套接字接收完整的deksopt位圖,然後從套接字中檢索許多小的位圖塊,並且需要在一個picturebox中更新它們 - 這將提供一個更新的桌面圖像。 - – Slashy

+0

@Slashy我知道這很糟糕,我說過,這是你想達到的一個非常基本的想法。我不會爲你寫代碼,只是指出你正確的方向來自己找到解決方案。這就是在將圖像繪製在PictureBox之前合併圖像。 – TheLethalCoder

+0

@TheLethalCoder查看更新的評論:)。 現在我知道我可以從圖片框中創建'圖形'對象,並且繪製每個塊而不用創建用戶控件 - 但是'Picturebox.CreateGraphics'導致了一些繪圖問題..所以我最好使用'OnPaint'事件/// – Slashy

1

你應該做的是將新圖像疊加在前一張圖像上。 假設有一張主圖像(第一張圖像),並且您想在同一主圖像上打印下一張圖像(重疊圖像)。使用下面的方法來做到這一點。

​​

然後將此新圖像設置爲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. 
} 

這應該適合你。

注意:您應該在使用後處理圖像。

更新: 您需要重新繪製整個圖像,因爲OnPaint中被調用時,只需要重新繪製的圖片框顯示當前圖像。 每次繪製表單時,都會重寫OnPaint方法以重新繪製圖像;否則圖像只會持續到下一次重新繪製。 的OnPaint中here

+0

不錯,這本質上是在我的回答底部的想法的基本形式的代碼 – TheLethalCoder

+0

@ user12572我不希望這樣的解決方案,像這樣...它會撕裂我的表現:(我越來越像somthing每秒60〜70個小塊,重新繪製完整位圖的60〜70倍就會......該死。 – Slashy