Captura de pantalla o ventana activa en C#

Capturar la pantalla o la ventana activa usando la clase SendKeys sin recurrir a librerías externas en Visual Studio 2017 con C#

En este ejercicio se propone una manera relativamente sencilla para capturar tanto la pantalla completa como la ventana activa, copiarla al portapapeles y almacenarla en disco como JPG. Es la versión hecha en C# del ejercicio anterior hecho en Visual Basic. El proceso para hacer la captura es el siguiente:

  • se minimiza la aplicación para que no salga en la captura con el ítem Minimized de la enumeración FormWindowState
  • el proceso queda suspendido durante 500 milisegundos con el método Sleep de la clase Thread
  • la pulsación de teclas es enviada con el método SendWait de la clase SendKeys para obtener la captura en ese intervalo
  • las teclas que se envían son las que se utilizan en Windows para hacer estas capturas
  • desde el portapapeles se obtiene un objeto Bitmap que permite guardar la imagen en disco y mostrarla en el PictureBox

Capturar la pantalla

private void BtGrabScr_Click(object sender, EventArgs e)
{
    //minimizar el formulario para que no aparezca en la captura
    this.WindowState = FormWindowState.Minimized;
    //tiempo de espera con el formulario minimizado
    System.Threading.Thread.Sleep(500);
    //enviar la pulsación equivalente a May + ImprPant
    SendKeys.SendWait("+{PRTSC}");
    //capturar, guardar y mostrar la captura en el PictureBox
    //crear variable Bitmap
    Bitmap pantalla;
    //asignar al Bitmap el contenido del portapapeles
    pantalla = ((Bitmap)(Clipboard.GetDataObject().GetData("Bitmap")));
    //guardar el Bitmap como JPG
    pantalla.Save("Pantalla.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
    //mostrar el Bitmap en el control PictureBox
    ImgPantalla.Image = pantalla;
    //restaurar el formulario a su tamaño normal desde minimizado
    this.WindowState = FormWindowState.Normal;
}

Capturar la ventana

private void BtGrabWin_Click(object sender, EventArgs e)
{
    //minimizar el formulario para que no aparezca en la captura
    this.WindowState = FormWindowState.Minimized;
    //tiempo de espera con el formulario minimizado
    //el proceso de esperar y enviar Alt + ImprPant se lanza 2 veces 
    //si se lanza una sola vez no captura bien la ventana con foco
    //tiempo de espera con el formulario minimizado
    System.Threading.Thread.Sleep(500);
    //enviar la pulsación equivalente a Alt + ImprPant
    SendKeys.SendWait("%{PRTSC}");
    //tiempo de espera con el formulario minimizado
    System.Threading.Thread.Sleep(500);
    //enviar la pulsación equivalente a Alt + ImprPant
    SendKeys.SendWait("%{PRTSC}");
    //capturar, guardar y mostrar la captura en el PictureBox
    //crear variable Bitmap
    Bitmap pantalla;
    //asignar al Bitmap el contenido del portapapeles
    pantalla = ((Bitmap)(Clipboard.GetDataObject().GetData("Bitmap")));
    //guardar el Bitmap como JPG
    pantalla.Save("Ventana.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
    //mostrar el Bitmap en el control PictureBox
    ImgPantalla.Image = pantalla;
    //restaurar el formulario a su tamaño normal desde minimizado
    this.WindowState = FormWindowState.Normal;
}

Clase SendKeys

Proporciona métodos para enviar pulsaciones de tecla a la aplicación activa. Como parámetro se pasa una cadena que contiene la tecla pulsada. No se puede crear una instancia de esta clase. Para enviar una pulsación de tecla y continuar inmediatamente con el flujo del programa, utiliza Send. Para esperar a que terminen los procesos iniciados por la pulsación de tecla, utiliza SendWait.

Cada tecla está representada por uno o más caracteres. Para especificar un único carácter del teclado, utiliza dicho carácter. Por ejemplo, para representar la letra A, pasa la cadena «A» al método. Si se desea representar más de un carácter, agrega cada carácter adicional al que lo precede. Para representar las letras A, B y C, especifica el parámetro como «ABC».

El signo más (+), el signo de intercalación (^), el signo de porcentaje (%), la tilde (~) y los paréntesis () tienen significados especiales para SendKeys. Para especificar uno de estos caracteres, ponlo entre llaves ({}). Por ejemplo, para especificar el signo más, utiliza «{+}».

Para especificar caracteres que no se muestran al presionar una tecla, como ENTRAR o TAB, y teclas que representan acciones en lugar de caracteres, utiliza códigos como:

  • RETROCESO – usar {BACKSPACE}, {BS} o {BKSP}
  • ESC – usar {ESC}
  • IMPR PANT – usar {PRTSC}

Para especificar teclas con cualquier combinación de las teclas MAYÚS, CTRL y ALT, escribe delante del código de la tecla: % para ALT, ^ para CTRL y + para MAYÚS. Para especificar una repetición de teclas, utiliza el formato {tecla número}. Hay que separar la tecla y el número de repeticiones con un espacio.

Como ejemplo de todo ello, para enviar 1 pulsación de ALT + IMPR PANT (captura la ventana activa) usaremos %{PRTSC} y para enviar 1 pulsación de MAYÚS + IMPR PANT (captura la pantalla entera) usaremos +{PRTSC}.

NOTA: si se pulsa «Capturar la ventana» cuando no hay ventana alguna visible, lo que se captura es la barra de tareas.

Clase ClipBoard

La clase ClipBoard (derivada de la clase Object) tiene 3 miembros (constructor, GetDataObject y SetDataObject). Esta clase nos permite copiar al o pegar desde el portapapeles, como se ha visto en el código anterior:

//asignar al Bitmap el contenido del portapapeles
pantalla = ((Bitmap)(Clipboard.GetDataObject().GetData("Bitmap")));

Puedes descargar el proyecto de Visual Studio 2017 desde aquí.

Nota: el ajuste automático de escala del formulario que muestra la ventana de la aplicación se puede configurar de varias maneras, lo tienes en las propiedades del formulario como AutoScaleMode, la opción con la que obtengo el mejor resultado es con Dpi.