C# 透明图形缓冲区清除?
我目前正在从事一个项目,我必须使用GDI+(C# 透明图形缓冲区清除?,c#,image,forms,gdi+,transparency,C#,Image,Forms,Gdi+,Transparency,我目前正在从事一个项目,我必须使用GDI+(System.Drawing)。我想做一个多用途的仪表(一个像时钟一样的轮子),上面有动态的指针 我不想每一帧都画背景图像(带有所有标记)。我现在解决这个问题的方法是将其设置为图形化“容器”的背景图像,这是一个面板(请记住,我可能必须以不同的方式进行) 然后我拔针。针当前每秒更新25次(我可能会对此进行优化,使其仅在必要时更新)。但问题是,我必须在开始新帧之前清除缓冲区,导致背景图像被缓冲区的背景颜色覆盖。显然我不想要这个 我尝试将缓冲区的背景色设置为
System.Drawing
)。我想做一个多用途的仪表(一个像时钟一样的轮子),上面有动态的指针
我不想每一帧都画背景图像(带有所有标记)。我现在解决这个问题的方法是将其设置为图形化“容器”的背景图像,这是一个面板(请记住,我可能必须以不同的方式进行)
然后我拔针。针当前每秒更新25次(我可能会对此进行优化,使其仅在必要时更新)。但问题是,我必须在开始新帧之前清除缓冲区,导致背景图像被缓冲区的背景颜色覆盖。显然我不想要这个
我尝试将缓冲区的背景色设置为color.Transparent
,但它根据父级的透明度键为缓冲区提供了一种颜色(在我的例子中,它变成黑色)
以下是我当前用于绘制打捆针的代码(在控制盘
类中):
//
///拉动轮子和针。
///
公众抽签()
{
图形。清晰(颜色。透明);
//拔出所有的针,效果很好
foreach(打捆针中的打捆针Ndl)
{
Ndl.绘图(参考本图);
}
//在轮子的中心画一个小圆。只看起来。
图形。填充椭圆(新钢笔(颜色。白色)。画笔,新矩形(120,120,16,16));
}
是的,我遵守了堆栈溢出规则,我做了家庭作业。其他人解决这个问题的方法是使用BitBlt在每一帧中绘制一幅图像,这是一种让我的大脑能够理解的先进方法
我对此持非常开放的态度,所以如果你认为我应该使用BitBlt,并且你知道我在哪里可以找到一些有竞争力的深入的例子,我肯定会使用BitBlt。当然,如果有不使用BitBlt的解决方案,或者在这里使用它没有任何意义,那就更好了
是否可以使缓冲区的背景透明,或者我应该采取完全不同的方法
注意:我不希望使用XNA,因为此应用程序主要用于简单/旧计算机上的维护目的,所以我不想与可再发行文件有任何关系。您可以将基础图像放在PictureBox中。然后,您的代码可以处理PictureBox的绘制事件来绘制指针。这样,您就不必担心透明度或图形的缓慢操作。Clear():您的代码只需要计算针的位置 作为一个快速测试,我编写了一个小的表单应用程序,它创建了一个时钟,有一个时针(红色)、一个秒针(贪婪)和一个毫秒针(蓝色)。分针得不到尊重,因此不显示。背景是在GIMP中创建的黑色圆形矩形的图像 为了模拟您的环境,我添加了一个间隔为10毫秒(100个周期/秒)的计时器。处理事件计时器.Tick时,将强制重新绘制PictureBox 我手工编辑代码,只保留毫秒手的代码:
public Form1()
{
InitializeComponent();
pictureBox1.Paint += new PaintEventHandler(pictureBox1_Paint);
Center = new PointF((float)pBox1.Width / 2, (float)pBox1.Height / 2);
MillisecondLength = (float)pBox1.Width / 4; //length of millisecond hand
timer1.Interval = 10;
timer1.Enabled = true;
timer1.Tick += new EventHandler(timer1_Tick);
}
PointF Center;
float MillisecondLength;
Pen MillisecondsPen = new Pen(Brushes.Blue, (float)3);
double HALF_PI = Math.PI / 2;
double TWO_PI = 2 * Math.PI;
double millisecondHandAngle(DateTime dt)
{
//12 o'clock is at the top! (- PI / 2)
return TWO_PI * dt.Millisecond / 1000 - HALF_PI;
}
void pBox1_Paint(object sender, PaintEventArgs e)
{
DateTime dt = DateTime.Now;
double mangle = millisecondHandAngle(dt);
SizeF millisecondOffset = new SizeF(
(float)(MillisecondLength * Math.Cos(mangle)),
(float)(MillisecondLength * Math.Sin(mangle))
);
PointF endMillisecond = PointF.Add(Center, millisecondOffset);
e.Graphics.DrawLine(MillisecondsPen, Center, endMillisecond);
}
void timer1_Tick(object sender, EventArgs e)
{
pBox1.Invalidate();
}
虽然代码中没有显示,但我添加了System.Diagnostics.Stopwatch和一个计数器变量来计算实际帧速率,在我的旧笔记本电脑上,实际帧速率的峰值约为64帧/秒。即使将计时器间隔设置得很小,也会有一个最大重新绘制速率 双缓冲将解决闪烁问题,但每次都绘制所有内容可能会导致性能不佳(这可能不是问题)。检查您的图形是否绘制到32bpp的表面或透明度不起作用。@JasonWilliams,我该怎么做?对不起,我是GDI+see的新手。选择表单本身时,可以在属性窗口中设置值Form.DoubleBuffered=true。我建议使用PictureBox技术。您可以在控件的绘制事件中绘制相当复杂的图形,而不必担心清除图形、透明度等问题。谢谢,尽管我采用了完全不同的方法。相反,我重写了整个应用程序,并使用了WPF。我在WPF(或者GDI+就是XNA)方面没有任何经验,但现在我认为它更容易使用。无论如何,谢谢你的回答!不客气!如果您使用的是WPF,那么我强烈建议您选择Adam Nathan的书WPF Unreleased,该书现在可用于.NET 4.0。这本书可读性强,相关性强,并且有很多很好的技巧。与WinForms相比,我更喜欢WPF,但当我很忙时,我通常使用WinForms和GDI+。如果你在WPF中遇到图形更新速度问题,我可能会提供帮助。祝你好运