2010-11-07 10 views
10

Encontré esta pregunta en StackOverflow. Básicamente, el usuario quería dibujar botones personalizados en la barra de título.Dibujar botones personalizados en Windows Vista/7 Aero Titlebar

Probé el código y me di cuenta de que funciona en vista/7 solo cuando Aero está deshabilitado. Mi pregunta es, ¿hay alguna manera de dibujar botones personalizados en la barra de título mientras que aero está habilitado?

Además, ¿hay alguna forma de leer la información del tema actual para que pueda personalizar mis botones para que coincidan con los ya existentes?


actualización

Aquí es una captura de pantalla de mi ordenador que demuestra el concepto anterior. Obtuve los botones adicionales de la barra de título después de instalar DisplayFusion.
Notepad2 showing additional buttons.

Y sé que DisplayFusion es un programa .NET porque se abre en .NET Reflector. El inconveniente es que el programa está ofuscado. No es como si quisiera descompilar el programa o algo así; Solo quiero agregar un botón a mi barra de título para hacer otra cosa (como minimizar a la bandeja del sistema, por ejemplo).
A continuación se muestra la captura de pantalla, lo que demuestra que el programa es una aplicación .NET.
.NET Reflector showing DisplayFusion

+0

Olvídate de esto, ya no funciona. –

+4

Sé que es posible porque hay una aplicación de monitores múltiples llamada ** Display Fusion ** que hace precisamente eso. Sé que es una aplicación .NET porque la miré con el reflector .NET de Lutz Roeder. –

Respuesta

4

Mientras usted está dispuesto a volver a dibujar el contenido completo la barra de título, a continuación, puede utilizar el método de la API DwmExtendFrameIntoClientArea DWM, lo que implica la creación de la ventana que no tiene barra de título, permitiendo que el DWM para dibujar su cristal en su área utilizable para crear un nuevo espacio que se parece a la barra de título, pero de hecho está en su área de cliente, de modo que puede dibujar botones en él.

La desventaja de este método es que tendrá que hacer los botones estándar si los quiere. Minimizar, Maximizar y Cerrar no son un problema para recrear (aunque descubrirá que el botón maximizar es un botón de selección con apariencia basada en el estado), pero es posible que tenga problemas para volver a crear el botón de la esquina superior izquierda. También tendrá que volver a dibujar su título, por supuesto, pero no puedo imaginar que tenga algún problema con eso.

En cuanto a leer los datos del tema actual para volver a cambiar sus botones como los suyos, lo siento pero no sé nada al respecto. Mi sugerencia sería utilizar la transparencia al construir los botones en la barra de título, y usar efectos de luz translúcidos, etcétera. De esta forma, podrá conservar el fondo de cristal y simplemente modificar su apariencia al superponer un color translúcido. Además, si lo haces de esta manera, los reflejos especulares cambiantes del cristal se moverán de forma natural, mientras que si simplemente obtuvieras los colores de los temas, descubrirías que no obtuviste acceso a sus reflejos o que recrearon de nuevo el espacio de tus botones Solo mis dos centavos, por supuesto, si puede encontrar la manera de hacer los colores de su tema, etcétera, por supuesto.

Sin embargo, hay una advertencia: hay otro hilo de StackOverflow (http://stackoverflow.com/questions/2666979/net-framework-4-0-and-drawing-on-aero-glass-issue/4656182# 4656182) que describe un problema con el método DwM API DwmExtendFrameIntoClientArea, por lo que si fuera usted, lo leería antes de probar esta solución.

4

Hice algunas investigaciones sobre esto ya que implementé esto también en mi propia solución de monitores múltiples. La forma en que DisplayFusion y TeamViewer implementaron esto es superponer un formulario personalizado sobre la ventana deseada que contiene los botones. Puedes usar Spy ++ para confirmar esto.

Ésta es la idea general:

  1. Escribir un gancho DLL para recibir notificaciones cuando se crea una ventana, retirado, activa, vuelve a colocar o cambiar de tamaño.
  2. Haz una forma transparente usando la tecla de transparencia o usando este alpha-PNG and GDI+ solution y simula el botón (s) pintándolo.
  3. En la creación/eliminación de ventanas, muestra u oculta su forma de botón de la barra de título para la (s) ventana (s) deseada (s).
  4. Al cambiar el tamaño de la ventana/cambiar la posición de los mensajes, realineará su formulario de la barra de título.
  5. Al activar la ventana, establece la posición Z de la ventana para que esté en la parte superior de la ventana deseada.

Obteniendo y configurando la posición Z a través de las API GetWindow y SetWindowPos.
Tenga en cuenta que la DLL debe escribirse en un idioma nativo. Sin embargo se van usar algo como esto para evitar ese problema: Using Window Messages to Implement Global System Hooks in C#

Y aquí está mi resultado:

enter image description here

+0

Su solución parece prometedora. Pensé cómo crear la forma transparente y detectar apertura, movimiento y cierre de ventanas. Lo que me gustaría saber es cómo crear los botones con temas en blanco para que yo pueda pintar los míos. Si es posible, ¿puedes subir tu solución? –

+0

¿Puede publicar algún código para mostrar cómo creó los botones de la barra de título en la captura de pantalla? –

+0

@Jelle Vergeer Por favor, considere agregar un enlace para el código fuente del "resultado", necesito esta solución ... +1 – ElektroStudios

0

Ok, ganchos del sistema son el enfoque directo para obtener información sobre las posiciones de las ventanas modificaciones realizadas y se Jelle's propuesta con forma transparente es muy buena. Sin embargo, se puede utilizar un método menos invasivo para obtener información sobre el escritorio de Windows mediante el uso de user32.dll

[DllImport("user32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
public static extern bool GetWindowRect(HandleRef hWnd, out RECT lpRect); 

La ventana maneja puede obtener utilizando EnumDesktopWindows

[DllImport("user32.dll", EntryPoint = "EnumDesktopWindows", 
ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)] 
[return: MarshalAs(UnmanagedType.Bool)] 
public static extern bool EnumDesktopWindows(IntPtr hDesktop, EnumDelegate lpEnumCallbackFunction, IntPtr lParam); 

Un ejemplo de esto se puede obtener de la thread getting-a-list-of-all-applications-in-c-sharp

Cuestiones relacionadas