0

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

我认为有一种简单的方法可以覆盖 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());
        }
    }

下面是一些物体移动和刷新几次前后的图片:

抱歉,除非我有 10 个 Rep,否则它不会让我嵌入图像。

4

1 回答 1

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和我的事件处理程序得到的结果:

结果图片

更新:问题是您必须Graphics.Clear在每个绘图周期开始时调用方法才能摆脱所有以前的绘图。它会弄乱你的透明背景。此链接为您提供有关该问题的一些建议。关键是您应该使面板的父控件无效,以获得“透明”背景。

所以,我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);
    } 

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

于 2011-06-05T08:49:17.033 回答