2009-04-13 10 views
9

Estamos desarrollando una aplicación de piel con varios bordes redondeados en la mayoría de sus ventanas. Estoy usando regiones de ventana para definir formas no rectangulares, pero casi todos se oponen al alias irregular que esto causa, porque los píxeles solo pueden ser completamente opacos o completamente transparentes.Uso de ventanas en capas para crear bordes de ventana lisos

He encontrado una solución para esto usando ventanas en capas, pero queremos asegurarnos de que funcione (y que funcione bien) en una variedad de sistemas, y quiero ver si alguien tiene mejores ideas , o formas de optimizar lo que estoy haciendo. Sé que las ventanas en capas requieren win2000 o posterior, y eso está bien, ya que eso ya es un requisito por otras razones. A partir de algunas pruebas básicas se ve bien en Vista, pero eso no es garantía todavía.

Esto es lo que hago: Tengo una ventana, llámala A, con controles y texto y lo que sea que comprenda esa ventana. Tengo la ventana B como hija de la ventana A, excepto que tiene el estilo WS_POPUP en lugar de WS_CHILD, por lo que puede posicionarse fuera de la región A y se dibuja sobre los controles de A. La ventana B también tiene el estilo WS_EX_LAYERED, y en la inicialización, llamo al UpdateLayeredWindow con el indicador ULW_ALPHA y un DC fuente con un mapa de bits de 32 bits con un canal alfa, para que dibuje con alfa por píxel.

El mapa de bits utilizado en la fuente DC para la ventana B es más o menos los píxeles alrededor del borde de la ventana que quiero combinar sin problemas desde el fondo de la ventana a la transparencia total. Me saltaría todo el enfoque de dos ventanas y solo usaría una sola ventana en capas, excepto que cuando estás usando UpdateLayeredWindow, se extrae de un buffer guardado en la memoria, en lugar de los típicos mensajes WM_PAINT y todo eso, y tratando de obtener Los controles interactivos para niños (y las ventanas hijas) para que funcionen bien con eso suena como una molestia notable (y probablemente ni siquiera funcionaría para todo).

Por lo tanto, básicamente se trata de la ventana A con todos los controles secundarios y lo que sea, con la ventana B flotando directamente sobre ella, dibujando un bonito borde liso. Respondo a los mensajes de WM_MOVE y demás moviendo la ventana B junto con él, y tengo la ventana B deshabilitada para que nunca pueda obtener el foco o la entrada (los clics ya se han procesado, ya que partes de él son de opacidad cero, como la mayoría de sus partes internas, ya están excluidas de la selección).

Para las patadas, así es como se ven las piezas, para mostrar lo que quiero decir un poco mejor.

Por lo tanto, funciona, pero no puedo estar seguro de que es realmente la mejor manera de hacer esto. Tengo dos preguntas:

  • ¿Suena aceptable, o hay algo terriblemente terrible al respecto?
  • Como funciona actualmente, parece que está utilizando un búfer fuera de la pantalla del tamaño de la ventana (que puede ser de hasta 1024x768) a pesar de que muy pocos píxeles tienen datos de opacidad distintos de cero. ¿Vale la pena la sobrecarga y la complejidad adicional de cortarlo en pedazos de borde separados y componerlos juntos?
+0

Doug, sería genial si puedes compartir el código para esto. Gracias por adelantado. –

Respuesta

2

Mi producto utiliza ventanas en capas para dibujar las pequeñas pestañas que adjunto a cada ventana. Usé ventanas en capas para obtener el redondeo suave sin aliasing. El único problema desagradable que me he encontrado hasta ahora es que algunas ventanas de OpenGL garabatean ventanas superpuestas en Windows XP y Vista sin DWM. Es un problema de bajo nivel y Microsoft no ha sido terriblemente útil. Puede reproducirlo abriendo Google Earth y arrastrando su aplicación sobre la ventana principal de representación, su ventana en capas desaparecerá.

+0

Eso debería estar bien; esta aplicación funciona básicamente como un iniciador para una aplicación DirectX más grande, de pantalla completa, por lo que es poco probable que otro programa 3D/intensivo en gráficos se ejecute al mismo tiempo (que causaría problemas peores de todos modos, ya que admitimos hardware de gama baja). ¡Gracias por la advertencia! –

3

He descubierto una cosa: tener piezas de fotograma separadas puede renderizar significativamente más rápido que tener una única ventana de fotograma gigante, con una gran extensión de píxeles vacíos en el medio.No tengo ningún número real, pero a partir de una prueba rápida de probar ambos, hubo una latencia notable cuando varias ventanas con ventanas de marco completo se superponían entre sí, pero cuando sus marcos se cortaban en componentes más pequeños, era mucho más ágil . Cualquiera que sea la sobrecarga de tener varias ventanas en capas con sus propios contextos de dispositivo no contribuye mucho, y tener grandes extensiones de píxeles (en blanco o no!) Todavía contribuye con mucha más carga.

1
  1. No se olvide de probar bajo RDP y VM (Hyper-V & VMWare)
  2. probar varias tarjetas gfx y en netbooks y portátiles (si es aplicable).
Cuestiones relacionadas