C++ Builder/Delphi是否有内置函数保存恢复窗体及控件布局?
在C++ Builder/Delphi中保存与恢复窗体布局的实现方案
C++ Builder和Delphi没有直接一键搞定所有控件布局的内置函数,但VCL框架提供了便捷的方法和组件,能轻松实现窗体大小、分割视图尺寸、DBGrid列宽等布局的保存与恢复,以下是具体实现方式:
1. 手动读写INI文件实现基础布局控制
这是最通用的方案,适用于所有版本的VCL,通过TIniFile组件读写窗体和控件的关键属性:
窗体位置与大小
Delphi代码示例
// 关闭窗体时保存布局 procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction); var IniFile: TIniFile; begin IniFile := TIniFile.Create(ChangeFileExt(Application.ExeName, '.ini')); try // 保存窗体位置和尺寸 IniFile.WriteInteger('MainForm', 'Left', Left); IniFile.WriteInteger('MainForm', 'Top', Top); IniFile.WriteInteger('MainForm', 'Width', Width); IniFile.WriteInteger('MainForm', 'Height', Height); finally IniFile.Free; end; end; // 启动窗体时加载布局 procedure TMainForm.FormCreate(Sender: TObject); var IniFile: TIniFile; begin IniFile := TIniFile.Create(ChangeFileExt(Application.ExeName, '.ini')); try Left := IniFile.ReadInteger('MainForm', 'Left', Left); Top := IniFile.ReadInteger('MainForm', 'Top', Top); Width := IniFile.ReadInteger('MainForm', 'Width', Width); Height := IniFile.ReadInteger('MainForm', 'Height', Height); finally IniFile.Free; end; end;
C++ Builder代码示例
void __fastcall TMainForm::FormClose(TObject *Sender, TCloseAction &Action) { TIniFile *IniFile = new TIniFile(ChangeFileExt(Application->ExeName, ".ini")); try { IniFile->WriteInteger("MainForm", "Left", Left); IniFile->WriteInteger("MainForm", "Top", Top); IniFile->WriteInteger("MainForm", "Width", Width); IniFile->WriteInteger("MainForm", "Height", Height); } __finally { delete IniFile; } } void __fastcall TMainForm::FormCreate(TObject *Sender) { TIniFile *IniFile = new TIniFile(ChangeFileExt(Application->ExeName, ".ini")); try { Left = IniFile->ReadInteger("MainForm", "Left", Left); Top = IniFile->ReadInteger("MainForm", "Top", Top); Width = IniFile->ReadInteger("MainForm", "Width", Width); Height = IniFile->ReadInteger("MainForm", "Height", Height); } __finally { delete IniFile; } }
TSplitter分割视图尺寸
TSplitter没有直接的保存属性,只需保存它关联控件的尺寸即可,加载时控件尺寸变化后,Splitter会自动调整位置:
Delphi代码片段
// 保存 IniFile.WriteInteger('MainForm', 'Panel1Width', Panel1.Width); // 加载 Panel1.Width := IniFile.ReadInteger('MainForm', 'Panel1Width', Panel1.Width);
C++ Builder代码片段
// 保存 IniFile->WriteInteger("MainForm", "Panel1Width", Panel1->Width); // 加载 Panel1->Width = IniFile->ReadInteger("MainForm", "Panel1Width", Panel1->Width);
TDBGrid列宽度
遍历DBGrid的Columns集合,逐个保存和恢复列宽:
Delphi代码片段
// 保存列宽 var i: Integer; begin for i := 0 to DBGrid1.Columns.Count - 1 do begin IniFile.WriteInteger('DBGrid1', 'Col' + IntToStr(i) + 'Width', DBGrid1.Columns[i].Width); end; end; // 加载列宽 for i := 0 to DBGrid1.Columns.Count - 1 do begin DBGrid1.Columns[i].Width := IniFile.ReadInteger('DBGrid1', 'Col' + IntToStr(i) + 'Width', DBGrid1.Columns[i].Width); end;
C++ Builder代码片段
// 保存列宽 for (int i = 0; i < DBGrid1->Columns->Count; i++) { IniFile->WriteInteger("DBGrid1", "Col" + IntToStr(i) + "Width", DBGrid1->Columns->Items[i]->Width); } // 加载列宽 for (int i = 0; i < DBGrid1->Columns->Count; i++) { DBGrid1->Columns->Items[i]->Width = IniFile->ReadInteger("DBGrid1", "Col" + IntToStr(i) + "Width", DBGrid1->Columns->Items[i]->Width); }
2. 用TFormStorage组件简化操作(XE及以后版本)
从Delphi/C++ Builder XE版本开始,VCL提供了TFormStorage组件(位于Samples组件页),可以可视化绑定需要保存的属性,自动完成保存和加载,无需手动写大量读写代码:
- 拖放
TFormStorage到目标窗体 - 设置
StorageType为stINIFile,指定FileName为INI文件路径(比如ChangeFileExt(Application.ExeName, '.ini')) - 打开
PropertyBindings编辑器,添加需要保存的属性:- 窗体的
Left、Top、Width、Height - 关联Splitter的控件(如Panel)的
Width或Height - TDBGrid各列的
Width
- 窗体的
- 在窗体创建事件调用
Restore,关闭事件调用Store:
Delphi代码示例
procedure TMainForm.FormCreate(Sender: TObject); begin FormStorage1.Restore; end; procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction); begin FormStorage1.Store; end;
C++ Builder代码示例
void __fastcall TMainForm::FormCreate(TObject *Sender) { FormStorage1->Restore(); } void __fastcall TMainForm::FormClose(TObject *Sender, TCloseAction &Action) { FormStorage1->Store(); }
内容的提问来源于stack exchange,提问作者user3161924
相关产品推荐
相关产品推荐

