gulki
asked on
changing the captions of all controls on a form during runtime wiht some out of a file
Hi
I have a file with the following structure:
Control_type Contol_Name Control_Caption
------------ ----------- ----------------
Label MyLabel1 Label1_Caption_something
Label MyLabel2 Label2_Caption_something
Label MyLabel3 Label3_Caption_something
MainMenu MyMainMenu MainMenu_Caption
MenuItem MyMenuItem MenuItem_Caption
GroupBox MyGroupBox GroupBox_Caption
etc.
Here is my question:
How can I modify during the runtime the captions of each control that is mentioned in that file (or other external source) ?
Does anyone have a short procedure ?
I start thinking to complex now (after 2 nights triying to find a simple solution) !
Thanks
Ismet
I have a file with the following structure:
Control_type Contol_Name Control_Caption
------------ ----------- ----------------
Label MyLabel1 Label1_Caption_something
Label MyLabel2 Label2_Caption_something
Label MyLabel3 Label3_Caption_something
MainMenu MyMainMenu MainMenu_Caption
MenuItem MyMenuItem MenuItem_Caption
GroupBox MyGroupBox GroupBox_Caption
etc.
Here is my question:
How can I modify during the runtime the captions of each control that is mentioned in that file (or other external source) ?
Does anyone have a short procedure ?
I start thinking to complex now (after 2 nights triying to find a simple solution) !
Thanks
Ismet
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
I guess you want to modify the running exe by changing the captions? How about Label1.Caption := 'My New Caption'; or is that not what you want?
If you need to permanently change the caption...like to change it's language then you need to permanently alter the exe .. you can do this at runtime by altering the disk sectors directly (but I recommend against this!)
OR you can use a small unit I wrote to change it at runtime...this requires a quick re-start but it only takes half a second or so and if done correctly the user might not even notice.
Changing the captions in another exe is easy... but you will be limited by the length of the current captions.. you can make the caption shorter..but not longer! well you could make it longer but you will have to do surgery on the exe :-)
You can find the caption data inside the exe file.. for instance the caption of label 1 if it has 'Hello world!!!' as a caption will look like this
Label1<bh:04>Left<bh:02><b h:0e><bh:0 3>Top<bh:0 2><bh:18>< bh:05>Widt h<bh:02>@< bh:06>Heig ht<bh:02>
<bh:07>Caption<bh:06><bh:0 f>Hello world!!!!
Label1 then some hex bytes
top then hex bytes
width then hex bytes
height then hex bytes
Caption 2 hex bytes and then the caption
so just alter the caption directly... you could load the exe into a stream from disk and then find and change the proper bytes to change the caption.
I could write a small demo for you to show some of this if you like :-)
If you need to permanently change the caption...like to change it's language then you need to permanently alter the exe .. you can do this at runtime by altering the disk sectors directly (but I recommend against this!)
OR you can use a small unit I wrote to change it at runtime...this requires a quick re-start but it only takes half a second or so and if done correctly the user might not even notice.
Changing the captions in another exe is easy... but you will be limited by the length of the current captions.. you can make the caption shorter..but not longer! well you could make it longer but you will have to do surgery on the exe :-)
You can find the caption data inside the exe file.. for instance the caption of label 1 if it has 'Hello world!!!' as a caption will look like this
Label1<bh:04>Left<bh:02><b
<bh:07>Caption<bh:06><bh:0
Label1 then some hex bytes
top then hex bytes
width then hex bytes
height then hex bytes
Caption 2 hex bytes and then the caption
so just alter the caption directly... you could load the exe into a stream from disk and then find and change the proper bytes to change the caption.
I could write a small demo for you to show some of this if you like :-)
ASKER
Hey AvonWys
Thanks a lot for that simple statement !
It works perfectly well and within a short loop I can modify any control caption I need in runtime !
Great !!
Ismet
Thanks a lot for that simple statement !
It works perfectly well and within a short loop I can modify any control caption I need in runtime !
Great !!
Ismet
Hi,
are you particularly stuck on that file format ? would an ini file be easier. e.g.
[TLABEL]
MyLabel1=Label1_Caption_so mething
MyLabel2=Label2_Caption_so mething
MyLabel3=Label3_Caption_so mething
[TMAINMENU]
MyMainMenu=MainMenu_Captio n
[TMENUITEM]
MyMenuItem=MenuItem_Captio n
[TGROUPBOX]
MyGroupBox=GroupBox_Captio n
then your code could work like this.
procedure TForm1.PopulateCaptions(co nst AFileName: string);
var
Comp: TComponent;
IniFile: TIniFile;
I: Integer;
begin
IniFile := TIniFile.Create(AFileName) ;
try
for I := 0 to ComponentCount -1 do
begin
Comp := Components[I];
Comp.Caption := IniFile.ReadString(Comp.Cl assname, Comp.Name, Comp.Caption);
end;
finally
IniFile.Free;
end;
end;
basically open the inifile, loop through all components on the form, and try to read its caption from the inifile. The 3 params on the read string method are SectionName (in the inifile Classname is sectionname), ValueName (in the inifile the component name is the valuename) and lastly default value should the read fail, so if the read fails the component will keep its caption as its default value.
if you include the typInfo unit in your uses clauses you could also do this to optimize the code slightly, code belongs between for loops begin and end.
Comp := Components[I];
if IsPublishedProp(Comp, 'Caption') then
Comp.Caption := IniFile.ReadString(Comp.Cl assname, Comp.Name, Comp.Caption);
You could also read the file item by item and do:
Comp := FindComponent(Comp_Name);
Comp.Caption := Comp_Caption
I would go for the first option particularly if there is other things you wish to apply to all components on the form, if there isn't well either, depending on how important performance is ?
Derrick
are you particularly stuck on that file format ? would an ini file be easier. e.g.
[TLABEL]
MyLabel1=Label1_Caption_so
MyLabel2=Label2_Caption_so
MyLabel3=Label3_Caption_so
[TMAINMENU]
MyMainMenu=MainMenu_Captio
[TMENUITEM]
MyMenuItem=MenuItem_Captio
[TGROUPBOX]
MyGroupBox=GroupBox_Captio
then your code could work like this.
procedure TForm1.PopulateCaptions(co
var
Comp: TComponent;
IniFile: TIniFile;
I: Integer;
begin
IniFile := TIniFile.Create(AFileName)
try
for I := 0 to ComponentCount -1 do
begin
Comp := Components[I];
Comp.Caption := IniFile.ReadString(Comp.Cl
end;
finally
IniFile.Free;
end;
end;
basically open the inifile, loop through all components on the form, and try to read its caption from the inifile. The 3 params on the read string method are SectionName (in the inifile Classname is sectionname), ValueName (in the inifile the component name is the valuename) and lastly default value should the read fail, so if the read fails the component will keep its caption as its default value.
if you include the typInfo unit in your uses clauses you could also do this to optimize the code slightly, code belongs between for loops begin and end.
Comp := Components[I];
if IsPublishedProp(Comp, 'Caption') then
Comp.Caption := IniFile.ReadString(Comp.Cl
You could also read the file item by item and do:
Comp := FindComponent(Comp_Name);
Comp.Caption := Comp_Caption
I would go for the first option particularly if there is other things you wish to apply to all components on the form, if there isn't well either, depending on how important performance is ?
Derrick
Although the questions is already answered, I will post my code here :
unit Unit_GlobalFunctions;
interface
uses Controls;
procedure UpdateControlCaptions(WinC trl: TWinControl ; ReadFile : String);
implementation
uses DbTables, StdCtrls, Dialogs;
procedure UpdateControlCaptions(WinC trl: TWinControl ; ReadFile : String);
var
x : integer;
lkp : TTable;
varKeyValues : Variant;
procedure UpdateCaption(ClsName, NewCaption: String ; Ctrl: TControl);
begin
if ClsName = 'TButton' then (Ctrl as TButton).Caption := NewCaption
else if ClsName = 'TLabel' then (Ctrl as TLabel).Caption := NewCaption
else ShowMessage('Component not supported for updating Caption : ' + ClsName);
end;
begin
Try
lkp := TTable.Create(nil);
lkp.TableType := ttASCII;
lkp.TableName := ReadFile;
lkp.Open;
for x := 0 to WinCtrl.ControlCount-1 do
begin
With lkp do
begin
varKeyValues := VarArrayOf([WinCtrl.Contro ls[x].Clas sName,WinC trl.Contro ls[x].Name ]);
If Locate('Class;Name' , varKeyValues , []) then
begin
UpdateCaption(WinCtrl.Cont rols[x].Cl assName, FieldByName('Caption').AsS tring, WinCtrl.Controls[x]);
end;
end;
end;
lkp.Close;
except
ShowMessage('ERROR DURING "UpdateControlCaptions"');
end;
end;
end.
P.S. You can save this code as xxxxxxx.pas
It's a unit that contains 1 procedure : UpdateControlCaptions
You have to give the parent of the controls you want to change the Caption of. You also have to give the name of the file you keep the captions in.
This procedure uses a textfile as a normal TTable. You also have to put a SCH-File in the same directoy as you Captions-File.
Here you find the contents of the SCH-File :
[CONTROLS]
FileType=FIXED
Delimiter=
Separator=
CharSet=ascii
Field1=Class,CHAR,15,0,0
Field2=Name,CHAR,15,0,15
Field3=Caption,CHAR,30,0,3 0
Field4=CRLF,CHAR,2,0,60
Hope te be of some help anyway ...
The Mayor.
unit Unit_GlobalFunctions;
interface
uses Controls;
procedure UpdateControlCaptions(WinC
implementation
uses DbTables, StdCtrls, Dialogs;
procedure UpdateControlCaptions(WinC
var
x : integer;
lkp : TTable;
varKeyValues : Variant;
procedure UpdateCaption(ClsName, NewCaption: String ; Ctrl: TControl);
begin
if ClsName = 'TButton' then (Ctrl as TButton).Caption := NewCaption
else if ClsName = 'TLabel' then (Ctrl as TLabel).Caption := NewCaption
else ShowMessage('Component not supported for updating Caption : ' + ClsName);
end;
begin
Try
lkp := TTable.Create(nil);
lkp.TableType := ttASCII;
lkp.TableName := ReadFile;
lkp.Open;
for x := 0 to WinCtrl.ControlCount-1 do
begin
With lkp do
begin
varKeyValues := VarArrayOf([WinCtrl.Contro
If Locate('Class;Name' , varKeyValues , []) then
begin
UpdateCaption(WinCtrl.Cont
end;
end;
end;
lkp.Close;
except
ShowMessage('ERROR DURING "UpdateControlCaptions"');
end;
end;
end.
P.S. You can save this code as xxxxxxx.pas
It's a unit that contains 1 procedure : UpdateControlCaptions
You have to give the parent of the controls you want to change the Caption of. You also have to give the name of the file you keep the captions in.
This procedure uses a textfile as a normal TTable. You also have to put a SCH-File in the same directoy as you Captions-File.
Here you find the contents of the SCH-File :
[CONTROLS]
FileType=FIXED
Delimiter=
Separator=
CharSet=ascii
Field1=Class,CHAR,15,0,0
Field2=Name,CHAR,15,0,15
Field3=Caption,CHAR,30,0,3
Field4=CRLF,CHAR,2,0,60
Hope te be of some help anyway ...
The Mayor.
Thanks for the feedback. Glad to help! :-)
If this is done, then you can link your text file to a normal TTable. This has the advantage that you can easily locate record in the file.
Maybe you can write a procedure which loops all the controls on the form (using a fil-loop with ControlCount), looks up the ClassName + Name in your textfile and returns the caption of it.
I'll work out a procedure and let you know.
PS : Maybe another possibility is to use a Resource-File, but I'm not sure if these can be used at runtime to, in your case, fill the captions of all the components.
I'll be back ...
The Mayor.