How to change controls simultaneously without repainting each one?

走远了吗. 提交于 2019-12-12 07:58:06

问题


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:

  1. freeze the Form (disable repainting)
  2. disable first button
  3. disable second button
  4. 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

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