📄 unit_screenspy.pas
字号:
{*******************************************}
{ 图片分块快速比较单元 }
{ 作者:hf }
{ Blog:http://hfnet.n3t.nu/ }
{ MSN:hf-net@hotmail.com }
{*******************************************}
unit Unit_ScreenSpy;
interface
uses
Windows,Graphics,Classes,SysUtils,ShellAPI ;
const
BMPBlockSize = 128; //BMP块大小(宽和高都为BMPBlockSize)
type
PDifBlock = ^TDifBlock ;
TDifBlock = record //不同块
x,y:Integer;
changed:boolean; //是否变化
end;
// TScreenChangeEvent = procedure(var Width,Height:Integer ) of object;
TScreenSpy = class
private
FPixelFormat : TPixelFormat ;
TMPStream : TMemoryStream ;
TmpBmp : TBitmap;
BlockCount,LineBlockCount,LineCount:Integer; //
BlockList : array of PDifBlock;
// FOnScreenChange : TScreenChangeEvent;
FirstL:Integer;
function GetPixelFormat:Byte;
procedure SetixelFormat(PixelFormat : Byte );
procedure MakeIndex4;
procedure MakeIndex8;
procedure MakeIndex16;
procedure MakeIndex32;
function IsScreenChange:Boolean ;
procedure IniBlockList;
protected
ScreenBMP,LineBMP:TBitmap;
ScreenDC: HDC;
procedure MakeIndex; //生成索引
function GetFirstLine:Integer;
public
ScreenWidth,ScreenHeight:Integer ;
procedure GetFirstBMP(FirstBmp : TStream ); //取第一幅屏幕图片并存入流中
procedure GetNextBMP(NextBmp : TStream ); //取下一幅屏幕图片并存入流中
constructor Create; reintroduce;
destructor Destroy; override;
property PixelFormat : Byte read GetPixelFormat write SetixelFormat default 8;
// property OnScreenSizeChange : TScreenChangeEvent read FOnScreenChange write FOnScreenChange;
end;
implementation
constructor TScreenSpy.Create;
begin
TMPStream :=TMemoryStream.Create;
ScreenBMP:= TBitmap.Create;
LineBMP:= TBitmap.Create;
FPixelFormat := pf8bit ; //默认
FirstL := 0;
ScreenWidth := GetSystemMetrics(SM_CXSCREEN); //显示器水平分辨率
ScreenHeight := GetSystemMetrics(SM_CYSCREEN); //显示器垂直分辨率
ScreenBMP.PixelFormat := FPixelFormat;
ScreenBMP.Width := ScreenWidth;
ScreenBMP.Height := ScreenHeight;
LineBMP.PixelFormat := FPixelFormat;
LineBMP.Width := ScreenWidth;
LineBMP.Height := 1;
TmpBmp := TBitmap.Create;
TmpBmp.PixelFormat := FPixelFormat;
TmpBmp.Width := BMPBlockSize;
TmpBmp.Height := BMPBlockSize;
IniBlockList; //初始化列表
inherited Create;
end;
destructor TScreenSpy.Destroy;
var
i:Integer;
begin
TMPStream.Free;
TmpBmp.Destroy;
ScreenBMP.Destroy;
LineBMP.Destroy;
for I := Low(BlockList) to High(BlockList) do //释放
begin
freeMem(BlockList[i]);
end;
inherited destroy;
end;
procedure TScreenSpy.IniBlockList;
var
x,y,i:Integer;
begin
if (ScreenWidth mod BMPBlockSize <> 0) then
LineBlockCount := ScreenWidth div BMPBlockSize +1
else
LineBlockCount := ScreenWidth div BMPBlockSize;
if ScreenHeight mod BMPBlockSize <> 0 then
LineCount := ScreenHeight Div BMPBlockSize +1
else
LineCount := ScreenHeight Div BMPBlockSize;
BlockCount := LineBlockCount * LineCount;
SetLength(BlockList,BlockCount);
y := 0;
i :=0;
while y < LineCount do
begin
x := 0;
while x < LineBlockCount do
begin
GetMem(BlockList[i],SizeOf(TDifBlock));
BlockList[i]^.X := x*BMPBlockSize;
BlockList[i]^.Y := y*BMPBlockSize;
BlockList[i]^.changed := false;
Inc(i);
Inc(x);
end;
Inc(y);
end;
end;
function TScreenSpy.GetPixelFormat:Byte;
begin
case FPixelFormat of
pf4bit: Result := 4;
pf8bit: Result := 8;
pf24bit: Result := 24;
end;
end;
procedure TScreenSpy.SetixelFormat(PixelFormat : Byte );
begin
case PixelFormat of
4:FPixelFormat := pf4bit;
8:FPixelFormat := pf8bit;
16:FPixelFormat := pf16bit;
24:FPixelFormat := pf24bit;
end;
if TmpBmp.PixelFormat <> FPixelFormat then
TmpBmp.PixelFormat := FPixelFormat;
end;
function TScreenSpy.GetFirstLine:Integer;
var
i:Integer;
begin
Inc(FirstL );
if FirstL = 20 then FirstL := 0;
Result := FirstL;
end;
procedure TScreenSpy.MakeIndex4;
var
c1,c2:PDWORD;
x,y,yi,i,j:Integer;
begin
y := FirstL;
while y < ScreenBMP.height do
begin
BitBlt(LineBMP.Canvas.Handle,0,0,ScreenWidth,1,ScreenDC,0,y,SRCCOPY);
c1 := LineBMP.ScanLine[0];
c2 := ScreenBMP.ScanLine[y];
x := 0;
yi := (y div BMPBlockSize) * LineBlockCount;
while x < ScreenBMP.Width do
begin
j:=0;
i :=yi + x div BMPBlockSize;
while j < BMPBlockSize do
begin
if c1^ <> c2^ then
BlockList[i]^.changed := true;
Inc(c1,1);
Inc(c2,1);
inc(j,8);
end;
Inc(x,BMPBlockSize);
end;
Inc(y,20); //隔行扫描
end;
FirstL := GetFirstLine();
end;
procedure TScreenSpy.MakeIndex8;
var
c1,c2:PDWORD;
x,y,yi,i,j:Integer;
begin
y := FirstL;
while y < ScreenBMP.height do
begin
BitBlt(LineBMP.Canvas.Handle,0,0,ScreenWidth,1,ScreenDC,0,y,SRCCOPY);
c1 := LineBMP.ScanLine[0];
c2 := ScreenBMP.ScanLine[y];
x := 0;
yi := (y div BMPBlockSize) * LineBlockCount;
while x < ScreenBMP.Width do
begin
j:=0;
i :=yi + x div BMPBlockSize;
while j < BMPBlockSize do
begin
if c1^ <> c2^ then //8位色一次比较的是4个象素
BlockList[i]^.changed := true;
Inc(c1,1);
Inc(c2,1);
inc(j,4);
end;
Inc(x,BMPBlockSize);
end;
Inc(y,20); //隔行扫描
end;
FirstL := GetFirstLine();
end;
procedure TScreenSpy.MakeIndex16;
var
c1,c2:PDWORD;
x,y,yi,i,j:Integer;
begin
y := FirstL;
while y < ScreenBMP.height do
begin
BitBlt(LineBMP.Canvas.Handle,0,0,ScreenWidth,1,ScreenDC,0,y,SRCCOPY);
c1 := LineBMP.ScanLine[0];
c2 := ScreenBMP.ScanLine[y];
x := 0;
yi := (y div BMPBlockSize) * LineBlockCount;
while x < ScreenBMP.Width do
begin
j:=0;
i :=yi + x div BMPBlockSize;
while j < BMPBlockSize do
begin
if c1^ <> c2^ then
BlockList[i]^.changed := true;
Inc(c1,1);
Inc(c2,1);
inc(j,2);
end;
Inc(x,BMPBlockSize);
end;
Inc(y,20); //隔行扫描
end;
FirstL := GetFirstLine();
end;
procedure TScreenSpy.MakeIndex32;
var
c1,c2:PDWORD;
x,y,yi,i,j:Integer;
begin
y := FirstL;
while y < ScreenBMP.height do
begin
BitBlt(LineBMP.Canvas.Handle,0,0,ScreenWidth,1,ScreenDC,0,y,SRCCOPY);
c1 := LineBMP.ScanLine[0];
c2 := ScreenBMP.ScanLine[y];
x := 0;
yi := (y div BMPBlockSize) * LineBlockCount;
i :=yi + x div BMPBlockSize;
while x < ScreenBMP.Width do
begin
j:=0;
while j < BMPBlockSize do
begin
if c1^ <> c2^ then
BlockList[i]^.changed := true;
Inc(c1,1);
Inc(c2,1);
inc(j,1);
end;
Inc(x,BMPBlockSize);
Inc(i);
end;
Inc(y,20); //隔行扫描
end;
FirstL := GetFirstLine();
end;
procedure TScreenSpy.MakeIndex;
begin
case FPixelFormat of
pf4bit: MakeIndex4;
pf8bit: MakeIndex8;
pf16bit : MakeIndex16;
pf32bit: MakeIndex32;
end;
end;
function TScreenSpy.IsScreenChange:Boolean;
begin
end;
procedure TScreenSpy.GetFirstBMP(FirstBmp : TStream ); //取第一幅屏幕图片并存入流中
var
P:TPoint;
c:Char;
begin
FirstBmp.Size := 0;
c:='F';
FirstBmp.Write(c,1);
// GetCursorPos(p);
// FirstBmp.Write(p,SizeOf(TPoint));
p.X := ScreenWidth ;
p.Y := ScreenHeight;
FirstBmp.Write(p,SizeOf(TPoint));
ScreenDC:=GetDC(0);
BitBlt(ScreenBMP.Canvas.Handle ,0,0,ScreenWidth,ScreenHeight,ScreenDC,0,0,SRCCOPY);
ReleaseDC(0,ScreenDC);
// TmpBmp.Width :=ScreenWidth;
// ScreenHeight;
ScreenBMP.SaveToStream(FirstBmp );
end;
procedure TScreenSpy.GetNextBMP(NextBmp : TStream ); //取下一幅屏幕图片并存入流中
var
i:Integer;
Ssize:Integer;
R1,R2:TRect;
c:Char;
p:TPoint;
begin
NextBmp.Size := 0;
R2.Left := 0;
R2.Top := 0;
R2.Bottom := BMPBlockSize;
c:='N';
NextBmp.Write(c,1);
ScreenDC:=GetDC(0);
MakeIndex;
// GetCursorPos(p);
// NextBmp.Write(p,SizeOf(TPoint));
I := Low(BlockList);
while I <= High(BlockList) do
begin
if BlockList[i]^.changed then
begin
R1.Left := BlockList[i]^.x; R1.Top := BlockList[i]^.y;
R1.Right := R1.Left + BMPBlockSize ; R1.Bottom := R1.Top + BMPBlockSize;
BlockList[i]^.changed := False;
R2.Right := R1.Right - R1.Left ;
TmpBmp.Width := R2.Right;
BitBlt(ScreenBMP.Canvas.Handle,R1.Left,R1.Top,R1.Right ,R1.Bottom,
ScreenDC,R1.Left ,R1.Top ,SRCCOPY );
BitBlt(TmpBmp.Canvas.Handle,0,0,R2.Right ,R2.Bottom,
ScreenBMP.Canvas.Handle,R1.Left ,R1.Top ,SRCCOPY );
TMPStream.Clear;
TmpBmp.SaveToStream(TMPStream);
NextBmp.WriteBuffer(R1.TopLeft,SizeOf(TPoint)); //图象坐标
Ssize := TMPStream.Size;
NextBmp.WriteBuffer(Ssize,SizeOf(Integer));
NextBmp.CopyFrom(TMPStream,0);
end
else
inc(i);
end;
ReleaseDC(0,ScreenDC);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -