Как изменить элементы управления одновременно, не перекрашивая каждый? - PullRequest
7 голосов
/ 11 марта 2010

Например, мне нужно отключить две кнопки во время выполнения. После того, как я отключил первую кнопку, она стала серой, вторая - тоже стала серой. Но я не знаю, как сделать перекрашивание одновременно!

Мне нужно что-то подобное:

  1. заморозить форму (отключить перерисовку)
  2. отключить первую кнопку
  3. отключить вторую кнопку
  4. Включить перерисовку формы

Как это реализовать?

Ответы [ 5 ]

10 голосов
/ 11 марта 2010

Посмотрите на сообщение Win32 API WM_SETREDRAW. Например:

SendMessage(Handle, WM_SETREDRAW, False, 0);
Button1.Enabled := False;
Button2.Enabled := False;
SendMessage(Handle, WM_SETREDRAW, True, 0);
InvalidateRect(Handle, nil, True);
5 голосов
/ 11 марта 2010

Сообщения не могут быть обработаны, пока ваше приложение не войдет в цикл обработки сообщений, поэтому любая попытка изменить / обновить состояние управления, основанное на обработке сообщений, не будет работать в пределах одной последовательности кода, которая не «прокачивает» сообщения.

К счастью, элементы управления VCL обычно предоставляют средства для перерисовки без ожидания обработки сообщений с помощью метода обновления:

Button1.Enabled := False;
Button2.Enabled := False;
Button1.Update;
Button2.Update;

Это работает независимо от необходимости отключать перерисовку формы. Форма не будет перекрашиваться до тех пор, пока ваше приложение в любом случае не войдет в цикл обработки сообщений, поэтому отключение рисования формы и повторное включение в одной процедуре, которая сама по себе не вызывает обработку сообщения, является пустой тратой времени.

Это может быть не совсем одновременное перекрашивание двух кнопок, но по-настоящему одновременное рисование двух отдельных элементов управления невозможно без проникновения в многопоточный код рисования GUI, который, я думаю, выходит за рамки этой проблемы. Таким образом, вызов Update для двух кнопок будет практически одновременным, если вам нужно.

3 голосов
/ 24 сентября 2015

Приведенное выше решение с WM_SETREDRAW не обновляет дочерние окна.

Вместо этого я рекомендую RedrawWindow:

RedrawWindow(Handle, nil, 0, RDW_INVALIDATE or RDW_ALLCHILDREN);
3 голосов
/ 18 января 2011

до Элиаса551:

LockWindowUpdate, вероятно, не лучший способ справиться с этим, поскольку он предназначен для операций перетаскивания и может привести к незначительным ошибкам при неправильном использовании.

См. http://blogs.msdn.com/b/oldnewthing/archive/2007/02/22/1742084.aspx

Вместо этого используйте SendMessage(hwnd, WM_SETREDRAW, FALSE, 0)

0 голосов
/ 20 июля 2010

Это может помочь: API LockWindowUpdate (Handle: HWND) блокирует рисование для ручки и дочерних элементов.

например:

procedure TForm1.ColorButtons();
begin
  LockWindowUpdate(Self.Handle);
  // Make some stuff
  LockWindowUpdate(0);
end;

После сброса заблокированной ручки компонент перекрашивается

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...