使多个矩形或区域无效

时间:2013-02-16 17:55:45

标签: c# .net winforms invalidation onpaint

我遇到Invalidate()问题,因为在我准备好之前它会调用OnPaint ... 当我需要重绘一个且只有一个区域时,Invalidate(new Rectangle(x, y, width, height))工作正常,但我需要做的是创建一个矩形集合以使其无效,然后使用Update()方法重新绘制所有无效区域。我在Invalidate()Update()之间有点迷失:如何使用它们以及干净的方法是什么。

我需要实现这个目标,因为我正在研究细胞自动机,例如“Langton's ant”或“Conway的生命游戏”。小网格不是问题,但是对于大尺寸网格(700x500),这幅画是一个非常重要的问题。

所以我的问题是如何在没有在每次失效时调用OnPaint使X矩形无效,然后调用OnPaint仅刷新指定区域(X矩形将=至少数百,数千肯定) ?

1 个答案:

答案 0 :(得分:5)

调用Invalidate方法不会立即引发Paint事件。它仅将指定区域设置为无效并对绘制事件进行排队。下一次调用Invalidate只会将该区域与以前无效的区域相加。只有在队列中没有Paint事件时,它才会发出新的Paint事件。

来自Invalidate方法的备注部分:

  

调用Invalidate方法不会强制执行同步绘制;要强制执行同步绘制,请在调用Invalidate方法后调用Update方法。如果在没有参数的情况下调用此方法,则会将整个客户区添加到更新区域。


更多解释

Windows Forms技术是Win32的{​​{1}}库的包装器。要了解paint事件的内幕,您需要了解user32的工作原理。

Message Queue:

Windows中的每个进程都有一个message queue。当属于该进程的窗口发生任何事情时,Windows会将事件推送到该进程的message queue。每个应用程序中都有一个message loop,它从队列中提取消息(通过调用GetMessage())并调用消息(调用适当的函数,称为Window Procedure,通过调用{{3} }})。所以消息正在陆续处理。这意味着在处理消息时,不能处理任何其他消息 这就是为什么当你在表单中执行耗时的操作(withoud启动一个新线程)时,应用程序停止respongind:你被困在处理一条消息(例如按钮的user32事件),所以应用程序无法处理其他消息(鼠标事件,绘画事件等)。

在Windows窗体中,DispatchMessage()方法运行应用程序的消息循环。邮件会传递给Application.Run方法,此方法会确定要调用的Click方法(OnXxxxOnKeyPressOnMouseMove等),以及该方法提出相应的事件(OnResizeKeyPressMouseMove等。

Control.WndProc

当需要绘制程序的窗口时(例如,当它首次显示或从最小化状态恢复时),Windows将WM_PAINT:消息排入消息队列,但前提是没有未处理的WM_PAINT消息。 3}}用于消息队列中的窗口。此外,仅当队列中没有其他消息时,消息循环才从队列中提取WM_PAINT消息。来自WM_PAINT

的Qoute
  

当应用程序的消息队列中没有其他消息时,GetMessage返回WM_PAINT消息,并且DispatchMessage将消息发送到适当的窗口过程。

在Windows窗体中,WM_PAINT page in MSDN会转换为引发WM_PAINT事件的Rezie方法。

当您在单个方法中多次调用OnPaint(调用Win32 Paint函数)时,Invalidate事件仍然无法被提升。必须完成正在处理的当前事件,同时应处理同时发送的其他消息,然后引发Paint事件。

请按照答案中的链接仔细阅读。