windows gdi+ aero dwm

Windows Aero: ¿Qué color pintar para que aparezca el "vidrio"?



gdi+ dwm (3)

Intente establecer la TransparencyKey del formulario en Color.FromArgb (1,1,1) (o algún otro valor adecuado de su elección) y luego ajuste el color de fondo de la forma (o la parte que desea que sea el vidrio) al mismo valor.

Así es como conseguí que funcionara sin hacer que todo mi texto negro fuera transparente / cristal.

Sin embargo, nunca pude imaginar cómo pintar el texto "brillante" en el vidrio. Siempre tenía un rectángulo negro detrás.

¿Qué color debo pintar en el área del cliente para que aparezca el cristal ?

He extendido el marco de mi formulario en el área del cliente usando:

DwmExtendFrameIntoClientArea(self.Handle, margins);

No puedo encontrar ninguna documentación oficial de Microsoft sobre qué color y / o alfa buscará el DWM para reemplazar con vidrio. La documentación en DwmExtendFrameInClientArea ni siquiera menciona que se requiere un color personalizado. Solo hay rumores y mitos de que incluso se requiere un color especial.

Lo más cercano que puedo encontrar es un tema en MSDN:

Marco de ventana personalizado utilizando DWM

Para que los marcos extendidos sean visibles, las regiones subyacentes a cada lado del marco extendido deben tener datos de píxeles que tengan un valor alfa de 0.

Actualización: Y una entrada de blog:

Windows Vista para desarrolladores - Parte 3 - El Administrador de ventanas de escritorio

Sucede que el patrón de bits para RGB negro (0x00000000) es el mismo que el patrón de bits para ARGB 100% transparente, por lo que puede dibujar con el pincel GDI "negro" y suponiendo que haya indicado al DWM que desenfoque el área pintada, El resultado será el efecto de cristal deseado.

Si tomo lo que dicen literalmente ( datos de píxeles con un valor alfa de cero ), construyo un color con cero alfa y pinto eso en el área extendida:

Color fillColor = Color.FromArgb(0, 0, 0, 0); //(a, r, g, b) e.Graphics.FillRectangle(new SolidBrush(fillColor), e.ClipRectangle);

Pero el efecto de cristal no aparece.

texto alt http://i46.tinypic.com/anlmd4.png

Si ignoro el tema de MSDN citado y, en cambio, uso un negro totalmente opaco (en lugar de un negro completamente transparente):

Color fillColor = Color.FromArgb(255, 0, 0, 0); //(a, r, g, b) e.Graphics.FillRectangle(new SolidBrush(fillColor), e.ClipRectangle);

Aparece el efecto de vidrio:

texto alt http://i45.tinypic.com/2ug2ias.png

Luego, creo que el negro opaco es el valor de píxel que el DWM buscará reemplazar con el vidrio.

Pero entonces, ¿cómo pinto artículos negros en el área de vidrio?

He probado pintar un rectángulo negro en el área de vidrio, con un círculo al lado. Por extraño que parezca, el rectángulo no aparece, mientras que el círculo sí aparece; ambos son del mismo color

Brush b = new SolidBrush(Color.FromArgb(255, 0, 0, 0)); e.Graphics.FillRectangle(b, 11, 11, 32, 32); e.Graphcis.FillEllipse(b, 43, 11, 32, 32);

texto alt http://i49.tinypic.com/aayykk.png

Entonces, ¿qué diablos está pasando? ¿Cuál es el color adecuado para pintar en el área del marco extendido para que aparezca el vidrio?

Actualización 2

Usando la sugerencia de Adisak para aislar exactamente dónde vive la estupidez de Aero, aquí dibujo un rectángulo negro dentro del círculo negro:

texto alt http://i47.tinypic.com/5dw861.png

¿FillEllipse no admite el dibujo de círculos negros?

Actualización 3

Pondidum preguntó si llamar a Graphics.Clear con un color negro transparente haría que el vidrio fuera visible:

e.Graphics.Clear(Color.FromArgb(0,0,0,0));

Funciona, pero aún no puedes dibujar elementos negros opacos en el vidrio:

texto alt http://i47.tinypic.com/5dw861.png

Actualización 4

Al observar la Vista Bridge Library de Microsoft (envoltorios administrados alrededor de la funcionalidad de Vista que no se agregarán a .NET), solo logran que el marco de vidrio extendido funcione en formularios WPF, no en WinForms.

Ver también


Una de las publicaciones de blog que vinculó anteriormente tiene una discusión sobre esto. La solución nativa fue usar SetLayeredWindowAttributes para cambiar la clave de color del negro.


Color fillColor = Color.FromArgb(0, 0, 0, 0); //(a, r, g, b) e.Graphics.FillRectangle(new SolidBrush(fillColor), e.ClipRectangle);

Esto es en realidad bastante divertido. Significa que estás dibujando algo completamente transparente, ¡así que esto no cambia absolutamente nada! :-)

Adivina: si negro (0,0,0) debería significar "vidrio", ¿qué hay de dibujar (1,1,1) para obtener (casi) negro?