1

我的目标是移动使用 Graphics 对象的方法绘制的可视元素在没有闪烁或伪影的情况下(在 .NET 3.5 中)在 Form 上移动。我可以通过使用自动双缓冲(将 Form 的 DoubleBuffered 属性设置为 true)或自己实现后缓冲来成功实现无闪烁移动。然而,我正在努力寻找一种方法来使用这两种方法,而不会显示清晰可见的伪影。

使用自动双缓冲时,页面撕裂效果很明显。在我的 60Hz LCD 的多达 3 次刷新过程中,似乎后台缓冲区正在缓慢地、逐步地​​从上到下复制到表单中。

当我自己实现双缓冲时(有关详细信息,请参阅代码块),它看起来好像后台缓冲区被复制到表单的速度足够快,不会发生页面撕裂。然而,有时会出现另一种类型的伪影。下面的代码允许您使用箭头键在窗体上左右移动白色背景上的蓝色矩形,应该将效果再现为一系列水平的白色带,这些带有时会出现在矩形的左右边缘就像它被移动一样。

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(其他人能够重现效果){
    我做错了什么,可能
    在绘画代码中触发了某种竞争条件,或者
    这只是我必须
    忍受的运行时行为?
}
else {
    这可能是我的显卡的特性或
    显示驱动程序有问题吗?
}

4

4 回答 4

1

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

于 2009-04-16T16:34:46.770 回答
1

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

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

RenderScene()
Invalidate()

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

于 2009-04-16T16:44:40.227 回答
0

除了 overslacked 所说的使用之外Invalidate,您还不需要抗锯齿来填充没有应用变换的矩形。

于 2009-04-16T17:33:22.060 回答
0

当按下一个键并释放时,它实际上看起来“很好”(尽管如果你按住键,在下一步移动时会有一点撕裂会自行解决)。

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

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

于 2009-04-16T16:41:12.340 回答