如何同时更改控件而不重新绘制每个控件?
例如,我需要在运行时禁用两个按钮。在我禁用第一个按钮后,它变成灰色,第二个按钮也变成灰色。但我不知道如何使重画同时进行!
我需要类似的东西:
- 冻结表单(禁用重画)
- 禁用第一个按钮
- 禁用第二个按钮
- 启用表单重画
如何实现?
For example I need to disable two buttons in runtime. After I disabled first button it bacame gray, the second - it also became gray. But I do not know how to make the repainting simultaneous!
I need something like that:
- freeze the Form (disable repainting)
- disable first button
- disable second button
- Enable Form repainting
How to implement that?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
查看 Win32 API
WM_SETREDRAW
消息。例如:Look at the Win32 API
WM_SETREDRAW
message. For example:在应用程序重新进入消息循环之前,无法处理消息,因此任何修改/更新依赖于消息处理的控制状态的尝试都不会在不“泵送”消息的单个代码序列中起作用。
幸运的是,VCL 控件通常提供一种通过 Update 方法强制重新绘制的方法,而无需等待消息被处理:
这与禁用表单重新绘制无关。无论如何,在您的应用程序进入消息循环之前,表单不会重新绘制,因此在本身不会导致消息处理的单个过程中禁用表单绘制并重新启用是浪费时间。
这可能不是完全同时重新绘制两个按钮,但是如果不进入多线程 GUI 绘制代码,真正同时绘制两个单独的控件是不可能的,我认为这远远超出了这个问题的范围。然而,以这种方式在两个按钮上调用 Update 将根据您的需要几乎同时生效。
Messages cannot be processed until your application re-enters a message loop, so any attempt to modify/update control state that relies on message processing will not work within a single sequence of code that does not "pump" messages.
Fortunately the VCL controls typically provide a means for force repainting without waiting for messages to be processed, via the Update method:
This works independently of having to disable form repainting. The form will not repaint until your application goes into a message loop anyway, so disabling form painting and re-enabling within a single procedure that does not itself cause message processing is a waste of time.
This may not be exactly simultaneous repainting of the two buttons, but truly simultaneous painting of two separate control is impossible without getting into multithreaded GUI painting code which I think is way beyond the scope of this problem. Calling Update on two buttons in this way will be as near simultaneous in effect as you need however.
致 Elias551:
LockWindowUpdate 可能不是处理此问题的最佳方法,因为它旨在用于拖放操作,并且在误用时可能会引入微妙的错误。
请参阅 http://blogs.msdn.com/b/ oldnewthing/archive/2007/02/22/1742084.aspx
而是使用
SendMessage(hwnd, WM_SETREDRAW, FALSE, 0)
To Elias551:
LockWindowUpdate is probably not the best way to handle this since it is intended for drag and drop operations and can introduce subtle bugs when misused.
See http://blogs.msdn.com/b/oldnewthing/archive/2007/02/22/1742084.aspx
Instead use
SendMessage(hwnd, WM_SETREDRAW, FALSE, 0)
上述 WM_SETREDRAW 决定不会更新子窗口。
相反,我推荐 RedrawWindow:
The above decision with WM_SETREDRAW does not update child windows.
Instead, i recommend RedrawWindow:
这可能会有所帮助:API LockWindowUpdate(Handle: HWND) 将绘图锁定到句柄和子级。
例如:
一旦锁定的手柄被重置,组件就会被重新绘制
This could help: the API LockWindowUpdate(Handle: HWND) locks drawing to the handle and children.
ex:
Once the locked handle is reset, the component is repainted