送分(100分)

  • 主题发起人 Another_eYes
  • 开始时间
A

Another_eYes

Unregistered / Unconfirmed
GUEST, unregistred user!
1.请教有关TReader, TWriter详细用法,适用环境与注意事项。最好给出例子。

2.针对自己的继承自TComponent的控件中private部分的变量内容,通过TWriter
保存控件时是否会自动保存?

3.如果2 可以, 那么假设该控件private部分有一TList,该TList保存的可能
是另外的Component(每个items可能保存的是不同的Component), 这些Component
是否会自动保存?

4.TReader恢复控件时是否保证内存地址不变? 假设我用字符串(或整数)保存了
某个Component的地址, TReader恢复后这个字符串(或整数)中的地址是否仍然
指向原先指向的那个Component?

5.如果2或4的答案为否定的, 那么有什么方法可以实现上述要求?
 
1、写入:
var s:Tfilestream
w:Twriter;
s:=Tfilestream.create('filename',fmcreate or fmopenwrite);
w:=Twrite.create(s,1024);
w.WriteCurrency(12.3);
...
读出用Treader对象!
2、可以!
3、不公布的属性delphi不会入流!
4、地址是变的。
5、如果要保持自己的数据!
要override DefineProperties;
begin
inherited;
filer.DefineBinaryProperty('data',read,write,条件);
end;
read,write为函数!
 
照你的说法
5. override DefineProperties也不会有用呀
难道我的read函数能指定该控件加载于内存中某个确定地址上吗?
在16位系统编程时要达到上述要求只要生成时内存分配是段对齐的就行。这样读取时
加载于不同的段中,尽管实际物理地址变化了, 但相对于段首的偏移量是不变的。具体
操作时只要指定不同的段地址就行了。 难道32位的delphi没有类似功能?
 
好个送分
 
既然把属性写入文件,又何必加载到用一地址!
你有特殊用途吗!
 
To Delphi 2:
比如类中有个变量保存的是一个pointer或类(比方是个TEdit),注意,存盘时可是作为一
个integer数字保存的(本来就是一个指针嘛). 这个变量指向某个class(假设保存的是
屏幕上某个Edit)
存盘然后再读取, 如果地址变掉了(Edit的实际地址), 但这个pointer中的数值可没
变, 难道就不能通过这个变量访问原先可以访问的Edit了吗?
照实际情况来看好象并非如此. 不然生成的form不是都不能运行了吗?
form create时可是从stream中加载设计时的信息的哦.
简单的例子: TForm.Components[n]本来就是一个指针, 指向具体的component. 不要
告诉我说这里面的值不是设计时就由delphi写进去的, 而是create时临时生成的(这样的话TabOrder又如何解释?它也是一个TList)
 
把类中pointer做为私有属性,
在write函数里
if pointer<>nil then WriteComponent(Tedit(pointer))
read函数可读出!
这样可以写入!
 
假设:
TMyComponent = class(TComponent)
MyEditInComponent: TEdit;
MyListInComponent: TList;
MyEditAsPointer: TEdit;
MyListAsPointer: TList;
.......
end;

procedure BeforeSave;
begin
MyEditInComponent:=TEdit.Create(owner);
MyListInComponent:=TList.Create;
with MyListInComponent do
begin
add(TTable.Create(nil)); // items[0] is a TTable
add(TStringGrid.Create(owner)); // items[1] is a TStringGrid
add(allocmem(1024)); // items[2] is a block of buffer
add(ptr(5000)); // items[3] used as an integer
end;
MyEditAsPointer:=MyEditInComponent;
MyListAsPointer:=MyListInComponent;
// otherparams used here.
end;

假设beforesave是在保存该component前调用的
请问这种component用TWriter和TReader能否读写?
读出的内容是否仍正确?(特别是MyListInComponent中各个items的内容是否会保存,
以及读出后MyEditAsPointer和MyListAsPointer是否仍指向MyEditInComponent和
MyListInComponent?)
 
假设:
TMyComponent = class(TComponent)
MyEditInComponent: TEdit;
MyListInComponent: TList;
MyEditAsPointer: TEdit;
MyListAsPointer: TList;
.......
end;

procedure BeforeSave;
begin
MyEditInComponent:=TEdit.Create(owner);
MyListInComponent:=TList.Create;
with MyListInComponent do
begin
add(TTable.Create(nil)); // items[0] is a TTable
add(TStringGrid.Create(owner)); // items[1] is a TStringGrid
add(allocmem(1024)); // items[2] is a block of buffer
add(ptr(5000)); // items[3] used as an integer
end;
MyEditAsPointer:=MyEditInComponent;
MyListAsPointer:=MyListInComponent;
end;

假设beforesave是在保存该component前调用的
请问这种component用TWriter和TReader能否读写?
读出的内容是否仍正确?(特别是MyListInComponent中各个items的内容是否会保存,
以及读出后MyEditAsPointer和MyListAsPointer是否仍指向MyEditInComponent和
MyListInComponent?)
 
我一直认为你要写控件的属性!
如果只是记录数据在外部文件里,下面有的例子!只用Tstream就可以!
如果要达到你的要求还要修改!我只记录TEdit类!
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
List:Tlist;
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
RegisterClasses([TEdit]);
List:=Tlist.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
if Assigned(List) then List.Free;
end;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var T:TControl;
begin
T:=TEdit.Create(Self);
with (T as TEdit) do
begin
Parent:=self;
Left:=x;
Top:=y;
Visible:=True;
end;
List.Add(T);
end;

procedure TForm1.Button1Click(Sender: TObject);
var S:TFileStream;
i:integer;
begin
try
s:=TFileStream.Create('save',fmopenwrite or fmcreate);

for i :=0 to list.Count-1 do
begin
s.WriteComponent(TControl(list));
end;
finally
s.Free;
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var S:TFileStream;
var T:TComponent;

begin
try
s:=TFileStream.Create('save',fmopenRead);

while s.Position<s.Size do
begin
T:=s.ReadComponent(Nil);
InsertControl(T as TControl);
end;


finally
s.Free;
end;

end;

end.
 
如果只是记录数据在外部文件里,下面有的例子!只用Tstream就可以!
如果要达到你的要求还要修改!我只记录TEdit类!
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
List:Tlist;
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
RegisterClasses([TEdit]);
List:=Tlist.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
if Assigned(List) then List.Free;
end;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var T:TControl;
begin
T:=TEdit.Create(Self);
with (T as TEdit) do
begin
Parent:=self;
Left:=x;
Top:=y;
Visible:=True;
end;
List.Add(T);
end;

procedure TForm1.Button1Click(Sender: TObject);
var S:TFileStream;
i:integer;
begin
try
s:=TFileStream.Create('save',fmopenwrite or fmcreate);

for i :=0 to list.Count-1 do
begin
s.WriteComponent(TControl(list));
end;
finally
s.Free;
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var S:TFileStream;
var T:TComponent;

begin
try
s:=TFileStream.Create('save',fmopenRead);

while s.Position 小于 s.Size do
begin
T:=s.ReadComponent(Nil);
InsertControl(T as TControl);
end;


finally
s.Free;
end;

end;

end.
 
那么MyListAsPointer的内容呢?
那么MyEditAsPointer的内容呢?
 
例子里用list记录Tedit的地址!并把它写入文件!并且可以恢复!
 
实际上记录元件只是记录它的属性,delphi会根据它创建控件!
象delphi 的Dfm文件
 
你的例子里TList保存TEdit的语句相当于TList.Add(TEdit.create(owner))呀。
我要求的是
edit1:=TEdit.Create(owner); // 注意:edit1是也需要保存并恢复的一个变量
List1:=TList.create;
List1.add(edit1); // List1是第二个需要保存和恢复的变量
问读取后edit1和List1.items[0]是不是同一个值(保存前是)
 
保存后,edit1:=list[0]不就完了!干吗非要保存一个地址!
 
你的意思是说地址不能保存了?(给的是一个纯例子,没有任何实际意义。实际情况下
有时非要保存地址不可!)
 
地址是一个Integer,当然可以保存。
当我们开发程序时,看一看delphi本身是如何做的呢!
每一个窗体都有一个dfm文件,和一个Tform的变量!(如 form1)
delphi不可能保留form1的实际地址,而是把form1的所指向的Tform型的数据保留。
下一次加载Tform时是用保留的数据创建一个窗体,然后让form1指向创建窗体的实际
地址!
我写的例子是程序动态创建TEdit,用Tlist保留它的地址,保存每个Edit的数据,
下次使用时再根据数据创建Edit,然后让Tlist指向它,以便操作!
 
很好:
那么下例如何保存?
list1: TList;
list2: TList;

list1:=tlist.create;
list1.add(tedit.create);
list1.add(tedit.create);
list2:=tlist.create;
这次保存可能的可能是
list2.add(list1.items[0]);
list2.add(list1.items[1]);
下次保存的可能是
list2.add(list1.items[1]);
list2.add(list1.items[0]);
请问读取后list2中的指针还会正确吗?(保存的是那种情况下的不确定)
或者简单点
p1,p2: pointer;

edit1: tedit;
edit2: tedit;

edit1:=tedit.create;
edit2:=tedit.create;

p1和p2中可能是随机保存的edit1或edit2
读取后p1和p2还会指向保存前的正确的地址吗?
 
这样的话不用保存地址,保存list2的每一项在list1的位置,也是个Integer;
保存完List1的数据后!
Twriter.WriteInteger(Integer(list1.indexof(list2[index])));
下回读出后知道list2的每一项指向list1的位置了!
 
顶部