此示例保存类类型对象的数据。 有多种不使用数据库而存储数据的方法,但是最通用的方法是创建一个从TComponent派生的类并将其另存为已发布的属性。这使您可以处理大多数类型的数据。当与TComponentList结合使用时,它功能强大,但是在这里,它存储和检索了一组名为TData的属性的对象。(1)创建一个名为TData的类的实例 (2)为每个属性设置一个值 (3)保存 (4)保存前读出并显示设置值 我正在按照以下过程进行测试。TData也具有类类型的属性。保存并读取时,可以看到这些属性也已保存。这意味着,当您保存一个类的对象时,还可以在其属性中保存另一类类型的对象。 可以保存的数据只是发布中定义的属性。需要存储的数据(包括类类型对象)定义为发布的属性。保存未发布的属性(在我的组件中使用)需要特殊方法。 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ExtDlgs;
type
TSubData = class;
TData = class(TComponent)
private
FIntVal : Integer;
FColor : TColor;
FFont : TFont;
FSubData : TSubData;
procedure SetFont(const Value: TFont);
procedure SetSubData(const Value: TSubData);
protected
public
constructor Create(AOwner: TComponent);override;
destructor Destroy; override;
published
property IntVal : Integer read FIntVal write FIntVal;
property Color : TColor read FColor write FColor;
property Font : TFont read FFont write SetFont;
property SubData : TSubData read FSubData write SetSubData;
end;
TSubData = class(TPersistent)
private
FName : String;
FID : Integer;
public
published
property Name : String read FName write FName;
property ID : Integer read FID write FID;
end;
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
FTestData : TData;
FFileName : TFileName;
public
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
{ TData }
//-------------------------------------------------- ---------------------------
// 创建TData类
// 在此处创建对象类型属性
//-------------------------------------------------- ---------------------------
constructor TData.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FSubData := TSubData.Create;
FFont := TFont.Create;
end;
//-------------------------------------------------- ---------------------------
// 销毁TData类,同时销毁创建的对象
//-------------------------------------------------- ---------------------------
destructor TData.Destroy;
begin
FreeAndNil(FSubData);
FreeAndNil(FFont);
inherited;
end;
//-------------------------------------------------- ---------------------------
// 字体对象设置
//-------------------------------------------------- ---------------------------
procedure TData.SetFont(const Value: TFont);
begin
FFont.Assign(Value);
end;
//-------------------------------------------------- ---------------------------
// SubData对象设置
//-------------------------------------------------- ---------------------------
procedure TData.SetSubData(const Value: TSubData);
begin
FSubData.Assign(Value);
end;
//================================================== ==========================
// 生成Form时,也会生成TData类对象TestData
// AFileName是保存文件名
//================================================== ==========================
procedure TForm1.FormCreate(Sender: TObject);
begin
FTestData := TData.Create(Self);
FFileName := ExtractFilePath(Application.ExeName) + 'ATest.dat';
end;
//================================================== ==========================
// 设置运行检查数据
// 当然,如果这些值是固定的,则可以使用TData的构造函数进行设置。
// (或使用构造函数执行初始设置)
//
// 在此代码中,它不会显示在Memo1中,因为Memo1中没有代码可显示
//================================================== ==========================
procedure TForm1.Button1Click(Sender: TObject);
var
LFont : TFont;
begin
if Assigned(FTestData) then begin
LFont := TFont.Create;
try
LFont.Size := 12;
LFont.Color := clBlue;
FTestData.Font := LFont;
FTestData.IntVal := 2005;
FTestData.Color := clMoneyGreen;
FTestData.SubData.Name := 'Mr.XRAY';
FTestData.SubData.ID := 1234567890;
finally
FreeAndNil(LFont);
end;
end;
end;
//================================================== ==========================
// 保存当前数据
// 由于它是TComponent的派生类属性,因此仅WriteComponent可以
//================================================== ==========================
procedure TForm1.Button2Click(Sender: TObject);
var
LFileStream : TFileStream;
begin
LFileStream := TFileStream.Create(FFileName, fmCreate);
try
if Assigned(FTestData) then begin
LFileStream.WriteComponent(FTestData);
end;
finally
FreeAndNil(LFileStream);
end;
end;
//================================================== ==========================
// 读取并显示保存的数据
// 由于它是TComponent派生类的属性,因此只有ReadComponent可以
//================================================== ==========================
procedure TForm1.Button3Click(Sender: TObject);
var
LFileStream : TFileStream;
LTestData : TData;
begin
Memo1.Clear;
//创建另一个名称为TData的对象以确认读取的数据
LTestData := TData.Create(Self);
try
LFileStream := TFileStream.Create(FFileName, fmOpenRead);
try
LFileStream.ReadComponent(LTestData);
finally
LFileStream.Free;
end;
//显示读取的数据
Memo1.Lines.Add(IntToStr(LTestData.IntVal));
Memo1.Lines.Add(LTestData.SubData.Name);
Memo1.Lines.Add(IntToStr(LTestData.SubData.ID));
Memo1.Color:=LTestData.Color;
Memo1.Font.Assign(LTestData.Font);
finally
//立即丢弃,因为这是测试
FreeAndNil(LTestData);
end;
end;
end.
这是保存单个组件的示例。
这次不是保存组件的状态,而是保存组件本身。 只能创建一个具有相同名称的组件。因此,在读取之前,会将原来组件删除。
在此示例代码中,只能保存已发布的属性。发布的属性就是在对象属性器中显示的属性。
图片1:界面如下 、 图片2:从文件加载Panel
|
清单2.
使用TFileStream保存和检索组件的示例
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, ExtDlgs;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Panel1: TPanel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private }
public
{ Public }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//================================================== ==========================
// 将组件保存到文件
//================================================== ==========================
procedure TForm1.Button1Click(Sender: TObject);
var
LFileName : String;
LFileStream : TFileStream;
begin
LFileName := 'AAA.dat';
LFileStream := TFileStream.Create(LFileName, fmCreate);
try
if Assigned(Panel1) then begin
LFileStream.WriteComponent(Panel1);
end;
finally
FreeAndNil(LFileStream);
end;
end;
//================================================== ==========================
// 加载并显示已保存的组件
//================================================== ==========================
procedure TForm1.Button2Click(Sender: TObject);
var
LFileName : String;
LFileStream : TFileStream;
LPanel : TPanel;
begin
//保存Panel1组件时,名字也会一起保存
//先删除,因为无法创建具有相同名称的组件
FreeAndNil(Panel1);
Update;
Sleep(1000);
LFileName := 'AAA.dat';
LPanel := TPanel.Create(Self);
LFileStream := TFileStream.Create(LFileName, fmOpenRead);
try
//如果不指定了parent,否则无法显示
LPanel.Parent := Self;
//读取组件
LFileStream.ReadComponent(LPanel);
Application.MessageBox(PChar(LPanel.Name), '加载成功');
finally
LFileStream.Free;
end;
end;
end.