Cómo dibujar eficientemente con MFCY la mayoría de la gente piensa que la función de dibujo de MFC es ineficiente y siempre quiere encontrar otras soluciones. La eficiencia de dibujo de MFC no es alta, pero tampoco mala, y la función de dibujo es muy sencilla de usar. Siempre que lo uses correctamente y agregues algunas habilidades, puedes obtener un programa de dibujo eficiente con MFC. Me gustaría hablar sobre mi experiencia de muchos años (bueno, por supuesto, solo más de dos años) dibujando con MFC. 1.¿Por qué parpadean los gráficos mostrados? La mayoría de nuestros procesos de dibujo se colocan en la función OnDraw o OnPaint que OnPaint llama cuando se muestra en la pantalla. Cuando es necesario volver a dibujar la ventana por algún motivo, el área de visualización siempre se borra primero con el color de fondo y luego se llama a OnPaint. Sin embargo, el color de fondo suele ser muy diferente del contenido del dibujo, lo que provoca que el color de fondo y los gráficos de visualización. aparecerá alternativamente en un corto período de tiempo. La ventana de visualización parece parpadear. Si el pincel de fondo está vacío, la forma no parpadeará sin importar cómo se vuelva a dibujar. Por supuesto, esto hará que la ventana se muestre desordenada, porque no hay color de fondo para borrar la imagen original al volver a dibujar, y se superponen nuevos gráficos. Algunas personas pueden decir que el parpadeo se debe a una velocidad de dibujo lenta o a gráficos mostrados complejos, pero en realidad esto es incorrecto. El efecto de la velocidad de visualización de los gráficos sobre el parpadeo no es fundamental. Por ejemplo, en OnDraw(CDC *pDC), está escrito así: pDC-->MoveTo(0, 0); pDC->LineTo(100, 100); Aún verás parpadeo cuando abras la ventana para cambiar. De hecho, cuanto más complejo y lento sea el proceso de dibujo, menos parpadeo debería ser. Porque cuanto mayor sea la proporción del tiempo de dibujo con respecto al fondo de la pantalla, menos obvio será el parpadeo. Por ejemplo, está claro que el tiempo de pantalla es de 1 segundo y el tiempo de dibujo también es de 1 segundo, por lo que el redibujado continuo dentro de 10 segundos parpadeará 5 veces, si está claro que el tiempo de pantalla es de 1 segundo y el tiempo de dibujo es de 9 segundos, luego se vuelve a dibujar continuamente; dentro de 10 segundos solo parpadeará una vez. Esto también se puede probar, escrito con OnDraw(CDC *pDC): for(int I = 0;i<100000;i++){pDC->MoveTo(0,I);pDC->LineTo(1000,I ); El programa es un poco pervertido, pero puede explicar el problema. Quizás alguien quiera decir algo aquí. ¿Por qué las formas simples parecen menos brillantes que las formas complejas? Esto se debe a que los gráficos complejos ocupan un área más grande y el contraste causado al volver a dibujar es relativamente grande, lo que hace que los gráficos parpadeen mucho, pero la frecuencia de parpadeo es baja. Entonces, ¿por qué la animación se vuelve a dibujar con frecuencia pero no parece parpadear? Aquí quiero enfatizar nuevamente ¿qué es el engaño? El parpadeo es contraste, cuanto mayor es el contraste, mayor es el parpadeo. Debido a que la diferencia entre dos fotogramas consecutivos de animación es muy pequeña, no parece parpadear. Si no lo cree, puede agregar un cuadro blanco puro en el medio de cada cuadro de la animación. Sería extraño si no parpadeara. *Puedes aplicar NULL* al fondo de la clase de registro de ventana cuando se forma la ventana. *También puedes modificar el pincel CBrush estático de fondo(RGB(255,0,0));setclass long(this->m_hWnd,GCL_HBRBACKGROUND después de que se forme la ventana), (largo) (HBRUSH) pincel); *En pocas palabras, también puede sobrecargar OnEraseBkgnd(CDC* pDC) y devolver directamente TRUE, de modo que el fondo desaparezca y la visualización de gráficos no parpadee. pero como se mencionó anteriormente, la pantalla se vuelve Qué desastre. Lo que hacemos es utilizar un enfoque de doble almacenamiento en búfer. El almacenamiento en búfer doble significa que, además de mostrar los gráficos en la pantalla, los gráficos también se dibujan en la memoria. Primero podemos dibujar los gráficos que se mostrarán en la memoria y luego cubrir los gráficos en la memoria en la pantalla uno por uno (este proceso es muy rápido porque es una copia de memoria muy regular). De esta manera, cualquier color de fondo de alto contraste no parpadeará porque es invisible al dibujar en la memoria. Cuando se pegue en la pantalla, no habrá parpadeo ya que los gráficos finales en la memoria y los gráficos mostrados en la pantalla no son muy diferentes (por supuesto, no hay diferencia si no hay movimiento). // Luego crea un dispositivo de visualización de memoria MemDC. CreateCompatibleDC(NULL) es compatible con la visualización en pantalla; // No se puede dibujar en este momento porque no hay lugar para dibujar un mapa de bits que sea compatible con la visualización en pantalla. En cuanto al tamaño del mapa de bits, puede utilizar el tamaño del mapa de bits de la ventana.
Cree un mapa de bits compatible (PDC, nwidth, n height); //Seleccione el mapa de bits para el dispositivo de visualización de memoria //Solo el dispositivo de visualización de memoria que selecciona el mapa de bits tiene un lugar para dibujar, dibuje el mapa de bits * pold en el bit del mapa de bits especificado. = memdc . Select object(&MemBitmap); // Primero borra el mapa de bits con el color de fondo. Aquí uso el blanco como fondo // También puedes usar tu propio color memdc. Fillsolidrect (0, 0, nwidth, nheight, RGB (255, 255, 255)); //Dibujar memdc.moveto(...);MemDC. line to(...); // Copia los gráficos en la memoria a la pantalla para mostrar PDC->BitBlt(0, 0, nWidth, nHeight y ampMemDC, 0, 0, src copy); . Eliminar objeto() después de dibujar; DeleteDC(); 4. Cómo mejorar la eficiencia del dibujo. Trabajo principalmente en el software CAD de gráficos de red del sistema de energía. En una ventana se suelen mostrar miles de componentes de potencia, cada componente está compuesto por gráficos básicos como puntos, líneas, círculos, etc. Si realmente tienes que volver a dibujar tantos componentes en un solo proceso, puedes imaginar que este proceso será muy largo. Si se agrega la función de exploración de gráficos, se requerirá una gran cantidad de redibujado cuando el mouse arrastre los gráficos para desplazarse, y la velocidad será demasiado lenta para que el usuario la soporte. Lo que hacemos es volver a aprender el proceso de dibujo de MFC. De hecho, no se mostrarán todos los dibujos dibujados en OnDraw(CDC *pDC). Por ejemplo, si dibuja dos rectángulos en OnDraw, aunque las funciones de dibujo de ambos rectángulos se ejecutan en un nuevo dibujo, es muy probable que solo se muestre uno porque el propio MFC establece un área de recorte para mejorar la eficiencia del nuevo dibujo. La función del área de recorte es que solo el proceso de dibujo dentro de esta área será realmente efectivo, y el proceso de dibujo fuera del área no será válido. Incluso si la función de dibujo se ejecuta fuera del área, no se mostrará. Porque en la mayoría de los casos, el rediseño de la ventana se debe principalmente a que la ventana está parcialmente bloqueada o al desplazamiento de la ventana. Lo que se debe cambiar no es todo el gráfico, sino solo una pequeña parte del área de recorte en pDC. Dado que la visualización (conocida como visualización en memoria o memoria de video) requiere mucho más tiempo que el cálculo en el proceso de dibujo, solo la parte que debe mostrarse se muestra después de proporcionar el área de recorte, lo que mejora en gran medida la eficiencia de la visualización. Pero esta área de recorte la establece MFC, lo que mejora la eficiencia de la visualización para nosotros. ¿Cómo mejorar aún más la eficiencia al dibujar gráficos complejos? Luego tenemos que eliminar el proceso de dibujo fuera del área de corte. Puede usar PDC->GetClipBox() para obtener el área de recorte y luego determinar si su gráfico está en esta área al dibujar. Si es así, dibújalo; si no, no lo dibujes. Si su proceso de dibujo no es complicado, es posible que no mejore su eficiencia de dibujo.