He preparado un ejemplo con GDI+ API Flat que va a funcionar en versiones antiguas de delphi como la 6 y 7. Simplemente enviamos a bajo nivel un bloque de memoria contenido en un istream por un soket:
Código Delphi
[-]
uses
Windows, ActiveX, WinSock;
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';
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
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
GdiPlusStartupInput[0]:= 1; GdiPlusStartupInput[1]:= 0;
if GdiplusStartup(gdiplusToken, @GdiPlusStartupInput, nil) <> 0 then exit;
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);
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;
CreateStreamOnHGlobal(0, true, stream);
GdipCreateBitmapFromHBITMAP(Bitmap, 0, GBitmap);
GetEncoderCLSID('image/png', Clsid);
GdipSaveImageToStream(GBitmap, stream, Clsid, nil);
stream.Stat(stat, STATFLAG_NONAME);
GetHGlobalFromStream(stream, hMem);
Memory:= GlobalLock(hMem);
send(hSocket, Memory^, stat.cbSize, 0);
GdipDisposeImage(GBitmap);
GlobalUnlock(hMem);
DeleteObject(Bitmap);
DeleteDC(hCanvas);
ReleaseDC(0, hScreen);
GdiplusShutdown(gdiplusToken);
end;
Saludos.