C# 强制在函数期间不绘制

C# 强制在函数期间不绘制,c#,winforms,C#,Winforms,我写了一个程序,画了一个棋盘游戏的特定场景(我认为它在英语中被称为“Ludo”)。现在我可以画所有的领域和棋子等,但如果一个棋子被移动,我必须重新绘制该棋子。问题是,当我这样做时,屏幕会闪烁很短的时间。这可能是因为我首先清除所有字段和典当,然后重新绘制它们(我将对此进行改进,但我认为问题仍会以较小的形式出现),然后在我清除所有内容的时间之间屏幕闪烁,直到我重新绘制所有内容。有没有办法告诉C#即使我专门调用了类似于this.Controls.Clear()的东西,也不要重画,直到我告诉它 我已经用

我写了一个程序,画了一个棋盘游戏的特定场景(我认为它在英语中被称为“Ludo”)。现在我可以画所有的领域和棋子等,但如果一个棋子被移动,我必须重新绘制该棋子。问题是,当我这样做时,屏幕会闪烁很短的时间。这可能是因为我首先清除所有字段和典当,然后重新绘制它们(我将对此进行改进,但我认为问题仍会以较小的形式出现),然后在我清除所有内容的时间之间屏幕闪烁,直到我重新绘制所有内容。有没有办法告诉C#即使我专门调用了类似于
this.Controls.Clear()
的东西,也不要重画,直到我告诉它


我已经用
this.SuspendLayout()
尝试过了,因为它的名字暗示它应该完全这样做,但这不起作用。

当你告诉它清除所有内容,然后重新绘制时,它会像那样闪烁。但是为什么当你移动一个棋子时,你不在新的空间里画它,而是在它原来的位置上画一个空白。这将在不刷新整个屏幕或清除所有内容的情况下移动棋子


我还认为你说的是国际象棋。这是我所知道的唯一一个用兵玩的游戏,我从来没有听说过卢多P

当您告诉它清除所有内容,然后重新绘制时,它会像那样闪烁。但是为什么当你移动一个棋子时,你不在新的空间里画它,而是在它原来的位置上画一个空白。这将在不刷新整个屏幕或清除所有内容的情况下移动棋子


我还认为你说的是国际象棋。这是我所知道的唯一一个用兵玩的游戏,我从来没有听说过卢多在Winforms自定义图形中,闪烁始终是一个问题


试试这个:不要在表单上的某处绘制棋子的位置,而是将它们绘制到位图上。完成后,只需将表单上的PictureBox图像更改为位图。表单将使用新图像重新绘制。您可以使用两个位图对象(它们确实相当大),并每次清理它们,以避免程序占用内存。瞧,您现在有了“翻页”图形,它可以独立于重新绘制表单的其他请求来绘制和显示。

在Winforms自定义图形中,闪烁始终是一个问题


试试这个:不要在表单上的某处绘制棋子的位置,而是将它们绘制到位图上。完成后,只需将表单上的PictureBox图像更改为位图。表单将使用新图像重新绘制。您可以使用两个位图对象(它们确实相当大),并每次清理它们,以避免程序占用内存。瞧,您现在有了“翻页”图形,它可以独立于其他重新绘制表单的请求来绘制和显示。

最佳解决方案是KeithS之一,但更快的选择可能是:每个部分有两个图像,一个在白色,一个在黑色,加上两个空正方形。在移动中,将适当的空方块放在离开方块中,将适当的部分放在目的方块上。这是一种零闪烁、古老(如此之快)的方法:)

最好的解决方案是KeithS之一,但更快的选择可能是:每个部分有两个图像,一个在白色,一个在黑色,加上两个空正方形。在移动中,将适当的空方块放在离开方块中,将适当的部分放在目的方块上。这是一种零闪烁、古老(如此之快)的方法:)

尽管@KeightS的解决方案很好,但我更愿意通过暂停/恢复所有绘图来解决它:

public partial class Form1 : Form
{
    private bool suspendDraw;

    public Form1()
    {
        this.InitializeComponent();
    }

    public void SuspendDraw()
    {
        this.suspendDraw = true;
    }

    public void ResumeDraw()
    {
        this.suspendDraw = false;
    }

    private const int WM_PAINT = 0x000F;

    protected override void WndProc(ref Message m)
    {
        if ((m.Msg != WM_PAINT) || (!this.suspendDraw && m.Msg == WM_PAINT))
        {
            base.WndProc(ref m);
        }
    }

}

您只需要调用
SuspendDraw/ResumeDraw()
方法来控制允许绘制。

尽管@KeightS的解决方案很好,但我更愿意通过能够同时暂停/恢复绘制来解决它:

public partial class Form1 : Form
{
    private bool suspendDraw;

    public Form1()
    {
        this.InitializeComponent();
    }

    public void SuspendDraw()
    {
        this.suspendDraw = true;
    }

    public void ResumeDraw()
    {
        this.suspendDraw = false;
    }

    private const int WM_PAINT = 0x000F;

    protected override void WndProc(ref Message m)
    {
        if ((m.Msg != WM_PAINT) || (!this.suspendDraw && m.Msg == WM_PAINT))
        {
            base.WndProc(ref m);
        }
    }

}

您只需要调用
SuspendDraw/ResumeDraw()
方法来控制是否允许绘制。

刚刚尝试了这个方法。DoubleBuffered=true;它确实减少了闪烁,但它仍然没有消失。这里介绍了更具体的缓冲选项,它对我的图表绘制项目非常有用。单击:如果.NET双缓冲实现不适用于您,您应该尝试通过将绘图缓存到位图来实现自己的缓冲机制,然后渲染整个位图。您正在经历屏幕撕裂,因为您实际上是在强制显示设备快速连续刷新屏幕的多个部分。您希望最小化对显示器的绘图请求数。这可能有用:只需尝试此操作。DoubleBuffered=true;它确实减少了闪烁,但它仍然没有消失。这里介绍了更具体的缓冲选项,它对我的图表绘制项目非常有用。单击:如果.NET双缓冲实现不适用于您,您应该尝试通过将绘图缓存到位图来实现自己的缓冲机制,然后渲染整个位图。您正在经历屏幕撕裂,因为您实际上是在强制显示设备快速连续刷新屏幕的多个部分。您希望尽量减少对显示器的绘图请求数量。这可能有用:现在有一种疯狂的东西叫做Internet,它非常适合查找有关内容的信息。::(这看起来像《马里奥卡丁车64》中的战斗级别。是的,我不知道这个话题,但它必须是赛迪。我实际上是荷兰人,这里相当有名的一款游戏,虽然它在这里被称为“Mens Erger Je Niet”^^^^@sehe不,ludo不是这个游戏的意大利人:)好吧,我的错,那一定是拉丁语@teuneboon:Mens Erger Je Niet向我解释说,现在有一种疯狂的东西叫做互联网,它非常适合了解事物:(这看起来像是《马里奥卡丁车64》中的战斗级别。是的,我知道这是个离题的话题,但必须是赛迪,我是真的。)