procedure SaveScrToStream();         //屏幕截取函数
var winHWND :integer;
     winDC:integer;
     rect:TRect;
     fBitmap:TBitmap;
begin
     winHWND := GetDesktopWindow();
     winDC := GetDC(winHWND);
     fBitmap := TBitmap.create;
     fBitmap.width := screen.Width;
     fBitmap.height := screen.Height;     BitBlt(fBitmap.canvas.handle, 0, 0, fBitmap.width, fBitmap.height, winDC, 0, 0, SRCCOPY);
     fBitmap.SaveToFile('c:\aa.bmp');
     fBitmap.PixelFormat :=pf8bit;
     fBitmap.Free;
end;//连接要做的事
procedure TForm1.CS_Connect(Sender: TObject; Socket: TCustomWinSocket);
beginm.Position := 0;socket.SendStream(m);cs.OnDisconnect:=CS_DisConnect;
end;
//关闭
procedure TForm1.CS_DisConnect(Sender: TObject; Socket: TCustomWinSocket);
begin
  (Sender as TClientSocket).socket.close;
end;
//点击按钮发送消息
procedure TForm1.Button1Click(Sender: TObject);begin
  cs:= TClientSocket.Create(nil);
  cs.Host:='192.168.0.21';
  cs.Port:= 1234;
  SaveScrToStream();  m.Free;  m := tfilestream.Create('C:\aa.bmp',fmOpenRead );  cs.OnConnect:= CS_Connect;
  
  cs.Open;
end;第一次在服务器端已经完整传过去了,第二次的时候出现External exception C0000008的错误

解决方案 »

  1.   

    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.
      

  2.   

    我有这方面的vc源码,涉及到用动态jpeg压缩方法在服务端处理数据,然后通过缓存数据流传输数据,c/s 结构,两端程序,有兴趣就跟我联系。qq 149431298你也可以看页面http://auction1.taobao.com/auction/0/item_detail-0db1-4a08b41441d8c9cb1e8de30d1b65cce2.jhtml里面有详细的功能说明。
      

  3.   

    show_20() 
    以上代码在D7中亲测通过,非常方便,一个字,爽------------------
    你这种代码也就只能在局域网中用。CPU占用还要100%,才能得到每秒5帧的更新速率现在我做了一个 15fps 的,CPU只占40%
      

  4.   


    VC++.delphi
    VB C# .NET远程屏幕监视
    局域网屏幕监视
    局域网桌面监视
    屏幕监控
    屏幕抓取
    屏幕传输
    屏幕截图
    QQ交流群:33367148
      

  5.   

    QQ群 DELPHI远程监控专家论坛本群专业讨论 计算机远程监控相关问题
    本群由原来近200人精简到目前几十人的精英,淘汰了若干无助群发展的人
    现在需要继续壮大本群,望有意者\高手\专家们加盟
    QQ群号:29489381务必注意:加入时请看群公告内容,否则将会取消成员资格