我在网上看了一段别人写的一个发送屏幕图像.他那个是服务端得到屏幕图像后发给客户端显示出来的.我现在我想直接发送硬盘上某个图片比如(D:\ceshi.bmp)发给客户端它在显示出来并保存到客户机的某个目录中.程序全部代码如下:
unit Unit1;{服务端程序}
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, JPEG,ExtCtrls, ScktComp;
type
TForm1 = class(Tform)
ServerSocket1: TServerSocket;
procedure ServerSocket1ClientRead(Sender: Tobject;Socket: TCustomWinSocket);
procedure FormCreate(Sender: Tobject);
procedure FormClose(Sender: Tobject; var Action: TCloseAction);
private
procedure Cjt_GetScreen(var Mybmp: Tbitmap; DrawCur: Boolean);
{自定义抓屏函数,DrawCur表示抓鼠标图像与否}
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
MyStream: Tmemorystream;{内存流对象} 
implementation
{$R *.DFM}
procedure TForm1.Cjt_GetScreen(var Mybmp: Tbitmap; DrawCur: Boolean);
var
Cursorx, Cursory: integer;
dc: hdc;
Mycan: Tcanvas;
R: Trect;
DrawPos: Tpoint;
MyCursor: Ticon;
hld: hwnd;
Threadld: dword;
mp: tpoint;
pIconInfo: TIconInfo;
begin
Mybmp := Tbitmap.Create; {建立BMPMAP }
Mycan := Tcanvas.Create; {屏幕截取}
dc := GetWindowDC(0);
try
Mycan.Handle := dc;
R := Rect(0, 0, screen.Width, screen.Height);
Mybmp.Width := R.Right;
Mybmp.Height := R.Bottom;
Mybmp.Canvas.CopyRect(R, Mycan, R);
finally
releaseDC(0, DC);
end;
Mycan.Handle := 0;
Mycan.Free;
if DrawCur 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);
Mybmp.Canvas.Draw(cursorx, cursory, MyCursor); {画上鼠标}
DeleteObject(pIconInfo.hbmColor);{GetIconInfo 使用时创建了两个bitmap对象. 需要手工释放这两个对象}
DeleteObject(pIconInfo.hbmMask);{否则,调用他后,他会创建一个bitmap,多次调用会产生多个,直至资源耗尽}
Mycursor.ReleaseHandle; {释放数组内存}
MyCursor.Free; {释放鼠标指针}
end; 
end;
procedure TForm1.FormCreate(Sender: Tobject);
begin
ServerSocket1.Port := 3000; {端口}
ServerSocket1.Open; {Socket开始侦听}
end;
procedure TForm1.FormClose(Sender: Tobject; var Action: TCloseAction);
begin
if ServerSocket1.Active then ServerSocket1.Close; {关闭Socket}
end;
procedure TForm1.ServerSocket1ClientRead(Sender: Tobject;
Socket: TCustomWinSocket);
var
S, S1: string;
MyBmp: Tbitmap;
Myjpg: Tjpegimage;
begin
S := Socket.ReceiveText;
if S = 'cap' then {客户端发出抓屏幕指令}
begin
try
MyStream := Tmemorystream.Create;{建立内存流}
MyBmp := Tbitmap.Create;
Myjpg := Tjpegimage.Create;
Cjt_GetScreen(MyBmp, True); {True表示抓鼠标图像}
Myjpg.Assign(MyBmp); {将BMP图象转成JPG格式,便于在互联网上传输}
Myjpg.CompressionQuality := 10; {JPG文件压缩百分比设置,数字越大图像越清晰,但数据也越大}
Myjpg.SaveToStream(MyStream); {将JPG图象写入流中}
Myjpg.free;
MyStream.Position := 0;{注意:必须添加此句}
s1 := inttostr(MyStream.size);{流的大小}
Socket.sendtext(s1); {发送流大小}
finally
MyBmp.free;
end;
end;
if s = 'ready' then {客户端已准备好接收图象}
begin
MyStream.Position := 0;
Socket.SendStream(MyStream); {将流发送出去}
end;
end;
end.
上面是服务端,下面我们来写客户端程序。新建一个工程,添加Socket控件ClientSocket、图像显示控件Image、一个 Panel 、一个Edit、两个 Button和一个状态栏控件StatusBar1。注意:把Edit1和两个 Button放在Panel1上面。ClientSocket的属性跟ServerSocket差不多,不过多了一个Address属性,表示要连接的服务端IP地址。填上IP地址后点"连接"将与服务端程序建立连接,如果成功就可以进行通讯了。点击"抓屏"将发送字符给服务端。因为程序用到了JPEG图像单元,所以要在Uses中添加Jpeg.
全部代码如下:
unit Unit2{客户端};
interface
uses
Windows,Messages,SysUtils,Classes,Graphics,Controls,Forms,Dialogs,StdCtrls,ScktComp,ExtCtrls,Jpeg, ComCtrls;
type
TForm1 = class(Tform)
ClientSocket1: TClientSocket;
Image1: Timage;
StatusBar1: TStatusBar;
Panel1: Tpanel;
Edit1: Tedit;
Button1: Tbutton;
Button2: Tbutton;
procedure Button1Click(Sender: Tobject);
procedure ClientSocket1Connect(Sender: Tobject;
Socket: TCustomWinSocket);
procedure Button2Click(Sender: Tobject);
procedure ClientSocket1Error(Sender: Tobject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
procedure ClientSocket1Read(Sender: Tobject; Socket: TCustomWinSocket);
procedure FormCreate(Sender: Tobject);
procedure FormClose(Sender: Tobject; var Action: TCloseAction);
procedure ClientSocket1Disconnect(Sender: Tobject;
Socket: TCustomWinSocket);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
MySize: Longint;
MyStream: Tmemorystream;{内存流对象}
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: Tobject);
begin
{-------- 下面为设置窗口控件的外观属性 ------------- }
{注意:把Button1、Button2和Edit1放在Panel1上面}
Edit1.Text := '127.0.0.1';
Button1.Caption := '连接主机';
Button2.Caption := '抓屏幕';
Button2.Enabled := false;
Panel1.Align := alTop;
Image1.Align := alClient;
Image1.Stretch := True;
StatusBar1.Align:=alBottom;
StatusBar1.SimplePanel := True;
{----------------------------------------------- }
MyStream := Tmemorystream.Create; {建立内存流对象}
MySize := 0; {初始化}
end;
procedure TForm1.Button1Click(Sender: Tobject);
begin
if not ClientSocket1.Active then
begin
ClientSocket1.Address := Edit1.Text; {远程IP地址}
ClientSocket1.Port := 3000; {Socket端口}
ClientSocket1.Open; {建立连接}
end;
end;
procedure TForm1.Button2Click(Sender: Tobject);
begin
Clientsocket1.Socket.SendText('cap'); {发送指令通知服务端抓取屏幕图象}
Button2.Enabled := False;
end;
procedure TForm1.ClientSocket1Connect(Sender: Tobject;
Socket: TCustomWinSocket);
begin
StatusBar1.SimpleText := '与主机' + ClientSocket1.Address + '成功建立连接!';
Button2.Enabled := True;
end;
procedure TForm1.ClientSocket1Error(Sender: Tobject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
Errorcode := 0; {不弹出出错窗口}
StatusBar1.SimpleText := '无法与主机' + ClientSocket1.Address + '建立连接!';
end;
procedure TForm1.ClientSocket1Disconnect(Sender: Tobject;
Socket: TCustomWinSocket);
begin
StatusBar1.SimpleText := '与主机' + ClientSocket1.Address + '断开连接!';
Button2.Enabled := False;
end;
procedure TForm1.ClientSocket1Read(Sender: Tobject;
Socket: TCustomWinSocket);
var
MyBuffer: array[0..10000] of byte; {设置接收缓冲区}
MyReceviceLength: integer;
S: string;
MyBmp: Tbitmap;
MyJpg: Tjpegimage;
begin
StatusBar1.SimpleText := '正在接收数据……';
if MySize = 0 then {MySize为服务端发送的字节数,如果为0表示为尚未开始图象接收}
begin
S := Socket.ReceiveText;
MySize := Strtoint(S); {设置需接收的字节数}
Clientsocket1.Socket.SendText('ready'); {发指令通知服务端开始发送图象}
end
else
begin {以下为图象数据接收部分}
MyReceviceLength := socket.ReceiveLength; {读出包长度}
StatusBar1.SimpleText := '正在接收数据,数据大小为:' + inttostr(MySize);
Socket.ReceiveBuf(MyBuffer, MyReceviceLength); {接收数据包并读入缓冲区内}
MyStream.Write(MyBuffer, MyReceviceLength); {将数据写入流中}
if MyStream.Size >= MySize then {如果流长度大于需接收的字节数,则接收完毕}
begin
MyStream.Position := 0;
MyBmp := tbitmap.Create;
MyJpg := tjpegimage.Create;
try
MyJpg.LoadFromStream(MyStream); {将流中的数据读至JPG图像对象中}
MyBmp.Assign(MyJpg); {将JPG转为BMP}
StatusBar1.SimpleText := '正在显示图像';
Image1.Picture.Bitmap.Assign(MyBmp); {分配给image1元件 }
finally {以下为清除工作 }
MyBmp.free;
MyJpg.free;
Button2.Enabled := true;
{ Socket.SendText('cap');添加此句即可连续抓屏 }
MyStream.Clear;
MySize := 0;
end;
end;
end;
end;
procedure TForm1.FormClose(Sender: Tobject; var Action: TCloseAction);
begin
MyStream.Free; {释放内存流对象}
if ClientSocket1.Active then ClientSocket1.Close; {关闭Socket连接}
end;
end.

解决方案 »

  1.   

    写的太乱78糟。。
    Socket.sendtext(s1); {发送流大小}
    S := Socket.ReceiveText;Socket.SendStream(MyStream); {将流发送出去}
    Socket.ReceiveBuf(MyBuffer, MyReceviceLength); {接收数据包并读入缓冲区内}
    这里发送用sendstream, 接收怎么用receivebuf?
    MyReceviceLength := socket.ReceiveLength; {读出包长度}
    难道这个长度不是MySize.if MySize = 0 then {MySize为服务端发送的字节数,如果为0表示为尚未开始图象接收}
    begin
    end
    else
    begin
    end你这个用得不明不白。
      

  2.   

    从你提供的代码来看 服务端MyStream的对象没创建。别的地方都可以用。至少你能够看见远程的桌面图像
      

  3.   

    unit Unit1; { 服务端程序 }interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      JPEG, ExtCtrls, ScktComp;type
      TForm1 = class(Tform)
        ServerSocket1: TServerSocket;
        procedure ServerSocket1ClientRead(Sender: Tobject;
          Socket: TCustomWinSocket);
        procedure FormCreate(Sender: Tobject);
        procedure FormClose(Sender: Tobject; var Action: TCloseAction);
      private
        // procedure Cjt_GetScreen(var Mybmp: Tbitmap; DrawCur: Boolean);
        { 自定义抓屏函数,DrawCur表示抓鼠标图像与否 }
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;
      MyStream: Tmemorystream; { 内存流对象 }implementation{$R *.DFM}
    // procedure TForm1.Cjt_GetScreen(var Mybmp: Tbitmap; DrawCur: Boolean);
    // var
    // Cursorx, Cursory: integer;
    // dc: hdc;
    // Mycan: Tcanvas;
    // R: Trect;
    // DrawPos: Tpoint;
    // MyCursor: Ticon;
    // hld: hwnd;
    // Threadld: dword;
    // mp: Tpoint;
    // pIconInfo: TIconInfo;
    // begin
    // Mybmp := Tbitmap.Create; { 建立BMPMAP }
    // Mycan := Tcanvas.Create; { 屏幕截取 }
    // dc := GetWindowDC(0);
    // try
    // Mycan.Handle := dc;
    // R := Rect(0, 0, screen.Width, screen.Height);
    // Mybmp.Width := R.Right;
    // Mybmp.Height := R.Bottom;
    // Mybmp.Canvas.CopyRect(R, Mycan, R);
    // finally
    // releaseDC(0, dc);
    // end;
    // Mycan.Handle := 0;
    // Mycan.Free;
    // if DrawCur 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);
    // Mybmp.Canvas.Draw(Cursorx, Cursory, MyCursor); { 画上鼠标 }
    // DeleteObject(pIconInfo.hbmColor);
    // { GetIconInfo 使用时创建了两个bitmap对象. 需要手工释放这两个对象 }
    // DeleteObject(pIconInfo.hbmMask); { 否则,调用他后,他会创建一个bitmap,多次调用会产生多个,直至资源耗尽 }
    // MyCursor.ReleaseHandle; { 释放数组内存 }
    // MyCursor.Free; { 释放鼠标指针 }
    // end;
    // end;procedure TForm1.FormCreate(Sender: Tobject);
    begin
      ServerSocket1.Port := 3000; { 端口 }
      ServerSocket1.Open; { Socket开始侦听 }
    end;procedure TForm1.FormClose(Sender: Tobject; var Action: TCloseAction);
    begin
      if ServerSocket1.Active then
        ServerSocket1.Close; { 关闭Socket }
    end;procedure TForm1.ServerSocket1ClientRead(Sender: Tobject;
      Socket: TCustomWinSocket);
    var
      S, S1: string;
      Mybmp: Tbitmap;
      Myjpg: Tjpegimage;
    begin
      S := Socket.ReceiveText;
      if S = 'cap' then { 客户端发出抓屏幕指令 }
      begin
        try
          MyStream := Tmemorystream.Create; { 建立内存流 }
          Mybmp := Tbitmap.Create;
          Mybmp.LoadFromFile('c:\Test.bmp');
          Myjpg := Tjpegimage.Create;
          // Cjt_GetScreen(Mybmp, True); { True表示抓鼠标图像 }
          Myjpg.Assign(Mybmp); { 将BMP图象转成JPG格式,便于在互联网上传输 }
          Myjpg.CompressionQuality := 10; { JPG文件压缩百分比设置,数字越大图像越清晰,但数据也越大 }
          Myjpg.SaveToStream(MyStream); { 将JPG图象写入流中 }
          Myjpg.Free;
          MyStream.Position := 0; { 注意:必须添加此句 }
          S1 := inttostr(MyStream.size); { 流的大小 }
          Socket.sendtext(S1); { 发送流大小 }
        finally
          Mybmp.Free;
        end;
      end;
      if S = 'ready' then { 客户端已准备好接收图象 }
      begin
        MyStream.Position := 0;
        Socket.SendStream(MyStream); { 将流发送出去 }
      end;
    end;end.
    //=============================================================================
    { 客户端新增一个 Button3 }
    unit Unit1 { 客户端 };interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls, ScktComp, ExtCtrls, JPEG, ComCtrls;type
      TForm1 = class(Tform)
        ClientSocket1: TClientSocket;
        Image1: Timage;
        StatusBar1: TStatusBar;
        Panel1: Tpanel;
        Edit1: Tedit;
        Button1: Tbutton;
        Button2: Tbutton;
        Button3: Tbutton;
        procedure Button1Click(Sender: Tobject);
        procedure ClientSocket1Connect(Sender: Tobject; Socket: TCustomWinSocket);
        procedure Button2Click(Sender: Tobject);
        procedure ClientSocket1Error(Sender: Tobject; Socket: TCustomWinSocket;
          ErrorEvent: TErrorEvent; var ErrorCode: integer);
        procedure ClientSocket1Read(Sender: Tobject; Socket: TCustomWinSocket);
        procedure FormCreate(Sender: Tobject);
        procedure FormClose(Sender: Tobject; var Action: TCloseAction);
        procedure ClientSocket1Disconnect(Sender: Tobject;
          Socket: TCustomWinSocket);
        procedure Button3Click(Sender: Tobject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;
      MySize: Longint;
      MyStream: Tmemorystream; { 内存流对象 }implementation{$R *.DFM}procedure TForm1.FormCreate(Sender: Tobject);
    begin
      { -------- 下面为设置窗口控件的外观属性 ------------- }
      { 注意:把Button1、Button2和Edit1放在Panel1上面 }
      Edit1.Text := '127.0.0.1';
      Button1.Caption := '连接主机';
      Button2.Caption := '抓屏幕';
      Button3.Caption := '保存';
      Button2.Enabled := False;
      Button3.Enabled := False;
      Panel1.Align := alTop;
      Image1.Align := alClient;
      Image1.Stretch := True;
      StatusBar1.Align := alBottom;
      StatusBar1.SimplePanel := True;
      { ----------------------------------------------- }
      MyStream := Tmemorystream.Create; { 建立内存流对象 }
      MySize := 0; { 初始化 }
    end;procedure TForm1.Button1Click(Sender: Tobject);
    begin
      if not ClientSocket1.Active then
      begin
        ClientSocket1.Address := Edit1.Text; { 远程IP地址 }
        ClientSocket1.Port := 3000; { Socket端口 }
        ClientSocket1.Open; { 建立连接 }
      end;
    end;procedure TForm1.Button2Click(Sender: Tobject);
    begin
      ClientSocket1.Socket.sendtext('cap'); { 发送指令通知服务端抓取屏幕图象 }
      Button2.Enabled := False;
      Button3.Enabled := True;
    end;procedure TForm1.Button3Click(Sender: Tobject);
    begin
      Image1.Picture.SaveToFile('C:\Test2.jpg');
    end;procedure TForm1.ClientSocket1Connect(Sender: Tobject;
      Socket: TCustomWinSocket);
    begin
      StatusBar1.SimpleText := '与主机' + ClientSocket1.Address + '成功建立连接!';
      Button2.Enabled := True;
    end;procedure TForm1.ClientSocket1Error(Sender: Tobject; Socket: TCustomWinSocket;
      ErrorEvent: TErrorEvent; var ErrorCode: integer);
    begin
      ErrorCode := 0; { 不弹出出错窗口 }
      StatusBar1.SimpleText := '无法与主机' + ClientSocket1.Address + '建立连接!';
    end;procedure TForm1.ClientSocket1Disconnect(Sender: Tobject;
      Socket: TCustomWinSocket);
    begin
      StatusBar1.SimpleText := '与主机' + ClientSocket1.Address + '断开连接!';
      Button2.Enabled := False;
    end;procedure TForm1.ClientSocket1Read(Sender: Tobject; Socket: TCustomWinSocket);
    var
      MyBuffer: array [0 .. 10000] of byte; { 设置接收缓冲区 }
      MyReceviceLength: integer;
      S: string;
      Mybmp: Tbitmap;
      Myjpg: Tjpegimage;
    begin
      StatusBar1.SimpleText := '正在接收数据……';
      if MySize = 0 then { MySize为服务端发送的字节数,如果为0表示为尚未开始图象接收 }
      begin
        S := Socket.ReceiveText;
        MySize := Strtoint(S); { 设置需接收的字节数 }
        ClientSocket1.Socket.sendtext('ready'); { 发指令通知服务端开始发送图象 }
      end
      else
      begin { 以下为图象数据接收部分 }
        MyReceviceLength := Socket.ReceiveLength; { 读出包长度 }
        StatusBar1.SimpleText := '正在接收数据,数据大小为:' + inttostr(MySize);
        Socket.ReceiveBuf(MyBuffer, MyReceviceLength); { 接收数据包并读入缓冲区内 }
        MyStream.Write(MyBuffer, MyReceviceLength); { 将数据写入流中 }
        if MyStream.size >= MySize then { 如果流长度大于需接收的字节数,则接收完毕 }
        begin
          MyStream.Position := 0;
          Mybmp := Tbitmap.Create;
          Myjpg := Tjpegimage.Create;
          try
            Myjpg.LoadFromStream(MyStream); { 将流中的数据读至JPG图像对象中 }
            Mybmp.Assign(Myjpg); { 将JPG转为BMP }
            StatusBar1.SimpleText := '正在显示图像';
            Image1.Picture.Bitmap.Assign(Mybmp); { 分配给image1元件 }
          finally { 以下为清除工作 }
            Mybmp.Free;
            Myjpg.Free;
            Button2.Enabled := True;
            { Socket.SendText('cap');添加此句即可连续抓屏 }
            MyStream.Clear;
            MySize := 0;
          end;
        end;
      end;
    end;procedure TForm1.FormClose(Sender: Tobject; var Action: TCloseAction);
    begin
      MyStream.Free; { 释放内存流对象 }
      if ClientSocket1.Active then
        ClientSocket1.Close; { 关闭Socket连接 }
    end;end.
      

  4.   

    如果是局域网倒是很简单  可以给你发个小例子。Intenet的话,因为服务器的问题,比较麻烦