Colaboraciones en el Guille

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)
Autor: Miliuco (Emilio Pérez Egido)

 


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:

Las funciones propias de la clase realizan capturas diferentes:

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 Function

La explicación de los parámetros de la función BitBlt es la siguiente:

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 Sub

La 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 Function

Abrir 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 Sub
Aquí 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])


ir al índice principal del Guille