2010-03-11 8 views
6

Por ejemplo, necesito desactivar dos botones en tiempo de ejecución. Después de deshabilitar el primer botón, se puso gris, el segundo - también se volvió gris. ¡Pero no sé cómo hacer que el repintado sea simultáneo!¿Cómo cambiar los controles simultáneamente sin volver a pintar cada uno?

necesito algo así:

  1. congelar el Formulario (desactivar repintar)
  2. primer botón desactivar
  3. segundo botón desactivar
  4. Habilitar Formulario repintar

Cómo implementar ¿ese?

Respuesta

10

Mire el mensaje Win32 API WM_SETREDRAW. Por ejemplo:

SendMessage(Handle, WM_SETREDRAW, False, 0); 
Button1.Enabled := False; 
Button2.Enabled := False; 
SendMessage(Handle, WM_SETREDRAW, True, 0); 
InvalidateRect(Handle, nil, True); 
+1

Claramente no probado (no funciona y ni siquiera compilar) – Deltics

+0

utilizo WM_SETREDRAW en varios proyectos, que trabaja muy bien. Además, los componentes VCL que sí tienen los métodos Begin/EndUpdate() usan WM_SETREDRAW internamente. –

+0

No funcionó en este caso ... * 1) * FALSE y TRUE no son parámetros válidos para SendMessage() [Integer required] * 2) * Después de cambiar los parámetros FALSE y TRUE a 0 y 1 respectivamente para que compila y trabaja según lo previsto, la forma no se vuelve a pintar al final - los botones permanecen visiblemente "activados" a menos que/hasta que se oscurezcan y por lo tanto forzados a volver a pintar * 3) * incluso si hubiera funcionado, intente/finalmente sería de rigor * 4) * incluso si hubiera funcionado, aún no habría tenido sentido debido a la dependencia del procesamiento de mensajes para que ocurra la pintura – Deltics

5

Los mensajes no pueden ser procesadas hasta que su solicitud vuelve a entrar en un bucle de mensajes, por lo que cualquier intento de modificar el estado/control de actualización que se basa en el procesamiento de mensajes no va a funcionar dentro de una única secuencia de código que no lo hace mensajes de "bomba".

Afortunadamente, el VCL controla típicamente proporcionan un medio para volver a pintar vigor sin esperar a que los mensajes a procesar, a través del método de actualización:

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

Esto funciona independientemente de tener que desactivar forma repintado. El formulario no se volverá a pintar hasta que su aplicación entre en un bucle de mensajes de todos modos, por lo que deshabilitar la pintura de formulario y volver a habilitarlo en un solo procedimiento que no causa el procesamiento de mensajes es una pérdida de tiempo.

Esto puede no ser exactamente el repintado simultáneo de los dos botones, pero la pintura verdaderamente simultánea de dos controles separados es imposible sin entrar en el código de pintura GUI multiproceso que creo que está más allá del alcance de este problema. Sin embargo, la actualización de dos botones de esta manera tendrá el efecto casi simultáneo que necesites.

+0

Los mensajes síncronos se procesan inmediatamente. Los asincrónicos necesitan que se bombee la cola de mensajes. –

+0

Solo si el HWND al que se envía el mensaje (SendMessage) fue creado por el mismo hilo que está enviando el mensaje. De lo contrario, el mensaje sigue siendo sincrónico, pero la ventana de recepción solo procesará el mensaje cuando bombee la cola de mensajes. De forma similar, aunque podría enviar un mensaje de PINTURA sincrónica, el procesamiento de ese mensaje podría depender de mensajes asíncronos resultantes del controlador de PAINT. cont ... – Deltics

+0

... la consecuencia de la falta de fiabilidad de los mensajes síncronos que se procesan de manera verdaderamente sincrónica (o inmediata) es que si desea llamar a una rutina que normalmente se llama en respuesta a un mensaje y hacerlo de forma síncrona, entonces el La manera más confiable de hacerlo es simplemente llamar a esa rutina de forma síncrona y no confiar en los mensajes. A la inversa, por supuesto, los mensajes serán el mecanismo preferido y más confiable en otras circunstancias. :) – Deltics

-1

Esto podría ayudar: el API LockWindowUpdate (Handle: HWND) bloquea el dibujo en el controlador y los elementos secundarios.

ejemplo:

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

Una vez que la manija de bloqueo se restablece, el componente se repinta

+6

Consulte http://blogs.msdn.com/b/oldnewthing/archive/2007/02/19/1716211.aspx y http://blogs.msdn.com/b/oldnewthing/archive/2007/02/20 /1726880.aspx y http://blogs.msdn.com/b/oldnewthing/archive/2007/02/21/1735472.aspx y http://blogs.msdn.com/b/oldnewthing/archive/2007/02 /22/1742084.aspx y http://blogs.msdn.com/b/oldnewthing/archive/2007/02/23/1747713.aspx para ver por qué no es una buena idea. –

2

Para Elias551:

LockWindowUpdate no es probablemente la mejor manera de manejar esto, ya que está destinado a operaciones de arrastrar y soltar y pueden introducir errores sutiles cuando se usan incorrectamente.

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

usar en su lugar SendMessage(hwnd, WM_SETREDRAW, FALSE, 0)

2

La decisión anterior con WM_SETREDRAW no actualiza las ventanas hijas.

En cambio, recomiendo RedrawWindow:

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