例如,我需要在运行时禁用两个按钮。在我禁用第一个按钮后,它变成灰色,第二个 - 它也变成灰色。但是我不知道如何使重绘同时进行!
我需要这样的东西:
- 冻结表单(禁用重绘)
- 禁用第一个按钮
- 禁用第二个按钮
- 启用表单重绘
如何实施?
查看 Win32 APIWM_SETREDRAW
消息。例如:
SendMessage(Handle, WM_SETREDRAW, False, 0);
Button1.Enabled := False;
Button2.Enabled := False;
SendMessage(Handle, WM_SETREDRAW, True, 0);
InvalidateRect(Handle, nil, True);
在您的应用程序重新进入消息循环之前无法处理消息,因此任何依赖消息处理的修改/更新控制状态的尝试都不会在不“泵送”消息的单个代码序列中起作用。
幸运的是,VCL 控件通常通过 Update 方法提供了一种强制重绘的方法,而无需等待消息被处理:
Button1.Enabled := False;
Button2.Enabled := False;
Button1.Update;
Button2.Update;
这与必须禁用表单重绘无关。在您的应用程序进入消息循环之前,表单不会重新绘制,因此在一个本身不会导致消息处理的过程中禁用表单绘制和重新启用是浪费时间。
这可能不是完全同时重新绘制两个按钮,但是如果不进入多线程 GUI 绘制代码,那么真正同时绘制两个单独的控件是不可能的,我认为这超出了这个问题的范围。但是,以这种方式在两个按钮上调用 Update 将几乎同时生效。
致 Elias551:
LockWindowUpdate 可能不是处理这个问题的最佳方法,因为它是为拖放操作而设计的,并且在误用时可能会引入细微的错误。
请参阅http://blogs.msdn.com/b/oldnewthing/archive/2007/02/22/1742084.aspx
而是使用SendMessage(hwnd, WM_SETREDRAW, FALSE, 0)
WM_SETREDRAW 的上述决定不会更新子窗口。
相反,我推荐 RedrawWindow:
RedrawWindow(Handle, nil, 0, RDW_INVALIDATE or RDW_ALLCHILDREN);
这可能会有所帮助:API LockWindowUpdate(Handle: HWND) 将绘图锁定到句柄和子级。
前任:
程序 TForm1.ColorButtons(); 开始 LockWindowUpdate(Self.Handle); // 做一些东西 LockWindowUpdate(0); 结尾;
一旦锁定的句柄被重置,组件就会被重新绘制