2005. december 10., szombat
How to save and load the captions of all components on a form to / from a text file
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;
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése