服务端 (截取屏幕) 客户端(显示屏幕)
程序能够正常截屏 并传输 但是 传输过程中 如果在服务端窗口进行鼠标移动 或单击 即会触发异常错误:“存储空间不足,无法处理此类命令” 服务端代码如下:截屏幕类:
unit UnitTScreen;interfaceuses
Windows, Classes, Graphics, Forms, jpeg;type
TScreen = class
private
bmp: TBitmap;
jpeg: TJpegimage;
imgstm: TMemoryStream;
public
procedure ScreenMap(str: string);
function GetImgstm: Tmemorystream;
constructor Create; overload;
destructor Destroy; override;
end;implementation{ TScreen }constructor TScreen.Create;
begin
bmp := TBitmap.Create;
jpeg := Tjpegimage.Create;
imgstm := TMemorystream.Create;end;destructor TScreen.Destroy;
begin
bmp.Free;
jpeg.Free;
imgstm.Free;
inherited;
end;function TScreen.GetImgstm: Tmemorystream;
begin
result := imgstm;
end;procedure TScreen.ScreenMap(str: string);
var
Cursorx, Cursory: integer;
DC: hdc;
Mycan: Tcanvas;
R: TRect;
DrawPos: TPoint;
MyCursor: TIcon;
hld: hwnd;
Threadld: dword;
mp: tpoint;
pIconInfo: TIconInfo;
begin
Mycan := TCanvas.Create; {屏幕截取}
DC := GetWindowDC(0);
try
Mycan.Handle := dc;
R := Rect(0, 0, Screen.Width, Screen.Height);
bmp.Width := R.Right;
bmp.Height := R.Bottom;
bmp.Canvas.CopyRect(R, Mycan, R);
finally
releaseDC(0, DC);
Mycan.Free;
end;
{画上鼠标图象}
if str[2] = '1' then
begin
GetCursorPos(DrawPos);
MyCursor := TIcon.Create;
getcursorpos(mp);
hld := WindowFromPoint(mp);
Threadld := GetWindowThreadProcessId(hld, nil);
AttachThreadInput(GetCurrentThreadId, Threadld, True);
MyCursor.Handle := Getcursor();
AttachThreadInput(GetCurrentThreadId, threadld, False);
GetIconInfo(Mycursor.Handle, pIconInfo);
cursorx := DrawPos.x - round(pIconInfo.xHotspot);
cursory := DrawPos.y - round(pIconInfo.yHotspot);
bmp.Canvas.Draw(cursorx, cursory, MyCursor); {画上鼠标}
DeleteObject(pIconInfo.hbmColor);{GetIconInfo 使用时创建了两个bitmap对象. 需要手工释放这两个对象}
DeleteObject(pIconInfo.hbmMask);{否则,调用他后,他会创建一个bitmap,多次调用会产生多个,直至资源耗尽}
Mycursor.ReleaseHandle; {释放数组内存}
MyCursor.Free; {释放鼠标指针}
end;
Application.ProcessMessages;
{图象处理}
if str[1] = '0' then
bmp.PixelFormat := pf16Bit
else if str[1] = '1' then
bmp.PixelFormat := pf8Bit
else if str[1] = '2' then
bmp.PixelFormat := pf4Bit;
{压缩成JPG}
Application.ProcessMessages;
jpeg.Assign(bmp);
bmp.FreeImage;
imgstm.Clear;
jpeg.SaveToStream(imgstm);
end;end.传输线程:
unit UnitTServerThread;interfaceuses
ScktComp, SysUtils, UnitConst, Classes, UnitTScreen;type
TServerThread = class(TServerClientThread)
private
ProcessID: Cardinal; //结束进程ID
stm: TMemorystream;
scn: Tscreen;
{ Private declarations }
protected
{TServerClientThread的执行过程,相当于普通现成的Thread.Execute}
procedure ClientExecute; override;
public
{重载构造函数}
constructor Create(CreateSuspended: Boolean;
Asocket: TServerClientWinSocket);overload;
destructor Destroy; override;
end;implementation
uses
unitmain;
{ TServerThread }procedure TServerThread.ClientExecute;
var
Len, //收到的数据长度
Order: integer; //指令
DataSize, //发送的数据大小
SendSize: integer; //已发送数据大小
SendBuffer: pchar; //发送缓冲
Pstream: TWinsocketStream;
Buffer: pointer; //接收数据缓冲区
Revstr: string; //接收的数据
const
BufferSize = 1024;
SendBufferSize = 4096;
begin
try
Pstream := TWinsocketStream.Create(ClientSocket,60000);
ClientSocket.SendText(inttostr(XF_IAMREADY));
while (not Terminated) and ClientSocket.Connected do
if Pstream.WaitForData(6000) then {等待数据到来 }
begin
try
Buffer := AllocMem(BufferSize+1);
len := PStream.Read(Buffer^, BufferSize);
if Len = 0 then
begin
sleep(5);
continue;
end;
Revstr := Pchar(buffer);
setlength(Revstr,len);//frmmain.mmo.Lines.Add('thread rev msg:'+copy(Revstr,1,len));
if not trystrtoint(copy(Revstr,1,4), Order) then
begin
sleep(5);
continue;
end;
case Order of
XF_TERMINATE:
begin
ClientSocket.Close;
Terminate;
end;
XF_SCREENSTART:
begin
scn := TScreen.Create;
Clientsocket.SendText(inttostr(XF_SCREENREADY));
end;
XF_GETIMGSIZE:
begin
scn.ScreenMap(copy(Revstr,5,6));
stm := scn.GetImgstm;
Datasize := stm.Size;
Clientsocket.SendText(inttostr(XF_IMGSIZEINFO)+inttostr(Datasize));
SendSize := 0;
end;
XF_SENDIMGDATA:
begin
SendBuffer := AllocMem(SendBufferSize+4);
stm.Position := SendSize;
if (SendSize + SendBufferSize) < Datasize then
begin
stm.ReadBuffer(SendBuffer[4],SendBufferSize);
move(pchar(inttostr(XF_IMGDATAINFO))^,SendBuffer^,4);
pstream.WriteBuffer(SendBuffer[0],SendBufferSize+4);
SendSize := SendSize + SendBufferSize;
end
else begin {最后一个包}
stm.ReadBuffer(SendBuffer[4],Datasize-SendSize);
move(pchar(inttostr(XF_IMGDATAINFO))^,SendBuffer^,4);
pstream.WriteBuffer(SendBuffer[0],Datasize-SendSize+4);
SendSize := Datasize;
end;
FreeMem(SendBuffer);
end;
end;
finally
FreeMem(Buffer);
Sleep(5);
end;
end;
finally
Pstream.Free;
end;
end;constructor TServerThread.Create(CreateSuspended: Boolean;
Asocket: TServerClientWinSocket);
begin
inherited create(CreateSuspended,Asocket);
stm := TMemorystream.Create;
end;destructor TServerThread.Destroy;
begin
if assigned(scn) and (scn <> nil) then
scn.Free;
inherited;
end;end.常量定义:
XF_IAMREADY = 2000; //连接就续消息
XF_TERMINATE = 2001; //线程结束指令
XF_SCREENSTART = 3000; //开始发送图象指令
XF_SCREENREADY = 3001; //准备好信息
XF_GETIMGSIZE = 3002; //获取图象大小指令
XF_IMGSIZEINFO = 3003; //图象大小信息
XF_SENDIMGDATA = 3004; //发送图片数据指令
XF_IMGDATAINFO = 3005; //图片数据信息
程序能够正常截屏 并传输 但是 传输过程中 如果在服务端窗口进行鼠标移动 或单击 即会触发异常错误:“存储空间不足,无法处理此类命令” 服务端代码如下:截屏幕类:
unit UnitTScreen;interfaceuses
Windows, Classes, Graphics, Forms, jpeg;type
TScreen = class
private
bmp: TBitmap;
jpeg: TJpegimage;
imgstm: TMemoryStream;
public
procedure ScreenMap(str: string);
function GetImgstm: Tmemorystream;
constructor Create; overload;
destructor Destroy; override;
end;implementation{ TScreen }constructor TScreen.Create;
begin
bmp := TBitmap.Create;
jpeg := Tjpegimage.Create;
imgstm := TMemorystream.Create;end;destructor TScreen.Destroy;
begin
bmp.Free;
jpeg.Free;
imgstm.Free;
inherited;
end;function TScreen.GetImgstm: Tmemorystream;
begin
result := imgstm;
end;procedure TScreen.ScreenMap(str: string);
var
Cursorx, Cursory: integer;
DC: hdc;
Mycan: Tcanvas;
R: TRect;
DrawPos: TPoint;
MyCursor: TIcon;
hld: hwnd;
Threadld: dword;
mp: tpoint;
pIconInfo: TIconInfo;
begin
Mycan := TCanvas.Create; {屏幕截取}
DC := GetWindowDC(0);
try
Mycan.Handle := dc;
R := Rect(0, 0, Screen.Width, Screen.Height);
bmp.Width := R.Right;
bmp.Height := R.Bottom;
bmp.Canvas.CopyRect(R, Mycan, R);
finally
releaseDC(0, DC);
Mycan.Free;
end;
{画上鼠标图象}
if str[2] = '1' then
begin
GetCursorPos(DrawPos);
MyCursor := TIcon.Create;
getcursorpos(mp);
hld := WindowFromPoint(mp);
Threadld := GetWindowThreadProcessId(hld, nil);
AttachThreadInput(GetCurrentThreadId, Threadld, True);
MyCursor.Handle := Getcursor();
AttachThreadInput(GetCurrentThreadId, threadld, False);
GetIconInfo(Mycursor.Handle, pIconInfo);
cursorx := DrawPos.x - round(pIconInfo.xHotspot);
cursory := DrawPos.y - round(pIconInfo.yHotspot);
bmp.Canvas.Draw(cursorx, cursory, MyCursor); {画上鼠标}
DeleteObject(pIconInfo.hbmColor);{GetIconInfo 使用时创建了两个bitmap对象. 需要手工释放这两个对象}
DeleteObject(pIconInfo.hbmMask);{否则,调用他后,他会创建一个bitmap,多次调用会产生多个,直至资源耗尽}
Mycursor.ReleaseHandle; {释放数组内存}
MyCursor.Free; {释放鼠标指针}
end;
Application.ProcessMessages;
{图象处理}
if str[1] = '0' then
bmp.PixelFormat := pf16Bit
else if str[1] = '1' then
bmp.PixelFormat := pf8Bit
else if str[1] = '2' then
bmp.PixelFormat := pf4Bit;
{压缩成JPG}
Application.ProcessMessages;
jpeg.Assign(bmp);
bmp.FreeImage;
imgstm.Clear;
jpeg.SaveToStream(imgstm);
end;end.传输线程:
unit UnitTServerThread;interfaceuses
ScktComp, SysUtils, UnitConst, Classes, UnitTScreen;type
TServerThread = class(TServerClientThread)
private
ProcessID: Cardinal; //结束进程ID
stm: TMemorystream;
scn: Tscreen;
{ Private declarations }
protected
{TServerClientThread的执行过程,相当于普通现成的Thread.Execute}
procedure ClientExecute; override;
public
{重载构造函数}
constructor Create(CreateSuspended: Boolean;
Asocket: TServerClientWinSocket);overload;
destructor Destroy; override;
end;implementation
uses
unitmain;
{ TServerThread }procedure TServerThread.ClientExecute;
var
Len, //收到的数据长度
Order: integer; //指令
DataSize, //发送的数据大小
SendSize: integer; //已发送数据大小
SendBuffer: pchar; //发送缓冲
Pstream: TWinsocketStream;
Buffer: pointer; //接收数据缓冲区
Revstr: string; //接收的数据
const
BufferSize = 1024;
SendBufferSize = 4096;
begin
try
Pstream := TWinsocketStream.Create(ClientSocket,60000);
ClientSocket.SendText(inttostr(XF_IAMREADY));
while (not Terminated) and ClientSocket.Connected do
if Pstream.WaitForData(6000) then {等待数据到来 }
begin
try
Buffer := AllocMem(BufferSize+1);
len := PStream.Read(Buffer^, BufferSize);
if Len = 0 then
begin
sleep(5);
continue;
end;
Revstr := Pchar(buffer);
setlength(Revstr,len);//frmmain.mmo.Lines.Add('thread rev msg:'+copy(Revstr,1,len));
if not trystrtoint(copy(Revstr,1,4), Order) then
begin
sleep(5);
continue;
end;
case Order of
XF_TERMINATE:
begin
ClientSocket.Close;
Terminate;
end;
XF_SCREENSTART:
begin
scn := TScreen.Create;
Clientsocket.SendText(inttostr(XF_SCREENREADY));
end;
XF_GETIMGSIZE:
begin
scn.ScreenMap(copy(Revstr,5,6));
stm := scn.GetImgstm;
Datasize := stm.Size;
Clientsocket.SendText(inttostr(XF_IMGSIZEINFO)+inttostr(Datasize));
SendSize := 0;
end;
XF_SENDIMGDATA:
begin
SendBuffer := AllocMem(SendBufferSize+4);
stm.Position := SendSize;
if (SendSize + SendBufferSize) < Datasize then
begin
stm.ReadBuffer(SendBuffer[4],SendBufferSize);
move(pchar(inttostr(XF_IMGDATAINFO))^,SendBuffer^,4);
pstream.WriteBuffer(SendBuffer[0],SendBufferSize+4);
SendSize := SendSize + SendBufferSize;
end
else begin {最后一个包}
stm.ReadBuffer(SendBuffer[4],Datasize-SendSize);
move(pchar(inttostr(XF_IMGDATAINFO))^,SendBuffer^,4);
pstream.WriteBuffer(SendBuffer[0],Datasize-SendSize+4);
SendSize := Datasize;
end;
FreeMem(SendBuffer);
end;
end;
finally
FreeMem(Buffer);
Sleep(5);
end;
end;
finally
Pstream.Free;
end;
end;constructor TServerThread.Create(CreateSuspended: Boolean;
Asocket: TServerClientWinSocket);
begin
inherited create(CreateSuspended,Asocket);
stm := TMemorystream.Create;
end;destructor TServerThread.Destroy;
begin
if assigned(scn) and (scn <> nil) then
scn.Free;
inherited;
end;end.常量定义:
XF_IAMREADY = 2000; //连接就续消息
XF_TERMINATE = 2001; //线程结束指令
XF_SCREENSTART = 3000; //开始发送图象指令
XF_SCREENREADY = 3001; //准备好信息
XF_GETIMGSIZE = 3002; //获取图象大小指令
XF_IMGSIZEINFO = 3003; //图象大小信息
XF_SENDIMGDATA = 3004; //发送图片数据指令
XF_IMGDATAINFO = 3005; //图片数据信息
VC++.delphi
VB C# .NET远程屏幕监视
局域网屏幕监视
局域网桌面监视
屏幕监控
屏幕抓取
屏幕传输
屏幕截图
QQ交流群:33367148