ScrSpy.pas
上传用户:juxian
上传日期:2013-04-01
资源大小:38k
文件大小:43k
源码类别:

驱动编程

开发平台:

Delphi

  1. unit ScrSpy;
  2. interface
  3. uses
  4.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  5.   BufferUDP;
  6. Type
  7.   TScreenBlock= record
  8.     BlockIndex: Integer;
  9.     BMP: TBitmap;
  10.     ptr: Pointer;
  11.     Bound: TRect;
  12.   end;
  13. type
  14.   TScreenSpyBitmapEvent = procedure(Sender: TObject; const Block: TScreenBlock; LastScanline: Pointer; IsIFrame: Boolean) of object;
  15.   TFrameStartEvent = procedure(Sender: TObject; const FrameCount: Cardinal; const IsIFrame: Boolean) of object;
  16.   TFrameEndEvent = procedure(Sender: TObject; const FrameCount: Cardinal; const IsIFrame: Boolean; const HasBitmapEvent: Boolean) of object;
  17.   TScreenSpy = class;
  18.   EScrSpy = Exception;
  19.   TScreenSpyThread = class(TThread)
  20.   private
  21.     // Properties
  22.     FScreenSpy: TScreenSpy;
  23.     // Golbal variable
  24.     SBIndex: Integer; // ScreenBitmaps' Index
  25.     IsIFrame: Boolean;
  26.     TCWhenCapture: Cardinal;
  27.   protected
  28.     Procedure CaptureScreen; Virtual;
  29.     procedure ScreenBitmap;
  30.     Procedure FrameStart;
  31.     Procedure FrameEnd;
  32.     procedure Execute; override;
  33.     property ScreenSpy: TScreenSpy read FScreenSpy write FScreenSpy;
  34.   public
  35.     constructor Create; reintroduce;
  36.     destructor Destroy; override;
  37.   end;
  38.   TScreenSpy = class(TComponent)
  39.   private
  40.     { Private declarations }
  41.     // Properties
  42.     FIFrame: Cardinal;
  43.     FActive: Boolean;
  44.     FThreadPriority: TThreadPriority;
  45.     FScreenCanvas: TCanvas;
  46.     FScreenWidth: Word;
  47.     FScreenHeight: Word;
  48.     FBytesPerPixel: Byte;
  49.     FPixelFormat: TPixelFormat;
  50.     FMaxFrameRate: Byte;
  51.     FMaxBlockSize: Integer;
  52.     FBlockRowCount: Integer;
  53.     FBlockColumnCount: Integer;
  54.     FBlockCount: Integer;
  55.     FBlockWidth: Integer;
  56.     FBlockHeight: Integer;
  57.     FBlockSize: Integer;
  58.     FBlockBound: TRect; // Block size = (0, 0, BWidth, BHeight)
  59.     FFrameCount: Cardinal;
  60.     // Events
  61.     FOnScreenBitmap: TScreenSpyBitmapEvent;
  62.     FOnFrameStart: TFrameStartEvent;
  63.     FOnFrameEnd: TFrameEndEvent;
  64.     // Golbal private Variables
  65.     HasBitmapEvent: Boolean;
  66.     MaxDelayMilliseconds: Cardinal;
  67.     ScreenBitmaps: array of TScreenBlock;
  68.     LastScreen: array of Pointer;
  69.     BMPBlockSize: Integer; // Size of Bitmap for one block
  70.     MemoryAllowcated: Boolean;
  71.     SCThread: TScreenSpyThread;
  72.     Procedure SetActive(const Value: Boolean);
  73.     Procedure SetThreadPriority(const Value: TThreadPriority);
  74.     Procedure SetMaxBlockSize(const Value: Integer);
  75.     Procedure SetMaxFrameRate(const Value: Byte);
  76.     Procedure SetIFrame(const Value: Cardinal);
  77.   protected
  78.     { Protected declarations }
  79.     procedure CalculateScreenData;
  80.     procedure ReleaseScreenData;
  81.     procedure DoScreenBitmap(ScreenBitmapIndex: Integer; IsIFrame: Boolean);
  82.     procedure DoFrameStart(const IsIFrame: Boolean);
  83.     procedure DoFrameEnd(const IsIFrame: Boolean);
  84.   public
  85.     { Public declarations }
  86.     Constructor Create(AOwner: TComponent); override;
  87.     Destructor Destroy; override;
  88.     Property ScreenCanvas: TCanvas read FScreenCanvas;
  89.     Property ScreenWidth: Word read FScreenWidth;
  90.     Property ScreenHeight: Word read FScreenHeight;
  91.     Property BytesPerPixel: Byte read FBytesPerPixel;
  92.     Property PixelFormat: TPixelFormat read FPixelFormat;
  93.     Property BlockCount: Integer read FBlockCount;
  94.     Property BlockRowCount: Integer read FBlockRowCount;
  95.     Property BlockColumnCount: Integer read FBlockColumnCount;
  96.     Property BlockWidth: Integer read FBlockWidth;
  97.     Property BlockHeight: Integer read FBlockHeight;
  98.     Property BlockSize: Integer read FBlockSize;
  99.     Property BlockBound: TRect read FBlockBound;
  100.     Property FrameCount: Cardinal read FFrameCount;
  101.   published
  102.     { Published declarations }
  103.     Property OnScreenBitmap: TScreenSpyBitmapEvent read FOnScreenBitmap write FOnScreenBitmap;
  104.     Property OnFrameStart: TFrameStartEvent read FOnFrameStart write FOnFrameStart;
  105.     Property OnFrameEnd: TFrameEndEvent read FOnFrameEnd write FOnFrameEnd;
  106.     Property IFrame: Cardinal read FIFrame write SetIFrame default 30;
  107.     Property ThreadPriority: TThreadPriority read FThreadPriority write SetThreadPriority default tpNormal;
  108.     Property MaxBlockSize: Integer read FMaxBlockSize write SetMaxBlockSize default 30000;
  109.     Property MaxFrameRate: Byte read FMaxFrameRate write SetMaxFrameRate default 10;
  110.     Property Active : Boolean read FActive write SetActive default False;
  111.   end;
  112.   TSFastRLE = class(TObject)
  113.   private
  114.     t, s: Pointer;
  115.     function PackSeg(Source, Target: Pointer; SourceSize: Word): Word;
  116.     function UnPackSeg(Source, Target: Pointer; SourceSize: Word): Word;
  117.   protected
  118.   public
  119.     Constructor Create;
  120.     Destructor Destroy; override;
  121.     function Pack(Source, Target: Pointer; SourceSize: LongInt): LongInt; { Return TargetSize }
  122.     function UnPack(Source, Target: Pointer; SourceSize: LongInt): LongInt; {Return TargetSize }
  123.     function PackString(Source: String): String;
  124.     function UnPackString(Source: String): String;
  125.     function PackFile(SourceFileName, TargetFileName: String): Boolean; { Return FALSE if IOError }
  126.     function UnPackFile(SourceFileName, TargetFileName: String): Boolean; { Return FALSE if IOError }
  127.   end;
  128. { Protocol }
  129. Const
  130.   RID_Invalid    = $00;
  131.   RID_Header     = $02;
  132.   RID_Block      = $04;
  133.   RID_FrameStart = $06;
  134.   RID_FrameEnd   = $08;
  135.   RID_MousePos   = $0A;
  136.   RID_Start      = $0C;
  137.   RID_Stop       = $0E;
  138. type
  139.   TRID = Word;
  140.   TRSize = Cardinal;
  141.   TScreenDataStyle = (sdsUncompress, sdsRLENormal, sdsRLEXor);
  142. Type // Data type for transmission pack
  143.   TftAny= Packed Record
  144.     dwSize: TRSize;
  145.     PackID : TRID;
  146.     Data: Array [0..0] of Byte;
  147.   End;
  148.   PftAny= ^TftAny;
  149.   TftHeader= Packed Record
  150.     dwSize: TRSize;
  151.     PackID : TRID;
  152.     ScreenWidth: Word;
  153.     ScreenHeight: Word;
  154.     BytesPerPixel: Byte;
  155.     BlockWidth: Word;
  156.     BlockHeight: Word;
  157.   End;
  158.   PftHeader = ^TftHeader;
  159.   TftBlock = Packed Record
  160.     dwSize: TRSize;
  161.     PackID: TRID;
  162.     BlockIndex: Cardinal;
  163.     FrameStyle: TScreenDataStyle;
  164.     Data: Array [0..0] of Byte;
  165.   End;
  166.   PftBlock = ^TftBlock;
  167.   TftFrameStart = Packed Record
  168.     dwSize: TRSize;
  169.     PackID: TRID;
  170.     FrameCount: Cardinal;
  171.     IsIFrame: Boolean;
  172.   End;
  173.   PftFrameStart = ^TftFrameStart;
  174.   TftFrameEnd = Packed Record
  175.     dwSize: TRSize;
  176.     PackID: TRID;
  177.     FrameCount: Cardinal;
  178.     IsIFrame: Boolean;
  179.     HasBitmapEvent: Boolean;
  180.   End;
  181.   PftFrameEnd = ^TftFrameEnd;
  182. Const
  183.   SizeOfTftBlock = SizeOf(TftBlock);
  184.   SizeOfTftHeader = SizeOf(TftHeader);
  185.   SizeOfTftFrameStart = SizeOf(TftFrameStart);
  186.   SizeOfTftFrameEnd = SizeOf(TftFrameEnd);
  187. { TScreen Transfer}
  188. Type
  189.   TScreenEncoder = class(TComponent)
  190.   private
  191.     { Private declarations }
  192.     // Properties
  193.     FActive : Boolean;
  194.     FBlockDelay : Cardinal;
  195.     FBlockInterval: Cardinal;
  196.     FIFrameDelay: Cardinal;
  197.     // Events
  198.     FOnFrameStart: TFrameStartEvent;
  199.     FOnFrameEnd: TFrameEndEvent;
  200.     // Golbal variables
  201.     FScreenSpy : TScreenSpy;
  202.     FUDPSender : TUDPSender;
  203.     FSFastRLE : TSFastRLE;
  204.     XorDataPtr: array [1..4] of Pointer; // MAX 4 bytes per pixel
  205.     RHeader : TftHeader;
  206.     RFrameStart: TftFrameStart;
  207.     RFrameEnd: TftFrameEnd;
  208.     Blockptr: PftBlock;
  209.     BlockIntervalCount: Cardinal;
  210.     function GetIFrame: Cardinal;
  211.     function GetMaxBlockSize: Integer;
  212.     function GetMaxFrameRate: Byte;
  213.     function GetThreadPriority: TThreadPriority;
  214.     procedure SetActive(Value: Boolean);
  215.     procedure SetIFrame(const Value: Cardinal);
  216.     procedure SetMaxBlockSize(const Value: Integer);
  217.     procedure SetMaxFrameRate(const Value: Byte);
  218.     procedure SetThreadPriority(const Value: TThreadPriority);
  219.     function GetRemoteHost: String;
  220.     function GetRemoteIP: String;
  221.     function GetRemotePort: Word;
  222.     procedure SetRemoteHost(const Value: String);
  223.     procedure SetRemoteIP(const Value: String);
  224.     procedure SetRemotePort(const Value: Word);
  225.     procedure SetBlockDelay(const Value: Cardinal);
  226.     procedure SetBlockInterval(const Value: Cardinal);
  227.     procedure SetIFrameDelay(const Value: Cardinal);
  228.   protected
  229.     { Protected declarations }
  230.     procedure ScreenSpyOnScreenBitmap(Sender: TObject; const Block: TScreenBlock; LastScanline: Pointer; IsIFrame: Boolean);
  231.     procedure ScreenSpyOnFrameStart(Sender: TObject; const FrameCount: Cardinal; const IsIFrame: Boolean);
  232.     procedure ScreenSpyOnFrameEnd(Sender: TObject; const FrameCount: Cardinal; const IsIFrame: Boolean; const HasBitmapEvent: Boolean);
  233.     Procedure SendHeader;
  234.     procedure DoFrameStart(const FrameCount: Cardinal; const IsIFrame: Boolean); virtual;
  235.     procedure DoFrameEnd(const FrameCount: Cardinal; const IsIFrame: Boolean; const HasBitmapEvent: Boolean); virtual;
  236.   public
  237.     { Public declarations }
  238.     Constructor Create(AOwner: TComponent); override;
  239.     Destructor Destroy; override;
  240.   published
  241.     { Published declarations }
  242.     Property OnFrameStart: TFrameStartEvent read FOnFrameStart write FOnFrameStart;
  243.     Property OnFrameEnd: TFrameEndEvent read FOnFrameEnd write FOnFrameEnd;
  244.     Property BlockInterval: Cardinal read FBlockInterval write SetBlockInterval default 10;
  245.     Property BlockDelay: Cardinal read FBlockDelay write SetBlockDelay default 1;
  246.     Property IFrameDelay: Cardinal read FIFrameDelay write SetIFrameDelay default 100;
  247.     Property IFrame: Cardinal read GetIFrame write SetIFrame;
  248.     Property ThreadPriority: TThreadPriority read GetThreadPriority write SetThreadPriority;
  249.     Property MaxBlockSize: Integer read GetMaxBlockSize write SetMaxBlockSize;
  250.     Property MaxFrameRate: Byte read GetMaxFrameRate write SetMaxFrameRate;
  251.     property RemoteIP: String read GetRemoteIP write SetRemoteIP;
  252.     property RemoteHost: String read GetRemoteHost write SetRemoteHost;
  253.     property RemotePort: Word read GetRemotePort write SetRemotePort;
  254.     Property Active : Boolean read FActive write SetActive default False;
  255.   end;
  256.   TScreenPlayerBitmapEvent = procedure(Sender: TObject; const Block: TScreenBlock) of object;
  257.   TScreenPlayer = class(TComponent)
  258.   private
  259.     { Private declarations }
  260.     // Properties
  261.     FScreenWidth: Word;
  262.     FScreenHeight: Word;
  263.     FBytesPerPixel: Byte;
  264.     FPixelFormat: TPixelFormat;
  265.     FBlockRowCount: Integer;
  266.     FBlockColumnCount: Integer;
  267.     FBlockCount: Integer;
  268.     FBlockWidth: Integer;
  269.     FBlockHeight: Integer;
  270.     FBlockSize: Integer;
  271.     // Events
  272.     FOnScreenBitmap: TScreenPlayerBitmapEvent;
  273.     FOnHeaderUpdate: TNotifyEvent;
  274.     FOnFrameEnd: TFrameEndEvent;
  275.     FOnFrameStart: TFrameStartEvent;
  276.     // Golbal Variables
  277.     FUDPReceiver : TUDPReceiver;
  278.     FSFastRLE : TSFastRLE;
  279.     XorDataPtr: array [1..4] of Pointer; // MAX 4 bytes per pixel
  280.     ScreenBitmaps: array of TScreenBlock;
  281.     BMPBlockSize: Integer; // Size of Bitmap for one block
  282.     MemoryAllowcated: Boolean;
  283.     Header: TftHeader;
  284.     AnyPtr: PftAny;
  285.     BlockPtr: PftBlock;
  286.     FrameStartPtr: PftFrameStart;
  287.     FrameEndPtr: PftFrameEnd;
  288.     function GetActive: Boolean;
  289.     function GetMulticastIP: String;
  290.     function GetPort: Word;
  291.     procedure SetActive(const Value: Boolean);
  292.     procedure SetMulticastIP(const Value: String);
  293.     procedure SetPort(const Value: Word);
  294.   protected
  295.     { Protected declarations }
  296.     procedure CalculateScreenData; virtual;
  297.     procedure ReleaseScreenData; virtual;
  298.     procedure DoScreenBitmap(ScreenBitmapIndex: Integer); virtual;
  299.     procedure DoHeaderUpdate;
  300.     procedure UDPReceiverOnUDPData(Sender: TObject; const Buffer: Pointer; const RecvSize:Integer; const Peer: string; const Port: Integer); virtual;
  301.   public
  302.     { Public declarations }
  303.     Constructor Create(AOwner: TComponent); override;
  304.     Destructor Destroy; override;
  305.     Property ScreenWidth: Word read FScreenWidth;
  306.     Property ScreenHeight: Word read FScreenHeight;
  307.     Property BytesPerPixel: Byte read FBytesPerPixel;
  308.     Property PixelFormat: TPixelFormat read FPixelFormat;
  309.     Property BlockCount: Integer read FBlockCount;
  310.     Property BlockRowCount: Integer read FBlockRowCount;
  311.     Property BlockColumnCount: Integer read FBlockColumnCount;
  312.     Property BlockWidth: Integer read FBlockWidth;
  313.     Property BlockHeight: Integer read FBlockHeight;
  314.     Property BlockSize: Integer read FBlockSize;
  315.   published
  316.     { Published declarations }
  317.     Property OnScreenBitmap: TScreenPlayerBitmapEvent read FOnScreenBitmap write FOnScreenBitmap;
  318.     Property OnHeaderUpdate: TNotifyEvent read FOnHeaderUpdate write FOnHeaderUpdate;
  319.     Property OnFrameStart: TFrameStartEvent read FOnFrameStart write FOnFrameStart;
  320.     Property OnFrameEnd: TFrameEndEvent read FOnFrameEnd write FOnFrameEnd;
  321.     property Port: Word read GetPort write SetPort;
  322.     property MulticastIP: String read GetMulticastIP write SetMulticastIP;
  323.     property Active: Boolean read GetActive write SetActive default False;
  324.   end;
  325. procedure Register;
  326. resourcestring
  327.   ESSACTIVED = 'Connot perform this action while component is in active!';
  328.   ESSINVALIDVALUE = 'Invalid value assigned!';
  329. implementation
  330. procedure Register;
  331. begin
  332.   RegisterComponents('Samples', [TScreenSpy, TScreenEncoder, TScreenPlayer]);
  333. end;
  334. { TScreenSpy }
  335. procedure TScreenSpy.CalculateScreenData;
  336.   //  e.g.: ANumber = 800, MaxRoot = 21; Result = 20 (800 mod 20=0)
  337.   Function MultiRoot(ANumber, MaxRoot: Cardinal): Cardinal;
  338.   Begin
  339.     If MaxRoot>0 then
  340.       While (ANumber mod MaxRoot)<>0 do
  341.         MaxRoot:= MaxRoot-1;
  342.     Result:= MaxRoot;
  343.   End;
  344.   //  e.g.: ANumber = 800, MinRoot=20, MaxRoot = 41; Result = 40 (800 mod 40=0)
  345.   Function MaxRootOf(ANumber, MinRoot, MaxRoot: Cardinal): Cardinal;
  346.   Begin
  347.     If (MaxRoot>0) and (MinRoot>0) then
  348.       While ((ANumber mod MaxRoot)<>0) and (MaxRoot>=MinRoot) do
  349.         MaxRoot:= MaxRoot-1;
  350.     If MaxRoot>=MinRoot then
  351.       Result:= MaxRoot
  352.     Else
  353.       Result:= 0; // not found
  354.   End;
  355. Var
  356.   i: Integer;
  357.   BitsPerPixel: Integer;
  358. begin
  359.   If MemoryAllowcated then
  360.     ReleaseScreenData;
  361.   MemoryAllowcated:= True;
  362. // Find system information for screen
  363.   // Get ready to capture screen
  364.   FScreenCanvas.Handle:= GetDC(0);
  365.   // Get All information about screen
  366.   FScreenWidth:= Screen.Width;
  367.   FScreenHeight:= Screen.Height;
  368.   BitsPerPixel := GetDeviceCaps(ScreenCanvas.Handle, BITSPIXEL);
  369.   Case BitsPerPixel of
  370.     8 :
  371.       Begin
  372.         FBytesPerPixel:= 1;
  373.         FPixelFormat:= pf8bit;
  374.       End;
  375.     16:
  376.       Begin
  377.         FBytesPerPixel:= 2;
  378.         FPixelFormat:= pf16bit;
  379.       End;
  380.     24:
  381.       Begin
  382.         FBytesPerPixel:= 3;
  383.         FPixelFormat:= pf24bit;
  384.       End;
  385.     32:
  386.       Begin
  387.         FBytesPerPixel:= 4;
  388.         FPixelFormat:= pf32bit;
  389.       End;
  390.     Else
  391.       Begin
  392.         FBytesPerPixel:= 3;
  393.         FPixelFormat:= pf24bit;
  394.       End;
  395.   End;{CASE}
  396. // Calculate Block information
  397.   // Max block area for avaliable block size
  398.   i:= FMaxBlockSize div FBytesPerPixel;
  399.   FBlockHeight:= Trunc(sqrt(i));
  400.   FBlockHeight:= MultiRoot(ScreenHeight, FBlockHeight);
  401.   FBlockWidth:= i div FBlockHeight;
  402.   FBlockWidth:= MultiRoot(ScreenWidth, FBlockWidth);
  403.   FBlockHeight:= MaxRootOf(ScreenHeight, FBlockHeight, i div FBlockWidth);
  404.   FBlockSize:= BlockWidth * FBlockHeight;
  405.   BMPBlockSize := BlockSize * BytesPerPixel;
  406.   FBlockColumnCount:= FScreenWidth div FBlockWidth;
  407.   FBlockRowCount:= FScreenHeight div FBlockHeight;
  408.   FBlockCount:= FBlockColumnCount * FBlockRowCount;
  409. // Re-Allocate memory
  410.   // Create off-screen memory for store last screen
  411.   SetLength(LastScreen, BlockCount);
  412.   For i:=0 to BlockCount-1 do
  413.   Begin
  414.     GetMem(LastScreen[i], BMPBlockSize);
  415.     FillChar(LastScreen[i]^, BMPBlockSize, $0);
  416.   End;
  417.   // Get buffer for send-data
  418.   // GetMem(ScreenBlockPtr, SizeOf(TScreenBlock)+BMPBlockSize+8);
  419.   //ScreenBlockPtr^.UNID:= 0; // In fact it is a user defined value
  420.   //ScreenBlockDataPtr:= @(ScreenBlockPtr^.Data[0]); // Why use it?
  421.   FBlockBound:= Rect(0, 0, FBlockWidth, FBlockHeight);
  422.   // Create temp bitmap for copy a pice of desktop image
  423.   SetLength(ScreenBitmaps, BlockCount);
  424.   For i:=0 to BlockCount-1 do
  425.   Begin
  426.     ScreenBitmaps[i].BlockIndex:= i;
  427.     ScreenBitmaps[i].Bound:= Rect(0,0,BlockWidth,BlockHeight);
  428.     OffsetRect(ScreenBitmaps[i].Bound, (i mod FBlockColumnCount) * FBlockWidth, (i div FBlockColumnCount) * FBlockHeight);
  429.     {ScreenBitmaps[i].Bound:= Rect((i mod BlockWidth) * BMPBlockWidth, (i div BlockWidth) * BMPBlockHeight,
  430.                                   (i mod BlockWidth) * BMPBlockWidth + BMPBlockWidth, (i div BlockWidth) * BMPBlockHeight + BMPBlockHeight);{}
  431.     ScreenBitmaps[i].BMP:= TBitmap.Create;
  432.     With ScreenBitmaps[i].BMP do
  433.     Begin
  434.       Width:= BlockWidth;
  435.       Height:= BlockHeight;
  436.       PixelFormat:= FPixelFormat;
  437.       If Cardinal(ScanLine[0])<Cardinal(ScanLine[1]) then
  438.         ScreenBitmaps[i].ptr:= ScanLine[0]
  439.       Else
  440.         ScreenBitmaps[i].ptr:= ScanLine[Height-1];
  441.     End;
  442.   End;
  443. end;
  444. constructor TScreenSpy.Create(AOwner: TComponent);
  445. begin
  446.   inherited;
  447.   // Init default properties
  448.   FMaxBlockSize := 30000;
  449.   FMaxFrameRate := 0;
  450.   MaxFrameRate := 10;
  451.   FIFrame := 30;
  452.   FActive:= False;
  453.   FThreadPriority:= tpNormal;
  454.   FScreenCanvas:= TCanvas.Create;
  455.   // Calculate information of screen
  456.   MemoryAllowcated:= False;
  457.   if not (csLoading in ComponentState) and not (csDesigning in ComponentState) then
  458.     CalculateScreenData;
  459. end;
  460. destructor TScreenSpy.Destroy;
  461. begin
  462.   Active:= False;
  463.   ReleaseScreenData;
  464.   FScreenCanvas.Free;
  465.   inherited;
  466. end;
  467. procedure TScreenSpy.DoFrameEnd(const IsIFrame: Boolean);
  468. begin
  469.   If Assigned(FOnFrameEnd) then
  470.     FOnFrameEnd(Self, FrameCount, IsIFrame, HasBitmapEvent);
  471. end;
  472. procedure TScreenSpy.DoFrameStart(const IsIFrame: Boolean);
  473. begin
  474.   If Assigned(FOnFrameStart) then
  475.     FOnFrameStart(Self, FrameCount, IsIFrame);
  476. end;
  477. procedure TScreenSpy.DoScreenBitmap(ScreenBitmapIndex: Integer;
  478.   IsIFrame: Boolean);
  479. begin
  480.   If Assigned(FOnScreenBitmap) then
  481.   try
  482.     FOnScreenBitmap(Self, ScreenBitmaps[ScreenBitmapIndex], LastScreen[ScreenBitmapIndex], IsIFrame);
  483.   except
  484.     FOnScreenBitmap:= nil;
  485.   end;
  486. end;
  487. procedure TScreenSpy.ReleaseScreenData;
  488. Var
  489.   i: Integer;
  490. begin
  491.   If MemoryAllowcated then
  492.   Begin
  493.     If FActive then
  494.       Raise EScrSpy.CreateRes(@ESSACTIVED);
  495.     MemoryAllowcated:= False;
  496.     // Do release
  497.     ReleaseDC(0, FScreenCanvas.Handle);
  498.     For i:=0 to BlockCount-1 do
  499.       FreeMem(LastScreen[i]);
  500.     SetLength(LastScreen, 0);
  501.     For i:=0 to BlockCount-1 do
  502.     Begin
  503.       ScreenBitmaps[i].ptr:= nil;
  504.       ScreenBitmaps[i].BMP.Free;
  505.     End;
  506.     SetLength(ScreenBitmaps, 0);
  507.   End;
  508. end;
  509. procedure TScreenSpy.SetActive(const Value: Boolean);
  510. begin
  511.   If FActive<>Value then
  512.   Begin
  513.     FActive:= Value;
  514.     If Not (csDesigning in ComponentState) then
  515.     Begin
  516.       If Value then
  517.       Begin
  518.         If Not MemoryAllowcated then
  519.           CalculateScreenData;
  520.         {// Init for new Frame
  521.         FFrameCount:= 0;
  522.         HasBitmapEvent:= False;{}
  523.         SCThread:= TScreenSpyThread.Create;
  524.         With SCThread do
  525.         Begin
  526.           ScreenSpy:= Self;
  527.           Priority:= FThreadPriority;
  528.           FreeOnTerminate:= True;
  529.           Resume;
  530.         End;{}
  531.       End Else
  532.       Begin
  533.         SCThread.Terminate;
  534.         SCThread.WaitFor;
  535.         //FSCThread:= nil;{}
  536.       End;
  537.     End;
  538.   End;
  539. end;
  540. procedure TScreenSpy.SetIFrame(const Value: Cardinal);
  541. begin
  542.   If FIFrame<>Value then
  543.   Begin
  544.     if not (csLoading in ComponentState) and not (csDesigning in ComponentState) and
  545.        FActive then
  546.       Raise EScrSpy.CreateRes(@ESSACTIVED);
  547.     If Value = 0 then
  548.       Raise EScrSpy.CreateRes(@ESSINVALIDVALUE);
  549.     FIFrame:= Value;
  550.   End;
  551. end;
  552. procedure TScreenSpy.SetMaxBlockSize(const Value: Integer);
  553. begin
  554.   If FMaxBlockSize<>Value then
  555.   Begin
  556.     if not (csLoading in ComponentState) and not (csDesigning in ComponentState) and
  557.        FActive then
  558.       Raise EScrSpy.CreateRes(@ESSACTIVED);
  559.     FMaxBlockSize:= Value;
  560.     if not (csLoading in ComponentState) and not (csDesigning in ComponentState) then
  561.       CalculateScreenData;
  562.   End;
  563. end;
  564. procedure TScreenSpy.SetMaxFrameRate(const Value: Byte);
  565. begin
  566.   If FMaxFrameRate<>Value then
  567.   Begin
  568.     if not (csLoading in ComponentState) and not (csDesigning in ComponentState) and
  569.        FActive then
  570.       Raise EScrSpy.CreateRes(@ESSACTIVED);
  571.     If Value = 0 then
  572.       Raise EScrSpy.CreateRes(@ESSINVALIDVALUE);
  573.     FMaxFrameRate:= Value;
  574.     MaxDelayMilliseconds:= 1000 div FMaxFrameRate;
  575.   End;
  576. end;
  577. procedure TScreenSpy.SetThreadPriority(const Value: TThreadPriority);
  578. begin
  579.   If FThreadPriority<>Value then
  580.   Begin
  581.     if not (csLoading in ComponentState) and not (csDesigning in ComponentState) and
  582.        FActive then
  583.       Raise EScrSpy.CreateRes(@ESSACTIVED);
  584.     FThreadPriority := Value;
  585.   End;
  586. end;
  587. { TScreenSpyThread }
  588. procedure TScreenSpyThread.CaptureScreen;
  589. Var
  590.   i: Integer;
  591. Begin
  592.   TCWhenCapture:= GetTickCount;
  593.   With FScreenSpy do
  594.   Begin
  595.     FFrameCount:= FFrameCount + 1;
  596.     For i:=0 to BlockCount-1 do
  597.       With ScreenBitmaps[i] do
  598.         If BMP.Canvas.TryLock then
  599.         try
  600.           BMP.Canvas.CopyRect(BlockBound, ScreenCanvas, Bound);
  601.         finally
  602.           BMP.Canvas.Unlock;
  603.         end;
  604.   End;
  605. end;
  606. constructor TScreenSpyThread.Create;
  607. begin
  608.   Inherited Create(True);
  609. end;
  610. destructor TScreenSpyThread.Destroy;
  611. begin
  612.   inherited;
  613. end;
  614. procedure TScreenSpyThread.Execute;
  615. Var
  616. //  BlockSame: Boolean;
  617.   TickCountLag: Integer;
  618. begin
  619.   With FScreenSpy do
  620.   Begin
  621.     SBIndex:= 0;
  622.     IsIFrame:= True; // For Hide Complie message
  623.     FFrameCount:= 0;
  624.     // Init TickCounts
  625.     TCWhenCapture:= 0;
  626.     While FScreenSpy.Active and Not Terminated do
  627.     Begin
  628.       If SBIndex=0 then
  629.       Begin
  630.         IsIFrame:= (FFrameCount mod FIFrame)=0;
  631.         // Delay for MaxFrameRate!
  632.         TickCountLag:= MaxDelayMilliseconds- (GetTickCount-TCWhenCapture);
  633.         If TickCountLag>0 then
  634.           Sleep(TickCountLag);
  635.         Synchronize(CaptureScreen);
  636.         Synchronize(FrameStart);
  637.       End;
  638.       If IsIFrame or Not CompareMem(ScreenBitmaps[SBIndex].ptr, LastScreen[SBIndex], BMPBlockSize) then
  639.       {If IsIFrame then
  640.         BlockSame:= False
  641.       Else
  642.         BlockSame:= CompareMem(ScreenBitmaps[SBIndex].ptr, LastScreen[SBIndex], BMPBlockSize);
  643.       If Not BlockSame then{}
  644.       Begin
  645.         Synchronize(ScreenBitmap);
  646.         Move(ScreenBitmaps[SBIndex].ptr^, LastScreen[SBIndex]^, BMPBlockSize);
  647.       End;
  648.       SBIndex:= (SBIndex + 1) mod BlockCount;
  649.       If (SBIndex=0) then
  650.         Synchronize(FrameEnd);
  651.     End;
  652.   End;
  653. end;
  654. procedure TScreenSpyThread.FrameEnd;
  655. begin
  656.   FScreenSpy.DoFrameEnd(IsIFrame);
  657. end;
  658. procedure TScreenSpyThread.FrameStart;
  659. begin
  660.   FScreenSpy.HasBitmapEvent:= False;
  661.   FScreenSpy.DoFrameStart(IsIFrame);
  662. end;
  663. procedure TScreenSpyThread.ScreenBitmap;
  664. begin
  665.   FScreenSpy.DoScreenBitmap(SBIndex, IsIFrame);
  666.   FScreenSpy.HasBitmapEvent:= True;
  667. end;
  668. { TRLE }
  669. Type
  670.   LongType = record
  671.     case Word of
  672.       0: (Ptr: Pointer);
  673.       1: (Long: LongInt);
  674.       2: (Lo: Word;
  675.   Hi: Word);
  676.   end;
  677. constructor TSFastRLE.Create;
  678. begin
  679.   inherited;
  680.   GetMem(s, $FFFF);
  681.   GetMem(t, $FFFF);
  682. end;
  683. destructor TSFastRLE.Destroy;
  684. begin
  685.   FreeMem(t);
  686.   FreeMem(s);
  687.   inherited;
  688. end;
  689. function TSFastRLE.PackSeg(Source, Target: Pointer; SourceSize: Word): Word;
  690. begin
  691.   asm
  692.         push    esi
  693.         push    edi
  694.         push    eax
  695.         push    ebx
  696.         push    ecx
  697.         push    edx
  698. cld
  699.         xor     ecx, ecx
  700. mov cx, SourceSize
  701. mov edi, Target
  702. mov esi, Source
  703. add esi, ecx
  704. dec esi
  705. lodsb
  706. inc eax
  707. mov [esi], al
  708. mov ebx, edi
  709.         add     ebx, ecx
  710. inc ebx
  711. mov esi, Source
  712.         add     ecx, esi
  713. add edi, 2
  714. @CyclePack:
  715. cmp ecx, esi
  716. je @Konec
  717. lodsw
  718. stosb
  719. dec esi
  720. cmp al, ah
  721. jne @CyclePack
  722. cmp ax, [esi+1]
  723. jne @CyclePack
  724. cmp al, [esi+3]
  725. jne @CyclePack
  726. sub ebx, 2
  727.         push    edi
  728.         sub     edi, Target
  729. mov [ebx], di
  730.         pop     edi
  731. mov edx, esi
  732. add esi, 3
  733. @Nimnul:
  734. inc esi
  735. cmp al, [esi]
  736. je @Nimnul
  737. mov eax, esi
  738. sub eax, edx
  739. or ah, ah
  740. jz @M256
  741. mov byte ptr [edi], 0
  742. inc edi
  743. stosw
  744. jmp     @CyclePack
  745. @M256:
  746. stosb
  747. jmp     @CyclePack
  748. @Konec:
  749.         push    ebx
  750.         mov     ebx, Target
  751.         mov     eax, edi
  752.         sub     eax, ebx
  753. mov [ebx], ax
  754.         pop     ebx
  755. inc ecx
  756. cmp ebx, ecx
  757. je @Lock1
  758. mov esi, ebx
  759.         sub     ebx, Target
  760.         sub     ecx, Source
  761. sub ecx, ebx
  762. rep movsb
  763. @Lock1:
  764.         sub     edi, Target
  765. mov Result, di
  766.         pop     edx
  767.         pop     ecx
  768.         pop     ebx
  769.         pop     eax
  770.         pop     edi
  771.         pop     esi
  772.   end;
  773. end;
  774. function TSFastRLE.UnPackSeg(Source, Target: Pointer; SourceSize: Word): Word;
  775. begin
  776.   asm
  777.         push    esi
  778.         push    edi
  779.         push    eax
  780.         push    ebx
  781.         push    ecx
  782.         push    edx
  783. cld
  784. mov esi, Source
  785. mov edi, Target
  786.         mov     ebx, esi
  787.         xor     edx, edx
  788.         mov     dx, SourceSize
  789. add ebx, edx
  790. mov dx, word ptr [esi]
  791.         add     edx, esi
  792. add esi, 2
  793. @UnPackCycle:
  794. cmp edx, ebx
  795. je @Konec2
  796. sub ebx, 2
  797.         xor     ecx, ecx
  798. mov cx, word ptr [ebx]
  799.         add     ecx, Source
  800. sub ecx, esi
  801. dec ecx
  802. rep movsb
  803. lodsb
  804. mov cl, byte ptr [esi]
  805. inc esi
  806. or cl, cl
  807. jnz @Low1
  808.         xor     ecx, ecx
  809. mov cx, word ptr [esi]
  810. add esi, 2
  811. @Low1:
  812. inc ecx
  813. rep stosb
  814. jmp     @UnPackCycle
  815. @Konec2:
  816. mov ecx, edx
  817. sub ecx, esi
  818. rep movsb
  819.         sub     edi, Target
  820.         mov     Result, di
  821.         pop     edx
  822.         pop     ecx
  823.         pop     ebx
  824.         pop     eax
  825.         pop     edi
  826.         pop     esi
  827.   end;
  828. end;
  829. function TSFastRLE.Pack(Source, Target: Pointer; SourceSize: Integer): LongInt;
  830. var
  831.   w, tmp: Word;
  832.   Sourc, Targ: LongType;
  833. begin
  834. {  // Move
  835.   Move(Source^, Target^, SourceSize);
  836.   Result:= SourceSize;
  837.   Exit;{}
  838.   // RLE Compress
  839.   Sourc.Ptr := Source;
  840.   Targ.Ptr := Target;
  841.   Result := 0;
  842.   while SourceSize <> 0 do
  843.   begin
  844.     if SourceSize > $FFFA then tmp := $FFFA
  845.     else tmp := SourceSize;
  846.     dec(SourceSize, tmp);
  847.     move(Sourc.Ptr^, s^, tmp);
  848.     w := PackSeg(s, t, tmp);
  849.     inc(Sourc.Long, tmp);
  850.     Move(w, Targ.Ptr^, 2);
  851.     inc(Targ.Long, 2);
  852.     Move(t^, Targ.Ptr^, w);
  853.     inc(Targ.Long, w);
  854.     Result := Result + w + 2;
  855.   end;
  856. end;
  857. function TSFastRLE.PackFile(SourceFileName, TargetFileName: String): Boolean;
  858. var
  859.   Source, Target: Pointer;
  860.   SourceFile, TargetFile: File;
  861.   RequiredMaxSize, TargetFSize, FSize: LongInt;
  862. begin
  863.   AssignFile(SourceFile, SourceFileName);
  864.   Reset(SourceFile, 1);
  865.   FSize := FileSize(SourceFile);
  866.   RequiredMaxSize := FSize + (FSize div $FFFF + 1) * 2;
  867.   GetMem(Source, RequiredMaxSize);
  868.   GetMem(Target, RequiredMaxSize);
  869.   BlockRead(SourceFile, Source^, FSize);
  870.   CloseFile(SourceFile);
  871.   TargetFSize := Pack(Source, Target, FSize);
  872.   AssignFile(TargetFile, TargetFileName);
  873.   Rewrite(TargetFile, 1);
  874.   { Also, you may put header }
  875.   BlockWrite(TargetFile, FSize, SizeOf(FSize)); { Original file size (Only from 3.0) }
  876.   BlockWrite(TargetFile, Target^, TargetFSize);
  877.   CloseFile(TargetFile);
  878.   FreeMem(Target, RequiredMaxSize);
  879.   FreeMem(Source, RequiredMaxSize);
  880.   Result := IOResult = 0;
  881. end;
  882. function TSFastRLE.PackString(Source: String): String;
  883. var
  884.   PC, PC2: PChar;
  885.   SS, TS: Integer;
  886. begin
  887.   SS := Length(Source);
  888.   GetMem(PC, SS);
  889.   GetMem(PC2, SS + 8); // If line can't be packed its size can be longer
  890.   Move(Source[1], PC^, SS);
  891.   TS := Pack(PC, PC2, SS);
  892.   SetLength(Result, TS + 4);
  893.   Move(SS, Result[1], 4);
  894.   Move(PC2^, Result[5], TS);
  895.   FreeMem(PC2);
  896.   FreeMem(PC);
  897. end;
  898. function TSFastRLE.UnPack(Source, Target: Pointer;
  899.   SourceSize: Integer): LongInt;
  900. var
  901.   Increment, i: LongInt;
  902.   tmp: Word;
  903.   Swap: LongType;
  904. begin
  905. {  // Move
  906.   Move(Source^, Target^, SourceSize);
  907.   Result:= SourceSize;
  908.   Exit;{}
  909.   // RLE Decompress
  910.   Increment := 0;
  911.   Result := 0;
  912.   while SourceSize <> 0 do
  913.   begin
  914.     Swap.Ptr := Source;
  915.     inc(Swap.Long, Increment);
  916.     Move(Swap.Ptr^, tmp, 2);
  917.     inc(Swap.Long, 2);
  918.     dec(SourceSize, tmp + 2);
  919.     i := UnPackSeg(Swap.Ptr, t, tmp);
  920.     Swap.Ptr := Target;
  921.     inc(Swap.Long, Result);
  922.     inc(Result, i);
  923.     Move(t^, Swap.Ptr^, i);
  924.     inc(Increment, tmp + 2);
  925.   end;
  926. end;
  927. function TSFastRLE.UnPackFile(SourceFileName, TargetFileName: String): Boolean;
  928. var
  929.   Source, Target: Pointer;
  930.   SourceFile, TargetFile: File;
  931.   OriginalFileSize, FSize: LongInt;
  932. begin
  933.   AssignFile(SourceFile, SourceFileName);
  934.   Reset(SourceFile, 1);
  935.   FSize := FileSize(SourceFile) - SizeOf(OriginalFileSize);
  936.   { Read header ? }
  937.   BlockRead(SourceFile, OriginalFileSize, SizeOf(OriginalFileSize));
  938.   GetMem(Source, FSize);
  939.   GetMem(Target, OriginalFileSize);
  940.   BlockRead(SourceFile, Source^, FSize);
  941.   CloseFile(SourceFile);
  942.   UnPack(Source, Target, FSize);
  943.   AssignFile(TargetFile, TargetFileName);
  944.   Rewrite(TargetFile, 1);
  945.   BlockWrite(TargetFile, Target^, OriginalFileSize);
  946.   CloseFile(TargetFile);
  947.   FreeMem(Target, OriginalFileSize);
  948.   FreeMem(Source, FSize);
  949.   Result := IOResult = 0;
  950. end;
  951. function TSFastRLE.UnPackString(Source: String): String;
  952. var
  953.   PC, PC2: PChar;
  954.   SS, TS: Integer;
  955. begin
  956.   SS := Length(Source) - 4;
  957.   GetMem(PC, SS);
  958.   Move(Source[1], TS, 4);
  959.   GetMem(PC2, TS);
  960.   Move(Source[5], PC^, SS);
  961.   TS := UnPack(PC, PC2, SS);
  962.   SetLength(Result, TS);
  963.   Move(PC2^, Result[1], TS);
  964.   FreeMem(PC2);
  965.   FreeMem(PC);
  966. end;
  967. { TScreenEncoder }
  968. constructor TScreenEncoder.Create(AOwner: TComponent);
  969. begin
  970.   inherited;
  971. // default properties value
  972.   FActive:= False;
  973.   FBlockInterval:= 1;
  974.   FBlockDelay:= 1;
  975.   FIFrameDelay:= 100;
  976. // Create aggerated components
  977.   FSFastRLE:= TSFastRLE.Create;
  978.   FUDPSender:= TUDPSender.Create(Self);
  979.   FScreenSpy:= TScreenSpy.Create(Self);
  980.   FScreenSpy.OnScreenBitmap:= ScreenSpyOnScreenBitmap;
  981.   FScreenSpy.OnFrameStart:= ScreenSpyOnFrameStart;
  982.   FScreenSpy.OnFrameEnd:= ScreenSpyOnFrameEnd;
  983. // default golbal value
  984.   {Records}
  985.   With RHeader do
  986.   Begin
  987.     dwSize:= SizeOfTftHeader;
  988.     PackID:= RID_Header;
  989.   End;
  990.   With RFrameStart do
  991.   Begin
  992.     dwSize:= SizeOfTftFrameStart;
  993.     PackID:= RID_FrameStart;
  994.   End;
  995.   With RFrameEnd do
  996.   Begin
  997.     dwSize:= SizeOfTftFrameEnd;
  998.     PackID:= RID_FrameEnd;
  999.   End;
  1000.   {Block}
  1001.   Blockptr:= nil;
  1002.   XorDataPtr[1]:= nil;
  1003.   MaxBlockSize:= FScreenSpy.MaxBlockSize;
  1004. end;
  1005. destructor TScreenEncoder.Destroy;
  1006. begin
  1007.   Active:= False;
  1008.   FScreenSpy.Free;
  1009.   FUDPSender.Free;
  1010.   FSFastRLE.Free;
  1011.   // Free golbal pointers
  1012.     If Assigned(Blockptr) then
  1013.       FreeMem(Blockptr);
  1014.     If Assigned(XorDataPtr[1]) then
  1015.       FreeMem(XorDataPtr[1]);
  1016.   inherited;
  1017. end;
  1018. procedure TScreenEncoder.ScreenSpyOnScreenBitmap(Sender: TObject;
  1019.   const Block: TScreenBlock; LastScanline: Pointer; IsIFrame: Boolean);
  1020. Var
  1021.   i, l: Integer;
  1022.   PackedSize: Integer;
  1023.   ptrNow, ptrLast: ^Byte;
  1024.   ptrXOR: array [1..4] of ^Byte; // Max 4 bytes per pixel
  1025. begin
  1026.   If IsIFrame then
  1027.   Begin // Send IFrame
  1028.     With Blockptr^ do
  1029.     Begin
  1030.       BlockIndex:= Block.BlockIndex;
  1031.       FrameStyle:= sdsRLENormal;
  1032.       //Compress
  1033.       PackedSize:= FSFastRLE.Pack(Block.ptr, @(Blockptr^.Data[0]), FScreenSpy.BMPBlockSize);
  1034.       If PackedSize>0 then
  1035.       Begin
  1036.         dwSize:= SizeofTftBlock-1+PackedSize;
  1037.         FUDPSender.SendBuf(Blockptr^, Blockptr^.dwSize);
  1038.         // Delay when Interval
  1039.         BlockIntervalCount:= (BlockIntervalCount+1) mod FBlockInterval;
  1040.         If BlockIntervalCount=0 then
  1041.           Sleep(FBlockDelay);
  1042.       End;
  1043.     End;
  1044.   End Else
  1045.   Begin // Send NON IFrame
  1046.     With FScreenSpy, Blockptr^ do
  1047.     Begin
  1048.       { Init Packet values }
  1049.       BlockIndex:= Block.BlockIndex;
  1050.       FrameStyle:= sdsRLEXor;
  1051.       { Xor }
  1052.       ptrNow:= Block.ptr;
  1053.       ptrLast:= LastScanLine;
  1054.       For i:=1 to BytesPerPixel do
  1055.         ptrXOR[i]:= XorDataPtr[i];
  1056.       For i:=1 to BlockSize do
  1057.       Begin
  1058.         // Move (R, G, B) to each area if (24bits), for better RLE compression.
  1059.         For l:=1 to BytesPerPixel do
  1060.         Begin
  1061.           ptrXOR[l]^:= ptrNow^ xor ptrLast^;   // XOR
  1062.           Inc(ptrNow);
  1063.           Inc(ptrLast);
  1064.           Inc(ptrXOR[l]);
  1065.         End;
  1066.       End;
  1067.       { Compress }
  1068.       PackedSize:= FSFastRLE.Pack(XorDataPtr[1], @(Blockptr^.Data[0]), BMPBlockSize);
  1069.       { Send }
  1070.       If PackedSize>0 then
  1071.       Begin
  1072.         dwSize:= SizeofTftBlock-1+PackedSize;
  1073.         FUDPSender.SendBuf(Blockptr^, Blockptr^.dwSize);
  1074.         // Delay when Interval
  1075.         BlockIntervalCount:= (BlockIntervalCount+1) mod FBlockInterval;
  1076.         If BlockIntervalCount=0 then
  1077.           Sleep(FBlockDelay);
  1078.       End;
  1079.     End;
  1080.   End;
  1081. end;
  1082. function TScreenEncoder.GetIFrame: Cardinal;
  1083. begin
  1084.   Result:= FScreenSpy.IFrame;
  1085. end;
  1086. function TScreenEncoder.GetMaxBlockSize: Integer;
  1087. begin
  1088.   Result:= FScreenSpy.MaxBlockSize;
  1089. end;
  1090. function TScreenEncoder.GetMaxFrameRate: Byte;
  1091. begin
  1092.   Result:= FScreenSpy.MaxFrameRate;
  1093. end;
  1094. function TScreenEncoder.GetRemoteHost: String;
  1095. begin
  1096.   Result:= FUDPSender.RemoteHost;
  1097. end;
  1098. function TScreenEncoder.GetRemoteIP: String;
  1099. begin
  1100.   Result:= FUDPSender.RemoteIP;
  1101. end;
  1102. function TScreenEncoder.GetRemotePort: Word;
  1103. begin
  1104.   Result:= FUDPSender.RemotePort;
  1105. end;
  1106. function TScreenEncoder.GetThreadPriority: TThreadPriority;
  1107. begin
  1108.   Result:= FScreenSpy.ThreadPriority;
  1109. end;
  1110. procedure TScreenEncoder.SetActive(Value: Boolean);
  1111. begin
  1112.   If Value<>FActive then
  1113.   try
  1114.     If Value then
  1115.     Begin
  1116.       // Init
  1117.       BlockIntervalCount:= 0;
  1118.       try
  1119.         FUDPSender.Active:= True; // Active UDP sender first
  1120.       except
  1121.         Value:= False;
  1122.         Raise;
  1123.       end;
  1124.       If Value then
  1125.         SendHeader;
  1126.       try
  1127.         FScreenSpy.Active:= Value;
  1128.       except
  1129.         Value:= False;
  1130.         Raise;
  1131.       end;
  1132.     End;
  1133.     If Not Value then
  1134.     Begin
  1135.       FScreenSpy.Active:= Value; // Deactive ScreenSpy first
  1136.       FUDPSender.Active:= Value;
  1137.     End;
  1138.   finally
  1139.     FActive:= Value;
  1140.   end;
  1141. end;
  1142. procedure TScreenEncoder.SetIFrame(const Value: Cardinal);
  1143. begin
  1144.   FScreenSpy.IFrame:= Value;
  1145. end;
  1146. procedure TScreenEncoder.SetMaxBlockSize(const Value: Integer);
  1147. Var
  1148.   i: Integer;
  1149. begin
  1150.   If Active then
  1151.     Raise EScrSpy.CreateRes(@ESSACTIVED);
  1152.   FScreenSpy.MaxBlockSize:= Value;
  1153.   try
  1154.     If Assigned(Blockptr) then
  1155.       FreeMem(Blockptr);
  1156.     If Assigned(XorDataPtr[1]) then
  1157.       FreeMem(XorDataPtr[1]);
  1158.   finally
  1159.     With FScreenSpy do
  1160.     Begin
  1161.       // GetBlock
  1162.       GetMem(Blockptr, SizeofTftBlock+BMPBlockSize+8);
  1163.       FillChar(Blockptr^, SizeofTftBlock+BMPBlockSize, 0);
  1164.       Blockptr^.PackID:= RID_BLOCK;
  1165.       // GetXor
  1166.       GetMem(XorDataPtr[1], BMPBlockSize);
  1167.       For i:=2 to BytesPerPixel do
  1168.         XorDataPtr[i]:= Pointer(Integer(XorDataPtr[1])+Integer(BlockSize)*(i-1));
  1169.     End;
  1170.   end;
  1171. end;
  1172. procedure TScreenEncoder.SetMaxFrameRate(const Value: Byte);
  1173. begin
  1174.   FScreenSpy.MaxFrameRate:= Value;
  1175. end;
  1176. procedure TScreenEncoder.SetRemoteHost(const Value: String);
  1177. begin
  1178.   FUDPSender.RemoteHost:= Value;
  1179. end;
  1180. procedure TScreenEncoder.SetRemoteIP(const Value: String);
  1181. begin
  1182.   FUDPSender.RemoteIP:= Value;
  1183. end;
  1184. procedure TScreenEncoder.SetRemotePort(const Value: Word);
  1185. begin
  1186.   FUDPSender.RemotePort:= Value;
  1187. end;
  1188. procedure TScreenEncoder.SetThreadPriority(const Value: TThreadPriority);
  1189. begin
  1190.   FScreenSpy.ThreadPriority:= Value;
  1191. end;
  1192. procedure TScreenEncoder.SendHeader;
  1193. begin
  1194.   If Not FScreenSpy.MemoryAllowcated then
  1195.     FScreenSpy.CalculateScreenData;
  1196.   With RHeader do
  1197.   Begin
  1198.     ScreenWidth:= FScreenSpy.ScreenWidth;
  1199.     ScreenHeight:= FScreenSpy.ScreenHeight;
  1200.     BytesPerPixel:= FScreenSpy.BytesPerPixel;
  1201.     BlockWidth:= FScreenSpy.BlockWidth;
  1202.     BlockHeight:= FScreenSpy.BlockHeight;
  1203.   End;
  1204.   FUDPSender.SendBuf(RHeader, RHeader.dwSize);
  1205. end;
  1206. procedure TScreenEncoder.SetBlockDelay(const Value: Cardinal);
  1207. begin
  1208.   FBlockDelay := Value;
  1209. end;
  1210. procedure TScreenEncoder.ScreenSpyOnFrameEnd(Sender: TObject;
  1211.   const FrameCount: Cardinal; const IsIFrame, HasBitmapEvent: Boolean);
  1212. begin
  1213.   DoFrameEnd(FrameCount, IsIFrame, HasBitmapEvent);
  1214.   If IsIFrame then
  1215.     Sleep(FIFrameDelay);
  1216. end;
  1217. procedure TScreenEncoder.DoFrameEnd(const FrameCount: Cardinal;
  1218.   const IsIFrame, HasBitmapEvent: Boolean);
  1219. begin
  1220.   RFrameEnd.FrameCount:= FrameCount;
  1221.   RFrameEnd.IsIFrame:= IsIFrame;
  1222.   RFrameEnd.HasBitmapEvent:= HasBitmapEvent;
  1223.   FUDPSender.SendBuf(RFrameEnd, RFrameEnd.dwSize);
  1224.   If Assigned(FOnFrameEnd) then
  1225.     FOnFrameEnd(Self, FrameCount, IsIFrame, HasBitmapEvent);
  1226. end;
  1227. procedure TScreenEncoder.DoFrameStart(const FrameCount: Cardinal;
  1228.   const IsIFrame: Boolean);
  1229. begin
  1230.   RFrameStart.FrameCount:= FrameCount;
  1231.   RFrameStart.IsIFrame:= IsIFrame;
  1232.   FUDPSender.SendBuf(RFrameStart, RFrameStart.dwSize);
  1233.   If Assigned(FOnFrameStart) then
  1234.     FOnFrameStart(Self, FrameCount, IsIFrame);
  1235. end;
  1236. procedure TScreenEncoder.ScreenSpyOnFrameStart(Sender: TObject;
  1237.   const FrameCount: Cardinal; const IsIFrame: Boolean);
  1238. begin
  1239.   DoFrameStart(FrameCount, IsIFrame);
  1240. end;
  1241. procedure TScreenEncoder.SetBlockInterval(const Value: Cardinal);
  1242. begin
  1243.   FBlockInterval := Value;
  1244. end;
  1245. procedure TScreenEncoder.SetIFrameDelay(const Value: Cardinal);
  1246. begin
  1247.   FIFrameDelay := Value;
  1248. end;
  1249. { TScreenPlayer }
  1250. procedure TScreenPlayer.CalculateScreenData;
  1251. Var
  1252.   i: Integer;
  1253. begin
  1254.   If MemoryAllowcated then
  1255.     ReleaseScreenData;
  1256.   With Header do
  1257.   Begin
  1258.     FScreenWidth:= ScreenWidth;
  1259.     FScreenHeight:= ScreenHeight;
  1260.     FBytesPerPixel:= BytesPerPixel;
  1261.     FBlockWidth:= BlockWidth;
  1262.     FBlockHeight:= BlockHeight;
  1263.   End;
  1264.   Case FBytesPerPixel of
  1265.     1: FPixelFormat:= pf8Bit;
  1266.     2: FPixelFormat:= pf16Bit;
  1267.     3: FPixelFormat:= pf24Bit;
  1268.     4: FPixelFormat:= pf32Bit;
  1269.     Else FPixelFormat:= pf24Bit;
  1270.   End;{CASE}
  1271.   FBlockColumnCount:= FScreenWidth div FBlockWidth;
  1272.   FBlockRowCount:= FScreenHeight div FBlockHeight;
  1273.   FBlockCount:= FBlockColumnCount * FBlockRowCount;
  1274.   FBlockSize:= FBlockWidth * FBlockHeight;
  1275.   BMPBlockSize:= FBlockSize * FBytesPerPixel;
  1276.   // Get Buffer for Decode Screen block
  1277.   GetMem(XorDataPtr[1], BMPBlockSize);
  1278.   For i:=2 to BytesPerPixel do
  1279.     XorDataPtr[i]:= Pointer(Integer(XorDataPtr[1])+BlockSize*(i-1));
  1280.   // Create temp bitmap for copy a pice of desktop image
  1281.   SetLength(ScreenBitmaps, BlockCount);
  1282.   For i:=0 to BlockCount-1 do
  1283.   Begin
  1284.     ScreenBitmaps[i].BlockIndex:= i;
  1285.     ScreenBitmaps[i].Bound:= Rect(0,0,BlockWidth,BlockHeight);
  1286.     OffsetRect(ScreenBitmaps[i].Bound, (i mod FBlockColumnCount) * FBlockWidth, (i div FBlockColumnCount) * FBlockHeight);
  1287.     {ScreenBitmaps[i].Bound:= Rect((i mod BlockWidth) * BMPBlockWidth, (i div BlockWidth) * BMPBlockHeight,
  1288.                                   (i mod BlockWidth) * BMPBlockWidth + BMPBlockWidth, (i div BlockWidth) * BMPBlockHeight + BMPBlockHeight);{}
  1289.     ScreenBitmaps[i].BMP:= TBitmap.Create;
  1290.     With ScreenBitmaps[i].BMP do
  1291.     Begin
  1292.       Width:= BlockWidth;
  1293.       Height:= BlockHeight;
  1294.       PixelFormat:= FPixelFormat;
  1295.       If Cardinal(ScanLine[0])<Cardinal(ScanLine[1]) then
  1296.         ScreenBitmaps[i].ptr:= ScanLine[0]
  1297.       Else
  1298.         ScreenBitmaps[i].ptr:= ScanLine[Height-1];
  1299.     End;
  1300.   End;
  1301.   MemoryAllowcated:= True;
  1302. end;
  1303. constructor TScreenPlayer.Create(AOwner: TComponent);
  1304. begin
  1305.   inherited;
  1306.   FSFastRLE := TSFastRLE.Create;
  1307.   FUDPReceiver:= TUDPReceiver.Create(Self);
  1308.   FUDPReceiver.OnUDPData:= UDPReceiverOnUDPData;
  1309.   MemoryAllowcated:= False;
  1310. end;
  1311. destructor TScreenPlayer.Destroy;
  1312. begin
  1313.   Active:= False;
  1314.   FUDPReceiver.Free;
  1315.   FSFastRLE.Free;
  1316.   ReleaseScreenData;
  1317.   inherited;
  1318. end;
  1319. procedure TScreenPlayer.DoHeaderUpdate;
  1320. begin
  1321.   If Assigned(FOnHeaderUpdate) then
  1322.     FOnHeaderUpdate(Self);
  1323. end;
  1324. procedure TScreenPlayer.DoScreenBitmap(ScreenBitmapIndex: Integer);
  1325. begin
  1326.   If Assigned(FOnScreenBitmap) then
  1327.   try
  1328.     FOnScreenBitmap(Self, ScreenBitmaps[ScreenBitmapIndex]);
  1329.   except
  1330.     FOnScreenBitmap:= nil;
  1331.   end;
  1332. end;
  1333. function TScreenPlayer.GetActive: Boolean;
  1334. begin
  1335.   Result := FUDPReceiver.Active;
  1336. end;
  1337. function TScreenPlayer.GetMulticastIP: String;
  1338. begin
  1339.   Result := FUDPReceiver.MulticastIP;
  1340. end;
  1341. function TScreenPlayer.GetPort: Word;
  1342. begin
  1343.   Result := FUDPReceiver.Port;
  1344. end;
  1345. procedure TScreenPlayer.ReleaseScreenData;
  1346. Var
  1347.   i: Integer;
  1348. begin
  1349.   If MemoryAllowcated then
  1350.   Begin
  1351.     {If Active then
  1352.       Raise EScrSpy.CreateRes(@ESSACTIVED);{}
  1353.     MemoryAllowcated:= False;
  1354.     // Do release
  1355.     For i:=2 to BytesPerPixel do
  1356.       XorDataPtr[i]:= nil;
  1357.     FreeMem(XorDataPtr[1]);
  1358.     For i:=0 to BlockCount-1 do
  1359.     Begin
  1360.       ScreenBitmaps[i].ptr:= nil;
  1361.       ScreenBitmaps[i].BMP.Free;
  1362.     End;
  1363.     SetLength(ScreenBitmaps, 0);
  1364.   End;
  1365. end;
  1366. procedure TScreenPlayer.SetActive(const Value: Boolean);
  1367. begin
  1368.   FUDPReceiver.Active:= Value;
  1369. end;
  1370. procedure TScreenPlayer.SetMulticastIP(const Value: String);
  1371. begin
  1372.   FUDPReceiver.MulticastIP:= Value;
  1373. end;
  1374. procedure TScreenPlayer.SetPort(const Value: Word);
  1375. begin
  1376.   FUDPReceiver.Port:= Value;
  1377. end;
  1378. procedure TScreenPlayer.UDPReceiverOnUDPData(Sender: TObject;
  1379.   const Buffer: Pointer; const RecvSize: Integer; const Peer: string;
  1380.   const Port: Integer);
  1381. Var
  1382.   i, l: Integer;
  1383.   ScanLinePtr: ^Byte;  
  1384.   PtrXor: array [1..4] of ^Byte; // MAX 4 bytes per pixel
  1385. begin
  1386.   AnyPtr:= Buffer;
  1387.   If Anyptr.dwSize <> TRSize(RecvSize) then
  1388.     Exit; // Error
  1389.   Case AnyPtr.PackID of
  1390.     RID_HEADER:
  1391.       Begin
  1392.         Move(AnyPtr^, Header, AnyPtr^.dwSize);
  1393.         CalculateScreenData;
  1394.         DoHeaderUpdate;
  1395.       End;
  1396.     RID_BLOCK:
  1397.       If MemoryAllowcated then
  1398.       Begin
  1399.         BlockPtr:= Pointer(AnyPtr);
  1400.         With BlockPtr^ do
  1401.           Case FrameStyle of
  1402.             sdsRLENormal:
  1403.               Begin
  1404.                 //decompress
  1405.                 //FSFastRLE.UnPack(@(Data[0]), ScreenBitmaps[BlockIndex].ptr, dwSize+1-SizeofTftBlock);
  1406.                 FSFastRLE.UnPack(@(Data[0]), XorDataPtr[1], dwSize+1-SizeofTftBlock);
  1407.                 Move(XorDataPtr[1]^, ScreenBitmaps[BlockIndex].ptr^, BMPBlockSize);
  1408.                 DoScreenBitmap(BlockIndex);
  1409.               End;
  1410.             sdsRLEXor:
  1411.               Begin
  1412.                 FSFastRLE.UnPack(@(Data[0]), XorDataPtr[1], dwSize+1-SizeofTftBlock);
  1413.                 // Init First Pointer for sequence XOR
  1414.                 ScanLinePtr:= ScreenBitmaps[BlockIndex].ptr;
  1415.                 For i:=0 to BytesPerPixel do
  1416.                   PtrXor[i]:= XorDataPtr[i];
  1417.                 For i:=0 to BlockSize-1 do
  1418.                 Begin
  1419.                   For l:=1 to BytesPerPixel do
  1420.                   Begin
  1421.                     ScanLinePtr^:= ScanLinePtr^ xor PtrXor[l]^;
  1422.                     Inc(ScanLinePtr);
  1423.                     Inc(PtrXor[l]);
  1424.                   End;
  1425.                 End;
  1426.                 DoScreenBitmap(BlockIndex);
  1427.               End;
  1428.           End;{CASE}
  1429.       End;
  1430.     RID_FrameStart:
  1431.       Begin
  1432.         FrameStartPtr:= Pointer(AnyPtr);
  1433.         If Assigned(FOnFrameStart) then
  1434.           FOnFrameStart(Self, FrameStartPtr^.FrameCount, FrameStartPtr^.IsIFrame);
  1435.       End;
  1436.     RID_FrameEnd:
  1437.       Begin
  1438.         FrameEndPtr:= Pointer(AnyPtr);
  1439.         If Assigned(FOnFrameEnd) then
  1440.           FOnFrameEnd(Self, FrameEndPtr^.FrameCount, FrameEndPtr^.IsIFrame, FrameEndPtr^.HasBitmapEvent);
  1441.       End;
  1442.     Else //Error
  1443.   End;{CASE}
  1444. end;
  1445. end.