C#透明面板刷新问题

时间:2011-06-05 08:09:03

标签: c# animation transparency picturebox panels

我目前正在开发一个需要在透明面板上制作动画的项目。我已经能够创建一个透明面板并在其上绘制,但是当我刷新面板时,我用钢笔工具绘制的地方没有被重绘为透明。这留下了我之前画在面板上的最后一个位置。

我假设有一种简单的方法来覆盖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位代表,否则不会让我嵌入图片

1 个答案:

答案 0 :(得分: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

更新:问题是您必须在每个绘制周期的开始时调用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本身无效,它将无法清除,你会看到一堆乱七八糟的红色矩形。


更新(亚历克斯): 这是Dyppl链接中提供的解决问题的代码。它只需要放在透明的面板类中:

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

我在面板上的每次刷新时调用此代码,它使背景保持透明。