12 junio 2007

Capturar la pantalla de Windows

Vamos a crear un procedimiento que captura un trozo de la pantalla de Windows y la guarda en un bitmap:

procedure CapturarPantalla( x, y, iAncho, iAlto: Integer; Imagen: TBitmap );
var
DC: HDC;
lpPal : PLOGPALETTE;
begin
if ( iAncho = 0 ) OR ( iAlto = 0 ) then
Exit;

Imagen.Width := iAncho;
Imagen.Height := iAlto;
DC := GetDc( 0 );

if ( DC = 0 ) then
Exit;

if ( GetDeviceCaps( dc, RASTERCAPS) and RC_PALETTE = RC_PALETTE ) then
begin
GetMem( lpPal, SizeOf( TLOGPALETTE ) + ( 255 * SizeOf( TPALETTEENTRY ) ) );
FillChar( lpPal^, SizeOf( TLOGPALETTE ) + ( 255 * SizeOf( TPALETTEENTRY ) ), #0 );
lpPal^.palVersion := $300;
lpPal^.palNumEntries := GetSystemPaletteEntries( DC, 0, 256, lpPal^.palPalEntry );

if (lpPal^.PalNumEntries <> 0) then
Imagen.Palette := CreatePalette( lpPal^ );

FreeMem( lpPal, SizeOf( TLOGPALETTE ) + ( 255 * SizeOf( TPALETTEENTRY ) ) );
end;

BitBlt( Imagen.Canvas.Handle, 0, 0, iAncho, iAlto, DC, x, y, SRCCOPY );
ReleaseDc( 0, DC );
end;

Resumiendo a grandes rasgos lo que hace el procedimiento es crear un dispositivo de contexto donde según el número de bits por pixel reserva una zona de memoria para capturar el escritorio. Después mediante la función BitBlt vuelca la imagen capturada al Canvas de la imagen que le pasamos.

Para capturar toda la pantalla de Windows utilizando este procedimiento hacemos lo siguiente:

var Imagen: TBitmap;
begin
Imagen := TBitmap.Create;
CapturarPantalla( 0, 0, Screen.Width, Screen.Height, Imagen );
Imagen.SaveToFile( ExtractFilePath( Application.ExeName ) + 'captura.bmp' );
Imagen.Free;
end;

La pantalla capturada la guarda en el archivo captura.bmp al lado de nuestro ejecutable. Sólo faltaría el poder capturar una tecla de Windows desde cualquier aplicación para activar nuestro capturador de pantalla (para que no se capture a si mismo).

Pruebas realizadas en Delphi 7.

5 comentarios:

Matadamas dijo...

Muy buen truco, tengo una duda
como haría para grabar en una imágen solo una parte de la pantalla, por ejemplo tengo en la forma varios elementos y solo me interesa grabar en una imágen alguno de ellos

Saludos...

Administrador dijo...

Una vez tienes toda la pantalla capturada podrías cortar sólo el trozo que te interesa con la función CopyRect que tiene la clase TCanvas.

Otra cosa sería capturar sólo el contenido de una ventana, pero eso lleva más trabajo porque hay que extraer el Handle de cada ventana, extraer sus coordenadas x, y, ancho y alto, para luego poder cogerlo con CopyRect.

Saludos.

Fran Ramone dijo...

Necesitaria realizar una captura de mi formulario, pero si existe un formulario por encima del mio, este aparece en la imagen. ¿Se puede realizar esto de alguna forma?

Gracias.

Fran Ramone dijo...

Si un formulario/aplicacion esta por encima de mi formulario aparece en la captura. ¿Como podria hacerlo?

Un Saludo y gracias

Administrador dijo...

Lo único que se me ocurre es que en vez de capturar la mantalla, debes capturar el canvas del formulario que está debajo.

Pero creo que no va a funcionar ya que hay otros componentes que tienen su propia ventana.

Se tiene que poder hacer, pero ahora mismo no se me ocurre ninguna idea.

Saludos.

Publicidad