Estoy usando GDI+ en C++/MFC aplicación y me parece que no puede evitar el parpadeo cuando la ventana cambia de tamaño.

Ya he probado estos pasos:

  • devuelve TRUE en caso de OnEraseBkGnd();
  • devuelve NULL en OnCtlColor();
  • utiliza el doble búfer de acuerdo a este código:
void vwView::OnDraw(CDC* pDC) 
{
   CRect rcClient;
   GetClientRect(rcClient);

   Bitmap bmp(rcClient.Width(), rcClient.Height());
   Graphics graphics(&bmp);

   graphics.DrawImage(m_image, rcClient.left, rcClient.top);

   Graphics grph(pDC->m_hDC);
   grph.DrawImage(&bmp, 0, 0);
}

Estoy haciendo algo mal? O hay otra manera de lograr esto?

InformationsquelleAutor djeidot | 2008-10-13

6 Comentarios

  1. 40

    Evitar completamente el parpadeo, usted necesitaría para completar todos dibujo en el intervalo entre actualizaciones de pantalla. Windows no proporciona ningún medio fácil de lograr esto para la ventana normal de la pintura (Vista proporciona un dibujo compuesto a través de la DWM, pero esto no puede ser invocado incluso en sistemas que ejecutan Vista). Por lo tanto, lo mejor que puedes hacer para minimizar el parpadeo es dibujar todo tan rápidamente como sea posible (reducir rasgado por el aumento de sus posibilidades de completar todo el dibujo dentro de un ciclo de actualización), y evitar sobregiros (la parte del dibujo de la pantalla y, a continuación, dibujo algo más sobre la parte superior: los riesgos de la presentación de usuario con un parcial de dibujado de pantalla).

    Vamos a hablar de las técnicas que aquí se presenta hasta el momento:

    • De no hacer nada OnEraseBkgnd(): ayuda a evitar el sobre-dibujar mediante la prevención de la invalidado área de la ventana se llena la ventana del color de fondo. Útil cuando usted va a ser el dibujo de toda la zona de nuevo durante la WM_PAINT el manejo de de todos modos, como en el caso de doble búfer de dibujo… pero ver Notas sobre cómo evitar un sobregiro por la prevención de dibujo después de WM_PAINT método.

    • Devolver NULL para OnCtlColor(): esto no debería realmente hacer nada… a menos que tenga el niño controles en el formulario. En ese caso, consulte Notas sobre cómo evitar un sobregiro por la prevención de dibujo después de WM_PAINT método en su lugar.

    • De doble buffer dibujo: ayuda a evitar que se rompa (y potencialmente sobregiro así), por la reducción de la real en la pantalla de dibujo a una sola BitBLT. Puede doler el tiempo necesario para la elaboración de: la aceleración de hardware no se puede utilizar (aunque con GDI+, las posibilidades de que cualquier asistida por hardware de dibujo que se utilizan son muy escasas), una pantalla de mapa de bits debe ser creado y llenado para cada redibujar, y la totalidad de la ventana debe ser repintada para cada actualización. Ver Notas en la eficacia de doble búfer.

    • Utilizando GDI llamadas en lugar de GDI+ para el BitBlt: Esto es a menudo una buena idea – Graphics::DrawImage() puede ser muy lento. Incluso he encontrado el GDI normal BitBlt() llamada a ser más rápido en algunos sistemas. Jugar con esto, pero sólo después de probar algunas otras sugerencias de primera.

    • Evitando la ventana de estilos de clase que obligan a una completa actualización en cada ajustar el tamaño (CS_VREDRAW, CS_HREDRAW): Esto va a ayudar, pero sólo si no necesidad para redibujar toda la ventana cuando los cambios de tamaño.

    Notas sobre cómo evitar un sobregiro por la prevención de dibujo antes de su WM_PAINT método

    Cuando la totalidad o una parte de la ventana se invalida, serán borrados y repintado. Como ya se ha señalado, puede omitir el borrado de si va a volver a pintar toda la zona no. Sin embargo, si usted está trabajando con un niño de la ventana, entonces usted debe asegurarse de que la ventana padre(s) no son también el borrado de su área de la pantalla. El WS_CLIPCHILDREN estilo debe ser de todos los padres de windows (esto evitará que las áreas ocupadas por niños de windows (incluyendo su punto de vista), desde el que se dibuja.

    Notas sobre cómo evitar un sobregiro por la prevención de dibujo después de WM_PAINT método

    Si usted tiene cualquier controles de niño alojado en su formulario, usted tendrá que usar el WS_CLIPCHILDREN de estilo para evitar dibujo sobre ellos (y, posteriormente, ser más atraídos por ellos. Ser consciente de, esto tendrá un impacto en la velocidad de la BitBlt rutina un poco.

    Notas en la eficacia de doble búfer

    Por ahora, se está creando una nueva vuelta de un búfer de imagen cada vez que la vista se basa en sí. Para mayores de windows, esto puede representar una gran cantidad de memoria asignados y liberados, y se resultado en importantes problemas de rendimiento. Recomiendo mantener un asignados de forma dinámica mapa de bits en el objeto de la vista, re-asignar como sea necesario para que coincida con el tamaño de su vista.

    Tenga en cuenta que mientras que la ventana se cambia de tamaño, esto se traducirá en igual cantidad de asignaciones como el sistema actual, ya que cada nuevo tamaño requerirá una nueva vuelta de búfer de mapa de bits a ser asignado a su altura – puede aliviar el dolor de alguna manera por el redondeo de las dimensiones hasta el mayor múltiplo de 4, 8, 16, etc., permitiendo a evitar la re-asignados en cada pequeño cambio en el tamaño.

    Tenga en cuenta que, si el tamaño de la ventana no ha cambiado desde la última vez que se procesa en el búfer de reserva, no es necesario volver a hacerla cuando la ventana se invalida – sólo Blt el ya procesado de la imagen en la pantalla.

    También, asignar un mapa de bits que coincide con la profundidad de bits de la pantalla. El constructor de Bitmap usted está usando actualmente se predeterminado de 32bpp, ARGB-diseño; si este no coincide con el de la pantalla, entonces tendrá que ser convertido. Considere la posibilidad de usar el método GDI CreateCompatibleBitmap() para obtener una coincidencia de mapa de bits.

    Finalmente… supongo que su ejemplo de código es sólo eso, un fragmento ilustrativo. Pero, si en realidad se está haciendo nada más allá de la representación de una imagen en la pantalla, entonces usted realmente no necesita para mantener una espalda de búfer en absoluto – sólo Blt directamente de la imagen (y convertir el formato de la imagen antes de tiempo para que coincida con la pantalla).

    • Así que «la reducción de la real en la pantalla de dibujo a un solo BitBLt» no es realmente suficiente para evitar que todos los lagrimeo? Como windows podría permitir que solo bitblt a ocurrir en el medio de una actualización de la pantalla, lo que permite desgarrar a pesar de que una sola operación?
    • Seguro. Se necesita tiempo para la transferencia de los datos reales, ¿cuánto tiempo dependiendo mucho de la instalación de una máquina en particular.
  2. 4

    Usted podría tratar de usar la vieja usanza de GDI en lugar de GDI+ para escribir a la DC, especialmente debido a que ya el búfer de imagen. El uso de mapa de bits::LockBits para acceder a las primas de mapa de bits de datos, crear una estructura BITMAPINFO, y el uso SetDIBitsToDevice para mostrar el mapa de bits.

  3. 3

    Usted puede conseguir algo de tracción mediante el uso de Direct3D para «contar» cuando vsync se producen, et al, por lo que puede BitBlt/actualización en un buen momento. Ver GDI vsync para evitar que se rompa (a pesar de obtener las cosas a un único y pequeño BitBlt puede ser «lo suficientemente bueno» para algunos casos).

    También tenga en cuenta que parece que GDI BitBlt que no se sincroniza con pantalla vsync. Ver
    Más rápido que BitBlt
    .

    También tenga en cuenta que el uso de CAPTUREBLT (que permite la captura de ventanas transparentes) hace que el ratón a parpadear (si aero no está en uso) si se utiliza.

  4. 2

    Este enlace contiene alguna información útil:
    http://www.catch22.net/tuts/flicker-free-drawing

    (Yo sé que es muy tarde, además el hilo, pero esto es para cualquier persona (como yo) que encontraron que cuando se busca reducir el parpadeo en mi Win32 app…)

    • Esto es más o menos un enlace única respuesta que es desanimado. Como de 6/11/2018 esto se parece bastante a un link muerto única respuesta, a pesar de que los lectores deben tener en cuenta que el sitio no ha sido «bajo mantenimiento» todos los que de largo (era válido en 2017). Personalmente estoy de acuerdo con esto, supongo, la página cuenta con útiles consejos. Esperemos que vuelva pronto. Recomiendo incluyendo el contenido de la página (en sus propias palabras) en su respuesta, en cualquier caso.
  5. 0

    Hay hijo de windows en el formulario? El gestor de ventanas se inicia mediante la obtención de los padres de la ventana para borrar sus antecedentes mediante el envío de un mensaje WM_ERASEBKGND, a CONTINUACIÓN, envía un mensaje wM_PAINT – presumiblemente esto se asigna a su wx::método OnDraw. A continuación, se itera sobre cada niño de control y consigue esos que se pintan.

    Si este es tu escenario… el uso de las Vistas de nueva aero mirada resolverá tu problema, como el aero administrador de ventanas de escritorio hace de la ventana de composición de forma automática. Con la edad de la ventana de administrador de su pan pita.

Dejar respuesta

Please enter your comment!
Please enter your name here