问题
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?
回答1:
Look at the Win32 API WM_SETREDRAW
message. For example:
SendMessage(Handle, WM_SETREDRAW, False, 0);
Button1.Enabled := False;
Button2.Enabled := False;
SendMessage(Handle, WM_SETREDRAW, True, 0);
InvalidateRect(Handle, nil, True);
回答2:
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:
Button1.Enabled := False;
Button2.Enabled := False;
Button1.Update;
Button2.Update;
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.
回答3:
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)
回答4:
The above decision with WM_SETREDRAW does not update child windows.
Instead, i recommend RedrawWindow:
RedrawWindow(Handle, nil, 0, RDW_INVALIDATE or RDW_ALLCHILDREN);
回答5:
This could help: the API LockWindowUpdate(Handle: HWND) locks drawing to the handle and children.
ex:
procedure TForm1.ColorButtons(); begin LockWindowUpdate(Self.Handle); // Make some stuff LockWindowUpdate(0); end;
Once the locked handle is reset, the component is repainted
来源:https://stackoverflow.com/questions/2421646/how-to-change-controls-simultaneously-without-repainting-each-one