C# Invalidate()将内容保留在屏幕上
我对invalidate的理解是,它向一个区域添加了一个标志,表示该区域需要更新,然后当没有其他事情要做时,该区域就会得到更新。 当这种情况发生时,区域中的所有内容都将被删除,然后由paint事件的订阅者重新绘制,如forms类的构造函数中所定义的 但是,当我点击我的程序(一个windows窗体应用程序)的reversi板时,reversi块在我点击的地方被绘制出来,但是有效移动的指示器(由Dropellipse绘制)仍然留在屏幕上,即使它们是以与绘制块相同的方法绘制的。当我将窗口拖离屏幕并返回时,有效的移动指示器确实会消失 我做错了什么 为了完整起见,我的代码在这里(最重要的注释是英文的,有些注释仍然是荷兰语):C# Invalidate()将内容保留在屏幕上,c#,winforms,invalidation,C#,Winforms,Invalidation,我对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将位图复制到屏幕表面。这里的另一个“啊哦”,它覆盖了您通过
绘制的任何内容。这是很容易注意到的,你会看到你在短短的几秒钟内画的东西,看起来像一个巨大的闪烁案例。与Double Buffered应该实现的功能完全相反:speelbordGraphics
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); } } } } } }