Capturar la ventana o una región[Capturar la ventana completa, con o sin decoración, o una región que se corresponde con un control PictureBox, usando GDI+]
Fecha: 15/Feb/2006 (14 de Febrero de 2006)
|
Resumen
Aprovechando los ejercicios sobre GDI+ de Fernando Luque Sánchez (1, 2, 3 y 4) y de Arbis Percy Reyes Paredes (1, 2, 3 y 4), publicados en 2005, y mi último artículo sobre un control PictureBox redondeado (1), continúo en esta línea. Como dice Arbis Percy Reyes Paredes en el primero de sus artículos:
"GDI+ es una interfaz de programación de aplicaciones (API) que se expone a través de un conjunto de clases implementadas como código administrado. GDI+ viene a ser la interfaz de dispositivo gráfico que se encarga de mostrar información en pantallas e impresoras, la cual nos permite a nosotros, como programadores de aplicaciones, mostrar información en una pantalla o impresora sin tener que preocuparnos por los detalles de un dispositivo de presentación específico, es decir, cuando desarrollemos aplicaciones usando los métodos suministrados por las clases de GDI+, no tendremos que preocuparnos por el hardware gráfico, ya que todo este trabajo lo harán los métodos GDI+ llamando a los controladores de dispositivo específicos, de esta manera GDI+ separa la aplicación del hardware gráfico, y esta separación es la que nos permite crear aplicaciones independientes del dispositivo. Ahora podemos decir con seguridad que GDI+ es una interfaz de dispositivo gráfico que permite a los programadores escribir aplicaciones independientes del dispositivo."
Retomando el ejercicio del control PictureBox redondeado, se añade la funcionalidad de captura de pantalla, usando métodos de las clases de GDI+, explicando cómo hacer para capturar la ventana de la aplicación, con o sin decoración (bordes, barras de herramientas, de menús y de scroll, etc.) o una región específica de la ventana, la del control PictureBox, y guardar el resultado como una imagen JPG en el directorio del ensamblado. Estas imágenes JPG se muestran en un documento HTML.
Invocación de plataforma
Se definen unas funciones (imagenFormA, imagenFormB y imagenFormC) que:
- crean un objeto Graphics de origen (desde la ventana o región)
- crean un Bitmap para contener la imagen (con la anchura y la altura del formulario o de la región)
- crean otro objeto Graphics de destino (desde el Bitmap)
- usan el tipo IntPtr (entero específico de la plataforma - sistema operativo) para obtener el hDC (device context handle - enlace al contexto de dispositivo gráfico) de los 2 objetos Graphics generados
- usan la función BitBlt (BitBlast) para copiar la imagen en el Bitmap
- esta imagen es guardada a disco con el formato JPG
Las funciones propias de la clase realizan capturas diferentes:
- imagenFormA: captura la ventana con decoración y la guarda como CapturaA.jpg
- imagenFormB: captura la ventana sin decoración y la guarda como CapturaB.jpg
- imagenFormC: captura la región PictureBox y la guarda como CapturaC.jpg
Las funciones que se llaman desde librerías externas se declaran así:
Imports System.Drawing Imports System.Drawing.Drawing2D Imports System.Drawing.Imaging<System.Runtime.InteropServices.DllImport("gdi32.dll")> _ Public Shared Function BitBlt(ByVal hdcDest As IntPtr, ByVal nXDest As Integer, ByVal nYDest As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hdcSrc As IntPtr, ByVal nXSrc As Integer, ByVal nYSrc As Integer, ByVal dwRop As System.Int32) As Boolean End Function 'constante para usar como último parámetro de la función BitBlt Private Const SRCCOPY As Integer = &HCC0020 'destino = origen 'GetWindowDC devuelve el contexto de dispositivo (DC) correspondiente a la ventana entera, 'con bordes, barras de herramientas, de menús y de scroll, etc. Un DC de la ventana permite 'pintar sobre la ventana ya que el origen del DC es la esquina superior izda. de la ventana 'y no la esquina superior izda. del área cliente de la ventana ' <System.Runtime.InteropServices.DllImport("User32.dll")> _ Public Shared Function GetWindowDC(ByVal hwnd As System.IntPtr) As System.IntPtr End FunctionLa explicación de los parámetros de la función BitBlt es la siguiente:
- hdcDest: apunta al contexto de dispositivo destino
- nXDest: coordenada x del rectángulo destino
- nYDest: coordenada y del rectángulo destino
- nWidth: anchura de los rectángulos origen y destino
- nHeight: altura de los rectángulos origen y destino
- hdcSrc: apunta al contexto de dispositivo origen
- nXSrc: coordenada x del rectángulo origen
- nYSrc: coordenada y del rectángulo origen
- dwRop: código de operación, define la manera en que los datos del origen se combinan con los del destino
En esta aplicación se usa el tipo de dato IntPtr. Se ha diseñado el tipo IntPtr para que sea un número entero cuyo tamaño sea específico de la plataforma (sistema operativo). Es decir, se espera que una instancia de este tipo tenga lugar en sistemas operativos y hardware de 32 bits, y en sistemas operativos y hardware de 64 bits. El tipo IntPtr se puede utilizar como un medio común para hacer referencia a los datos entre lenguajes (admitan o no punteros). El tipo IntPtr es compatible con CLS (Common Language Specification) que es el conjunto de características básicas de lenguaje englobadas en .NET Framework. El tipo IntPtr pertenece al espacio de nombres System.
Código en Visual Basic .NET
Como ejemplo, expondré una de las 3 funciones de la clase, la que captura la ventana pero sin la decoración (el código es casi idéntico en las 3 funciones).
Al pulsar un botón, se declara un Bitmap obtenido desde la función y se guarda como JPG:
'GUARDAR LA VENTANA SIN BORDES COMO JPG Private Sub btWin2_Click(sender As Object, e As EventArgs) Handles btWin2.Click Try Dim bm As Bitmap = imagenFormB() bm.Save(Application.StartupPath & "\CapturaB.jpg", ImageFormat.Jpeg) Catch pollo As Exception MsgBox("ERROR: " & pollo.Message, MsgBoxStyle.Information, "Aviso") End Try End SubLa función imagenFormB es la que contiene código relacionado con GDI+:
'OBTENER UN BITMAP CON LA IMAGEN DE LA VENTANA SIN DECORACIÓN Private Function imagenFormB() As Bitmap Try 'objeto Graphics de origen (desde la ventana o región) Dim g1 As Graphics = Me.CreateGraphics 'Bitmap para contener la imagen (anchura y altura del área cliente del formulario) Dim bm As New Bitmap(Me.ClientSize.Width, Me.ClientSize.Height, g1) 'objeto Graphics de destino (desde el Bitmap) Dim g2 As Graphics = g1.FromImage(bm) 'IntPtr: entero específico de la plataforma (sistema operativo) 'hDC: device context handle (enlace al contexto de dispositivo del objeto g2) Dim bm_hdc As IntPtr = g2.GetHdc ' hDC del formulario, se debe hacer después de crear el Bitmap (utiliza g1) Dim me_hdc As IntPtr = g1.GetHdc ' copiar la imagen del formulario en el Bitmap, ' el rectángulo origen y destino tienen coordenadas x.y = 0 BitBlt(bm_hdc, 0, 0, Me.ClientSize.Width, Me.ClientSize.Height, me_hdc, 0, 0, SRCCOPY) 'liberar recursos g1.ReleaseHdc(me_hdc) g2.ReleaseHdc(bm_hdc) 'devolver el resultado Return bm Catch pollo As Exception MsgBox("ERROR: " & pollo.Message, MsgBoxStyle.Information, "Aviso") End Try End FunctionAbrir un documento HTML
El código siguiente, ejecutado al pulsar un botón, abre un documento HTML con las capturas, mediante su programa asociado, pasando una cadena con el nombre del archivo:
'Iniciar y detener procesos del sistema local Imports System.Diagnostics Private Sub btMostrarA_Click(sender As Object, e As EventArgs) Handles btMostrarA.Click 'abrir un archivo mediante su programa asociado, pasando una cadena con el nombre del archivo System.Diagnostics.Process.Start(Application.StartupPath & "\imgCapturas.htm") End SubAquí puedes ver una imagen de las imágenes capturadas tal como se muestran en el documento HTML.
Espacios de nombres usados en el código de este artículo:
System.Drawing
System.Drawing.Drawing2D
System.Drawing.Imaging
System.Diagnostics
Fichero con el código de ejemplo: miliuco_picturebox2.zip - 170 KB
(MD5 checksum: [DBA7D28ADABC19BF704755FFA5F06803])