How to save and load the captions of all components on a form to / from a text file (Views: 28)
Problem/Question/Abstract: I'm using a component which is able to save the caption of components to a textfile and then retrieve it again. This works quite nice since if one wants another language one can just change some captions and load the desired language. The only problem is that it is using only the well known Windows controls and is also checking if a component is of a certain type. Of course I want to be able to use it for all components, so how would I be able to check all the components on a form for caption properties (even if it is e.g. in a item of a component) without having to do type checking etc.? Answer: You can use functions from the TypInfo unit. You'll need a GetPropInfo to get information about the property, GetStrProp and SetStrProp functions to read and set a new caption for components. The example below is a component which can save the captions of all components on a form to the text file and load them back after the form was loaded. There is also a design time component editor which you need to save and load captions (see a popup menu over the component). {The main component} TMyCaptionReader = class(TComponent) protected FFileName: string; procedure Loaded; override; public constructor Create(AOwner: TComponent); override; procedure ReadCaptions; procedure WriteCaptions; published property FileName: string read FFileName write FFileName; end; {The component editor} TMyCaptionReaderEditor = class(TDefaultEditor) public procedure ExecuteVerb(Index: Integer); override; function GetVerb(Index: Integer): string; override; function GetVerbCount: Integer; override; end; { ... } procedure TMyCaptionReaderEditor.ExecuteVerb(Index: Integer); begin case Index of 0: TMyCaptionReader(Component).WriteCaptions; 1: TMyCaptionReader(Component).ReadCaptions; else inherited ExecuteVerb(Index) end; end; function TMyCaptionReaderEditor.GetVerb(Index: Integer): string; begin case Index of 0: Result := 'Write Captions...'; 1: Result := 'Read Captions...' else Result := inherited GetVerb(Index); end; end; function TMyCaptionReaderEditor.GetVerbCount: Integer; begin Result := 2; end; constructor TMyCaptionReader.Create(AOwner: TComponent); begin inherited Create(AOwner); FFileName := 'TheFile.txt'; end; procedure TMyCaptionReader.Loaded; begin inherited Loaded; ReadCaptions; end; procedure TMyCaptionReader.ReadCaptions; var XStrings: TStringList; XComponent: TComponent; XPropInfo: PPropInfo; XName, XCaption: string; i, XPos: integer; begin if not FileExists(FFileName) then exit; XStrings := TStringList.Create; try XStrings.LoadFromFile(FFileName); for i := 0 to XStrings.Count - 1 do begin XPos := pos('=', XStrings[i]); if XPos > -1 then begin XName := copy(XStrings[i], 0, XPos - 1); XCaption := copy(XStrings[i], XPos + 1, length(XStrings[i]) - 1); XComponent := Owner.FindComponent(XName); if Assigned(XComponent) then begin XPropInfo := GetPropInfo(XComponent, 'Caption'); if Assigned(XPropInfo) then SetStrProp(XComponent, 'Caption', XCaption); end; end; end; finally XStrings.Free; end; end; procedure TMyCaptionReader.WriteCaptions; var XStrings: TStringList; XComponent: TComponent; XPropInfo: PPropInfo; XCaption: string; i: integer; begin XStrings := TStringList.Create; try if Assigned(Owner) then begin for i := 0 to Owner.ComponentCount - 1 do begin XComponent := Owner.Components[i]; if Assigned(XComponent) then begin try XPropInfo := GetPropInfo(XComponent, 'Caption'); if Assigned(XPropInfo) then begin XCaption := GetStrProp(XComponent, 'Caption'); XStrings.Add(XComponent.Name + '=' + XCaption); end; except end; end; end; end; XStrings.SaveToFile(FFileName); finally XStrings.Free; end; end; Here's how the Register procedure could be: procedure Register; begin RegisterComponents('My Components', [TMyCaptionReader]); RegisterComponentEditor(TMyCaptionReader, TMyCaptionReaderEditor); end; |