用Delphi实现远程屏幕抓取


======================================================
注:本文源代码点此下载
======================================================

---- 在网络管理中,有时需要通过监视远程计算机屏幕来了解网上微机的使用情况。虽然,市面上有很多软件可以实现该功能,有些甚至可以进行远程控制,但在使用上缺乏灵活性,如无法指定远程计算机屏幕区域的大小和位置,进而无法在一屏上同时监视多个屏幕。其实,可以用delphi自行编制一个灵活的远程屏幕抓取工具,简述如下。

---- 一、软硬件要求。

---- windows95/98对等网,用来监视的计算机(以下简称主控机)和被监视的计算机(以下简称受控机)都必须装有tcp/ip 协议,并正确配置。如没有网络,也可以在一台计算机上进行调试。

---- 二、实现方法。

---- 编制两个应用程序,一个为vclient.exe,装在受控机上,另一个为vserver.exe,装在主控机上。vserver.exe指定要监视的受控机的ip地址和将要在受控机屏幕上抓取区域的大小和位置,并发出屏幕抓取指令给vclient.exe,vclient.exe得到指令后,在受控机屏幕上选取指定区域,生成数据流,将其发回主控机,并在主控机上显示出抓取区域的bmp图象。由以上过程可以看出,该方法的关键有二:一是如何在受控机上进行屏幕抓取,二是如何通过tcp/ip协议在两台计算机中传输数据。

---- udp(user datagram protocol,意为用户报文协议)是internet上广泛采用的通信协议之一。与tcp协议不同,它是一种非连接的传输协议,没有确认机制,可靠性不如tcp,但它的效率却比tcp高,用于远程屏幕监视还是比较适合的。同时,udp控件不区分服务器端和客户端,只区分发送端和接收端,编程上较为简单,故选用udp协议,使用delphi 4.0提供的tnmudp控件。

---- 三、创建演示程序。

---- 第一步,编制vclient.exe文件。新建delphi工程,将默认窗体的name属性设为“client”。加入tnmudp控件,name属性设为“cudp”;localport属性设为“1111”,让控件cudp监视受控机的1111端口,当有数据发送到该口时,触发控件cudp的ondatareceived事件;remoteport属性设为“2222”,当控件cudp发送数据时,将数据发到主控机的2222口。

---- 在implementation后面加入变量定义

const bufsize=2048;{ 发送每一笔数据的缓冲区大小 }

var

  bmpstream:tmemorystream;

  leftsize:longint;{ 发送每一笔数据后剩余的字节数 }

为client的oncreate事件添加代码:

procedure tclient.formcreate(sender: tobject);

begin

  bmpstream:=tmemorystream.create;

end;

为client的ondestroy事件添加代码:

procedure tclient.formdestroy(sender: tobject);

begin

  bmpstream.free;

end;

为控件cudp的ondatareceived事件添加代码:

procedure tclient.cudpdatareceived(sender: tcomponent;

  numberbytes: integer; fromip: string);

var

  ctrlcode:array[0..29] of char;

  buf:array[0..bufsize-1] of char;

  tmpstr:string;

  sendsize,leftpos,toppos,rightpos,bottompos:integer;

begin

  cudp.readbuffer(ctrlcode,numberbytes);{ 读取控制码 }

  if ctrlcode[0]+ctrlcode[1]+ctrlcode[2]+ctrlcode[3]='show' then

  begin { 控制码前4位为“show”表示主控机发出了抓屏指令 }

if bmpstream.size=0 then { 没有数据可发,必须截屏生成数据 }

    begin

tmpstr:=strpas(ctrlcode);

tmpstr:=copy(tmpstr,5,length(tmpstr)-4);

leftpos:=strtoint(copy(tmpstr,1,pos(':',tmpstr)-1));

tmpstr:=copy(tmpstr,pos(':',tmpstr)+1,length(tmpstr)

-pos(':',tmpstr));

toppos:=strtoint(copy(tmpstr,1,pos(':',tmpstr)-1));

tmpstr:=copy(tmpstr,pos(':',tmpstr)+1,length(tmpstr)-

pos(':',tmpstr));

rightpos:=strtoint(copy(tmpstr,1,pos(':',tmpstr)-1));

bottompos:=strtoint(copy(tmpstr,pos(':',tmpstr

)+1,length(tmpstr)-pos(':',tmpstr)));

screencap(leftpos,toppos,rightpos,bottompos); {

截取屏幕 }

    end;

if leftsize>bufsize then sendsize:=bufsize

else sendsize:=leftsize;

bmpstream.readbuffer(buf,sendsize);

leftsize:=leftsize-sendsize;

if leftsize=0 then bmpstream.clear;{ 清空流 }

cudp.remotehost:=fromip; { fromip为主控机ip地址 }

cudp.sendbuffer(buf,sendsize); { 将数据发到主控机的2222口 }

  end;

end;

其中screencap是自定义函数,截取屏幕指定区域,

代码如下:

procedure tclient.screencap(leftpos,toppos,

rightpos,bottompos:integer);

var

  rectwidth,rectheight:integer;

  sourcedc,destdc,bhandle:integer;

  bitmap:tbitmap;

begin

  rectwidth:=rightpos-leftpos;

  rectheight:=bottompos-toppos;

  sourcedc:=createdc('display',',',nil);

  destdc:=createcompatibledc(sourcedc);

  bhandle:=createcompatiblebitmap(sourcedc,

rectwidth,rectheight);

  selectobject(destdc,bhandle);

  bitblt(destdc,0,0,rectwidth,rectheight,sourcedc,

leftpos,toppos,srccopy);

  bitmap:=tbitmap.create;

  bitmap.handle:=bhandle;

  bitmap.savetostream(bmpstream);

  bmpstream.position:=0;

  leftsize:=bmpstream.size;

  bitmap.free;

  deletedc(destdc);

  releasedc(bhandle,sourcedc);

end;

存为“c:vclientclnunit.pas”和“c:vclientvclient.dpr”,

并编译。

---- 第二步,编制vserver.exe文件。新建delphi工程,将窗体的name属性设为“server”。加入tnmudp控件,name属性设为“sudp”;localport属性设为“2222”,让控件sudp监视主控机的2222端口,当有数据发送到该口时,触发控件sudp的ondatareceived事件;remoteport属性设为“1111”,当控件sudp发送数据时,将数据发到受控机的1111口。加入控件image1,align属性设为“alclient”;加入控件button1,caption属性设为“截屏”;加入控件label1,caption属性设为“左:上:右:下”;加入控件edit1,text属性设为“0:0:100:100”;加入控件label2,caption属性设为“受控机ip地址”;加入控件edit2,text属性设为“127.0.0.1”;

在implementation后面加入变量定义

const bufsize=2048;

var

  rsltstream,tmpstream:tmemorystream;

为server的oncreate事件添加代码:

procedure tserver.formcreate(sender: tobject);

begin

  rsltstream:=tmemorystream.create;

  tmpstream:=tmemorystream.create;

end;

为client的ondestroy事件添加代码:

procedure tserver.formdestroy(sender: tobject);

begin

  rsltstream.free;

  tmpstream.free;

end;

为控件button1的onclick事件添加代码:

procedure tserver.button1click(sender: tobject);

var reqcode:array[0..29] of char;reqcodestr:string;

begin

  reqcodestr:='show'+edit1.text;

  strpcopy(reqcode,reqcodestr);

  tmpstream.clear;

  rsltstream.clear;

  sudp.remotehost:=edit2.text;

  sudp.sendbuffer(reqcode,30);

end;

为控件sudp的ondatareceived事件添加代码:

procedure tserver.sudpdatareceived(sender: tcomponent;

  numberbytes: integer; fromip: string);

var reqcode:array[0..29] of char;reqcodestr:string;

begin

  reqcodestr:='show'+edit1.text;

  strpcopy(reqcode,reqcodestr);

  sudp.readstream(tmpstream);

  rsltstream.copyfrom(tmpstream,numberbytes);

  if numberbytes< bufsize then { 数据已读完 }

  begin

rsltstream.position:=0;

image1.picture.bitmap.loadfromstream(rsltstream);

tmpstream.clear;

rsltstream.clear;

  end

  else

  begin

tmpstream.clear;

reqcode:='show';

sudp.remotehost:=edit2.text;

sudp.sendbuffer(reqcode,30);

  end;

end;

存为“c:vserversvrunit.pas”和

“c:vservervserver.dpr”,并编译。

---- 四、测试。

---- 1、本地机测试:在本地机同时运行vserver.exe和vclient.exe,利用程序的默认设置,即可实现截屏。查看“控制面板”-“网络”-“tcp/ip”-“ip地址”,将程序的“客户ip地址”设为该地址 ,同样正常运行。

---- 2、远程测试:选一台受控机,运行vclient.exe;另选一台主控机,运行vserver.exe,将“受控机ip地址”即edit2的内容设为受控机的ip地址,“截屏”即可。以上简要介绍了远程屏幕抓取的实现方法,至于在主控机上一屏同时监视多个受控机,读者可自行完善。以上程序,在windows98对等网、delphi 4.0下调试通过.


======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值