2011-06-05 58 views
0

我目前正在研究一個需要透明面板上的動畫的項目。我已經能夠創建一個透明面板並對其進行繪製,但是當我刷新面板時,使用鋼筆工具繪製的面板不會被重繪爲透明。這留下了我以前畫在面板上的最後一個位置。C#透明面板刷新問題

我假設有一個簡單的方法來重寫OnPaint或Refresh來重繪面板上的所有像素爲透明的,但我無法在網上找到解決方案或自己弄明白。

這裏是我用來做背景透明的代碼:

public class TransparentPanel : Panel 
{ 
    protected override CreateParams CreateParams 
    { 
     get 
     { 
      CreateParams cp = base.CreateParams; 
      cp.ExStyle |= 0x20; 
      return cp; 
     } 
    } 

    protected override void OnPaintBackground(PaintEventArgs e) 
    { 
    } 
} 

這是我最失敗的嘗試重繪透明背景:

protected override void OnPaint(PaintEventArgs pe) 
{ 
     pe.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(100,255,255,255)), this.ClientRectangle); 
} 

這種解決方案的問題是,在兩次刷新後,背景變得不透明。

任何人都可以幫我弄清楚如何做到這一點?我對圖形和動畫非常陌生,我認爲這有一個相當簡單的答案。提前致謝。


***編輯* ** 按Dyppl的迴應,我已經改變了我繪製圖形面板的方式。這裏是我當前的代碼:

public TransparentPanel fighterPanel; 
... 
    fighterPanel.Paint +=new PaintEventHandler(fighterPanel_Paint); 
... 
    fighterPanel = new TransparentPanel(); 
    fighterPanel.Location = new System.Drawing.Point(600, 300); 
    fighterPanel.Size = new System.Drawing.Size(400, 400); 
    gameArenaForm.Controls.Add(fighterPanel); 
    fighterPanel.BringToFront();   
... 
    private void fighterPanel_Paint(object sender, PaintEventArgs e) 
    { 
     using (Pen blackPen = new Pen(Color.Black, 3), redPen = new Pen(Color.Red, 3), bluePen = new Pen(Color.Blue, 3)) 
     { 
      //head  
      e.Graphics.DrawEllipse 
       (blackPen, 
       head.DrawPoint(torso.GetTorsoAngle(), torso.neck.getLocationX(), torso.neck.getLocationY()).X, 
       head.DrawPoint(torso.GetTorsoAngle(), torso.neck.getLocationX(), torso.neck.getLocationY()).Y, 
       head.radius * 2, 
       head.radius * 2 
       ); 
      //torso 
      e.Graphics.DrawLine(blackPen, torso.neck.getLocationX(), torso.neck.getLocationY(), torso.shoulders.getLocationX(), torso.shoulders.getLocationY()); 
      e.Graphics.DrawLine(blackPen, torso.shoulders.getLocationX(), torso.shoulders.getLocationY(), torso.hips.getLocationX(), torso.hips.getLocationY()); 
      //right arm 
      e.Graphics.DrawLine(blackPen, torso.shoulders.getLocationX(), torso.shoulders.getLocationY(), rightArm.elbow.getLocationX(), rightArm.elbow.getLocationY()); 
      e.Graphics.DrawLine(redPen, rightArm.elbow.getLocationX(), rightArm.elbow.getLocationY(), rightArm.attachHand.getLocationX(), rightArm.attachHand.getLocationY()); 
      //left arm 
      e.Graphics.DrawLine(blackPen, torso.shoulders.getLocationX(), torso.shoulders.getLocationY(), leftArm.elbow.getLocationX(), leftArm.elbow.getLocationY()); 
      e.Graphics.DrawLine(bluePen, leftArm.elbow.getLocationX(), leftArm.elbow.getLocationY(), leftArm.attachHand.getLocationX(), leftArm.attachHand.getLocationY()); 
      //right leg 
      e.Graphics.DrawLine(blackPen, torso.hips.getLocationX(), torso.hips.getLocationY(), rightLeg.knee.getLocationX(), rightLeg.knee.getLocationY()); 
      e.Graphics.DrawLine(redPen, rightLeg.knee.getLocationX(), rightLeg.knee.getLocationY(), rightLeg.attachFoot.getLocationX(), rightLeg.attachFoot.getLocationY()); 
      //left leg 
      e.Graphics.DrawLine(blackPen, torso.hips.getLocationX(), torso.hips.getLocationY(), leftLeg.knee.getLocationX(), leftLeg.knee.getLocationY()); 
      e.Graphics.DrawLine(bluePen, leftLeg.knee.getLocationX(), leftLeg.knee.getLocationY(), leftLeg.attachFoot.getLocationX(), leftLeg.attachFoot.getLocationY()); 
     } 
    } 

下面是之前和對象移動後的一些照片,並刷新了幾次:

Before

After

對不起,也不會讓我嵌入圖像,除非我有10個代表

+0

從一個對圖形並不陌生的人來說:當涉及到GDI +和winforms時,透明度從來就不是很簡單...... – Dyppl 2011-06-05 08:12:46

+0

Ewe,那對我來說聽起來不是很有希望。你對這個問題有什麼想法嗎? – Alex 2011-06-05 08:15:21

+0

@亞歷克斯:是的,現在嘗試 – Dyppl 2011-06-05 08:17:39

回答

0

您不應該使用CreateGraphics爲您的任務。訂閱Paint事件的面板,並使用PaintEventArgs.Graphics作爲Graphics對象來完成事件處理程序中的所有繪圖。

private void transparentPanel1_Paint(object sender, PaintEventArgs e) 
{ 
    e.Graphics.DrawRectangle(new Pen(Color.Red,2), 4,4,64,64); 
} 

這裏是我用你的TransparentPanel和我的事件處理程序:

Result image

UPDATE:的問題是,你必須調用Graphics.Clear方法中的每一個開始繪製週期爲了擺脫所有以前的圖紙。它會弄亂你的透明背景。 This link爲您提供有關該問題的一些建議。關鍵在於你應該使你的面板的父控制無效,並獲得你的「透明」背景。

所以,我離開的TransparentPanel不變的代碼,但改變主要形式的代碼:

readonly Random _rand =new Random(); 

private void transparentPanel1_Paint(object sender, PaintEventArgs e) 
{ 
    e.Graphics.DrawRectangle(new Pen(Color.Red,2), _rand.Next(60),_rand.Next(30),64,64); 
} 

private void button1_Click(object sender, EventArgs e) 
{ 
    Invalidate(new Rectangle(transparentPanel1.Location, transparentPanel1.Size),true); 
} 

現在,每當我點擊我的窗體上的按鈕面板被重繪,並顯示在任意位置的一個矩形。如果您使transparantPanel1本身無效,則不會清除,您會看到一團紅色的矩形。


修訂版(作者Alex): 這是從該Dyppl解決的問題的鏈接提供的代碼。它只是需要被放置在透明面板類:

public void InvalidateEx() 
    { 
     if (Parent == null) 
      return; 
     Rectangle rc = new Rectangle(this.Location, this.Size); 
     Parent.Invalidate(rc, true); 
    } 

我把這個代碼在面板上的每一個刷新和它保持背景透明。

+0

真棒,讓我給它一個鏡頭。 – Alex 2011-06-05 08:55:25

+0

@Dyppl:我搞砸了很多,它仍然導致與CreateGraphics相同的問題。我將添加我的實際更新的代碼,使用您的建議以及我的問題以及一些屏幕截圖。 – Alex 2011-06-05 10:08:33

+0

@Dyppl:我很確定我按照你期望的方式實現了這一點。如果我錯過了一些東西,你可以讓我知道在哪裏?你可以在我的編輯中看到代碼和圖片。 – Alex 2011-06-05 10:42:14