这是一个有点难度的问题,不知道大家遇到过没有?求助高手,进者有分,高分答谢!

时间:2022-04-20 19:38:25
我的问题是这样的:
我先描述一下我的环境,我在一个panel(相当于画布)上面动态创建很多图标,
图标的构成是动态生成一个panel的同时在他的上面有动态生成一个image,通过image载入图片,这些我都实现了,下一步实现的是,把所有panel(画布)上面的动态创建的东西保存起来可以是自定义格式文件,注意不是抓图功能,听说是以文件流操作,或者是别的方面,我这方面真的很白痴,请教各位高手以下。
做好的功能就象word的文件的扩展名是*.doc。。。。。。

48 个解决方案

#1


up,学习

#2


想动态地将一个窗体上所有控制的值保存到一个文件吗?利用初始化文件(ini文件)和RTTI,只需要编写一次代码,无论窗体上有多少控制,都可以将它们的值写到指定的文件。同样,写一个逆过程,可以将保存在文件的值直接读出,并设置到对应的控制中。
var
sSection,  sFileName, sIdent: String;
iniMyFile: TiniFile;

begin
try
  iniMyFile := TIniFile.Create(sFileName);
  for i := 0 to (Self.ComponentCount - 1) do
    begin
    sSection := Self.Name;
    if Components[i] is TEdit then
      begin
      with Components[i] as TEdit do
        begin
        sIdent := Name;
        if Trim(Text) = '' then
          iniMyFile.WriteString(sSection, sIdent, '0')
        else
          iniMyFile.WriteString(sSection, sIdent, Text);
        end;
      end
  else if Components[i] is TCheckBox then
      begin
      sIdent := Components[i].Name;
      iniMyFile.WriteBool(sSection, sIdent, (Components[i] as
TCheckBox).Checked);
      end
  else if { 下面编写窗体上使用过的所有的控制类型 }
      begin
      end;
  end;   { for i }
finally
  iniMyFile.Free;
end;  { try..finally }

end;   { End of SaveToFile }
结果文件类似于:
[窗体名称]
edit_ucost_c_3=61.80
edit_ucost_c_5=66.30
edit_ucost_c_6=69.90
edit_ucost_c_7=64.20
edit_ucost_c_8=66.30
cbShowUtilization=1

#3


呵呵,就是工作区的问题!可以用流类解决!如下:

procedure SaveWorkAreaContent(APanel: TPanel; AFileName: string);

var
  BinStream:TMemoryStream;
  StrStream: TStringStream;
  S: String;
begin
  BinStream := TMemoryStream.Create;
  try
    BinStream.WriteComponent(APanel);
    BinStream.Seek(0, soFromBeginning);
    BinStream.SaveToFile(AFileName);
  finally
    BinStream.Free
  end;
end;

使用流化的方式只可以保存公布Published的内容,而且文件后缀在AFileName自己指定!


#4


http://expert.csdn.net/Expert/topic/2179/2179440.xml?temp=.1161005

可以参考一下这个帖子的内容!

#5


我给出你部分动态创建的代码,我想把panel上的所有控件的属性和状态位置保存下来,帮我转一下
我动态创建的部分这样:
声明部分:
...
    panel:tpanel;//panel是一个画布,在他上面动态生成控件
var i:integer;
    img:array[1..99] of timage;
    pan: array[1..99] of tpanel;
创建过程:
...
inc(i1);
 {动态创建panel}
 pk[i1]:=tpanel.Create(self);
 pk[i1].Parent:=panel1;
 pk[i1].BevelOuter:=bvNone;
 pk[i1].Width:=32;
 pk[i1].Height:=32;
 {动态创建imgku[i]}
 imgku[i1]:=timage.Create(self);
 imgku[i1].parent:=pk[i1];
 imgku[i1].Align:=alclient;
 imgku[i1].Picture.LoadFromFile('..\icon\仓库.bmp');
 imgku[i1].Transparent:=true;  //白色图片透明
 imgku[i1].Stretch:=true;//拉伸
 imgku[i1].Visible:=true;
 imgku[i1].OnMouseMove:=ku_mm;
 imgku[i1].OnMouseDown:=ku_md;
 imgku[i1].PopupMenu:=ku_popupmenu;
 imgku[i1].ShowHint:=true;  
 imgku[i1].Cursor:=crhandpoint;
 imgku[i1].Tag:=i1; //设置标志位
 imgku[i1].OnDblClick:=ku_odc;
 k1:=i1;
...
是不是这样写:(写成ini文件也可以,只要可以解决问题就行);
var 
   s:tstringstream;
begin
   s:=tstringstream.create('');
   imgku[i].picture.savetostream(s);
   ...//这里写成自定义文件保存?怎么写,不用这种也可以,只要可以解决问题
end

#6


解决这个问题的方法应该比较多:主要看你到底想做什么,
 FrameSniper(§绕瀑游龙§) 的方法不错,,但是需要看一下VCL的源码,,看是否可以空破;
Publicshed段的限制:因为这个方法本意是VCL用来持久FoRm设计信息的;
sy_315(莫名孤独
的方法比较贴近你的实际:不过是不是可以不用数组。。。用TLIST,就行了,,另外是不是可以不用那么多的PANEL。。。。

#7


如果只保存界面的话,用FS的方法很好用的

这种方法做报表特别好用(据说)

我那贴因为还要保存一些事件和属性,

最后选择的INI+本地数据库(access)

ini里保存的是创建的对象的属性和类名

数据库里主要保存图片

打开的时候是根据属性和类名一个个动态创建的

因为方法和属性都写在类里,所以不存在事件丢失的问题

至于速度还可以,我保存几十张带图片的对象,打开只用1秒左右(可能都是小图标的原因)

自定义的文件也很简单,把文件的扩展名换一下就行了

#8


to:skypeople
panel和image是邦定在一起动态产生的,因为image类没有句柄,我是通过panel传递句柄信息的。如果要实现那个功能和是否是数组应该没有多大关系。

to:FrameSniper(§绕瀑游龙§) 
你的方式暂时看可行,不过具体实现我要try一下

大家还有别的好方法么?我要具体实际一点的。最好用实例证明。

#9


to:myling(阿德)
我这个也要连接数据库的,保存的只是panel(画布)上面的panel和image数组的属性和事件。

至于panel和image邦定在一起他们反映的属性全在image数组的属性体现出来了。
真的那么难么?

#10


先mark一下。不知道你到底什么地方不能实现,要是所有的代码都给你帖出来也太累了……

#11


var 
   s:tstringstream;
begin
   s:=tstringstream.create('');
   imgku[i].picture.savetostream(s);
   ...//这里写成自定义文件保存?怎么写,不用这种也可以,只要可以解决问题
end

:imgku[i].picture.savetostream(s);这样写能通过吗?直接imgku[i].picture.savetofile()还可以。
  

#12


其实这个问题也描述成这样:
在一个form上面 创建以个panel1 作为画板,再这个panel1上面只动态加两种控件,就是动态创建邦定在一起的panel和image,他们邦定在一起可以实现在panel1上面拖动,onclick,showhint...等属性和事件。

要求:是把panel1上面的一切(动态创建的panel和image)的属性(位置,top,weigth,left,wide...)和事件(mousemove,mousedown...其中还包括我自己写的几个自定义过程)保存成为为自己定义文件(比如是test.test),保存的目的是为了日后可以打开他修改他。就是这样一个过程。

#13


我那种方法不难,只是麻烦一点


是属于那种笨方法,呵呵

#14


to:PrgmLover(爱国者)
不好意思,那个地方我的笔误之处,请原谅!
imgku[i].picture.savetofile();
imkku[i].picture.icon.savetostream();
是这样的,实在不好意思。

#15


我那种方法不难,只是麻烦一点


是属于那种笨方法,呵呵

#16


to :FrameSniper(§绕瀑游龙§)

你最上面写的那个实例怎么把文件读出来?
还有这样保存panel,我只看到了他的属性,我也看到了希望。

更正一下,我只要求保存控件属性。我刚刚才想到其他的什么事件根本就不用保存,因为他如果重新在入画板的时候,我程序原来定义的过程和事件通过句柄或者标志位就可以操纵他。

 

#17


今天头晕..
帮你顶一下算了

#18


问题不解决,自己顶一下吧。
奇怪了,高手都去那里了?今天也不是周末。
都快要哭了。

#19


UP

#20


自己来顶一下的。

#21


http://expert.csdn.net/Expert/topic/2179/2179440.xml?temp=.1161005


这贴子你看没看?

#22


学习

#23


to 阿德:
这个方法好,我去try
我把现在的问题贴出来,包括部分代码

我现在写了一个保存的,不知道怎么还原了,大家帮忙看看,请教一下。

button1->动态创建到panel上面
button2->以流形式保存

procedure TForm1.Button1Click(Sender: TObject);
begin
  i:=1;
  img[i]:=timage.Create(self);
  img[i].Picture.LoadFromFile('c:\icon\仓库.bmp');//这个可以自定义
  img[i].Parent:=panel1;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 SaveWorkAreaContent(img[1],'c:\1.txt');
end;

//这部分我用前面的高手的部分
procedure SaveWorkAreaContent(img: TImage; AFileName: string);
var
  BinStream:TMemoryStream;
  StrStream: TStringStream;
  S: String;
begin
  BinStream := TMemoryStream.Create;
  try
    BinStream.WriteComponent(img);
    BinStream.Seek(0, soFromBeginning);
    BinStream.SaveToFile(AFileName);
  finally
    BinStream.Free
  end;
end;

如何实现openWorkAreacontent

#24


两个过程是这样的:
procedure SaveComponent(Con: TWinControl; Path: string);

var
  BinStream:TMemoryStream;
  StrStream: TStringStream;
  s: string;
begin
  BinStream := TMemoryStream.Create;
  try
    BinStream.WriteComponent(Con);
    BinStream.Seek(0, soFromBeginning);
    BinStream.SaveToFile(Path);
  finally
    BinStream.Free
  end;
end;
procedure ReadComponent(Path: string; Con: TWinControl);
var
  BinStream: TMemoryStream;
  lp: integer;
  Com: TComponent;
begin
  //注意删除你不要的就可以了,自己做过滤
  for lp := Con.ComponentCount - 1 downto 0 do
  begin
    Com := Con.Components[lp];
    Con.RemoveComponent(Com);
    Com.Free;
  end;
  BinStream := TMemoryStream.Create;
  try
    BinStream.LoadFromFile(Path);
    BinStream.ReadComponent(Con);
  finally
    BinStream.Free;
  end;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  SaveComponent(panel1,'c:\ff.txt');//保存panel1上面的所有组件和其属性?
  img[i].Free;//这里释放动态创建的image
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
  ReadComponent('c:\ff.txt',panel1);//怎么没有效果呢
end;

#25


当我把image换掉,动态创建button或者panel就好了
而且我发现上面这个保存工作区是不是就是针对form1的
panel1上面的东西算不算一个工作区?

#26


up

#27


Procedure Register;
Begin
  RegisterComponents(...);
End;

如何注册我要动态创建的类?
我发现csdn一个bug,就是不能连续3次留言。
郁闷死了。
哭了...

#28


initialization
RegisterClasses([Tform]);
RegisterClasses([timage]);

以后发现动态创建form类可以实现,可是一旦加上image类,也就是在创建image以后,保存工作区还可以,但是在区回的时候发是异常错误发生,我怀疑image的问题,是不是注册方面有误,或者是因为我的方法不对,怎么没有人了啊。

#29


还的自己顶啊,马上就到3次了,路过的也来顶下吧

试着这样作了一下,不过可以存一个控件,如果多了怎么办?

procedure TForm1.Button2Click(Sender: TObject);
begin
for k:=i downto 1 do
begin
  WriteComponentResFile('c:\1.t',Img[k]);//这里反复写那个文件,保留下来的只有最后一个
  freeandnil(img[k]);
  Self.Refresh;
  showmessage(inttostr(k));
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin

  (ReadComponentResFile('c:\1.t',Nil) As TImage).Parent :=Panel1;
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
inc(i);
img[i]:=timage.Create(self);
img[i].Parent:=panel1;
img[i].ShowHint:=true;
img[i].Hint:='测试';
img[i].Picture.LoadFromFile('c:\icon\仓库.bmp');
img[i].Visible:=true;
img[i].Tag:=i;
img[i].OnMouseMove:=mm;
k:=i;
end;

#30


function GetHexPhoto(Str: String): String;
var
  i: integer;
begin
  result:= '';
  if Str = '' then exit;
  for i:= 1 to Length(Str) do
  begin
    result:= result + IntToHex(Ord(str[i]), 2);
  end;
end;

function GetStrPhoto(Hex: String): String;
var
  i, len: integer;
  tmp: string;
begin
  result:= '';
  len:= Length(hex);
  if (Len div 2) = 0 then exit;
  for i:= 0 to (len div 2 -1) do
  begin
    tmp:= '';
    tmp:= Hex[i * 2 + 1] + Hex[i * 2 + 2];
    Result:= Result + Chr(StrToInt('$'+Tmp));
  end;
end;

function TPhoto.SavePhoto: string;
var
  ss: TStringStream;
  Str: String;
  JPG: TJPEGImage;
begin
  ss:= TStringStream.Create('');
  try
    JPG:= TJPEGImage.Create;
    try
      jpg.Assign(Img.Picture.Graphic);
      jpg.SaveToStream(ss);
    finally
      jpg.Free;
    end;
    ss.Position:= 0;
    Str:= ss.DataString;
  finally
    ss.Free;
  end;
  result:= GetHexPhoto(Str);
end;

procedure TPhoto.LoadPhoto(Str: String);
var
  tmp: String;
  jpg: TJPEGImage;
  ss: TStringStream;
begin
  tmp:= GetStrPhoto(Str);  //将16进制的字符串还原
  if tmp = '' then exit;
  ss:= TStringStream.Create(tmp);
  try
    ss.Position:= 0;
    jpg:= TJPEGImage.Create;  //处理JPG图象
    try
      jpg.Empty;
      jpg.LoadFromStream(ss);
      Image4.Width:= jpg.Width;
      Image4.Height:= jpg.Height;
      Panel2.Width:= Jpg.Width;
      Panel2.Height:= Jpg.Height;

      Image4.Picture.Assign(jpg);
      Image4.AutoSize:= true;
      Addjust;
    finally
      jpg.Free;
    end;
  finally
    ss.Free;
  end;
end;

procedure TPhoto.CopyClick(Sender: TObject);
begin
  try
    Image4.Picture.LoadFromClipboardFormat(cf_BitMap,ClipBoard.GetAsHandle(cf_Bitmap),0);
    Panel2.Width:= Image4.Width;
    Panel2.Height:= Image4.Height;
    Addjust;
  except

  end;
end;

#31


To sy_315(NoName):你用那两个过程保存你Form上的控件是没问题的,我测过的

不知你遇到的错是什么错误,能否贴出,或找我:QQ 28588343

我估计你是读入时出错,应在FORM的oncreate注册你所用到的类,如

   RegisterClasses([TPanel,TImage]);//你其他用到的类加入,主要是控件类

#32


我也做过,我写进数据库里面!

#33


to : fengjn(小枫) 
    你着是保存一个图片系列,不是我想要的。

比如我写的这个实际例子:
在说例子之前我先问一个问题:所谓的保存工作区是保存form上的所用东西?我如果保存panel1上面的所有的控件,可以把panel1看成一个工作区么?还是那句话,具体实例。

代码如下:
介绍:我在form1上面做了几个功能按扭
button1 保存工作区
button2 打开保存的工作区
button3 动态创建一个form,在form上面创建一些控件,问题就出现在这里。如果放上image在       button2.onclick的时候出错。象海天子那样的注册我在formcreate的时候注册过了。
...
var
  form1: TForm;
  img : array[1..100] of timage;
  i,j,k:integer;
  b: tpanel;
  ff:tform;
...
procedure TForm1.Button1Click(Sender: TObject);
begin
  showmessage(inttostr(panel1.ComponentCount));//这里在panel1上面创建什么都是0,奇怪
  SaveComponent(form1,'c:\ff.txt');
  img[i].Free;
  img[i]:=nil;
  ff.free;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Register;
  ReadComponent('c:\ff.txt',form1);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  ff:=tform.Create(self);
  ff.Parent:=form1;
  ff.Caption:='new';
  ff.Visible:=true;
  inc(i);
  b:=tpanel.Create(self);
  b.Parent:=ff;
  b.Caption:='不知道';
  img[i]:=timage.Create(self);
  img[i].Picture.LoadFromFile('c:\icon\仓库.bmp');
  img[i].Parent:=ff;
  img[i].Width:=100;
  img[i].Top:=100;
  img[i].Height:=100;
  img[i].Left:=100;
  showmessage(inttostr(i));

end;
...
procedure TForm1.FormCreate(Sender: TObject);
var
begin
i:=0;
RegisterClasses([Tform,Timage]);

end;

#34


to : fengjn(小枫) 
    你着是保存一个图片系列,不是我想要的。

比如我写的这个实际例子:
在说例子之前我先问一个问题:所谓的保存工作区是保存form上的所用东西?我如果保存panel1上面的所有的控件,可以把panel1看成一个工作区么?还是那句话,具体实例。

代码如下:
介绍:我在form1上面做了几个功能按扭
button1 保存工作区
button2 打开保存的工作区
button3 动态创建一个form,在form上面创建一些控件,问题就出现在这里。如果放上image在       button2.onclick的时候出错。象海天子那样的注册我在formcreate的时候注册过了。
...
var
  form1: TForm;
  img : array[1..100] of timage;
  i,j,k:integer;
  b: tpanel;
  ff:tform;
...
procedure TForm1.Button1Click(Sender: TObject);
begin
  showmessage(inttostr(panel1.ComponentCount));//这里在panel1上面创建什么都是0,奇怪
  SaveComponent(form1,'c:\ff.txt');
  img[i].Free;
  img[i]:=nil;
  ff.free;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Register;
  ReadComponent('c:\ff.txt',form1);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  ff:=tform.Create(self);
  ff.Parent:=form1;
  ff.Caption:='new';
  ff.Visible:=true;
  inc(i);
  b:=tpanel.Create(self);
  b.Parent:=ff;
  b.Caption:='不知道';
  img[i]:=timage.Create(self);
  img[i].Picture.LoadFromFile('c:\icon\仓库.bmp');
  img[i].Parent:=ff;
  img[i].Width:=100;
  img[i].Top:=100;
  img[i].Height:=100;
  img[i].Left:=100;
  showmessage(inttostr(i));

end;
...
procedure TForm1.FormCreate(Sender: TObject);
var
begin
i:=0;
RegisterClasses([Tform,Timage]);

end;

#35


UP,都是高手哦。

#36


怎么没有人回答啊?
form1.componentcount的数值代表当前工作区的组件数,当动态创建的时候这个数值也可以
如果记录panle1的工作区,这样panle1.componentcount对吧
如果在pannel1上动态加组件,这个count数一直是0,好奇怪。

还有就是我上面的问题,可以save,不可以open啊
急死了。都68小时了,高手那里去了?
:(

#37


自己顶吧

#38


。。。。。。

#39


up

#40


嗬嗬,我是菜鸟,帮你顶一下

#41


up
我快要疯掉了,不过我的进度有点进展
看看大家有没有好的意见了

#42


其实前面很多老兄都给出你答案了,不知你想要什么?

#43


procedure SaveComponent(Con: TWinControl; Path: string);

var
  BinStream:TMemoryStream;
  StrStream: TStringStream;
  lp:integer;
  s: string;
begin
  BinStream := TMemoryStream.Create;
  try

    BinStream.WriteComponent(con.Components[2]);
  //这里我要保存部分模版的组件,比如说我在动态创建组件之前的组件总数是8
  //动态创建以后比如说是11个,我要作个循环把9-11的组件index也就是后来
  //创建的保存到一个自定义文件中,现在发现可以保存,但是在读的时候怎么老出错误
    //BinStream.WriteComponent(con.Components[1]);
    BinStream.Seek(0, soFromBeginning);
    BinStream.SaveToFile(Path);
    con.Components[2].Free;
  finally
    BinStream.Free
  end;
end;
//读模版
procedure ReadComponent(Path: string; Con: TWinControl);
var
  BinStream: TMemoryStream;
  lp: integer;
  Com: TComponent;
begin
  //注意删除你不要的就可以了,自己做过滤
  for lp := Con.ComponentCount -  downto 0 do
  begin
    Com := Con.Components[lp];
    Con.RemoveComponent(Com);
    //Com := Con.Components[1];
    Con.RemoveComponent(Com);
    Com.Free;
  end;
  BinStream := TMemoryStream.Create;
  try
    BinStream.LoadFromFile(Path);
    BinStream.ReadComponent(Con.Components[2]);
  finally
    BinStream.Free;
  end;
end;

#44


我在保存整个模版以后
就是上面那两个自定义过程savecomponent和readcomponent可以实现保存和打开
不过打开的时候发现模版上面后来动态创建的组件的事件不能用了,比如邦定在一起的image和panel,不能移动和修改了。怎么回事?
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//定义一个保存整个工作区的过程

procedure SaveComponent(con : Twincontrol;path : string);
var
  BinStream:TMemoryStream;
  StrStream: TStringStream;
  s: string;
begin
  BinStream := TMemoryStream.Create;
      try
        BinStream.WriteComponent(con);
        BinStream.Seek(0, soFromBeginning);//读取内存流,有三种方式
        BinStream.SaveToFile(Path);
        con.Free;
      finally
        BinStream.Free;
      end;
end;

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//定义一个读取保存过的工作区

procedure ReadComponent(Path: string; Con: TWinControl);
var
  BinStream: TMemoryStream;
  lp: integer;
  Com: TComponent;
begin
  //注意删除你不要的就可以了,自己做过滤
  for lp := Con.ComponentCount - 1 downto 0 do
  begin
    Com := Con.Components[lp];
      if assigned(com) then
      begin
      Con.RemoveComponent(Com);   //依次清掉已经存在的工作区的组件
      Com.Free;
      end;
    end;
  BinStream := TMemoryStream.Create;
  try
    BinStream.LoadFromFile(Path);
    BinStream.ReadComponent(Con); //读取工作区文件
  finally
    BinStream.Free;
  end;
end;

#45


看来模版这条路是走不过去了。
时间的关系,我暂时用保存ini文件的方法搞定这个在说。
郁闷死了。

#46


up~

#47


感谢大家的参与,问题我已经自行解决,使用ini文件实现存储。我定义了类似的两个过程:
如下:

procedure SaveComponent(path: PChar);
var
  sum_img: PChar;
  Name, hint: PChar;
  Height, top, left, Width, tag: PChar;
  num: Integer;
  max_ku, max_ban, max_san, max_dun: PChar;
begin
  //path 从opendialog中得到用户保存的地址。
  //库一为例子,先保存现场,然后恢复现场的时候遍历重新创建一次
  //img属性weight,wide,top,left,showhit,loadpicture,parent,visible,transparent,Align,Stretch,popmunu,tag,cursor
  //img事件mm,md,obc,
  //pan属性同上
  //只保存6个属性
  {写入信息}

  sum_img := PChar(IntToStr(i1 + i2 + i3 + i4));
  writeprivateprofilestring('sum_img', 'sum_img', sum_img, path);
  max_ku := PChar(IntToStr(i1));
  max_ban := PChar(IntToStr(i2));
  max_san := PChar(IntToStr(i3));
  max_dun := PChar(IntToStr(i4));
  writeprivateprofilestring('max_ku', 'max', max_ku, path);
  writeprivateprofilestring('max_ban', 'max', max_ban, path);
  writeprivateprofilestring('max_san', 'max', max_san, path);
  writeprivateprofilestring('max_dun', 'max', max_dun, path);
  for num := 1 to i1 do
  begin
    if assigned(imgku[num]) then
    begin
      Name := PChar('imgku' + IntToStr(num));//session名
      Width := PChar(IntToStr(pk[num].Width));
      top := PChar(IntToStr(pk[num].Top));
      left := PChar(IntToStr(pk[num].Left));
      Height := PChar(IntToStr(pk[num].Height));
      tag := PChar(IntToStr(imgku[num].Tag));
      hint := PChar(imgku[num].Hint);
      writeprivateprofilestring(Name, 'height', Height, path);
      writeprivateprofilestring(Name, 'width', Width, path);
      writeprivateprofilestring(Name, 'top', top, path);
      writeprivateprofilestring(Name, 'left', left, path);
      writeprivateprofilestring(Name, 'tag', tag, path);
      writeprivateprofilestring(Name, 'hint', hint, path);
    end;
  end;

  for num := 1 to i2 do
  begin
    if assigned(imgban[num]) then
    begin
      Name := PChar('imgban' + IntToStr(num));//session名
      Width := PChar(IntToStr(pb[num].Width));
      top := PChar(IntToStr(pb[num].Top));
      left := PChar(IntToStr(pb[num].Left));
      Height := PChar(IntToStr(pb[num].Height));
      tag := PChar(IntToStr(imgban[num].Tag));
      hint := PChar(imgban[num].Hint);
      writeprivateprofilestring(Name, 'height', Height, path);
      writeprivateprofilestring(Name, 'width', Width, path);
      writeprivateprofilestring(Name, 'top', top, path);
      writeprivateprofilestring(Name, 'left', left, path);
      writeprivateprofilestring(Name, 'tag', tag, path);
      writeprivateprofilestring(Name, 'hint', hint, path);
    end;
  end;

  for num := 1 to i3 do
  begin
    if assigned(imgsan[num]) then
    begin
      Name := PChar('imgsan' + IntToStr(num));//session名
      Width := PChar(IntToStr(ps[num].Width));
      top := PChar(IntToStr(ps[num].Top));
      left := PChar(IntToStr(ps[num].Left));
      Height := PChar(IntToStr(ps[num].Height));
      tag := PChar(IntToStr(imgsan[num].Tag));
      hint := PChar(imgsan[num].Hint);
      writeprivateprofilestring(Name, 'height', Height, path);
      writeprivateprofilestring(Name, 'width', Width, path);
      writeprivateprofilestring(Name, 'top', top, path);
      writeprivateprofilestring(Name, 'left', left, path);
      writeprivateprofilestring(Name, 'tag', tag, path);
      writeprivateprofilestring(Name, 'hint', hint, path);
    end;
  end;

  for num := 1 to i4 do
  begin
    if assigned(imgdun[num]) then
    begin
      Name := PChar('imgdun' + IntToStr(num));//session名
      Width := PChar(IntToStr(pd[num].Width));
      top := PChar(IntToStr(pd[num].Top));
      left := PChar(IntToStr(pd[num].Left));
      Height := PChar(IntToStr(pd[num].Height));
      tag := PChar(IntToStr(imgdun[num].Tag));
      hint := PChar(imgdun[num].Hint);
      writeprivateprofilestring(Name, 'height', Height, path);
      writeprivateprofilestring(Name, 'width', Width, path);
      writeprivateprofilestring(Name, 'top', top, path);
      writeprivateprofilestring(Name, 'left', left, path);
      writeprivateprofilestring(Name, 'tag', tag, path);
      writeprivateprofilestring(Name, 'hint', hint, path);
    end;
  end;
end;

#48


/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//读取

procedure ReadComponent(path: PChar);
const
  buffer = 255;//定义缓冲区大小
var
  sum_img: PChar;
  Name, hint: PChar;
  Height, top, left, Width, tag: PChar;
  num: Integer;
  max_ku, max_ban, max_san, max_dun: PChar;
begin
//给三个变量分配内存大小,否则在getprinvateprofilestring的时候出错。
  getmem(sum_img, buffer);
  getmem(max_ku, buffer);
  getmem(max_ban, buffer);
  getmem(max_san, buffer);
  getmem(max_dun, buffer);
  getmem(Name, buffer);
  getmem(Height, buffer);
  getmem(hint, buffer);
  getmem(top, buffer);
  getmem(left, buffer);
  getmem(Width, buffer);
  getmem(tag, buffer);
//取出要创建的总数,前面应该在写的时候加以个每项的最大值
  getprivateprofilestring('sum_img', 'sum_img', '', sum_img, buffer, path);
//每一项的最大值
  getprivateprofilestring('max_ku', 'max', '', max_ku, buffer, path);
  getprivateprofilestring('max_ban', 'max', '', max_ban, buffer, path);
  getprivateprofilestring('max_san', 'max', '', max_san, buffer, path);
  getprivateprofilestring('max_dun', 'max', '', max_dun, buffer, path);
//遍历文件,重新创建

//ku
  for num := 1 to StrToInt(max_ku) do
  begin
    Name := PChar('imgku' + IntToStr(num));//session名
    begin
      //判断是否存在这个session用什么函数
      //如果找不到返回默认值为空 ''
      GetPrivateProfileString(Name, 'height', '', Height, buffer, path);
      GetPrivateProfileString(Name, 'width', '', Width, buffer, path);
      GetPrivateProfileString(Name, 'left', '', left, buffer, path);
      GetPrivateProfileString(Name, 'top', '', top, buffer, path);
      GetPrivateProfileString(Name, 'hint', '', hint, buffer, path);
      GetPrivateProfileString(Name, 'tag', 'error1', tag, buffer, path);
      //如果不存在,则返回error
      if tag <> 'error1' then
      begin
        i1 := num - 1;
        form1.ck_button.Click;
        pk[i1].left := StrToInt(left);
        pk[i1].Height := StrToInt(Height);
        pk[i1].Top := StrToInt(top);
        pk[i1].Width := StrToInt(Width);
        imgku[i1].Hint := hint;
      end;
    end;
  end;

//ban
  for num := 1 to StrToInt(max_ban) do
  begin
    Name := PChar('imgban' + IntToStr(num));//session名
    begin
      //判断是否存在这个session用什么函数
      //如果找不到返回默认值为空 ''
      GetPrivateProfileString(Name, 'height', '', Height, buffer, path);
      GetPrivateProfileString(Name, 'width', '', Width, buffer, path);
      GetPrivateProfileString(Name, 'left', '', left, buffer, path);
      GetPrivateProfileString(Name, 'top', '', top, buffer, path);
      GetPrivateProfileString(Name, 'hint', '', hint, buffer, path);
      GetPrivateProfileString(Name, 'tag', 'error2', tag, buffer, path);
      //如果不存在,则返回error
      if tag <> 'error2' then
      begin
        i2 := num - 1;
        form1.bg_button.Click;
        pb[i2].left := StrToInt(left);
        pb[i2].Height := StrToInt(Height);
        pb[i2].Top := StrToInt(top);
        pb[i2].Width := StrToInt(Width);
        imgban[i2].Hint := hint;
      end;
    end;
  end;

//san
  for num := 1 to StrToInt(max_san) do
  begin
    Name := PChar('imgsan' + IntToStr(num));//session名
    begin
      //判断是否存在这个session用什么函数
      //如果找不到返回默认值为空 ''
      GetPrivateProfileString(Name, 'height', '', Height, buffer, path);
      GetPrivateProfileString(Name, 'width', '', Width, buffer, path);
      GetPrivateProfileString(Name, 'left', '', left, buffer, path);
      GetPrivateProfileString(Name, 'top', '', top, buffer, path);
      GetPrivateProfileString(Name, 'hint', '', hint, buffer, path);
      GetPrivateProfileString(Name, 'tag', 'error3', tag, buffer, path);
      //如果不存在,则返回error
      if tag <> 'error3' then
      begin
        i3 := num - 1;
        form1.san_button.Click;
        ps[i3].left := StrToInt(left);
        ps[i3].Height := StrToInt(Height);
        ps[i3].Top := StrToInt(top);
        ps[i3].Width := StrToInt(Width);
        imgsan[i3].Hint := hint;
      end;
    end;
  end;

//dun

  for num := 1 to StrToInt(max_dun) do
  begin
    Name := PChar('imgdun' + IntToStr(num));//session名
    begin
      //判断是否存在这个session用什么函数
      //如果找不到返回默认值为空 ''
      GetPrivateProfileString(Name, 'height', '', Height, buffer, path);
      GetPrivateProfileString(Name, 'width', '', Width, buffer, path);
      GetPrivateProfileString(Name, 'left', '', left, buffer, path);
      GetPrivateProfileString(Name, 'top', '', top, buffer, path);
      GetPrivateProfileString(Name, 'hint', '', hint, buffer, path);
      GetPrivateProfileString(Name, 'tag', 'error4', tag, buffer, path);
      //如果不存在,则返回error
      if tag <> 'error4' then
      begin
        i4 := num - 1;
        form1.dun_button.Click;
        pd[i4].left := StrToInt(left);
        pd[i4].Height := StrToInt(Height);
        pd[i4].Top := StrToInt(top);
        pd[i4].Width := StrToInt(Width);
        imgdun[i4].Hint := hint;
      end;
    end;
  end;
  freemem(sum_img, buffer);
  freemem(max_ku, buffer);
  freemem(max_ban, buffer);
  freemem(max_san, buffer);
  freemem(max_dun, buffer);
  //freemem(name,buffer); //释放他有错误发生,暂时找不到原因
  freemem(Height, buffer);
  freemem(hint, buffer);
  freemem(top, buffer);
  freemem(left, buffer);
  freemem(Width, buffer);
  freemem(tag, buffer);
end;

#1


up,学习

#2


想动态地将一个窗体上所有控制的值保存到一个文件吗?利用初始化文件(ini文件)和RTTI,只需要编写一次代码,无论窗体上有多少控制,都可以将它们的值写到指定的文件。同样,写一个逆过程,可以将保存在文件的值直接读出,并设置到对应的控制中。
var
sSection,  sFileName, sIdent: String;
iniMyFile: TiniFile;

begin
try
  iniMyFile := TIniFile.Create(sFileName);
  for i := 0 to (Self.ComponentCount - 1) do
    begin
    sSection := Self.Name;
    if Components[i] is TEdit then
      begin
      with Components[i] as TEdit do
        begin
        sIdent := Name;
        if Trim(Text) = '' then
          iniMyFile.WriteString(sSection, sIdent, '0')
        else
          iniMyFile.WriteString(sSection, sIdent, Text);
        end;
      end
  else if Components[i] is TCheckBox then
      begin
      sIdent := Components[i].Name;
      iniMyFile.WriteBool(sSection, sIdent, (Components[i] as
TCheckBox).Checked);
      end
  else if { 下面编写窗体上使用过的所有的控制类型 }
      begin
      end;
  end;   { for i }
finally
  iniMyFile.Free;
end;  { try..finally }

end;   { End of SaveToFile }
结果文件类似于:
[窗体名称]
edit_ucost_c_3=61.80
edit_ucost_c_5=66.30
edit_ucost_c_6=69.90
edit_ucost_c_7=64.20
edit_ucost_c_8=66.30
cbShowUtilization=1

#3


呵呵,就是工作区的问题!可以用流类解决!如下:

procedure SaveWorkAreaContent(APanel: TPanel; AFileName: string);

var
  BinStream:TMemoryStream;
  StrStream: TStringStream;
  S: String;
begin
  BinStream := TMemoryStream.Create;
  try
    BinStream.WriteComponent(APanel);
    BinStream.Seek(0, soFromBeginning);
    BinStream.SaveToFile(AFileName);
  finally
    BinStream.Free
  end;
end;

使用流化的方式只可以保存公布Published的内容,而且文件后缀在AFileName自己指定!


#4


http://expert.csdn.net/Expert/topic/2179/2179440.xml?temp=.1161005

可以参考一下这个帖子的内容!

#5


我给出你部分动态创建的代码,我想把panel上的所有控件的属性和状态位置保存下来,帮我转一下
我动态创建的部分这样:
声明部分:
...
    panel:tpanel;//panel是一个画布,在他上面动态生成控件
var i:integer;
    img:array[1..99] of timage;
    pan: array[1..99] of tpanel;
创建过程:
...
inc(i1);
 {动态创建panel}
 pk[i1]:=tpanel.Create(self);
 pk[i1].Parent:=panel1;
 pk[i1].BevelOuter:=bvNone;
 pk[i1].Width:=32;
 pk[i1].Height:=32;
 {动态创建imgku[i]}
 imgku[i1]:=timage.Create(self);
 imgku[i1].parent:=pk[i1];
 imgku[i1].Align:=alclient;
 imgku[i1].Picture.LoadFromFile('..\icon\仓库.bmp');
 imgku[i1].Transparent:=true;  //白色图片透明
 imgku[i1].Stretch:=true;//拉伸
 imgku[i1].Visible:=true;
 imgku[i1].OnMouseMove:=ku_mm;
 imgku[i1].OnMouseDown:=ku_md;
 imgku[i1].PopupMenu:=ku_popupmenu;
 imgku[i1].ShowHint:=true;  
 imgku[i1].Cursor:=crhandpoint;
 imgku[i1].Tag:=i1; //设置标志位
 imgku[i1].OnDblClick:=ku_odc;
 k1:=i1;
...
是不是这样写:(写成ini文件也可以,只要可以解决问题就行);
var 
   s:tstringstream;
begin
   s:=tstringstream.create('');
   imgku[i].picture.savetostream(s);
   ...//这里写成自定义文件保存?怎么写,不用这种也可以,只要可以解决问题
end

#6


解决这个问题的方法应该比较多:主要看你到底想做什么,
 FrameSniper(§绕瀑游龙§) 的方法不错,,但是需要看一下VCL的源码,,看是否可以空破;
Publicshed段的限制:因为这个方法本意是VCL用来持久FoRm设计信息的;
sy_315(莫名孤独
的方法比较贴近你的实际:不过是不是可以不用数组。。。用TLIST,就行了,,另外是不是可以不用那么多的PANEL。。。。

#7


如果只保存界面的话,用FS的方法很好用的

这种方法做报表特别好用(据说)

我那贴因为还要保存一些事件和属性,

最后选择的INI+本地数据库(access)

ini里保存的是创建的对象的属性和类名

数据库里主要保存图片

打开的时候是根据属性和类名一个个动态创建的

因为方法和属性都写在类里,所以不存在事件丢失的问题

至于速度还可以,我保存几十张带图片的对象,打开只用1秒左右(可能都是小图标的原因)

自定义的文件也很简单,把文件的扩展名换一下就行了

#8


to:skypeople
panel和image是邦定在一起动态产生的,因为image类没有句柄,我是通过panel传递句柄信息的。如果要实现那个功能和是否是数组应该没有多大关系。

to:FrameSniper(§绕瀑游龙§) 
你的方式暂时看可行,不过具体实现我要try一下

大家还有别的好方法么?我要具体实际一点的。最好用实例证明。

#9


to:myling(阿德)
我这个也要连接数据库的,保存的只是panel(画布)上面的panel和image数组的属性和事件。

至于panel和image邦定在一起他们反映的属性全在image数组的属性体现出来了。
真的那么难么?

#10


先mark一下。不知道你到底什么地方不能实现,要是所有的代码都给你帖出来也太累了……

#11


var 
   s:tstringstream;
begin
   s:=tstringstream.create('');
   imgku[i].picture.savetostream(s);
   ...//这里写成自定义文件保存?怎么写,不用这种也可以,只要可以解决问题
end

:imgku[i].picture.savetostream(s);这样写能通过吗?直接imgku[i].picture.savetofile()还可以。
  

#12


其实这个问题也描述成这样:
在一个form上面 创建以个panel1 作为画板,再这个panel1上面只动态加两种控件,就是动态创建邦定在一起的panel和image,他们邦定在一起可以实现在panel1上面拖动,onclick,showhint...等属性和事件。

要求:是把panel1上面的一切(动态创建的panel和image)的属性(位置,top,weigth,left,wide...)和事件(mousemove,mousedown...其中还包括我自己写的几个自定义过程)保存成为为自己定义文件(比如是test.test),保存的目的是为了日后可以打开他修改他。就是这样一个过程。

#13


我那种方法不难,只是麻烦一点


是属于那种笨方法,呵呵

#14


to:PrgmLover(爱国者)
不好意思,那个地方我的笔误之处,请原谅!
imgku[i].picture.savetofile();
imkku[i].picture.icon.savetostream();
是这样的,实在不好意思。

#15


我那种方法不难,只是麻烦一点


是属于那种笨方法,呵呵

#16


to :FrameSniper(§绕瀑游龙§)

你最上面写的那个实例怎么把文件读出来?
还有这样保存panel,我只看到了他的属性,我也看到了希望。

更正一下,我只要求保存控件属性。我刚刚才想到其他的什么事件根本就不用保存,因为他如果重新在入画板的时候,我程序原来定义的过程和事件通过句柄或者标志位就可以操纵他。

 

#17


今天头晕..
帮你顶一下算了

#18


问题不解决,自己顶一下吧。
奇怪了,高手都去那里了?今天也不是周末。
都快要哭了。

#19


UP

#20


自己来顶一下的。

#21


http://expert.csdn.net/Expert/topic/2179/2179440.xml?temp=.1161005


这贴子你看没看?

#22


学习

#23


to 阿德:
这个方法好,我去try
我把现在的问题贴出来,包括部分代码

我现在写了一个保存的,不知道怎么还原了,大家帮忙看看,请教一下。

button1->动态创建到panel上面
button2->以流形式保存

procedure TForm1.Button1Click(Sender: TObject);
begin
  i:=1;
  img[i]:=timage.Create(self);
  img[i].Picture.LoadFromFile('c:\icon\仓库.bmp');//这个可以自定义
  img[i].Parent:=panel1;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 SaveWorkAreaContent(img[1],'c:\1.txt');
end;

//这部分我用前面的高手的部分
procedure SaveWorkAreaContent(img: TImage; AFileName: string);
var
  BinStream:TMemoryStream;
  StrStream: TStringStream;
  S: String;
begin
  BinStream := TMemoryStream.Create;
  try
    BinStream.WriteComponent(img);
    BinStream.Seek(0, soFromBeginning);
    BinStream.SaveToFile(AFileName);
  finally
    BinStream.Free
  end;
end;

如何实现openWorkAreacontent

#24


两个过程是这样的:
procedure SaveComponent(Con: TWinControl; Path: string);

var
  BinStream:TMemoryStream;
  StrStream: TStringStream;
  s: string;
begin
  BinStream := TMemoryStream.Create;
  try
    BinStream.WriteComponent(Con);
    BinStream.Seek(0, soFromBeginning);
    BinStream.SaveToFile(Path);
  finally
    BinStream.Free
  end;
end;
procedure ReadComponent(Path: string; Con: TWinControl);
var
  BinStream: TMemoryStream;
  lp: integer;
  Com: TComponent;
begin
  //注意删除你不要的就可以了,自己做过滤
  for lp := Con.ComponentCount - 1 downto 0 do
  begin
    Com := Con.Components[lp];
    Con.RemoveComponent(Com);
    Com.Free;
  end;
  BinStream := TMemoryStream.Create;
  try
    BinStream.LoadFromFile(Path);
    BinStream.ReadComponent(Con);
  finally
    BinStream.Free;
  end;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  SaveComponent(panel1,'c:\ff.txt');//保存panel1上面的所有组件和其属性?
  img[i].Free;//这里释放动态创建的image
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
  ReadComponent('c:\ff.txt',panel1);//怎么没有效果呢
end;

#25


当我把image换掉,动态创建button或者panel就好了
而且我发现上面这个保存工作区是不是就是针对form1的
panel1上面的东西算不算一个工作区?

#26


up

#27


Procedure Register;
Begin
  RegisterComponents(...);
End;

如何注册我要动态创建的类?
我发现csdn一个bug,就是不能连续3次留言。
郁闷死了。
哭了...

#28


initialization
RegisterClasses([Tform]);
RegisterClasses([timage]);

以后发现动态创建form类可以实现,可是一旦加上image类,也就是在创建image以后,保存工作区还可以,但是在区回的时候发是异常错误发生,我怀疑image的问题,是不是注册方面有误,或者是因为我的方法不对,怎么没有人了啊。

#29


还的自己顶啊,马上就到3次了,路过的也来顶下吧

试着这样作了一下,不过可以存一个控件,如果多了怎么办?

procedure TForm1.Button2Click(Sender: TObject);
begin
for k:=i downto 1 do
begin
  WriteComponentResFile('c:\1.t',Img[k]);//这里反复写那个文件,保留下来的只有最后一个
  freeandnil(img[k]);
  Self.Refresh;
  showmessage(inttostr(k));
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin

  (ReadComponentResFile('c:\1.t',Nil) As TImage).Parent :=Panel1;
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
inc(i);
img[i]:=timage.Create(self);
img[i].Parent:=panel1;
img[i].ShowHint:=true;
img[i].Hint:='测试';
img[i].Picture.LoadFromFile('c:\icon\仓库.bmp');
img[i].Visible:=true;
img[i].Tag:=i;
img[i].OnMouseMove:=mm;
k:=i;
end;

#30


function GetHexPhoto(Str: String): String;
var
  i: integer;
begin
  result:= '';
  if Str = '' then exit;
  for i:= 1 to Length(Str) do
  begin
    result:= result + IntToHex(Ord(str[i]), 2);
  end;
end;

function GetStrPhoto(Hex: String): String;
var
  i, len: integer;
  tmp: string;
begin
  result:= '';
  len:= Length(hex);
  if (Len div 2) = 0 then exit;
  for i:= 0 to (len div 2 -1) do
  begin
    tmp:= '';
    tmp:= Hex[i * 2 + 1] + Hex[i * 2 + 2];
    Result:= Result + Chr(StrToInt('$'+Tmp));
  end;
end;

function TPhoto.SavePhoto: string;
var
  ss: TStringStream;
  Str: String;
  JPG: TJPEGImage;
begin
  ss:= TStringStream.Create('');
  try
    JPG:= TJPEGImage.Create;
    try
      jpg.Assign(Img.Picture.Graphic);
      jpg.SaveToStream(ss);
    finally
      jpg.Free;
    end;
    ss.Position:= 0;
    Str:= ss.DataString;
  finally
    ss.Free;
  end;
  result:= GetHexPhoto(Str);
end;

procedure TPhoto.LoadPhoto(Str: String);
var
  tmp: String;
  jpg: TJPEGImage;
  ss: TStringStream;
begin
  tmp:= GetStrPhoto(Str);  //将16进制的字符串还原
  if tmp = '' then exit;
  ss:= TStringStream.Create(tmp);
  try
    ss.Position:= 0;
    jpg:= TJPEGImage.Create;  //处理JPG图象
    try
      jpg.Empty;
      jpg.LoadFromStream(ss);
      Image4.Width:= jpg.Width;
      Image4.Height:= jpg.Height;
      Panel2.Width:= Jpg.Width;
      Panel2.Height:= Jpg.Height;

      Image4.Picture.Assign(jpg);
      Image4.AutoSize:= true;
      Addjust;
    finally
      jpg.Free;
    end;
  finally
    ss.Free;
  end;
end;

procedure TPhoto.CopyClick(Sender: TObject);
begin
  try
    Image4.Picture.LoadFromClipboardFormat(cf_BitMap,ClipBoard.GetAsHandle(cf_Bitmap),0);
    Panel2.Width:= Image4.Width;
    Panel2.Height:= Image4.Height;
    Addjust;
  except

  end;
end;

#31


To sy_315(NoName):你用那两个过程保存你Form上的控件是没问题的,我测过的

不知你遇到的错是什么错误,能否贴出,或找我:QQ 28588343

我估计你是读入时出错,应在FORM的oncreate注册你所用到的类,如

   RegisterClasses([TPanel,TImage]);//你其他用到的类加入,主要是控件类

#32


我也做过,我写进数据库里面!

#33


to : fengjn(小枫) 
    你着是保存一个图片系列,不是我想要的。

比如我写的这个实际例子:
在说例子之前我先问一个问题:所谓的保存工作区是保存form上的所用东西?我如果保存panel1上面的所有的控件,可以把panel1看成一个工作区么?还是那句话,具体实例。

代码如下:
介绍:我在form1上面做了几个功能按扭
button1 保存工作区
button2 打开保存的工作区
button3 动态创建一个form,在form上面创建一些控件,问题就出现在这里。如果放上image在       button2.onclick的时候出错。象海天子那样的注册我在formcreate的时候注册过了。
...
var
  form1: TForm;
  img : array[1..100] of timage;
  i,j,k:integer;
  b: tpanel;
  ff:tform;
...
procedure TForm1.Button1Click(Sender: TObject);
begin
  showmessage(inttostr(panel1.ComponentCount));//这里在panel1上面创建什么都是0,奇怪
  SaveComponent(form1,'c:\ff.txt');
  img[i].Free;
  img[i]:=nil;
  ff.free;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Register;
  ReadComponent('c:\ff.txt',form1);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  ff:=tform.Create(self);
  ff.Parent:=form1;
  ff.Caption:='new';
  ff.Visible:=true;
  inc(i);
  b:=tpanel.Create(self);
  b.Parent:=ff;
  b.Caption:='不知道';
  img[i]:=timage.Create(self);
  img[i].Picture.LoadFromFile('c:\icon\仓库.bmp');
  img[i].Parent:=ff;
  img[i].Width:=100;
  img[i].Top:=100;
  img[i].Height:=100;
  img[i].Left:=100;
  showmessage(inttostr(i));

end;
...
procedure TForm1.FormCreate(Sender: TObject);
var
begin
i:=0;
RegisterClasses([Tform,Timage]);

end;

#34


to : fengjn(小枫) 
    你着是保存一个图片系列,不是我想要的。

比如我写的这个实际例子:
在说例子之前我先问一个问题:所谓的保存工作区是保存form上的所用东西?我如果保存panel1上面的所有的控件,可以把panel1看成一个工作区么?还是那句话,具体实例。

代码如下:
介绍:我在form1上面做了几个功能按扭
button1 保存工作区
button2 打开保存的工作区
button3 动态创建一个form,在form上面创建一些控件,问题就出现在这里。如果放上image在       button2.onclick的时候出错。象海天子那样的注册我在formcreate的时候注册过了。
...
var
  form1: TForm;
  img : array[1..100] of timage;
  i,j,k:integer;
  b: tpanel;
  ff:tform;
...
procedure TForm1.Button1Click(Sender: TObject);
begin
  showmessage(inttostr(panel1.ComponentCount));//这里在panel1上面创建什么都是0,奇怪
  SaveComponent(form1,'c:\ff.txt');
  img[i].Free;
  img[i]:=nil;
  ff.free;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Register;
  ReadComponent('c:\ff.txt',form1);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  ff:=tform.Create(self);
  ff.Parent:=form1;
  ff.Caption:='new';
  ff.Visible:=true;
  inc(i);
  b:=tpanel.Create(self);
  b.Parent:=ff;
  b.Caption:='不知道';
  img[i]:=timage.Create(self);
  img[i].Picture.LoadFromFile('c:\icon\仓库.bmp');
  img[i].Parent:=ff;
  img[i].Width:=100;
  img[i].Top:=100;
  img[i].Height:=100;
  img[i].Left:=100;
  showmessage(inttostr(i));

end;
...
procedure TForm1.FormCreate(Sender: TObject);
var
begin
i:=0;
RegisterClasses([Tform,Timage]);

end;

#35


UP,都是高手哦。

#36


怎么没有人回答啊?
form1.componentcount的数值代表当前工作区的组件数,当动态创建的时候这个数值也可以
如果记录panle1的工作区,这样panle1.componentcount对吧
如果在pannel1上动态加组件,这个count数一直是0,好奇怪。

还有就是我上面的问题,可以save,不可以open啊
急死了。都68小时了,高手那里去了?
:(

#37


自己顶吧

#38


。。。。。。

#39


up

#40


嗬嗬,我是菜鸟,帮你顶一下

#41


up
我快要疯掉了,不过我的进度有点进展
看看大家有没有好的意见了

#42


其实前面很多老兄都给出你答案了,不知你想要什么?

#43


procedure SaveComponent(Con: TWinControl; Path: string);

var
  BinStream:TMemoryStream;
  StrStream: TStringStream;
  lp:integer;
  s: string;
begin
  BinStream := TMemoryStream.Create;
  try

    BinStream.WriteComponent(con.Components[2]);
  //这里我要保存部分模版的组件,比如说我在动态创建组件之前的组件总数是8
  //动态创建以后比如说是11个,我要作个循环把9-11的组件index也就是后来
  //创建的保存到一个自定义文件中,现在发现可以保存,但是在读的时候怎么老出错误
    //BinStream.WriteComponent(con.Components[1]);
    BinStream.Seek(0, soFromBeginning);
    BinStream.SaveToFile(Path);
    con.Components[2].Free;
  finally
    BinStream.Free
  end;
end;
//读模版
procedure ReadComponent(Path: string; Con: TWinControl);
var
  BinStream: TMemoryStream;
  lp: integer;
  Com: TComponent;
begin
  //注意删除你不要的就可以了,自己做过滤
  for lp := Con.ComponentCount -  downto 0 do
  begin
    Com := Con.Components[lp];
    Con.RemoveComponent(Com);
    //Com := Con.Components[1];
    Con.RemoveComponent(Com);
    Com.Free;
  end;
  BinStream := TMemoryStream.Create;
  try
    BinStream.LoadFromFile(Path);
    BinStream.ReadComponent(Con.Components[2]);
  finally
    BinStream.Free;
  end;
end;

#44


我在保存整个模版以后
就是上面那两个自定义过程savecomponent和readcomponent可以实现保存和打开
不过打开的时候发现模版上面后来动态创建的组件的事件不能用了,比如邦定在一起的image和panel,不能移动和修改了。怎么回事?
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//定义一个保存整个工作区的过程

procedure SaveComponent(con : Twincontrol;path : string);
var
  BinStream:TMemoryStream;
  StrStream: TStringStream;
  s: string;
begin
  BinStream := TMemoryStream.Create;
      try
        BinStream.WriteComponent(con);
        BinStream.Seek(0, soFromBeginning);//读取内存流,有三种方式
        BinStream.SaveToFile(Path);
        con.Free;
      finally
        BinStream.Free;
      end;
end;

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//定义一个读取保存过的工作区

procedure ReadComponent(Path: string; Con: TWinControl);
var
  BinStream: TMemoryStream;
  lp: integer;
  Com: TComponent;
begin
  //注意删除你不要的就可以了,自己做过滤
  for lp := Con.ComponentCount - 1 downto 0 do
  begin
    Com := Con.Components[lp];
      if assigned(com) then
      begin
      Con.RemoveComponent(Com);   //依次清掉已经存在的工作区的组件
      Com.Free;
      end;
    end;
  BinStream := TMemoryStream.Create;
  try
    BinStream.LoadFromFile(Path);
    BinStream.ReadComponent(Con); //读取工作区文件
  finally
    BinStream.Free;
  end;
end;

#45


看来模版这条路是走不过去了。
时间的关系,我暂时用保存ini文件的方法搞定这个在说。
郁闷死了。

#46


up~

#47


感谢大家的参与,问题我已经自行解决,使用ini文件实现存储。我定义了类似的两个过程:
如下:

procedure SaveComponent(path: PChar);
var
  sum_img: PChar;
  Name, hint: PChar;
  Height, top, left, Width, tag: PChar;
  num: Integer;
  max_ku, max_ban, max_san, max_dun: PChar;
begin
  //path 从opendialog中得到用户保存的地址。
  //库一为例子,先保存现场,然后恢复现场的时候遍历重新创建一次
  //img属性weight,wide,top,left,showhit,loadpicture,parent,visible,transparent,Align,Stretch,popmunu,tag,cursor
  //img事件mm,md,obc,
  //pan属性同上
  //只保存6个属性
  {写入信息}

  sum_img := PChar(IntToStr(i1 + i2 + i3 + i4));
  writeprivateprofilestring('sum_img', 'sum_img', sum_img, path);
  max_ku := PChar(IntToStr(i1));
  max_ban := PChar(IntToStr(i2));
  max_san := PChar(IntToStr(i3));
  max_dun := PChar(IntToStr(i4));
  writeprivateprofilestring('max_ku', 'max', max_ku, path);
  writeprivateprofilestring('max_ban', 'max', max_ban, path);
  writeprivateprofilestring('max_san', 'max', max_san, path);
  writeprivateprofilestring('max_dun', 'max', max_dun, path);
  for num := 1 to i1 do
  begin
    if assigned(imgku[num]) then
    begin
      Name := PChar('imgku' + IntToStr(num));//session名
      Width := PChar(IntToStr(pk[num].Width));
      top := PChar(IntToStr(pk[num].Top));
      left := PChar(IntToStr(pk[num].Left));
      Height := PChar(IntToStr(pk[num].Height));
      tag := PChar(IntToStr(imgku[num].Tag));
      hint := PChar(imgku[num].Hint);
      writeprivateprofilestring(Name, 'height', Height, path);
      writeprivateprofilestring(Name, 'width', Width, path);
      writeprivateprofilestring(Name, 'top', top, path);
      writeprivateprofilestring(Name, 'left', left, path);
      writeprivateprofilestring(Name, 'tag', tag, path);
      writeprivateprofilestring(Name, 'hint', hint, path);
    end;
  end;

  for num := 1 to i2 do
  begin
    if assigned(imgban[num]) then
    begin
      Name := PChar('imgban' + IntToStr(num));//session名
      Width := PChar(IntToStr(pb[num].Width));
      top := PChar(IntToStr(pb[num].Top));
      left := PChar(IntToStr(pb[num].Left));
      Height := PChar(IntToStr(pb[num].Height));
      tag := PChar(IntToStr(imgban[num].Tag));
      hint := PChar(imgban[num].Hint);
      writeprivateprofilestring(Name, 'height', Height, path);
      writeprivateprofilestring(Name, 'width', Width, path);
      writeprivateprofilestring(Name, 'top', top, path);
      writeprivateprofilestring(Name, 'left', left, path);
      writeprivateprofilestring(Name, 'tag', tag, path);
      writeprivateprofilestring(Name, 'hint', hint, path);
    end;
  end;

  for num := 1 to i3 do
  begin
    if assigned(imgsan[num]) then
    begin
      Name := PChar('imgsan' + IntToStr(num));//session名
      Width := PChar(IntToStr(ps[num].Width));
      top := PChar(IntToStr(ps[num].Top));
      left := PChar(IntToStr(ps[num].Left));
      Height := PChar(IntToStr(ps[num].Height));
      tag := PChar(IntToStr(imgsan[num].Tag));
      hint := PChar(imgsan[num].Hint);
      writeprivateprofilestring(Name, 'height', Height, path);
      writeprivateprofilestring(Name, 'width', Width, path);
      writeprivateprofilestring(Name, 'top', top, path);
      writeprivateprofilestring(Name, 'left', left, path);
      writeprivateprofilestring(Name, 'tag', tag, path);
      writeprivateprofilestring(Name, 'hint', hint, path);
    end;
  end;

  for num := 1 to i4 do
  begin
    if assigned(imgdun[num]) then
    begin
      Name := PChar('imgdun' + IntToStr(num));//session名
      Width := PChar(IntToStr(pd[num].Width));
      top := PChar(IntToStr(pd[num].Top));
      left := PChar(IntToStr(pd[num].Left));
      Height := PChar(IntToStr(pd[num].Height));
      tag := PChar(IntToStr(imgdun[num].Tag));
      hint := PChar(imgdun[num].Hint);
      writeprivateprofilestring(Name, 'height', Height, path);
      writeprivateprofilestring(Name, 'width', Width, path);
      writeprivateprofilestring(Name, 'top', top, path);
      writeprivateprofilestring(Name, 'left', left, path);
      writeprivateprofilestring(Name, 'tag', tag, path);
      writeprivateprofilestring(Name, 'hint', hint, path);
    end;
  end;
end;

#48


/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//读取

procedure ReadComponent(path: PChar);
const
  buffer = 255;//定义缓冲区大小
var
  sum_img: PChar;
  Name, hint: PChar;
  Height, top, left, Width, tag: PChar;
  num: Integer;
  max_ku, max_ban, max_san, max_dun: PChar;
begin
//给三个变量分配内存大小,否则在getprinvateprofilestring的时候出错。
  getmem(sum_img, buffer);
  getmem(max_ku, buffer);
  getmem(max_ban, buffer);
  getmem(max_san, buffer);
  getmem(max_dun, buffer);
  getmem(Name, buffer);
  getmem(Height, buffer);
  getmem(hint, buffer);
  getmem(top, buffer);
  getmem(left, buffer);
  getmem(Width, buffer);
  getmem(tag, buffer);
//取出要创建的总数,前面应该在写的时候加以个每项的最大值
  getprivateprofilestring('sum_img', 'sum_img', '', sum_img, buffer, path);
//每一项的最大值
  getprivateprofilestring('max_ku', 'max', '', max_ku, buffer, path);
  getprivateprofilestring('max_ban', 'max', '', max_ban, buffer, path);
  getprivateprofilestring('max_san', 'max', '', max_san, buffer, path);
  getprivateprofilestring('max_dun', 'max', '', max_dun, buffer, path);
//遍历文件,重新创建

//ku
  for num := 1 to StrToInt(max_ku) do
  begin
    Name := PChar('imgku' + IntToStr(num));//session名
    begin
      //判断是否存在这个session用什么函数
      //如果找不到返回默认值为空 ''
      GetPrivateProfileString(Name, 'height', '', Height, buffer, path);
      GetPrivateProfileString(Name, 'width', '', Width, buffer, path);
      GetPrivateProfileString(Name, 'left', '', left, buffer, path);
      GetPrivateProfileString(Name, 'top', '', top, buffer, path);
      GetPrivateProfileString(Name, 'hint', '', hint, buffer, path);
      GetPrivateProfileString(Name, 'tag', 'error1', tag, buffer, path);
      //如果不存在,则返回error
      if tag <> 'error1' then
      begin
        i1 := num - 1;
        form1.ck_button.Click;
        pk[i1].left := StrToInt(left);
        pk[i1].Height := StrToInt(Height);
        pk[i1].Top := StrToInt(top);
        pk[i1].Width := StrToInt(Width);
        imgku[i1].Hint := hint;
      end;
    end;
  end;

//ban
  for num := 1 to StrToInt(max_ban) do
  begin
    Name := PChar('imgban' + IntToStr(num));//session名
    begin
      //判断是否存在这个session用什么函数
      //如果找不到返回默认值为空 ''
      GetPrivateProfileString(Name, 'height', '', Height, buffer, path);
      GetPrivateProfileString(Name, 'width', '', Width, buffer, path);
      GetPrivateProfileString(Name, 'left', '', left, buffer, path);
      GetPrivateProfileString(Name, 'top', '', top, buffer, path);
      GetPrivateProfileString(Name, 'hint', '', hint, buffer, path);
      GetPrivateProfileString(Name, 'tag', 'error2', tag, buffer, path);
      //如果不存在,则返回error
      if tag <> 'error2' then
      begin
        i2 := num - 1;
        form1.bg_button.Click;
        pb[i2].left := StrToInt(left);
        pb[i2].Height := StrToInt(Height);
        pb[i2].Top := StrToInt(top);
        pb[i2].Width := StrToInt(Width);
        imgban[i2].Hint := hint;
      end;
    end;
  end;

//san
  for num := 1 to StrToInt(max_san) do
  begin
    Name := PChar('imgsan' + IntToStr(num));//session名
    begin
      //判断是否存在这个session用什么函数
      //如果找不到返回默认值为空 ''
      GetPrivateProfileString(Name, 'height', '', Height, buffer, path);
      GetPrivateProfileString(Name, 'width', '', Width, buffer, path);
      GetPrivateProfileString(Name, 'left', '', left, buffer, path);
      GetPrivateProfileString(Name, 'top', '', top, buffer, path);
      GetPrivateProfileString(Name, 'hint', '', hint, buffer, path);
      GetPrivateProfileString(Name, 'tag', 'error3', tag, buffer, path);
      //如果不存在,则返回error
      if tag <> 'error3' then
      begin
        i3 := num - 1;
        form1.san_button.Click;
        ps[i3].left := StrToInt(left);
        ps[i3].Height := StrToInt(Height);
        ps[i3].Top := StrToInt(top);
        ps[i3].Width := StrToInt(Width);
        imgsan[i3].Hint := hint;
      end;
    end;
  end;

//dun

  for num := 1 to StrToInt(max_dun) do
  begin
    Name := PChar('imgdun' + IntToStr(num));//session名
    begin
      //判断是否存在这个session用什么函数
      //如果找不到返回默认值为空 ''
      GetPrivateProfileString(Name, 'height', '', Height, buffer, path);
      GetPrivateProfileString(Name, 'width', '', Width, buffer, path);
      GetPrivateProfileString(Name, 'left', '', left, buffer, path);
      GetPrivateProfileString(Name, 'top', '', top, buffer, path);
      GetPrivateProfileString(Name, 'hint', '', hint, buffer, path);
      GetPrivateProfileString(Name, 'tag', 'error4', tag, buffer, path);
      //如果不存在,则返回error
      if tag <> 'error4' then
      begin
        i4 := num - 1;
        form1.dun_button.Click;
        pd[i4].left := StrToInt(left);
        pd[i4].Height := StrToInt(Height);
        pd[i4].Top := StrToInt(top);
        pd[i4].Width := StrToInt(Width);
        imgdun[i4].Hint := hint;
      end;
    end;
  end;
  freemem(sum_img, buffer);
  freemem(max_ku, buffer);
  freemem(max_ban, buffer);
  freemem(max_san, buffer);
  freemem(max_dun, buffer);
  //freemem(name,buffer); //释放他有错误发生,暂时找不到原因
  freemem(Height, buffer);
  freemem(hint, buffer);
  freemem(top, buffer);
  freemem(left, buffer);
  freemem(Width, buffer);
  freemem(tag, buffer);
end;