Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 透明图形缓冲区清除?_C#_Image_Forms_Gdi+_Transparency - Fatal编程技术网

C# 透明图形缓冲区清除?

C# 透明图形缓冲区清除?,c#,image,forms,gdi+,transparency,C#,Image,Forms,Gdi+,Transparency,我目前正在从事一个项目,我必须使用GDI+(System.Drawing)。我想做一个多用途的仪表(一个像时钟一样的轮子),上面有动态的指针 我不想每一帧都画背景图像(带有所有标记)。我现在解决这个问题的方法是将其设置为图形化“容器”的背景图像,这是一个面板(请记住,我可能必须以不同的方式进行) 然后我拔针。针当前每秒更新25次(我可能会对此进行优化,使其仅在必要时更新)。但问题是,我必须在开始新帧之前清除缓冲区,导致背景图像被缓冲区的背景颜色覆盖。显然我不想要这个 我尝试将缓冲区的背景色设置为

我目前正在从事一个项目,我必须使用GDI+(
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中遇到图形更新速度问题,我可能会提供帮助。祝你好运