我做了一个MDI的程序,Form1为主窗体,Form2、Form3为子窗体,我想在Form2中名字为“保存”的菜单项中写代码,把Form2和里面的控件保存起来,存放在硬盘上;在名字为“打开”的菜单项中写代码,把上面保存的Form2的界面打开。
现在的问题是:程序运行后,点“保存”时可以通过,没问题; 点“打开”却出现错误:List index out of bounds(11).
这是怎么回事呢?(为了便于调试程序,窗体Form2上就有一个DBGrid可视控件)
“打开”菜单项中的代码是:
procedure TForm2.N3Click(Sender: TObject); //打开
var
BinStream:TmemoryStream;
i:integer;
begin
BinStream := TmemoryStream.Create;
if opendialog1.Execute then
try
for i:=0 to form2.ComponentCount-1 do
BinStream.LoadFromFile(pchar(opendialog1.FileName));
BinStream.Seek(0, soFrombeginning);
binstream.ReadComponent(form2.Components[i]);
finally
BinStream.Free
end;
end;
现在的问题是:程序运行后,点“保存”时可以通过,没问题; 点“打开”却出现错误:List index out of bounds(11).
这是怎么回事呢?(为了便于调试程序,窗体Form2上就有一个DBGrid可视控件)
“打开”菜单项中的代码是:
procedure TForm2.N3Click(Sender: TObject); //打开
var
BinStream:TmemoryStream;
i:integer;
begin
BinStream := TmemoryStream.Create;
if opendialog1.Execute then
try
for i:=0 to form2.ComponentCount-1 do
BinStream.LoadFromFile(pchar(opendialog1.FileName));
BinStream.Seek(0, soFrombeginning);
binstream.ReadComponent(form2.Components[i]);
finally
BinStream.Free
end;
end;
解决方案 »
- DELPHI 如何把函数指针传给C++的DLL内
- Delphi 7.0 安装问题
- 又是TidHttp控件访问代理服务器的问题?
- SQL数据库的问题:
- 打开一个文本文件,对它进行操作后清空文本文件内容!如何实现?
- 单精度类型的数据在dbgrid中的显示问题(在线等待)
- 一个简单的SQL语句的问题
- 接口的问题
- 在DBGrid中修改某字段内容时,怎样获取修改时的内容
- 如何在DATABASE DESKTOP 中使用函数?
- 为什么oracle数据库是varchar()类型的,用asString没办法插入啊,好痛苦,一个星期了,还不能解决//
- 在delphi运行期,怎么样把动态设置的界面保存为一个文件,然后在其它程序功能中进行调用?
请问,那,应该怎样写呀?
您写的那篇《分析DFM文件生成程序界面》的文章对小弟来说太深奥了,我知识浅薄,不一定能真正看懂。还是直接请教您吧!
“这个时候Form2上应该还没有任何控件的,当然会报index out of bound”
为此,我在binstream.ReadComponent(form2.Components[i]);前面加上
for i:=0 to form2.ComponentCount-1 do
form2.Components[i].Free;
后,提示:List index out of bounds(4).
我去掉ADOTable和 DataSource后,提示List index out of bounds(3).
接着我有去掉DBGrid,提示:List index out of bounds(2).
剩下的不能在去掉了,就剩MainMenu1、SaveDialog1、OpenDialog1了。
请问bounds后面的数字是什么意思?窗体上已经没有控件了。这个该怎样解决呢?
for i:=0 to form2.ComponentCount-1 do
form2.Components[i].Free;
这样的代码是不对的,假设form2上开始有2个控件,那么for循环第一次进入时,将Components[0]删除了,第二个控件的Index将会自动前移,变为0,而for循环第二次进入访问的则是Components[1],自然会Index out of bound了。
正确的写法应该为:
for I:=Form2.ComponentCount-1 downto 0 do begin
Form2.Components[I].Free;
end;
2.看看Delphi中对于ReadComponent的说明:
Initiates streaming of components and their properties.Delphi syntax:function ReadComponent(Instance: TComponent): TComponent;C++ syntax:TComponent* __fastcall ReadComponent(TComponent* Instance);DescriptionReadComponent is called indirectly by the global routine ReadComponentRes, by the ReadComponentRes method, or it can be called directly to initiate component streaming.ReadComponent reads data values from the stream and assigns them to Instance’s properties. It then constructs a reader object and calls the reader’s ReadRootComponent method to read Instance’s property values and construct child objects defined in the stream as children of the Instance. ReadComponent returns the component.If Instance is nil (Delphi) or NULL (C++), ReadComponent constructs a component based on the type information in the stream and returns the newly-constructed component.This example shows how to use the built-in component streaming support to convert any component into a string and convert that string back into a component.function ComponentToString(Component: TComponent): string;var
BinStream:TMemoryStream;
StrStream: TStringStream;
s: string;
begin
BinStream := TMemoryStream.Create;
try
StrStream := TStringStream.Create(s);
try
BinStream.WriteComponent(Component);
BinStream.Seek(0, soFromBeginning);
ObjectBinaryToText(BinStream, StrStream);
StrStream.Seek(0, soFromBeginning);
Result:= StrStream.DataString;
finally
StrStream.Free; end;
finally
BinStream.Free
end;
end;function StringToComponent(Value: string): TComponent;
var
StrStream:TStringStream;
BinStream: TMemoryStream;
begin
StrStream := TStringStream.Create(Value);
try
BinStream := TMemoryStream.Create;
try
ObjectTextToBinary(StrStream, BinStream);
BinStream.Seek(0, soFromBeginning);
Result := BinStream.ReadComponent(nil); finally
BinStream.Free;
end;
finally
StrStream.Free;
end;
end;如果传入参数为nil时,它会帮你自动创建一个对象,看上去你要的就是这种功能。
根据您的方法,我修改了程序:
for i:=form2.ComponentCount-1 downto 1 do
//注意:这里不能遍历到0,到0将出错:List index out of bounds(-1).
begin
form2.Components[i].Free;
end;
这样,运行后点击“打开”菜单项,选择Form2的保存路径,窗体Form2可以打开了。但打开后又出现了下面的问题:
1、Form2上面只显示一个控件。本程序是Lable1,别的控件都不显示。如果让Form2只剩Lable1控件,则运行后Lable1的Caption属性值将显示在Form2的标题栏的位置;
2、Form2打开后,点击它上面的菜单项,都没有反应;
3、如果再增加一个“退出”菜单项,则该菜单项的名字出现在Lable1的位置。
我想要的结果是:保存时是什么样子,打开时也是什么样子。
调试了大半天了,也没弄出来。还想请您帮帮忙!我修改后的代码是:
var
BinStream:TmemoryStream;
i:integer;
begin
BinStream := TmemoryStream.Create;
if opendialog1.Execute then
try BinStream.LoadFromFile(pchar(opendialog1.FileName));
BinStream.Seek(0, soFrombeginning);
i:=form2.ComponentCount-1;
for i:=form2.ComponentCount-1 downto 1 do
begin
form2.Components[i].Free;
end;
binstream.ReadComponent(form2.Components[i]);
finally
BinStream.Free
end;
end;
tonylk(=www.tonixsoft.com=) 兄在吗?高人在吗?哪位仁兄能帮帮我。我自己真的是做不出来了!!! 分,我可以再加呀。
var
i:integer;
begin
for I:=self.ComponentCount-1 downto 0 do begin
self.Components[I].Free;
ReadComponentResFile('Temp.dfm', Form1);
end;end;procedure TForm1.BitBtn3Click(Sender: TObject);
begin
WriteComponentResFile('Temp.dfm', Form1);
end;
procedure TForm1.BitBtn1Click(Sender: TObject);
var
i:integer;
begin
for I:=self.ComponentCount-1 downto 0 do
self.Components[I].Free;
ReadComponentResFile('Temp.dfm', Form1);
end;procedure TForm1.BitBtn3Click(Sender: TObject);
begin
WriteComponentResFile('Temp.dfm', Form1);
end;