How to change controls simultaneously without repainting each one?

天涯浪子 提交于 2019-12-03 13:37:03

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);

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.

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)

The above decision with WM_SETREDRAW does not update child windows.

Instead, i recommend RedrawWindow:

RedrawWindow(Handle, nil, 0, RDW_INVALIDATE or RDW_ALLCHILDREN);

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!