Con motivo de una sugerencia que hice sobre una duda en este tema, expongo un ejemplo de enviar el contenido de la pantalla por un socket.
Se trata de enviar un bloque de memoria que contiene la imagen de la pantalla comprimida en png usando GDI plus flat API con lo que va a funcionar en cualquier versión de delphi.
uses Windows, ActiveX, WinSock, Forms, Classes, Controls, StdCtrls; type TCLSID = TGUID; PCLSID = ^TCLSID; TImageCodecInfo = packed record Clsid: TCLSID; FormatID: TGUID; CodecName: PWCHAR; DllName: PWCHAR; FormatDescription: PWCHAR; FilenameExtension: PWCHAR; MimeType: PWCHAR; Flags: DWORD; Version: DWORD; SigCount: DWORD; SigSize: DWORD; SigPattern: PBYTE; SigMask: PBYTE; end; PImageCodecInfo = ^TImageCodecInfo; function wcscmp(wstr1, wstr2: PWCHAR): Integer; cdecl external 'crtdll'; // GDI+ Flat API... function GdiplusStartup(var GdiToken: DWORD; Startup, Output: PBYTE): Cardinal; stdcall external 'gdiplus'; procedure GdiplusShutdown(GdiToken: DWORD); stdcall external 'gdiplus'; function GdipCreateBitmapFromHBITMAP(hbm: HBITMAP; hpal: HPALETTE; var GBitmap: THANDLE): Cardinal; stdcall external 'gdiplus'; function GdipGetImageEncodersSize(var numEncoders: DWORD; var size: DWORD): Cardinal; stdcall external 'gdiplus'; function GdipGetImageEncoders(numEncoders, size: DWORD; encoders: PImageCodecInfo): Cardinal; stdcall external 'gdiplus'; function GdipDisposeImage(image: THANDLE): Cardinal; stdcall external 'gdiplus'; function GdipSaveImageToStream(image: THANDLE; stream: ISTREAM; var clsidEncoder: TCLSID; encoderParams: Pointer): Cardinal; stdcall external 'gdiplus'; implementation // Obtener el CLSID para la codificación de un formato gráfico function GetEncoderClsid(Format: PWCHAR; var Clsid: TCLSID): boolean; var i, N, Size: Cardinal; ICInfo: array of TImageCodecInfo; begin Result:= false; i:= 0; N:= 0; Size:= 0; GdipGetImageEncodersSize(N, Size); if Size > 0 then begin SetLength(ICInfo, Size); GdipGetImageEncoders(N, Size, @ICInfo[0]); while (i< N) and (wcscmp(ICInfo[i].MimeType, Format)<>0) do inc(i); if i<N then Clsid:= ICInfo[i].Clsid; end; Result:= boolean(i<N); end; procedure SendScreen(hSocket: TSOCKET); var gdiplusToken: DWORD; GdiPlusStartupInput: array[0..2] of int64; CursorInf: TCURSORINFO; IconInf: ICONINFO; hScreen, hCanvas: HDC; Bitmap: HBITMAP; GBitmap: THANDLE; Stream: IStream; stat: STATSTG; Clsid: TCLSID; hMem: HGLOBAL; Memory: Pointer; begin // Inicializamos GDI+. GdiPlusStartupInput[0]:= 1; GdiPlusStartupInput[1]:= 0; if GdiplusStartup(gdiplusToken, @GdiPlusStartupInput, nil) <> 0 then exit; // Capturo la pantalla hScreen:= GetDC(0); hCanvas:= CreateCompatibleDC(0); Bitmap:= CreateCompatibleBitmap(hScreen,GetDeviceCaps(hScreen, HORZRES), GetDeviceCaps(hScreen, VERTRES)); SelectObject(hCanvas, Bitmap); BitBlt(hCanvas, 0, 0, GetDeviceCaps(hScreen, HORZRES), GetDeviceCaps(hScreen, VERTRES), hScreen, 0, 0, SRCCOPY); // Capturo el cursor ZeroMemory(@CursorInf, sizeof(TCURSORINFO)); CursorInf.cbSize:= sizeof(TCURSORINFO); if GetCursorInfo(CursorInf) and (CursorInf.flags = CURSOR_SHOWING) then begin GetIconInfo(CursorInf.hCursor, IconInf); DrawIcon(hCanvas, CursorInf.ptScreenPos.x - IconInf.xHotspot, CursorInf.ptScreenPos.y - IconInf.yHotspot, CursorInf.hCursor); DeleteObject(IconInf.hbmColor); DeleteObject(IconInf.hbmMask); end; // Procedo a enviar un bloque de memoria con la imagen comprimida en png CreateStreamOnHGlobal(0, true, stream); GdipCreateBitmapFromHBITMAP(Bitmap, 0, GBitmap); GetEncoderCLSID('image/png', Clsid); GdipSaveImageToStream(GBitmap, stream, Clsid, nil); // Obtengo el tamaño del bloque de memoria stream.Stat(stat, STATFLAG_NONAME); // Obtengo el puntero del bloque de memoria (stat.cbSize) GetHGlobalFromStream(stream, hMem); Memory:= GlobalLock(hMem); // Envío el bloque de memoria send(hSocket, Memory^, stat.cbSize, 0); // libero los Objetos usados del GDI+ bloques y Handles GdipDisposeImage(GBitmap); GlobalUnlock(hMem); DeleteObject(Bitmap); DeleteDC(hCanvas); ReleaseDC(0, hScreen); // Shutdown GDI+ GdiplusShutdown(gdiplusToken); end;
Espero que el ejemplo sea de utilidad para aquellos que se interesen por la API de GDI+ y a algunos otros curiosos .
Saludos.