{抓屏幕图像,保存为内存流--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;
}
{还原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流 //uses jpeg
jpgstream:= TJPEGImage.Create;
jpgstream.Assign(image.picture.bitmap);
jpgstream.CompressionQuality:=50;//压缩质量
jpgstream.Compress;
jpgstream.SaveToStream(memoryStream);//保存为JPG流
//使用JPG流 image.Picture.Assign(jpgstream);
jpgstream.free;
}ReleaseDC(0,ss.Handle);
image.free;{发送内存流...}
end;

解决方案 »

  1.   

    用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;{ 发送每一笔数据的缓冲区大小 }varBmpStream:TMemoryStream;LeftSize:Longint;{ 发送每一笔数据后剩余的字节数 }
    为Client的OnCreate事件添加代码:procedure TClient.FormCreate(Sender: TObject);beginBmpStream:=TMemoryStream.Create;end;
    为Client的OnDestroy事件添加代码:procedure TClient.FormDestroy(Sender: TObject);beginBmpStream.Free;end;
    为控件CUDP的OnDataReceived事件添加代码:procedure TClient.CUDPDataReceived(Sender: TComponent;NumberBytes: Integer; FromIP: String);varCtrlCode:array[0..29] of char;Buf:array[0..BufSize-1] of char;TmpStr:string;SendSizeLeftPosTopPosRightPosBottomPos:integer;beginCUDP.ReadBuffer(CtrlCodeNumberBytes);{ 读取控制码 }if CtrlCode[0]+CtrlCode[1]+CtrlCode[2]+CtrlCode[3]='show' thenbegin { 控制码前4位为“show”表示主控机发出了抓屏指令 }if BmpStream.Size=0 then { 没有数据可发,必须截屏生成数据 }beginTmpStr:=StrPas(CtrlCode);TmpStr:=Copy(TmpStr5Length(TmpStr)-4);LeftPos:=StrToInt(Copy(TmpStr1Pos(':'TmpStr)-1));TmpStr:=Copy(TmpStrPos(':'TmpStr)+1Length(TmpStr)-Pos(':'TmpStr));TopPos:=StrToInt(Copy(TmpStr1Pos(':'TmpStr)-1));TmpStr:=Copy(TmpStrPos(':'TmpStr)+1Length(TmpStr)-Pos(':'TmpStr));RightPos:=StrToInt(Copy(TmpStr1Pos(':'TmpStr)-1));BottomPos:=StrToInt(Copy(TmpStrPos(':'TmpStr)+1Length(TmpStr)-Pos(':'TmpStr)));ScreenCap(LeftPosTopPosRightPosBottomPos); {截取屏幕 }end;if LeftSize>BufSize then SendSize:=BufSizeelse SendSize:=LeftSize;BmpStream.ReadBuffer(BufSendSize);LeftSize:=LeftSize-SendSize;if LeftSize=0 then BmpStream.Clear;{ 清空流 }CUDP.RemoteHost:=FromIP; { FromIP为主控机IP地址 }CUDP.SendBuffer(BufSendSize); { 将数据发到主控机的2222口 }end;end;
    其中ScreenCap是自定义函数,截取屏幕指定区域,代码如下:procedure TClient.ScreenCap(LeftPosTopPos
    RightPosBottomPos:integer);varRectWidthRectHeight:integer;SourceDCDestDCBhandle:integer;Bitmap:TBitmap;beginRectWidth:=RightPos-LeftPos;RectHeight:=BottomPos-TopPos;SourceDC:=CreateDC('DISPLAY'''''nil);DestDC:=CreateCompatibleDC(SourceDC);Bhandle:=CreateCompatibleBitmap(SourceDC
    RectWidthRectHeight);SelectObject(DestDCBhandle);BitBlt(DestDC00RectWidthRectHeightSourceDC
    LeftPosTopPosSRCCOPY);Bitmap:=TBitmap.Create;Bitmap.Handle:=BHandle;BitMap.SaveToStream(BmpStream);BmpStream.Position:=0;LeftSize:=BmpStream.Size;Bitmap.Free;DeleteDC(DestDC);ReleaseDC(BhandleSourceDC);end;存为“C:\VClient\ClnUnit.pas”和“C:\VClient\VClient.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;varRsltStreamTmpStream:TMemoryStream;
    为Server的OnCreate事件添加代码:procedure TServer.FormCreate(Sender: TObject);beginRsltStream:=TMemoryStream.Create;TmpStream:=TMemoryStream.Create;end;
    为Client的OnDestroy事件添加代码:procedure TServer.FormDestroy(Sender: TObject);beginRsltStream.Free;TmpStream.Free;end;
    为控件Button1的OnClick事件添加代码:procedure TServer.Button1Click(Sender: TObject);var ReqCode:array[0..29] of char;ReqCodeStr:string;beginReqCodeStr:='show'+Edit1.Text;StrpCopy(ReqCodeReqCodeStr);TmpStream.Clear;RsltStream.Clear;SUDP.RemoteHost:=Edit2.Text;SUDP.SendBuffer(ReqCode30);end;
    为控件SUDP的OnDataReceived事件添加代码:procedure TServer.SUDPDataReceived(Sender: TComponent;NumberBytes: Integer; FromIP: String);var ReqCode:array[0..29] of char;ReqCodeStr:string;beginReqCodeStr:='show'+Edit1.text;StrpCopy(ReqCodeReqCodeStr);SUDP.ReadStream(TmpStream);RsltStream.CopyFrom(TmpStreamNumberBytes);if NumberBytes< BufSize then { 数据已读完 }beginRsltStream.Position:=0;Image1.Picture.Bitmap.LoadFromStream(RsltStream);TmpStream.Clear;RsltStream.Clear;endelsebeginTmpStream.Clear;ReqCode:='show';SUDP.RemoteHost:=Edit2.Text;SUDP.SendBuffer(ReqCode30);end;end;
    存为“C:\VServer\SvrUnit.pas”和“C:\VServer\VServer.dpr”,并编译。四、测试。
    1、本地机测试:在本地机同时运行Vserver.exe和VClient.exe,利用程序的默认设置,即可实现截屏。查看“控制面板”-“网络”-“TCP/IP”-“IP地址”,将程序的“客户IP地址”设为该地址 ,同样正常运行。
    2、远程测试:选一台受控机,运行VClient.exe;另选一台主控机,运行VServer.exe,将“受控机IP地址”即Edit2的内容设为受控机的IP地址,“截屏”即可。以上简要介绍了远程屏幕抓取的实现方法,至于在主控机上一屏同时监视多个受控机,读者可自行完善。以上程序,在Windows98对等网、Delphi 4.0下调试通过。
      

  2.   

    TO 小新:
       OK,我试试 !
      

  3.   

    用Delphi实现远程控制 
     
    ---- WinSock是一组API,用于在网络上传输数据和交换信息。虽然现在有很多工具如FTP程序可以在网络上传输数据和文件,但是通过WinSock编程有更大的灵活性,它不需要关心网络连接的细节,然而用WinSock编程却很复杂,但是在Delphi中我们并不需要直接与WinSock的API打交道,因为TClientSocket元件和TServerSocket元件(在Internet页)封装了WinSock的大部分API,使得对WinSock的访问大大简化。下面这个远程控制的例子就很清楚地说明了这个问题,它可以发送一个消息给对方,并能够使对方的电脑关闭、重新启动或重新登录。  
     
    一、实现原理  
    ---- 实行远程控制,实际上就是一个服务器程序(以下简称被控程序)和一个客户程序(以下简称主控程序):被控方即为服务器程序,它监听客户的请求,并作出处理;主控方即为客户程序,它连接上服务器后,发出自己的请求,服务器便根据自已的请求进行不同的响应。  
    二、编写主控程序  
    ---- 1、新建一个项目Client.dpr,并把一个TClientSocket元件放到Form上,它的属性设置如下:Port设为100(端口号可任意设置,只要求双方统一),其它属性按默认值。在窗体上添加两个TEdit:Edit1用来输入发送的字符,Edit2用来输入IP地址;添加两个TButton:Button1点击后用来连接被控机,Button2点击后用来发送字符,然后声明一个私有变量ConnectFlag,表示双方是否连接好:  
           private 
             ConnectFlag:Boolean; 
     
    ---- 2、ClientSocket1的OnConnect事件代码如下:  
           procedure TForm1.ClientSocket1Connect 
    (Sender: TObject;Socket: TCustomWinSocket); 
           begin  
             ConnectFlag:=True; //表示连接成功 
           end; 
     
    ---- 3、ClientSocket1的OnError事件代码如下:  
    procedure TForm1.ClientSocket1Error(Sender: TObject; 
    Socket: TCustomWinSocket; ErrorEvent:  
    TErrorEvent;var ErrorCode: Integer); 
           begin 
    Application.MessageBox(PChar('    不能连接到IP地址 
     : ' + Edit2.Text+'。'+ 
    #13+'可能是监听程序没有运行或网络故障!'),' 
    连接错误',MB_OK+MB_ICONSTOP); 
              ErrorCode := 0;  
           end; 
     
    ---- 4、Button1的OnClick事件代码如下:  
    procedure TForm1.Button1Click(Sender: TObject); 
    begin 
    with ClientSocket1 do  begin 
    if Active then begin 
    Active := False;//在连接之前首先关闭 
    ConnectFlag:=False; //置连接标志为假 
    end; 
    if Length(Edit2.Text) > 0 then begin 
    Host := Edit2.Text; //指定IP地址或主机名 
    Active := True;      
                end;    
              end; 
           end; 
     
    ---- 5、Button2的OnClick事件代码如下:  
    procedure TForm1.Button2Click(Sender: TObject); 
           begin 
              if ConnectFlag then 
    ClientSocket1.Socket.SendText(Edit1.Text) 
      //如果连接成功则发送字符串 
              else 
    Application.MessageBox(PChar('    没有连接到地址 : 
     ' + Edit2.Text+'。'+ 
    #13+'检查IP地址是否存在或是否已经连接!'),' 
    提示信息',MB_OK+MB_ICONSTOP); 
           end;     
     
    三、编写被控程序  
    ---- 1、新建一个项目Server.dpr,并把一个TServerSocket元件放到Form上,它的属性设置如下:Active设为True;Port设为100,其它属性按默认值。  
    ---- 2、ServerSocket1的OnClientRead事件代码如下:  
     
    procedure TForm1.ServerSocket1ClientRead 
    (Sender: TObject;Socket: TCustomWinSocket); 
           var 
             Str:PChar; 
             Code,V:Integer; 
           begin 
       Str:=PChar(Socket.ReceiveText);  //接收字符串 
    Val(Str,V,Code); //处理接收的字符串,首先转换字符串为整数    
      if Code< >0 then   
    Application.MessageBox(Str,'提示信息', 
    MB_OK+MB_ICONINFORMATION)  
    //如果转换后的数据不是一个整型数就通过消息框来显示字符串 
             else 
               if (V=0)or(V=1)or(V=2) then  
                 ExitWindowsEx(V,0)  
    //调用Windows的API函数(V=0表示重新登录、 
    V=1表示关机、V=2表示重启动) 
               else 
    Application.MessageBox(Str,'提示信息', 
    MB_OK+MB_ICONINFORMATION);  
    //转换后数据不为0、1、2时在消息框内显示字符串 
           end; 
     
    ---- 3、修改项目文件,不让窗口显示并且防止它运行两次,修改begin和end之间的代码如下:  
           begin 
    Application.Initialize; 
    if FindWindow('TForm1','Form1')=0 then begin  
    //当没有找到Form1时执行下面代码 
    Application.ShowMainForm:=False; //不显示主窗口 
    Application.CreateForm(TForm1, Form1); 
    Application.Run; 
              end; 
           end. 
     
    四、注意事项  
    ---- 1、网络要装配正确并安装TCP/IP协议,且要正常运行。  
    ---- 2、首先要运行被控程序。  
     
    ---- 3、必须知道对方的IP地址或主机名。
      

  4.   

    这一步我早已完成,我想请教的是类似于PCanywhere软件的控制,对远程点的完全控制,呃,大概就是这样,主要是真对我们的一个远程网点的控制。可以骂 ?
      

  5.   

    sorry,最近比较忙,上网的地方改变了,资料只能迟一点帮你找,抱歉
      

  6.   

    远程控制编程揭密
     
    将远程控制应用于教学中,已成为目前计算机化教学的重要手段。一定有很多的网虫想了解
    这种网络教学方式的编程原理吧。在此我们就以一个简单的远程控制程序作为示例,说明这
    种网络编程的基本原理。本程序以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 );
    以上做法对大多数键有效,少数键要用到不同的值远程控制篇:获得网络邻居所有机器名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;连同上面的屏幕抓取,应该是相对完整的一份远程控制文档,good luck。
    做出好东西不要忘了给我一份,不过不要黑我哦!