2010-03-11 1 views
6

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

мне нужно что-то вроде этого:

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

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

ответ

10

Посмотрите на сообщение 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); 
+1

Ясно непроверенных (не работает и даже не компилировать) – Deltics

+0

я использую WM_SETREDRAW в нескольких проектах, он прекрасно работает. Кроме того, компоненты VCL, которые имеют методы Begin/EndUpdate(), используют WM_SETREDRAW внутренне. –

+0

В этом случае это не сработало ... * 1) * FALSE и TRUE являются недопустимыми параметрами для SendMessage() [Integer required] * 2) * После изменения параметров FALSE и TRUE на 0 и 1 соответственно, чтобы это выполняет компиляцию и работу по назначению, форма не перерисовывается в конце - кнопки остаются видимо «включенными», если/пока они не будут скрыты и тем самым вынуждены перекрасить * 3) *, даже если это сработало, попробуйте/окончательно определите * 4) *, даже если бы это сработало, все равно было бы бессмысленно из-за зависимости обработки сообщений для происходящей картины. – Deltics

5

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

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

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

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

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

+0

Синхронные сообщения обрабатываются немедленно. Асинхронным требуется очередь сообщений для перекачки. –

+0

Только если HWND, которому отправляется сообщение (SendMessage), был создан тем же потоком, который отправляет сообщение. В противном случае сообщение по-прежнему будет синхронным, но окно приема будет обрабатывать сообщение только тогда, когда оно накинет очередь сообщений. Аналогично, хотя вы можете отправить синхронное сообщение PAINT, обработка этого сообщения может сама опираться на асинхронные сообщения, полученные в результате обработчика PAINT. cont ... – Deltics

+0

... следствием ненадежности синхронных сообщений, обрабатываемых по-настоящему синхронно (или сразу), является то, что если вы хотите вызвать процедуру, которая обычно вызывается в ответ на сообщение и делать это синхронно, тогда Самый надежный способ сделать это - просто вызвать эту процедуру синхронно и не полагаться на обмен сообщениями. И наоборот, обмен сообщениями должен быть предпочтительным и надежным механизмом при других обстоятельствах. :) – Deltics

-1

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

например:

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

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

+6

См. Http://blogs.msdn.com/b/oldnewthing/archive/2007/02/19/1716211.aspx и http://blogs.msdn.com/b/oldnewthing/archive/2007/02/20 /1726880.aspx и http://blogs.msdn.com/b/oldnewthing/archive/2007/02/21/1735472.aspx и http://blogs.msdn.com/b/oldnewthing/archive/2007/02 /22/1742084.aspx и http://blogs.msdn.com/b/oldnewthing/archive/2007/02/23/1747713.aspx, чтобы понять, почему это не очень хорошая идея. –

2

Для Elias551:

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

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

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

2

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

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

RedrawWindow(Handle, nil, 0, RDW_INVALIDATE or RDW_ALLCHILDREN); 
Смежные вопросы