C# Invalidate()将内容保留在屏幕上

C# Invalidate()将内容保留在屏幕上,c#,winforms,invalidation,C#,Winforms,Invalidation,我对invalidate的理解是,它向一个区域添加了一个标志,表示该区域需要更新,然后当没有其他事情要做时,该区域就会得到更新。 当这种情况发生时,区域中的所有内容都将被删除,然后由paint事件的订阅者重新绘制,如forms类的构造函数中所定义的 但是,当我点击我的程序(一个windows窗体应用程序)的reversi板时,reversi块在我点击的地方被绘制出来,但是有效移动的指示器(由Dropellipse绘制)仍然留在屏幕上,即使它们是以与绘制块相同的方法绘制的。当我将窗口拖离屏幕并返回

我对invalidate的理解是,它向一个区域添加了一个标志,表示该区域需要更新,然后当没有其他事情要做时,该区域就会得到更新。 当这种情况发生时,区域中的所有内容都将被删除,然后由paint事件的订阅者重新绘制,如forms类的构造函数中所定义的

但是,当我点击我的程序(一个windows窗体应用程序)的reversi板时,reversi块在我点击的地方被绘制出来,但是有效移动的指示器(由Dropellipse绘制)仍然留在屏幕上,即使它们是以与绘制块相同的方法绘制的。当我将窗口拖离屏幕并返回时,有效的移动指示器确实会消失

我做错了什么

为了完整起见,我的代码在这里(最重要的注释是英文的,有些注释仍然是荷兰语):

void-tekenGrid(对象对象,PaintEventArgs-pea)
{
int-vakjeBreedte=speelbordPanel.Width/Math.Max(r,k);
int speelstukDiameter=vakjeBreedte-6;
Pen mijnPen=新笔(颜色:黑色,2);
Graphics gr=speelbordGraphics;//我们使用专门为播放板制作的图形对象
gr.SmoothingMode=System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
for(int rij=0;rij
该区域中的所有内容都将被删除

这可能是产生此类问题的最大误解。你不能“删除”屏幕上的一个像素。它总是在那里,有一种特殊的颜色。如果它有错误的颜色,那么你的工作就是再给它一个

Windows中的绘制周期如下所示:

  • 当你的窗口内容过时时,你需要对它进行喷漆。这是通过调用Invalidate()显式完成的,您的案例,或者当窗口管理器可以自己解决它时,例如当您将窗口从屏幕上拖下来并向后拖动,或者当用户调整窗口大小时。在Aero之前的旧Windows版本上,当另一个窗口在您的窗口上移动时

  • 操作系统要做的第一件事是为窗口创建“设备上下文”,它会将您绘制的任何内容定向到窗口表面。Graphics类是设备上下文的.NET包装器。此时,您应该选择“嗯-哦”,该设备上下文当然与您先前创建并存储在
    speelbordGraphics
    变量中的设备上下文不匹配。特别是,它的剪贴簿属性可能是错误的,这在窗口大小更改时发生

  • 接下来,它确定窗口的哪些部分需要重新绘制,并通过PaintEventArgs.ClipRectangle属性公开。你应该在这里再次说“啊哦”。在剪辑矩形外绘制的任何内容实际上都不会到达窗口曲面。这是一种优化,无法在代码中运行

  • 如果将DoubleBuffered属性设置为true,则Winforms会创建另一个设备上下文,它会将绘制指向内存中的位图,这样绘制的所有内容都不会直接指向屏幕,而是指向位图。它有助于抑制可见的绘画瑕疵,通常称为“闪烁”。你会非常喜欢你的游戏板。你应该在这里再次惊叹“啊哦”,你通过
    speelbordGraphics
    绘制的内容会进入屏幕表面,而不是位图

  • 接下来,运行表单的OnPaintBackground()方法。如果没有覆盖它,则剪辑矩形中的像素将设置为Graphics.FillRectangle()的背景色。这是与“该地区的一切都被删除”最接近的类比。还有一个原因是你的
    speelbordGraphics
    允许你直接将像素猛击到屏幕上,但不需要绘制背景。这样做的副作用是,您不会看到像素被设置回预期的背景色。看起来它们不会被“擦除”。与你所观察到的非常匹配

  • 接下来,运行表单的OnPaint()方法。它触发绘制事件,毫无疑问,您的
    tekenGrid
    方法将运行

  • 如果DoubleBuffered属性设置为true,则Winforms现在会使用快速bitblt将位图复制到屏幕表面。这里的另一个“啊哦”,它覆盖了您通过
    speelbordGraphics
    绘制的任何内容。这是很容易注意到的,你会看到你在短短的几秒钟内画的东西,看起来像一个巨大的闪烁案例。与Double Buffered应该实现的功能完全相反:
     void tekenGrid(object obj, PaintEventArgs pea)
            {
            int vakjeBreedte = speelbordPanel.Width / Math.Max(r, k);
            int speelstukDiameter     = vakjeBreedte - 6;
    
            Pen mijnPen        = new Pen(Color.Black, 2);
            Graphics gr = speelbordGraphics; //we use the graphics object specifically made for the playing board
            gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;    
    
            for (int rij = 0; rij < r; rij++)             //lets make the grid, in this for-loop
    
            {
                for (int kolom = 0; kolom < k; kolom++)
                {
                    {
                        int x = vakjeBreedte * kolom + 3;   //x,y coordinaat van de vierhoek waar de cirkel in zit
                        int y = vakjeBreedte * rij + 3;
    
                        gr.DrawRectangle(mijnPen,         vakjeBreedte * kolom, vakjeBreedte * rij, vakjeBreedte, vakjeBreedte);                  //gives the playing board black rectangles around every position
    
                        if (speelbord[kolom, rij] == speelstuk.Blauw)     //draw the blue pieces              
                        {
                            gr.FillEllipse(Brushes.Blue, x, y, speelstukDiameter, speelstukDiameter);     
                        }
    
                        else if (speelbord[kolom, rij] == speelstuk.Rood) //draw the red pieces
                        {
                            gr.FillEllipse(Brushes.Red,  x, y, speelstukDiameter, speelstukDiameter);
                        }
    
                        if (laatHintsZien == true) //the legal move function indicator is here
                        {
                            if (checkLegaalheid(kolom, rij))
                            {
                                gr.DrawEllipse(mijnPen, x, y, speelstukDiameter, speelstukDiameter);
                            }
    
                        }
                    }
                }
            }
        }