问题: 请教MemoryStream的使用方法 ( 积分: 50 )
分类: Object Pascal
来自: ranjiao, 时间: 2005-08-15 18:45:00, ID: 3167898
我想用MemoryStream反复读取文件操作,但是我调用clear和free想清除内存的时候都会报错。。。
应该怎么弄?
来自: chenybin, 时间: 2005-08-15 20:24:58, ID: 3167929
先看看你的代码
http://www.delphibbs.com/delphibbs/modifyl.asp?lid=1474545
谈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
Res := TResourceStream.Create(Hinstance, Resname, Pchar(ResType))
try
Res.SavetoFile(ResNewName)
Result:=true
finally
Res.Free
end
except
Result:=false
end
end
注意:我们上面的函数只不过是简单的把一个文件添加到另一个文件的尾部。实际应用中可以改成可以添加多个文件,只要根据实际大小和个数定义好偏移地址就可以了。比如说文件捆绑机就是把两个或者多个程序添加到一个头文件里面。那些自解压程序和安装程序的原理也是一样的,不过多了压缩而已。比如说我们可以引用一个LAH单元,把流压缩后再添加,这样文件就会变的很小。读出来时先解压就可以了。另外,文中EXE加密器的例子还有很多不完善的地方,比如说密码固定为"790617",取出EXE运行后应该等它运行完毕后删除等等,读者可以自行修改。
---------------------------------------------------------------------
三、实际应用之二:利用流制作可执行电子贺卡
我们经常看到一些电子贺卡之类的制作软件,可以让你自己选择图片,然后它会生成一个EXE可执行文件给你。打开贺卡时就会一边放音乐一边显示出图片来。现在学了流操作之后,我们也可以做一个了。
添加图片过程我们可以直接用前面的Cjt_AddtoFile,而现在要做的是如何把图像读出并显示。我们用前面的Cjt_LoadFromFile先把图片读出来保存为文件再调入也是可以的,但是还有更简单的方法,就是直接把文件流读出来显示,有了流这个利器,一切都变的简单了。
现在的图片比较流行的是BMP格式和JPG格式。我们现在就针对这两种图片写出读取并显示函数。
Function Cjt_BmpLoad(ImgBmp:TImage;SourceFile:String):Boolean
var
Source:TFileStream
MyFileSize:integer
begin
Source:=TFileStream.Create(SourceFile,fmOpenRead or fmShareDenyNone)
try
try
Source.Seek(-sizeof(MyFileSize),soFromEnd)
Source.ReadBuffer(MyFileSize,sizeof(MyFileSize));//读出资源
Source.Seek(-MyFileSize,soFromEnd);//定位到资源开始位置
ImgBmp.Picture.Bitmap.LoadFromStream(Source)
finally
Source.Free
end
except
Result:=False
Exit
end
Result:=True
end
上面是读出BMP图片的,下面的是读出JPG图片的函数,因为要用到JPG单元,所以要在程序中添加一句:uses jpeg。
Function Cjt_JpgLoad(JpgImg:Timage;SourceFile:String):Boolean
var
Source:TFileStream
MyFileSize:integer
Myjpg: TJpegImage
begin
try
Myjpg:= TJpegImage.Create
Source:=TFileStream.Create(SourceFile,fmOpenRead or fmShareDenyNone)
try
Source.Seek(-sizeof(MyFileSize),soFromEnd)
Source.ReadBuffer(MyFileSize,sizeof(MyFileSize))
Source.Seek(-MyFileSize,soFromEnd)
Myjpg.LoadFromStream(Source)
JpgImg.Picture.Bitmap.Assign(Myjpg)
finally
Source.Free
Myjpg.free
end
except
Result:=false
Exit
end
Result:=true
end
有了这两个函数,我们就可以制作读出程序了。下面我们以BMP图片为例:
运行Delphi,新建一个工程,放上一个显示图像控件Image1。在窗口的Create事件中写上一句就可以了:
Cjt_BmpLoad(Image1,Application.ExeName)
这个就是头文件了,然后我们用前面的方法生成一个head.res资源文件。
下面就可以开始制作我们的添加程序了。全部代码如下:
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.
怎么样?很神奇吧
把程序界面弄的漂亮点,再添加一些功能,你会发现比起那些要注册的软件来也不会逊多少吧。
来自: ranjiao, 时间: 2005-08-15 19:41:40, ID: 3167931
free一调用就会出错
来自: chenybin, 时间: 2005-08-15 20:24:37, ID: 3167954
把你的代码贴出来看看
来自: ranjiao, 时间: 2005-08-15 21:03:52, ID: 3168004
begin//download <<===BUG!!!
MemoryStream.Position:=0
loadfile(list.data[0],MemoryStream,msize)
memo1.Lines.add('file loaded.')
socket.SendText(inttostr(msize))
end
我在远程控制,其中涉及到的就是这几行代码了,下面是整个代码,有点多
unit server
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp, StdCtrls, ExtCtrls, Jpeg, unitserver
type
TServerForm = class(TForm)
ServerSocket1: TServerSocket
BtnListen: TButton
Memo1: TMemo
BtnExit: TButton
EdtSend: TEdit
BtnSend: TButton
Timer1: TTimer
CbControl: TCheckBox
Image: TImage
BtnClear: TButton
procedure BtnClearClick(Sender: TObject)
procedure Button1Click(Sender: TObject)
procedure EdtSendKeyPress(Sender: TObject
var Key: Char)
procedure ServerSocket1ClientError(Sender: TObject
Socket: TCustomWinSocket
ErrorEvent: TErrorEvent
var ErrorCode: Integer)
procedure CbControlClick(Sender: TObject)
procedure ServerSocket1ClientDisconnect(Sender: TObject
Socket: TCustomWinSocket)
procedure Timer1Timer(Sender: TObject)
procedure FormCreate(Sender: TObject)
procedure ServerSocket1ClientRead(Sender: TObject
Socket: TCustomWinSocket)
procedure BtnSendClick(Sender: TObject)
procedure ServerSocket1Accept(Sender: TObject
Socket: TCustomWinSocket)
procedure BtnListenClick(Sender: TObject)
procedure BtnExitClick(Sender: TObject)
private
{ Private declarations }
public
{ Public declarations }
end
var
ServerForm: TServerForm
control,shaking:boolean
memoryStream:TMemoryStream
size:longint
Receiving:integer
filepath:string
implementation
{$R *.dfm}
procedure capture
var
BitMap:TBitMap
jpg:TJpegImage
desk:TCanvas
begin
bitmap:=tbitmap.Create
jpg:=tjpegimage.Create
desk:=tcanvas.Create
//以下代码为取得当前屏幕图象
desk.Handle:=getdc(hwnd_desktop)
MemoryStream:=tmemorystream.Create
//初始化流m1,在用sendstream(m1)发送流后,
with bitmap do
begin
width:=screen.Width
height:=screen.Height
jpg.CompressionQuality:=50
{压缩质量}
jpg.Compress
canvas.CopyRect(canvas.cliprect,desk,desk.cliprect)
end
jpg.Assign(bitmap)
//将图象转成JPG格式
jpg.SaveToStream(MemoryStream)
//将JPG图象写入流中
jpg.free
MemoryStream.Position:=0
end
procedure TServerForm.BtnExitClick(Sender: TObject)
begin
close
end
procedure TServerForm.BtnListenClick(Sender: TObject)
begin
ServerSocket1.active:=NOT ServerSocket1.active
if not ServerSocket1.Active then
begin
BtnListen.Caption:='Listen'
memo1.Lines.add('Listen ended.')
end
else
begin
BtnListen.Caption:='End Listen'
memo1.Lines.add('Listening...')
end
end
procedure TServerForm.ServerSocket1Accept(Sender: TObject
Socket: TCustomWinSocket)
begin
memo1.Lines.Add('Client from '+ServerSocket1.Socket.Connections[0].RemoteAddress+' connected.')
end
procedure TServerForm.BtnSendClick(Sender: TObject)
begin
if not ServerSocket1.Socket.Connected then exit
ServerSocket1.Socket.Connections[0].SendText(EdtSend.Text)
memo1.Lines.add('Server :'+EdtSend.text)
end
procedure TServerForm.ServerSocket1ClientRead(Sender: TObject
Socket: TCustomWinSocket)
var
msize,iscmd:integer
cmd,temp:string
//delcaration of cmdlist
// maxcount=10
// CMDList:array[0..maxcount-1] of string=
// ('#CLogOff',
// '#CPowerOff',
// '#CReboot',
// '#CShakeMouse',
// '#CCapture',
// '#CSendStream',
// '#CListDrive',
// '#CListFile',
// '#CDownload',
// '#CUpload',
// '#CExit')
procedure ReceiveStream
var
len:integer
buffer:array [0..10000] of byte
begin
if size=0 then
begin
size:=strtoint(Socket.ReceiveText)
Socket.SendText('#CSendStream')
//ask client to send the stream
end
else
begin
len:=socket.ReceiveLength
//读出包长度
socket.ReceiveBuf(buffer,len)
//接收数据包并读入缓冲区内
memorystream.Write(buffer,len)
//追加入流M中
end
end
begin
if Receiving<>0 then
// Receiving is the Flag of what socket is going to receive
// 1:Stream of file that client is iploading
case Receiving of
1:begin//receive stream
ReceiveStream
if MemoryStream.Size>=size then
begin
MemoryStream.SaveToFile(list.data[0])
Receiving:=0
end
end
end
else
begin
temp:=Socket.ReceiveText
memo1.Lines.Add('Client: '+temp)
iscmd:=DealWithCMD(temp)
//check if the message recevied is a command
//and save the var in list.
if iscmd<>0 then
begin
if control then
begin
case iscmd of
1:begin//log off //<<=====DEBUGED======>>
ExitWindowsEx(EWX_Logoff,0)
end
2:begin//Power Off //<<=====DEBUGED======>>
ExitWindowsEx(EWX_PowerOff,0)
end
3:begin//Reboot //<<=====DEBUGED======>>
ExitWindowsEx(EWX_Reboot,0)
end
4:begin//Shake Mouse //<<=====DEBUGED======>>
shaking:=not shaking
Timer1.Enabled:=true
if shaking then
memo1.Lines.Add('Your mouse is going mad.')
else
memo1.Lines.Add('What''s wrong with your mouse?')
end
5:begin//Capture the Screen<<=====DEBUGED======>>
capture
//capture the screen and compress it into jpeg
//and then save it to MemoryStream
cmd:=inttostr(MemoryStream.Size)
socket.SendText(cmd)
end
6:begin//Transport the Stream<<=====DEBUGED======>>
MemoryStream.Position:=0
socket.SendStream(MemoryStream)
end
7:begin//List the drives.<<=====DEBUGED======>>
ListDrive(cmd)
socket.SendText(cmd)
end
8:begin//List the files and dirs<<=====DEBUGED======>>
listFile(list.data[0],'*.*',cmd)
socket.SendText(cmd)
init
end
9:begin//download <<===BUG!!!
MemoryStream.Position:=0
loadfile(list.data[0],MemoryStream,msize)
memo1.Lines.add('file loaded.')
socket.SendText(inttostr(msize))
end
10:begin //upload
// filepath:=list.data[0]
// socket.SendText('#CSendStream')
// receiving:=1
end
11:begin
Application.Terminate
end
12:begin
ServerForm.Show
end
end;//case
end //eof if control
else
socket.SendText('#Server is not controlable.')
end//eof if iscmd }
else
begin
// memo1.Lines.Add('Client: '+temp)
end
end;//eof else receiving
end
procedure TServerForm.FormCreate(Sender: TObject)
begin
BtnListen.Click
shaking:=false
control:=true
MemoryStream:=TMemoryStream.Create
Receiving:=0
size:=0
init;//procedure in unit1
end
procedure TServerForm.Timer1Timer(Sender: TObject)
const //This procedure change the pos of mouse
maxn=100
//and it make mouse like shaking...
var
pos:TPoint
// x,y:integer
begin
if shaking then
begin
GetCursorPos(pos)
randomize
pos.X:=pos.X+random(maxn)-(maxn div 2)
pos.Y:=pos.y+random(maxn)-(maxn div 2)
SetCursorPos(pos.x,pos.y)
end
else
Timer1.enabled:=false
end
procedure TServerForm.ServerSocket1ClientDisconnect(Sender: TObject
Socket: TCustomWinSocket)
begin
memo1.Lines.Add('Client disconected.')
end
procedure TServerForm.CbControlClick(Sender: TObject)
begin
if CBControl.Checked then
begin
control:=true
memo1.Lines.Add('You are able to be controled by client now.')
end
else
begin
control:=false
memo1.lines.add('You are not able to be controled by client now.')
end
end
procedure TServerForm.ServerSocket1ClientError(Sender: TObject
Socket: TCustomWinSocket
ErrorEvent: TErrorEvent
var ErrorCode: Integer)
begin
showmessage(ServerSocket1.Socket.Connections[0].RemoteHost+#13#10+'未开机或未安装服务程序')
errorcode:=0
MemoryStream.Clear
receiving:=0
end
procedure TServerForm.EdtSendKeyPress(Sender: TObject
var Key: Char)
begin
if key=#13 then
begin
BtnSend.Click
EdtSend.Clear
end
end
procedure TServerForm.Button1Click(Sender: TObject)
begin
capture
end
procedure TServerForm.BtnClearClick(Sender: TObject)
begin
memo1.Clear
end
end.
来自: chenybin, 时间: 2005-08-15 21:16:47, ID: 3168018
TMemoryStream.truncate
或者
TMemoryStream.SetSize(0);看看,明天帮你调试
来自: ranjiao, 时间: 2005-08-15 21:33:39, ID: 3168035
多谢了楼上的~
刚开始用delphibbs 怎么追加分数?
来自: chenybin, 时间: 2005-08-15 21:36:24, ID: 3168038
不用追加,追加要重新开帖子,如果答案能满足你结贴就可以了,记得发分数给偶,细细[
][
][
]
来自: ranjiao, 时间: 2005-08-19 9:39:08, ID: 3172471
还是不行啊 MemoryStream没有truncate 而我用setsize的话并没有真正清内存,还是会出错
来自: chenybin, 时间: 2005-08-20 2:58:49, ID: 3173788
方便的话留个联系方式,把代码发给我,我帮你调
来自: ranjiao, 时间: 2005-08-22 22:53:12, ID: 3176438
我的邮箱是ranjiao@gmail.com
这两天快开学了,可能回的会比较慢
问题讨论没有结束 ...