C#.NET .. 在 Paint 事件处理程序之外绘制是一种不好的做法吗?

C#.NET .. is it a bad practice to draw outside the Paint event handler?

为了澄清我的问题的意思。我在使用 .NET 框架在 C# 中制作游戏时习惯于实现我自己的 DrawScene() 方法并在我想重绘游戏图形时调用它(基本上在游戏中的任何实例移动或更改其 shape/state 之后,如下所示:

private void DrawScene()
{
    Graphics g = this.CreateGraphics();
    g.Clear(Color.Black);

    g.DrawImage(myBitmap, 0, 0);

    g.Dispose();
}

这样做,在我的 Paint 事件处理程序中,我所做的就是以下操作:

private void Form1_Paint(object sender, PaintEventArgs e)
{
    DrawScene();
}

例如,当我想在玩家移动后重绘时,我只需以相同的方式调用 DrawScene():

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Keycode == Keys.Up)
    {
        hero.y -= 5;
    }

    DrawScene();
}

这样做和这样做有什么严重的区别吗(我注意到大多数人都遵循):

private void Form1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.Clear(Color.Black);

    e.Graphics.DrawImage(myBitmap, 0, 0);
}

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Keycode == Keys.Up)
    {
        hero.y -= 5;
    }

    this.Invalidate();
}

对不起,如果说的太多了,但我只是想澄清一下我的问题..

因此,如果上述两种情况的绘图方式完全相同(从图形的角度来看),并且像第一种情况那样保持我通常的实现方式也没有什么坏处。那么什么时候最好使用invalidate() 方法?

这两种方法差别很大(首选第二种)。

首先 - 在您的方法中,您每次需要绘制某些东西时都会创建新的 Graphics 对象,而在 Paint 事件处理程序中,您每次都使用相同的图形对象。

这会增加内存使用量(因为重绘会非常频繁地发生),而且因为您没有处理正在创建的图形(基本上您应该对任何实现了 IDisposable 的对象执行此操作,您不再需要使用) - 图形使用的系统资源未被释放。

此外,您的表单可以通过调用手动重绘,但在某些其他情况下(与其他 window、show/hide 等重叠)。如果您的绘画将在 Paint 处理程序中完成 - 那么它们将自动完成,但在您的 "first" 方法中,除非您手动调用绘图方法,否则它们不会自动完成。

所以基本上最好在 Paint 事件处理程序中绘制所有内容(并调用 Invalidate 甚至 Refresh 强制重绘)而不是在单独的方法中手动绘制。

有时(如果您的绘图需要很多代码并且可以在逻辑上分成几部分)最好像这样处理它:

private void DrawScene(Graphics g)
{
    g.Clear(Color.Black);
    g.DrawImage(myBitmap, 0, 0);
}

private void Form1_Paint(object sender, PaintEventArgs e)
{
    DrawScene(e.Graphics);
    DrawSomething(e.Graphics);
}

所以您仍然使用 Paint 事件处理程序中的图形对象,但只是将其传递给绘图方法。