CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
山寨机中的战斗机! 程序优化工程师到底对IT界有没有贡献
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  VC/MFC >  基础类

怎样不通过文件共享来播放某个远程机上的VCD文件

楼主thedream(梦幻使者)2002-02-24 22:28:41 在 VC/MFC / 基础类 提问

怎样不通过文件共享来播放某个远程机上的VCD文件 问题点数:200、回复次数:7Top

1 楼littleXX(游鱼)回复于 2002-02-24 23:13:11 得分 0

DirectShow罗。Top

2 楼new_guy(蓝调刀锋)(乘风破浪会有时,直挂云帆济沧海)回复于 2002-02-24 23:31:32 得分 0

超级解霸的广播功能  
  还有其他很多播放软件Top

3 楼emailz(虫子)回复于 2002-02-24 23:49:10 得分 100

给你贴一段  
                                                    谈Delphi编程中“流”的应用  
   
                                                                                                        陈经韬  
   
   
        什么是流?流,简单来说就是建立在面向对象基础上的一种抽象的处理数据的工具。在流中,定义了一些处理数据的基本操作,如读取数据,写入数据等,程序员是对流进行所有操作的,而不用关心流的另一头数据的真正流向。流不但可以处理文件,还可以处理动态内存、网络数据等多种数据形式。如果你对流的操作非常熟练,在程序中利用流的方便性,写起程序会大大提高效率的。  
      下面,笔者通过四个实例:EXE文件加密器、电子贺卡、自制OICQ和网络屏幕传输来说明Delphi编程中“流”的利用。这些例子中的一些技巧曾经是很多软件的秘密而不公开的,现在大家可以无偿的直接引用其中的代码了。  
      “万丈高楼平地起”,在分析实例之前,我们先来了解一下流的基本概念和函数,只有在理解了这些基本的东西后我们才能进行下一步。请务必认真领会这些基本方法。当然,如果你对它们已经很熟悉了,则可以跳过这一步。  
   
  一、Delphi中流的基本概念及函数声明  
  在Delphi中,所有流对象的基类为TStream类,其中定义了所有流的共同属性和方法。  
  TStream类中定义的属性介绍如下:  
  1、Size:此属性以字节返回流中数据大小。  
  2、Position:此属性控制流中存取指针的位置。  
  Tstream中定义的虚方法有四个:  
  1、Read:此方法实现将数据从流中读出。函数原形为:  
  Function   Read(var   Buffer;Count:Longint):Longint;virtual;abstract;  
  参数Buffer为数据读出时放置的缓冲区,Count为需要读出的数据的字节数,该方法返回值为实际读出的字节数,它可以小于或等于Count中指定的值。  
  2、Write:此方法实现将数据写入流中。函数原形为:  
  Function   Write(var   Buffer;Count:Longint):Longint;virtual;abstract;  
  参数Buffer为将要写入流中的数据的缓冲区,Count为数据的长度字节数,该方法返回值为实际写入流中的字节数。  
  3、Seek:此方法实现流中读取指针的移动。函数原形为:  
  Function   Seek(Offset:Longint;Origint:Word):Longint;virtual;abstract;  
  参数Offset为偏移字节数,参数Origint指出Offset的实际意义,其可能的取值如下:  
  soFromBeginning:Offset为移动后指针距离数据开始的位置。此时Offset必须大于或者等于零。  
  soFromCurrent:Offset为移动后指针与当前指针的相对位置。  
  soFromEnd:Offset为移动后指针距离数据结束的位置。此时Offset必须小于或者等于零。该方法返回值为移动后指针的位置。  
  4、Setsize:此方法实现改变数据的大小。函数原形为:  
  Function   Setsize(NewSize:Longint);virtual;  
  另外,TStream类中还定义了几个静态方法:  
  1、ReadBuffer:此方法的作用是从流中当前位置读取数据。函数原形为:  
  Procedure   ReadBuffer(var   Buffer;Count:Longint);  
  参数的定义跟上面的Read相同。注意:当读取的数据字节数与需要读取的字节数不相同时,将产生EReadError异常。  
  2、WriteBuffer:此方法的作用是在当前位置向流写入数据。函数原形为:  
  Procedure   WriteBuffer(var   Buffer;Count:Longint);  
  参数的定义跟上面的Write相同。注意:当写入的数据字节数与需要写入的字节数不相同时,将产生EWriteError异常。  
  3、CopyFrom:此方法的作用是从其它流中拷贝数据流。函数原形为:  
  Function   CopyFrom(Source:TStream;Count:Longint):Longint;  
  参数Source为提供数据的流,Count为拷贝的数据字节数。当Count大于0时,CopyFrom从Source参数的当前位置拷贝Count个字节的数据;当Count等于0时,CopyFrom设置Source参数的Position属性为0,然后拷贝Source的所有数据;  
  TStream还有其它派生类,其中最常用的是TFileStream类。使用TFileStream类来存取文件,首先要建立一个实例。声明如下:  
  constructor   Create(const   Filename:string;Mode:Word);  
  Filename为文件名(包括路径),参数Mode为打开文件的方式,它包括文件的打开模式和共享模式,其可能的取值和意义如下:  
   
  打开模式:  
  fmCreate   :用指定的文件名建立文件,如果文件已经存在则打开它。  
  fmOpenRead   :以只读方式打开指定文件  
  fmOpenWrite   :以只写方式打开指定文件  
  fmOpenReadWrite:以写写方式打开指定文件  
  共享模式:  
  fmShareCompat   :共享模式与FCBs兼容  
  fmShareExclusive:不允许别的程序以任何方式打开该文件  
  fmShareDenyWrite:不允许别的程序以写方式打开该文件  
  fmShareDenyRead   :不允许别的程序以读方式打开该文件  
  fmShareDenyNone   :别的程序可以以任何方式打开该文件  
   
  TStream还有一个派生类TMemoryStream,实际应用中用的次数也非常频繁。它叫内存流,就是说在内存中建立一个流对象。它的基本方法和函数跟上面是一样的。  
  好了,有了上面的基础后,我们就可以开始我们的编程之行了。  
  -----------------------------------------------------------------------  
  二、实际应用之一:利用流制作EXE文件加密器、捆绑、自解压文件及安装程序  
   
      我们先来说一下如何制作一个EXE文件加密器吧。    
      EXE文件加密器的原理:建立两个文件,一个用来添加资源到另外一个EXE文件里面,称为添加程序。另外一个被添加的EXE文件称为头文件。该程序的功能是把添加到自己里面的文件读出来。Windows下的EXE文件结构比较复杂,有的程序还有校验和,当发现自己被改变后会认为自己被病毒感染而拒绝执行。所以我们把文件添加到自己的程序里面,这样就不会改变原来的文件结构了。我们先写一个添加函数,该函数的功能是把一个文件当作一个流添加到另外一个文件的尾部。函数如下:  
   
  Function   Cjt_AddtoFile(SourceFile,TargetFile:string):Boolean;  
  var  
  Target,Source:TFileStream;  
  MyFileSize:integer;  
  begin  
  try  
  Source:=TFileStream.Create(SourceFile,fmOpenRead   or   fmShareExclusive);  
  Target:=TFileStream.Create(TargetFile,fmOpenWrite   or   fmShareExclusive);  
  try  
  Target.Seek(0,soFromEnd);//往尾部添加资源  
  Target.CopyFrom(Source,0);  
  MyFileSize:=Source.Size+Sizeof(MyFileSize);//计算资源大小,并写入辅程尾部  
  Target.WriteBuffer(MyFileSize,sizeof(MyFileSize));  
  finally  
  Target.Free;  
  Source.Free;  
  end;  
  except  
  Result:=False;  
  Exit;  
  end;  
  Result:=True;  
  end;  
  有了上面的基础,我们应该很容易看得懂这个函数。其中参数SourceFile是要添加的文件,参数TargetFile是被添加到的目标文件。比如说把a.exe添加到b.exe里面可以:Cjt_AddtoFile('a.exe',b.exe');如果添加成功就返回True否则返回假。  
  根据上面的函数我们可以写出相反的读出函数:  
  Function   Cjt_LoadFromFile(SourceFile,TargetFile   :string):Boolean;  
  var  
  Source:TFileStream;  
  Target:TMemoryStream;  
  MyFileSize:integer;  
  begin  
  try  
  Target:=TMemoryStream.Create;  
  Source:=TFileStream.Create(SourceFile,fmOpenRead   or   fmShareDenyNone);  
  try  
  Source.Seek(-sizeof(MyFileSize),soFromEnd);  
  Source.ReadBuffer(MyFileSize,sizeof(MyFileSize));//读出资源大小  
  Source.Seek(-MyFileSize,soFromEnd);//定位到资源位置  
  Target.CopyFrom(Source,MyFileSize-sizeof(MyFileSize));//取出资源  
  Target.SaveToFile(TargetFile);//存放到文件  
  finally  
  Target.Free;  
  Source.Free;  
  end;  
  except  
  Result:=false;  
  Exit;  
  end;  
  Result:=true;  
  end;  
      其中参数SourceFile是已经添加了文件的文件名称,参数TargetFile是取出文件后保存的目标文件名。比如说Cjt_LoadFromFile('b.exe','a.txt');在b.exe中取出文件保存为a.txt。如果取出成功就返回True否则返回假。  
  打开Delphi,新建一个工程,在窗口上放上一个Edit控件Edit1和两个Button:Button1和Button2。Button的Caption属性分别设置为“确定”和“取消”。在Button1的Click事件中写代码:  
  var   S:string;  
  begin  
  S:=ChangeFileExt(Application.ExeName,'.Cjt');  
  if   Edit1.Text='790617'   then    
  begin  
  Cjt_LoadFromFile(Application.ExeName,S);  
  {取出文件保存在当前路径下并命名"原文件.Cjt"}  
  Winexec(pchar(S),SW_Show);{运行"原文件.Cjt"}  
  Application.Terminate;{退出程序}  
  end  
  else    
  Application.MessageBox('密码不对,请重新输入!','密码错误',MB_ICONERROR+MB_OK);  
      编译这个程序,并把EXE文件改名为head.exe。新建一个文本文件head.rc,内容为:   head   exefile   head.exe,然后把它们拷贝到Delphi的BIN目录下,执行Dos命令Brcc32.exe   head.rc,将产生一个head.res的文件,这个文件就是我们要的资源文件,先留着。  
      我们的头文件已经建立了,下面我们来建立添加程序。  
      新建一个工程,放上以下控件:一个Edit,一个Opendialog,两个Button1的Caption属性分别设置为"选择文件"和"加密"。在源程序中添加一句:{$R   head.res}并把head.res文件拷贝到程序当前目录下。这样一来就把刚才的head.exe跟程序一起编译了。  
      在Button1的Cilck事件里面写下代码:  
  if   OpenDialog1.Execute   then   Edit1.Text:=OpenDialog1.FileName;  
      在Button2的Cilck事件里面写下代码:  
  var   S:String;  
  begin  
  S:=ExtractFilePath(Edit1.Text);  
  if   ExtractRes('exefile','head',S+'head.exe')   then  
  if   Cjt_AddtoFile(Edit1.Text,S+'head.exe')   then  
  if   DeleteFile(Edit1.Text)   then  
  if   RenameFile(S+'head.exe',Edit1.Text)   then  
  Application.MessageBox('文件加密成功!','信息',MB_ICONINFORMATION+MB_OK)  
  else  
  begin  
  if   FileExists(S+'head.exe')   then   DeleteFile(S+'head.exe');  
  Application.MessageBox('文件加密失败!','信息',MB_ICONINFORMATION+MB_OK)  
  end;  
  end;  
  其中ExtractRes为自定义函数,它的作用是把head.exe从资源文件中取出来。  
  Function   ExtractRes(ResType,   ResName,   ResNewName   :   String):boolean;  
  var  
  Res   :   TResourceStream;  
  begin  
  try  
  ReTop

4 楼emailz(虫子)回复于 2002-02-24 23:49:58 得分 0

下面就可以开始制作我们的添加程序了。全部代码如下:  
  unit   Unit1;  
   
  interface  
   
  uses  
  Windows,   Messages,   SysUtils,   Classes,   Graphics,   Controls,   Forms,   Dialogs,  
  ExtCtrls,   StdCtrls,   ExtDlgs;  
   
  type  
  TForm1   =   class(TForm)  
  Edit1:   TEdit;  
  Button1:   TButton;  
  Button2:   TButton;  
  OpenPictureDialog1:   TOpenPictureDialog;  
  procedure   FormCreate(Sender:   TObject);  
  procedure   Button1Click(Sender:   TObject);  
  procedure   Button2Click(Sender:   TObject);  
  private  
  Function   ExtractRes(ResType,   ResName,   ResNewName   :   String):boolean;  
  Function   Cjt_AddtoFile(SourceFile,TargetFile:string):Boolean;  
  {   Private   declarations   }  
  public  
  {   Public   declarations   }  
  end;  
   
  var  
  Form1:   TForm1;  
   
  implementation  
   
  {$R   *.DFM}  
  Function   TForm1.ExtractRes(ResType,   ResName,   ResNewName   :   String):boolean;  
  var  
  Res   :   TResourceStream;  
  begin  
  try  
  Res   :=   TResourceStream.Create(Hinstance,   Resname,   Pchar(ResType));  
  try  
  Res.SavetoFile(ResNewName);  
  Result:=true;  
  finally  
  Res.Free;  
  end;  
  except  
  Result:=false;  
  end;  
  end;  
  Function   TForm1.Cjt_AddtoFile(SourceFile,TargetFile:string):Boolean;  
  var  
  Target,Source:TFileStream;  
  MyFileSize:integer;  
  begin  
  try  
  Source:=TFileStream.Create(SourceFile,fmOpenRead   or   fmShareExclusive);  
  Target:=TFileStream.Create(TargetFile,fmOpenWrite   or   fmShareExclusive);  
  try  
  Target.Seek(0,soFromEnd);//往尾部添加资源  
  Target.CopyFrom(Source,0);  
  MyFileSize:=Source.Size+Sizeof(MyFileSize);//计算资源大小,并写入辅程尾部  
  Target.WriteBuffer(MyFileSize,sizeof(MyFileSize));  
  finally  
  Target.Free;  
  Source.Free;  
  end;  
  except  
  Result:=False;  
  Exit;  
  end;  
  Result:=True;  
  end;  
  procedure   TForm1.FormCreate(Sender:   TObject);  
  begin  
  Caption:='Bmp2Exe演示程序.作者:陈经韬';  
  Edit1.Text:='';  
  OpenPictureDialog1.DefaultExt   :=   GraphicExtension(TBitmap);  
  OpenPictureDialog1.Filter   :=   GraphicFilter(TBitmap);  
   
  Button1.Caption:='选择BMP图片';  
  Button2.Caption:='生成EXE';  
  end;  
   
  procedure   TForm1.Button1Click(Sender:   TObject);  
  begin  
  if   OpenPictureDialog1.Execute   then  
  Edit1.Text:=OpenPictureDialog1.FileName;  
  end;  
   
  procedure   TForm1.Button2Click(Sender:   TObject);  
  var  
  HeadTemp:String;  
  begin  
  if   Not   FileExists(Edit1.Text)   then  
  begin  
  Application.MessageBox('BMP图片文件不存在,请重新选择!','信息',MB_ICONINFORMATION+MB_OK)  
  Exit;  
  end;  
  HeadTemp:=ChangeFileExt(Edit1.Text,'.exe');  
  if   ExtractRes('exefile','head',HeadTemp)   then  
  if   Cjt_AddtoFile(Edit1.Text,HeadTemp)   then  
  Application.MessageBox('EXE文件生成成功!','信息',MB_ICONINFORMATION+MB_OK)  
  else  
  begin  
  if   FileExists(HeadTemp)   then   DeleteFile(HeadTemp);  
  Application.MessageBox('EXE文件生成失败!','信息',MB_ICONINFORMATION+MB_OK)  
  end;  
  end;  
  end.  
      怎么样?很神奇吧:)把程序界面弄的漂亮点,再添加一些功能,你会发现比起那些要注册的软件来也不会逊多少吧。  
  -----------------------------------------------------------------------  
  实际应用之三:利用流制作自己的OICQ  
   
      OICQ是深圳腾讯公司的一个网络实时通讯软件,在国内拥有大量的用户群。但OICQ必须连接上互联网登陆到腾讯的服务器才能使用。所以我们可以自己写一个在局部网里面使用。  
      OICQ使用的是UDP协议,这是一种无连接协议,即通信双方不用建立连接就可以发送信息,所以效率比较高。Delphi本身自带的FastNEt公司的NMUDP控件就是一个UDP协议的用户数据报控件。不过要注意的是如果你使用了这个控件必须退出程序才能关闭计算机,因为TNMXXX控件有BUG。所有nm控件的基础   PowerSocket用到的ThreadTimer,用到一个隐藏的窗口(类为TmrWindowClass)处理有硬伤。  
  出问题的地方:  
  Psock::TThreadTimer::WndProc(var   msg:TMessage)  
  if   msg.message=WM_TIMER   then  
  他自己处理  
  msg.result:=0  
  else  
  msg.result:=DefWindowProc(0,....)  
  end    
      问题就出在调用   DefWindowProc时,传输的HWND参数居然是常数0,这样实际上DefWindowProc是不能工作的,对任何输入的消息的调用均返回0,包括WM_QUERYENDSESSION,所以不能退出windows。由于DefWindowProc的不正常调用,实际上除WM_TIMER,其他消息由DefWindowProc处理都是无效的。  
  解决的办法是在   PSock.pas  
  在   TThreadTimer.Wndproc   内  
  Result   :=   DefWindowProc(   0,   Msg,   WPARAM,   LPARAM   );  
  改为:  
  Result   :=   DefWindowProc(   FWindowHandle,   Msg,   WPARAM,   LPARAM   );  
      早期低版本的OICQ也有这个问题,如果不关闭OICQ的话,关闭计算机时屏幕闪了一下又返回了。  
      好了,废话少说,让我们编写我们的OICQ吧,这个实际上是Delphi自带的例子而已:)  
      新建一个工程,在FASTNET面版拖一个NMUDP控件到窗口,然后依次放上三个EDIT,名字分别为EditIP、EditPort、EditMyTxt,三个按钮BtSend、BtClear、BtSave,一个MEMOMemoReceive,一个SaveDialog和一个状态条StatusBar1。当用户点击BtSend时,建立一个内存流对象,把要发送的文字信息写进内存流,然后NMUDP把流发送出去。当NMUDP有数据接收时,触发它的DataReceived事件,我们在这里再把接收到的流转换为字符信息,然后显示出来。  
      注意:所有的流对象建立后使用完毕后要记得释放(Free),其实它的释构函数应该为Destroy,但如果建立流失败的话,用Destroy会产生异常,而用Free的话程序会先检查有没有成功建立了流,如果建立了才释放,所以用Free比较安全。  
      在这个程序中我们用到了NMUDP控件,它有几个重要的属性。RemoteHost表示远程电脑的IP或者计算机名,LocalPort是本地端口,主要监听有没有数据传入。而RemotePort是远程端口,发送数据时通过这个端口把数据发送出去。理解这些已经可以看懂我们的程序了。  
   
  全部代码如下:  
  unit   Unit1;  
   
  interface  
   
  uses  
  Windows,   Messages,   SysUtils,   Classes,   Graphics,   Controls,   Forms,   Dialogs,StdCtrls,   ComCtrls,NMUDP;  
   
  type  
  TForm1   =   class(TForm)  
  NMUDP1:   TNMUDP;  
  EditIP:   TEdit;  
  EditPort:   TEdit;  
  EditMyTxt:   TEdit;  
  MemoReceive:   TMemo;    
  BtSend:   TButton;  
  BtClear:   TButton;  
  BtSave:   TButton;  
  StatusBar1:   TStatusBar;    
  SaveDialog1:   TSaveDialog;  
  procedure   BtSendClick(Sender:   TObject);  
  procedure   NMUDP1DataReceived(Sender:   TComponent;   NumberBytes:   Integer;  
  FromIP:   String;   Port:   Integer);  
  procedure   NMUDP1InvalidHost(var   handled:   Boolean);  
  procedure   NMUDP1DataSend(Sender:   TObject);  
  procedure   FormCreate(Sender:   TObject);  
  procedure   BtClearClick(Sender:   TObject);  
  procedure   BtSaveClick(Sender:   TObject);  
  procedure   EditMyTxtKeyPress(Sender:   TObject;   var   Key:   Char);  
  private  
  {   Private   declarations   }  
  public  
  {   Public   declarations   }  
  end;  
   
  var  
  Form1:   TForm1;  
   
  implementation  
   
  {$R   *.DFM}  
   
  procedure   TForm1.BtSendClick(Sender:   TObject);  
  var  
  MyStream:   TMemoryStream;  
  MySendTxt:   String;  
  Iport,icode:integer;  
  Begin  
  Val(EditPort.Text,Iport,icode);  
  if   icode<>0   then  
  begin  
  Application.MessageBox('端口必须为数字,请重新输入!','信息',MB_ICONINFORMATION+MB_OK);  
  Exit;  
  end;  
  NMUDP1.RemoteHost   :=   EditIP.Text;   {远程主机}  
  NMUDP1.LocalPort:=Iport;   {本地端口}  
  NMUDP1.RemotePort   :=   Iport;   {远程端口}  
  MySendTxt   :=   EditMyTxt.Text;  
  MyStream   :=   TMemoryStream.Create;   {建立流}  
  try  
  MyStream.Write(MySendTxt[1],   Length(EditMyTxt.Text));{写数据}  
  NMUDP1.SendStream(MyStream);   {发送流}  
  finally  
  MyStream.Free;   {释放流}  
  end;  
  end;  
   
   
  procedure   TForm1.NMUDP1DataReceived(Sender:   TComponent;  
  NumberBytes:   Integer;   FromIP:   String;   Port:   Integer);  
  var  
  MyStream:   TMemoryStream;  
  MyReciveTxt:   String;  
  begin  
  MyStream   :=   TMemoryStream.Create;   {建立流}  
  try  
  NMUDP1.ReadStream(MyStream);{接收流}  
  SetLength(MyReciveTxt,NumberBytes);{NumberBytes为接收到的字节数}  
  MyStream.Read(MyReciveTxt[1],NumberBytes);{读数据}  
  MemoReceive.Lines.Add('接收到来自主机'+FromIP+'的信息:'+MyReciveTxt);  
  finally  
  MyStream.Free;   {释放流}  
  end;  
  end;  
   
  procedure   TForm1.NMUDP1InvalidHost(var   handled:   Boolean);  
  begin  
  Application.MessageBox('对方IP地址不正确,请重新输入!','信息',MB_ICONINFORMATION+MB_OK);  
  end;  
   
  procedure   TForm1.NMUDP1DataSend(Sender:   TObject);  
  begin  
  StatusBar1.SimpleText:='信息成功发出!';  
  end;  
   
  procedure   TForm1.FormCreate(Sender:   TObject);  
  begin  
  EditIP.Text:='127.0.0.1';  
  EditPort.Text:='8868';  
  BtSend.Caption:='发送';  
  BtClear.Caption:='清除聊天记录';  
  BtSave.Caption:='保存聊天记录';  
  MemoReceive.ScrollBars:=ssBoth;  
  MemoReceive.Clear;  
  EditMyTxt.Text:='在这里输入信息,然后点击发送.';  
   
  StatusBar1.SimplePanel:=true;  
  end;  
   
  procedure   TForm1.BtClearClick(Sender:   TObject);  
  begin  
  MemoReceive.Clear;  
  end;  
   
  procedure   TForm1.BtSaveClick(Sender:   TObject);  
  begin  
  if   SaveDialog1.Execute   then   MemoReceive.Lines.SaveToFile(SaveDialog1.FileName);  
  end;  
   
  procedure   TForm1.EditMyTxtKeyPress(Sender:   TObject;   var   Key:   Char);  
  begin  
  if   Key=#13   then   BtSend.Click;  
  endTop

5 楼emailz(虫子)回复于 2002-02-24 23:52:11 得分 100

Function   Trun_ip(S:string):string;  
  var   s1,s2,s3,ss,sss,Head:string;  
  n,m:integer;  
  begin  
  sss:=S;  
  n:=pos('.',s);  
  s1:=copy(s,1,n);  
  m:=length(s1);  
  delete(s,1,m);  
  Head:=copy(s1,1,(length(s1)-1));  
  n:=pos('.',s);  
  s2:=copy(s,1,n);  
  m:=length(s2);  
  delete(s,1,m);  
  n:=pos('.',s);  
  s3:=copy(s,1,n);  
  m:=length(s3);  
  delete(s,1,m);  
  ss:=sss;  
  if   strtoint(Head)   in   [1..126]   then   ss:=s1+'255.255.255';   //1~126.255.255.255   (A类网)  
  if   strtoint(Head)   in   [128..191]   then   ss:=s1+s2+'255.255';//128~191.XXX.255.255(B类网)  
  if   strtoint(Head)   in   [192..254]   then   ss:=s1+s2+s3+'255';   //192~254.XXX.XXX.255(C类网)  
  Result:=ss;    
  end;  
   
  -----------------------------------------------------------------------  
  五、实际应用之四:利用流实现网络传输屏幕图像  
   
      大家应该见过很多网管程序,这类程序其中有一个功能就是监控远程电脑的屏幕。实际上,这也是利用流操作来实现的。下面我们给出一个例子,这个例子分两个程序,一个服务端,一个是客户端。程序编译后可以直接在单机、局部网或者互联网上使用。程序中已经给出相应注释。后面我们再来作具体分析。  
      新建一个工程,在Internet面版上拖一个ServerSocket控件到窗口,该控件主要用于监听客户端,用来与客户端建立连接和通讯。设置好监听端口后调用方法Open或者Active:=True即开始工作。注意:跟前面的NMUDP不同,当Socket开始监听后就不能再改变它的端口,要改变的话必须先调用Close或设置Active为False,否则将会产生异常。另外,如果该端口已经打开的话,就不能再用这个端口了。所以程序运行尚未退出就不能再运行这个程序,否则也会产生异常,即弹出出错窗口。实际应用中可以通过判断程序是否已经运行,如果已经运行就退出的方法来避免出错。  
      当客户端有数据传入,将触发ServerSocket1ClientRead事件,我们可以在这里对接收的数据进行处理。在本程序中,主要是接收客户端发送过来的字符信息并根据事先的约定来进行相应操作。  
  程序全部代码如下:  
   
  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.  
  Top

6 楼thedream(梦幻使者)回复于 2002-02-25 00:11:13 得分 0

多谢啦Top

7 楼vcdll(左手.net右手美女)回复于 2002-02-25 00:12:56 得分 0

1Top

相关问题

  • Active Movie Control Object 如何做到局域网内远程播放?(不用共享)
  • NETMEETING 远程桌面共享
  • mediaplayer 实现远程播放
  • 如何禁止远程文件共享?
  • VCD播放
  • 需求共享Flash播放控件
  • 播放VCD文件!
  • 关于2000下硬盘共享的远程访问??
  • 怎样打开远程的共享文件夹?
  • 如何复制文件到远程计算机(网络共享)

关键词

  • 文件
  • 函数
  • 数据
  • 控件
  • 端口
  • 属性
  • 指针
  • 远程
  • 加密
  • myfilesize

得分解答快速导航

  • 帖主:thedream
  • emailz
  • emailz

相关链接

  • Visual C++类图书
  • Visual C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo