Ver Mensaje Individual
  #10  
Antiguo 07-02-2012
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.202
Reputación: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
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';

// 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;


Saludos.

Última edición por escafandra fecha: 07-02-2012 a las 13:28:31.
Responder Con Cita