Microsoft MVP

Email y Rss

email rss

Klout

Seguidores en facebook

Timeline de mi Twitter

Tienes preguntas?

Ideas de un Conejo
Más allá de los sistemas de información: (C#)=> videojuegos, soluciones a problemas interesantes y Sistemas Operativos
XNA
C#
Sistemas Operativos
Varios
Windows Phone
WinRT
XAML
Azure
HTML 5
Acerca de

C# – Cómo modificar la transparencia en la ventana de otro proceso?

March 17th, 2010 by JuanK

Follow @JuanKRuiz

Hola, continuando con la solución a temas un poco escabrosos (nada más recordar el tema de la ventana sin borde que no se deja minimizar ni maximizar) tengo este caso particular en el cual se desea que al abrir un nuevo proceso desde nuestra aplicación la ventana de este nuevo proceso tenga cierto nivel de transparencia.

 

Desde luego para resolver este caso aplica una solución más genérica a través de la cual podamos acceder a cualquier proceso en ejecución y modificar la transparencia de su ventana.

Pero como llegamos a hacerlo? como siempre nuestra buena amiga la API de Windows viene al rescate (super coooooooooooooow to the rescueeeeeee ).

 

Pasos a Seguir

En su nivel más básico los pasos a seguir se resumen en:

  1. Determinar el proceso al que le convertiremos la ventana a ventana con transparencia
  2. Buscar un handler a la ventana de ese proceso
  3. Establecer la transparencia en esa ventana

El paso 1 es bastante sencillo y no requiere mayor explicación, utilizaremos para este ejemplo una rutina para abrir un nuevo proceso y obtener su pid.

private static int LanzarProcesos(string ejecutable)
{
    ProcessStartInfo psInfo = new System.Diagnostics.ProcessStartInfo(ejecutable);
    Process process = new Process();
    process.StartInfo = psInfo;
    process.Start();
    return process.Id;
}

 

El paso 2. Buscar el handler a la ventana de un proceso, tiene un poco más de trabajo.

 

Conseguir un Handler a la Ventana de un Proceso

Esta parte no estaba tan sencilla :P . Pero gracias a este otro hilo podemos implementar una función Win32APITools.GetProcessWindowHandler lo que nos será de mucha utilidad:

 

Otro Post en Ideas de un Conejo

 

Establecer la Transparencia en la Ventana

Para realizar esta tarea utilizaremos la función GetWindowLong para hallar el estilo de la ventana por medio de su handler, y así mismo haremos uso de SetWindowLong para modificar dicho estilo adicionándole a la ventana el atributo de ventana por capas (layered window).

Una vez se ha modificado la ventana para soportar ser dibujada con transparencia, se debe llamar a SetLayeredWindowAttributes, para indicarle a la ventana que cantidad de transparencia debe tener.

/// <summary>Indca estilo de la ventana</summary>
const int GWL_EXSTYLE = unchecked((int)0xFFFFFFEC);
/// <summary>Atributo etendido para ventana por capas</summary>
const int WS_EX_LAYERED = 0x00080000;
/// <summary>Atributo para establecer la transparencia con base a un byte de color alpha</summary>
const int LWA_ALPHA = 0x2;

/// <summary>
/// Establece una ventana como transparente
/// </summary>
/// <param name="hwnd" />handlder de la ventana
/// <param name="transparencia" />Nivel de transparencia: 0 transparente, 255 opaco
private static void EstablecerTransparenciaVentana(IntPtr hwnd, byte transparencia)
{
    //Obtener valor de la propiedad
    int dwStyle = GetWindowLong(hwnd, GWL_EXSTYLE);

    //Establecer estilo de ventanas por capas
    dwStyle = dwStyle | WS_EX_LAYERED;
    SetWindowLong(hwnd, GWL_EXSTYLE, dwStyle);
    //Establecer valor de transparencia
    SetLayeredWindowAttributes(hwnd, 0, transparencia, LWA_ALPHA);
}

Perfecto eso es todo lo que necesitamos, así que ahora es hora de integrarlo todo.

Implementación

Ahora el ejemplo final, si se ejecuta sin parámetros llama a la consola de comandos estableciendo su nivel de transparencia en 128, pasarle como parámetro otro ejecutable y otra cantidad de transparencia ( de 0 a 255 ) es opcional.

Estos son dos screenshots que muestran lo que se pude hacer(click para ver versión grande)

image

image

Y este es el código completo.

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

class Program
{
    #region Constantes de la API
    /// <summary>Indca estilo de la ventana</summary>
    const int GWL_EXSTYLE = unchecked((int)0xFFFFFFEC);
    /// <summary>Atributo etendido para ventana por capas</summary>
    const int WS_EX_LAYERED = 0x00080000;
    /// <summary>Atributo para establecer la transparencia con base a un byte de color alpha</summary>
    const int LWA_ALPHA = 0x2;
    #endregion Constantes de la API

    #region Interoperabilidad con la API
    /// <summary>
    /// Retorna una propiedad de una ventana
    /// </summary>
    /// <param name="hWnd" />handler dela ventana
    /// <param name="nIndex" />propiedad a retornar
    /// <returns>la propiedad especificada</returns>
    [DllImport("user32.dll")]
    private static extern int GetWindowLong(IntPtr hWnd, int nIndex);

    /// <summary>
    /// Cambia una propiedad de una ventana
    /// </summary>
    /// <param name="hWnd" />handler de la ventana
    /// <param name="nIndex" />propiedad a modificar
    /// <param name="dwNewLong" />nuevo valor de la propiedad
    /// <returns>el valor anterior de la propiedad,0 si error, cuando el valor anterior de la propiedad era 0 devuelve 0 
    /// tambien pero si se usa GetLastError para verificar este no dara 0</returns>
    [DllImport("user32.dll")]
    private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

    /// <summary>
    /// Establece opacidad y transparencia de una ventana de capas (layered)
    /// </summary>
    /// <param name="hwnd" />handler de la ventana
    /// <param name="crKey" />color key
    /// <param name="bAlpha" />valor de byte alpha
    /// <param name="dwFlags" />acción a realizar
    /// <returns>true si exitoso, false sino</returns>
    [DllImport("user32.dll")]
    static extern bool SetLayeredWindowAttributes(IntPtr hwnd, int crKey, byte bAlpha, uint dwFlags);
    #endregion Interoperabilidad con la API

    /// <summary>Valor de transparencia por defecto</summary>
    const int INT_TRANSP_INICIAL = 128;
    /// <summary>Aplicación por defecto</summary>
    const string STR_DEFAULT_APP = @"cmd.exe";

    static void Main(string[] args)
    {
        byte transparencia;

        if (args.Length > 1)
            transparencia = ConvertirArgumentoTransparencia(args[1]);
        else
            transparencia = INT_TRANSP_INICIAL;

        int pid;
        //Lanzar proceso
        if (args.Length > 0)
            pid = LanzarProcesos(args[0]);
        else
            pid = LanzarProcesos(STR_DEFAULT_APP);

        //Obtener el handler de la ventana del proceso
        IntPtr hwnd = Win32APITools.GetProcessWindowHandler(pid);

        //Colocar la ventana con la transparencia
        EstablecerTransparenciaVentana(hwnd, transparencia);
    }

    /// <summary>
    /// Lanza el proceso y retorna el Pid
    /// </summary>
    /// <returns>Id de Proceso</returns>
    private static int LanzarProcesos(string ejecutable)
    {
        ProcessStartInfo psInfo = new System.Diagnostics.ProcessStartInfo(ejecutable);
        Process process = new Process();
        process.StartInfo = psInfo;
        process.Start();
        return process.Id;
    }

    /// <summary>
    /// Convierte el parámetro de entrada en un valor de transparencia válido
    /// </summary>
    /// <param name="cantidadTransparencia" />Cantidad de transparencia: 0 transparente ,  255 opaco
    /// <returns>El valor de transparencia calculado</returns>
    private static byte ConvertirArgumentoTransparencia(string cantidadTransparencia)
    {
        byte transparencia;
        if (!byte.TryParse(cantidadTransparencia, out transparencia))
            transparencia = INT_TRANSP_INICIAL;

        return transparencia;
    }

    /// <summary>
    /// Establece una ventana como transparente
    /// </summary>
    /// <param name="hwnd" />hnandlder de la ventana
    /// <param name="transparencia" />Nivel de transparencia: 0 transparente, 255 opaco
    private static void EstablecerTransparenciaVentana(IntPtr hwnd, byte transparencia)
    {
        //Obtener valor de la propiedad
        int dwStyle = GetWindowLong(hwnd, GWL_EXSTYLE);

        //Establecer estilo de ventanas por capas
        dwStyle = dwStyle | WS_EX_LAYERED;
        SetWindowLong(hwnd, GWL_EXSTYLE, dwStyle);
        //Establecer valor de transparencia
        SetLayeredWindowAttributes(hwnd, 0, transparencia, LWA_ALPHA);
    }
}

Happy Learning.

Print Friendly

Follow @JuanKRuiz

  • 2 Comentarios »
  • Publicado en la categoría 'C#, Windows'

2 comentarios to “C# – Cómo modificar la transparencia en la ventana de otro proceso? ”


  • Ideas de un Conejo Says:
    September 26th, 2009 at 11:48 pm  

    [...] http://juank.black-byte.com/c-modificar-transparencia-ventana-otro-proceso/ [...]

  • biabers Says:
    November 3rd, 2009 at 12:01 pm  

    Como es obvio domina muy bien todo el tratamiento por procesos…y yo me pregunto, usted debe haber visto muchas veces el problema de como evitar el parpadeo de la interfaz windows durante la carga de datos sobre todo en los componentes ComboBox…he usado todo lo que me han dicho al respecto pero la verdad siguen colgandose durante la carga aunque sea bien rapida….
    existe alguna manera de utilizar algo que realmente solucione el problema…he intentado con backgroundworkers…suspendiendo el diseño y reaunadandolo despues …. le agradeceria que publicase un veradero ejemplo como los que se encuentran en su web al respecto….

    Gracias por todo…

Deja un comentario

Redes Sociales

Follow @JuanKRuiz
Answer Questions

Busca en el blog

Artículos Relacionados

  • C# – Conseguir un Handler a la Ventana de un Proceso
  • C# – Como modificar el comportamiento del botón minimizar, maximizar, etc.
  • C# – usar el WndProc en una Ventana WPF
  • El extraño caso de la ventana sin borde que no se deja maximizar ni minimizar
  • C# – El extraño caso de la ventana sin borde que no se deja cambiar de tamaño
  • C# – Recibir notificaciones cuando hayan cambios de sesión parte 1
  • C# – Recibir notificaciones cuando hayan cambios de sesión parte 3 – WPF
  • Artículos Relacionados

  • C# – Conseguir un Handler a la Ventana de un Proceso
  • C# – Como modificar el comportamiento del botón minimizar, maximizar, etc.
  • C# – usar el WndProc en una Ventana WPF
  • El extraño caso de la ventana sin borde que no se deja maximizar ni minimizar
  • C# – El extraño caso de la ventana sin borde que no se deja cambiar de tamaño
  • C# – Recibir notificaciones cuando hayan cambios de sesión parte 1
  • C# – Recibir notificaciones cuando hayan cambios de sesión parte 3 – WPF
  • Nube de Temas

    API - Azure - C# - codigo - Forms - IE - IE9 - Image - imagenes - IT - Microsoft - MVP - Pinned - PowerShell - Proceso - rendimiento - RSS - sistema - Sistemas Operativos - Site - Visual - WCF - Windows - Windows 8 - Windows Store - WinRT - WndProc - WPF - XAML - XNA

    Blogs recomendados

  • VBCodigoPocketPC Espacio para tratar temas de programacion para dispositivos moviles, Pocket PC, Compact Framework, Embbeded Visual Basic, Visual Basic.NET , C# (C Sharp)
  • Róbinson Moscoso Estaré publicando acá cosas sobre tecnologia .NET, situacioines cotidianas de las que voy aprendiendo… sirve como extensión de memoria.
  • .Net C# Blog de Nelsón Venegas
  • Warnov Microsoft Developer Evangelist
  • IT LIfe Blog de mi Hermano que esta en el lado claro: IT
  • Sorey Garcia Una chica del común con la firme intención de no serlo
  • Black Byte videojuegos, modelado y animación 3d
  • Road to IT World Cosas interesantes de IT
  • Marcela Chitiva Un poco de esto… un poco de aquello
  • Surviving the Nigth El mejor blog para aquellos que nos gustan los “internals”
  • Meta

    1. Log in
    2. WordPress

    Ideas de un Conejo is powered by Wordpress. Theme designed by Juan Carlos Ruiz.