Onpaint事件(无效)在句点正常操作(运行时)后更改执行顺序

我有3个数据图,通过他们的绘画事件绘制。 当我有需要插入图表的数据时,我调用controls invalidate()命令。

第一个控件的paint事件实际上为其他2个图创建了一个位图缓冲区,以避免重复长循环。

因此,invalidate命令按特定顺序(1,2,3)。 这很好用,但是当绘制的数据到达图形窗口(PictureBox)的末尾时,数据通常会开始滚动,绘制事件开始以错误的顺序触发(2,3,1)。

以前有人遇到过这个吗? 为什么会发生这种情况?

更改代码,以便在三个控件中的任何一个上调用Invalidate之前,创建一个共享位图缓冲区(可以想象为控件类的静态成员), 然后在每个控件上调用Invalidate 。 在控件的Paint事件中,您可以使用静态位图缓冲区,并且Paint事件触发的顺序无关紧要。

当您在控件上调用Invalidate时,您基本上是在告诉操作系统向该控件发送WM_PAINT消息。 因为它是一条Windows消息,所以只要Windows能够实现这一点,它就能保证提供。 在您的情况下,它们通常按照收到的顺序交付,但有时它们不会。

您的代码需要考虑的另一件事:当您将相对复杂的绘图代码放在控件的Paint事件处理程序中时(或者直接从Paint事件处理程序调用的方法内)时,只要控件因任何原因失效,此代码就会执行,这意味着您调用Invalidate时代码将运行,但只要在控件上拖动另一个窗口,它也会运行。

对于复杂,耗时的图形,最好在隐藏缓冲区( Bitmap或不可见的PictureBox或其他)上执行复杂渲染,然后在控件的Paint事件中执行从隐藏缓冲区到可见窗口的简单复制(使用Graphics.DrawImageBitBlt或其他)。

如果在绘制的缓冲区和可见窗口之间添加第二个缓冲区(因此“双缓冲”),此方法还允许您避免闪烁。 在主缓冲区上完成绘制后,将其复制到第二个缓冲区。 在控件的Paint事件中,从第二个缓冲区复制到可见窗口。

因为在控件上调用Invalidate()实际上要求操作系统安排控件进行重绘,所以无法保证按特定顺序执行此操作。

由于您尝试按特定顺序调用Invalidate() ,我假设您有一个方法可以执行此操作。 您可以在这些调用之前添加代码以绘制位图缓冲区,然后由无效控件使用。 我不知道是否会发生这种情况,但是当数据没有改变时,这也让你可以自由地使控件无效。 此外,控制可以随时失效。 例如,在控件1上移动表单会使其无效,并且在当前设置中,重新计算缓冲区位图,而不需要。 因此,您应该分离此function。