2011-06-05 56 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