Una de las funciones agregadas a la biblioteca VCL en Delphi 11 es la capacidad de manejar fácilmente el mensaje WM_SETREDRAW de Windows con dos métodos específicos agregados a la clase TWinControl: LockDrawing y UnlockDrawing
Estaba revisando mi lista de tareas pendientes a principios de esta semana y encontré un mensaje que no indicaba que debería seguir la publicación de blog que hice sobre las nuevas características de VCL en Delphi y C++Builder 11 sobre LockDrawing. De hecho, escribí: “La clase base TWinControl ahora ofrece métodos LockDrawing y UnlockDrawing para deshabilitar y controlar la actualización. Esto desencadena la ejecución del mensaje de Windows WM_SETREDRAW. Esto probablemente valga la pena en su propia publicación de blog … ” pero me olvidé por completo de esto. Así que aquí está la entrada del blog, con unos meses de retraso.
Empecemos por la API de Windows. El mensaje WM_SETREDRAW se envía a una ventana para ” permitir que se vuelvan a dibujar los cambios en esa ventana, o para evitar que se vuelvan a dibujar los cambios en esa ventana”. “Cada vez que necesite realizar una serie de operaciones, cada una de las cuales requiere volver a pintar, puede ponerlas en espera y volver a pintar solo al final, evitando el parpadeo y acelerando el proceso. Por supuesto, es importante eliminar el bloqueo y luego llamar a una función especial para forzar el repintado (RedrawWindow).
Todo esto está correctamente encapsulado en dos métodos TWinControl agregados a la biblioteca VCL en RAD Studio 11, LockDrawing y UnlockDrawing, que envían el mensaje WM_SETREDRAW con los parámetros adecuados. También implementan una “lógica de recuento de bloqueos” de modo que si bloquea el mismo control dos veces, debe desbloquearlo dos veces para reanudar la pintura. Además, UnlockDrawing llama automáticamente a la API RedrawWindow.
Dicho esto, ¿cuáles son los casos de uso? Escribí una demostración que muestra dos escenarios, y también puedes consultar esta bonita publicación de blog de Radek Cervinka.
Un primer caso en mi demostración es agregar un montón de elementos a un cuadro de lista. Si bien Delphi ofrecía tradicionalmente y todavía tiene la capacidad de evitar volver a pintar al “congelar” la actualización de la lista de cadenas, tiene sentido bloquear el repintado de la interfaz de usuario en su lugar. Estos son los dos estilos de codificación alternativos:
[crayon-66dd06b0bed45685941434/]
En ambos casos el rendimiento es mucho mayor (y visiblemente notable) que sin una de las dos soluciones. Otro escenario es el de un conjunto de cambios en un componente que provoca un repintado. Esto no es trivial de simular en un ejemplo simple, pero es una forma de causar un parpadeo “a propósito” con un código como este:
[crayon-66dd06b0bed4c645871076/]
Lo sé, esto es bastante estúpido, pero puedes ver que no hay parpadeo con las llamadas de bloqueo/desbloqueo, mientras que el efecto se ve bastante horrible sin bloquear la interfaz de usuario. No es que pueda representar esto fácilmente en una captura de pantalla, pero aquí está el formulario en tiempo de ejecución de todos modos: