(.NET / C#/ winforms)在带有图形的表单上绘制时的工件

时间:2009-04-16 16:27:00

标签: .net winforms graphics gdi+ doublebuffered

我的目标是将使用Graphics对象的方法绘制的可视元素移动到没有闪烁或伪像的Form上(在.NET 3.5中)。我可以通过使用自动双缓冲(将Form的DoubleBuffered属性设置为true)或自己实现后缓冲来成功实现无闪烁运动。然而,我正在努力找到一种方法来使用任何一种方法,而没有明显可见的工件显示。

使用自动双缓冲时,页面撕裂效果很明显。看起来后退缓冲区正在缓慢地,逐渐地从上到下复制到表单中,多达三次刷新我的60Hz LCD。

当我自己实现双缓冲时(详见代码块),看起来后面的缓冲区被快速复制到表单中,不会发生页面撕裂。然而,有时会出现另一种类型的工件下面的代码,允许您使用箭头键在表单上左右移动白色背景上的蓝色矩形,应该将效果重现为一系列水平白色条带,有时会出现在矩形的左右边缘就像它被移动一样。

public partial class Form1 : Form {
    int x;
    Bitmap buffer;

    public Form1() {
        InitializeComponent();
        buffer = new Bitmap(Width, Height);
    }

    private void Form1_Paint(object sender, PaintEventArgs e) {
        Graphics g = Graphics.FromImage(buffer);
        g.Clear(Color.FromArgb(255, 255, 255));
        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
        g.FillRectangle(Brushes.Blue, x, 0, 100, 500);
        e.Graphics.DrawImageUnscaled(buffer, 0, 0);
    }

    protected override void OnPaintBackground(PaintEventArgs pevent) {
        //Don't allow the background to paint
    }

    private void Form1_KeyDown(object sender, KeyEventArgs e) {
        const int scrollSpeed = 20;
        if(e.KeyData == Keys.Left) {
            x -= scrollSpeed;
            Refresh();
        }
        else {
            if(e.KeyData == Keys.Right) {
                x += scrollSpeed;
                Refresh();
            }
        }
    }
}

if(其他人能够重现效果){
我做错了什么,也许会引发一些问题 在绘画代码中的种类条件或是 这只是我必须运行的运行时行为 和谁一起生活? }
否则{
它可能是我的显示卡或一个特殊的 有问题的显示驱动程序?
}

4 个答案:

答案 0 :(得分:1)

重要的是要知道加速2D操作的图形卡通常会加速GDI,而不是GDI +。我认为使用GDI位图并使用GDI方法(例如通过p / invoke)直接绘制它会使事情变得更快。

答案 1 :(得分:1)

每当我完成双缓冲时,我确保在Paint事件中没有渲染代码;事件中唯一的代码是从缓冲区复制到屏幕。

尝试将渲染代码移动到自己的函数中,然后使区域无效(在本例中为表单):

RenderScene()
Invalidate()

看看是否有帮助。为了更好地衡量,请覆盖OnResize以调整缓冲区的大小。

答案 2 :(得分:0)

当按下按键并释放时,对我来说实际上看起来“很好”(但是如果你按下按键,会有一点点撕裂,在下一步行动中自行解决)。

我使用的是ATI x1300和Intel e6400。也许处理速度或视频卡是一个问题?

编辑:上面说的是,我会同意其他人的说法,如果你正在寻找快速的话,说GDI +不是要走的路。 DirectX或使用Windows API可能是最佳选择。

答案 3 :(得分:0)

除了过度使用Invalidate所说的内容之外,你也不需要使用抗锯齿来填充没有应用变换的矩形。