我目前正在开发一个需要在透明面板上制作动画的项目。我已经能够创建一个透明面板并在其上绘制,但是当我刷新面板时,我用钢笔工具绘制的地方没有被重绘为透明。这留下了我之前画在面板上的最后一个位置。
我假设有一种简单的方法来覆盖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位代表,否则不会让我嵌入图片
答案 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
和我的事件处理程序获得的内容:
更新:问题是您必须在每个绘制周期的开始时调用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);
}
我在面板上的每次刷新时调用此代码,它使背景保持透明。