Страница 1 из 1
установить caption компоненту не зная его типа [решено]
Добавлено: 25.12.2011 22:39:40
minoshi
Доброго времени суток!
Собственно сабж.
Есть, например, файл с таким содержанием :
Как найти компонент с именем somecomp (тип неизвестен, возможно это trichbutton или tlabel или какой-то другой компонент) и установить его свойство caption равное 'caption1'.
Изначально предполагаем, что свойство caption присутствует.
Варианты c findcomponent и findwidget вроде все перепробовал, от ответа не нашел, хотя чую, ответ где-то рядом ....
Re: установить caption компоненту не зная его типа
Добавлено: 25.12.2011 22:52:50
alexs
У всех наследников от TControl есть CAPTION, он-же TEXT.
Код: Выделить всё
TControl = class(TLCLComponent)
....
public
// standard properties, which should be supported by all descendants
....
property Caption: TCaption read GetText write SetText stored IsCaptionStored;
....
property Text: TCaption read GetText write SetText;
Если по быстрому то можно так:
Код: Выделить всё
if somecomp is TControl then
somecomp.Caption:='bla-bla-bla'
Re: установить caption компоненту не зная его типа
Добавлено: 25.12.2011 23:17:38
minoshi
Блин, походу опять я некорректно обозначил проблему.
делаю так :
Код: Выделить всё
var componentname, componentcaption,s : string;
f : textfile;
begin
assignfile(f, ......
reset(f);
readln(s); //где s = somecomp = 'caption1'
componentname := trim(copy(s,1,pos('=',s) - 1)); // получаем 'somecomp'
delete(s,1,pos('=',s) - 1);
componentcaption := s; // получаем 'caption1'
....
далее должно как-то так
Код: Выделить всё
findcomponent(componentname).caption := componentcaption;
и вот здесь чего-то я тормознул
Добавлено спустя 7 минут 10 секунд:to alexs. MSE c Lazarus не путаете?
Re: установить caption компоненту не зная его типа
Добавлено: 26.12.2011 01:26:41
WAYFARER
В принципе не большая разница mse или lazarus, язык то один и тот же. Еще зависит с какой целью вы это делаете
Я например заранее не зная какие контролы и сколько их будет на форме, для перевода Caption использую в Lazarus примерно такую конструкцию:
Код: Выделить всё
procedure LocalizeControl(Frm: TForm);
//Локализует некотрые существующие контролы на форме
var
i: integer;
begin
for i := 0 to Frm.ControlCount - 1 do
begin
//Локализуем Caption'ы
//TLabel
if Frm.Controls[i] is TLabel then
(Frm.Controls[i] as TLabel).Caption := Localize((Frm.Controls[i] as TLabel).Caption);
//TButton
if Frm.Controls[i] is TButton then
(Frm.Controls[i] as TButton).Caption := Localize((Frm.Controls[i] as TButton).Caption);
//Локализуем хинты
if Frm.Controls[i] is TControl then
(Frm.Controls[i] as TControl).Hint := Localize((Frm.Controls[i] as TControl).Hint);
и т.д.
end;
end;
procedure LocalizeMenu(Menu: TMenu); //Локализует меню
var
i: integer;
begin
for i := 0 to Menu.Items.Count - 1 do
begin
Menu.Items[i].Caption := Localize(Menu.Items[i].Caption);
end;
end;
Caption для контролов назначаются в зависимости от английской caption, а не от имени компонента, хотя можно использовать и TComponent.Name...
Для самого перевода использую способ подсмотренный у
alexs (за что ему отдельное спасибо)
LngList - это TStringList куда загружается файл с переводом вида
EngCaption=РусПодпись
Код: Выделить всё
function Localize(const Caption: string): string; //Локализует строку
begin
if not assigned(LngList) then
begin
Result := Caption;
Exit;
end;
Result := LngList.Values[Caption];
if Result = '' then
Result := Caption;
end;
В MSE можно сделать аналогично, если подобный вариант приемлем..
Re: установить caption компоненту не зная его типа
Добавлено: 26.12.2011 09:11:26
v-t-l
Кусок моего старого дельфового проекта (с FreePascal не опробован):
Код: Выделить всё
uses TypInfo;
{$R *.dfm}
function HasProperty(Obj: TObject; PropName: String; PropKinds: TTypeKinds = []): boolean;
begin
Result := (GetPropInfo(Obj,PropName,PropKinds) <> nil);
end;
procedure TForm1.FormCreate(Sender: TObject);
var i: integer;
begin
for i:=0 to ComponentCount-1 do
if IsDBControl(Components[i]) and
HasProperty(Components[i],'OnEnter') then
SetMethodProp(Components[i],'OnEnter',GetMethodProp(DBCtrlGrid1,'onEnter'));
end;
procedure TForm1.DBCtrlGrid1Enter(Sender: TObject);
begin
if (Sender is TDBGrid) then
begin
DBNavigator1.DataSource := TDataSource(GetObjectProp(Sender,'DataSource'));
ActiveField := (Sender as TDBGrid).SelectedField;
lblFindField.Caption := '"'+ActiveField.DisplayName+'" (' + ActiveField.DataSet.GetNamePath + '::' + ActiveField.FieldName + ')';
end
else
if HasProperty(Sender,'DataSource') then
begin
DBNavigator1.DataSource := TDataSource(GetObjectProp(Sender,'DataSource'));
if HasProperty(Sender,'DataField') then
if GetStrProp(Sender,'DataField')<>'' then
if DBNavigator1.DataSource <> nil then
if DBNavigator1.DataSource.DataSet <> nil then
if DBNavigator1.DataSource.DataSet.Active then
begin
ActiveField := DBNavigator1.DataSource.DataSet.FieldByName(GetStrProp(Sender,'DataField'));
lblFindField.Caption := '"'+ActiveField.DisplayName+'" (' + ActiveField.DataSet.GetNamePath + '::' + ActiveField.FieldName + ')';
end;
end;
end;
function TForm1.IsDBControl(obj: TObject): boolean;
begin
result := (obj is TControl)
and HasProperty(obj,'DataSource');
end;
Re: установить caption компоненту не зная его типа
Добавлено: 26.12.2011 12:16:31
minoshi
WAYFARER писал(а):В принципе не большая разница mse или lazarus, язык то один и тот же. Еще зависит с какой целью вы это делаете
...
В MSE можно сделать аналогично, если подобный вариант приемлем..
Нету в MSE аналога TControl

Свойство caption у tlabel появляется у его непосредственного предка tcustomlabel. C другими компонентами аналогично.
WAYFARER писал(а):Я например заранее не зная какие контролы и сколько их будет на форме, для перевода Caption использую в Lazarus примерно такую конструкцию:
Код: Выделить всё
.....
//Локализуем Caption'ы
//TLabel
if Frm.Controls[i] is TLabel then
(Frm.Controls[i] as TLabel).Caption := Localize((Frm.Controls[i] as TLabel).Caption);
//TButton
if Frm.Controls[i] is TButton then
(Frm.Controls[i] as TButton).Caption := Localize((Frm.Controls[i] as TButton).Caption);
//Локализуем хинты
if Frm.Controls[i] is TControl then
(Frm.Controls[i] as TControl).Hint := Localize((Frm.Controls[i] as TControl).Hint);
и т.д.
end;
end;
...
Я в принципе пользуюсь аналогичным подходом
Код: Выделить всё
if findcomponent(compname) is tlabel then (findcomponent(compname) as tlabel).caption := componentcaption
else if findcomponent(compname) is tbutton then (findcomponent(compname) as tbutton).caption := componentcaption
ну и т.д.
Этот подход требует заранее прописывать используемые в программе типы компонентов, а хочется чего-то более универсального.
Добавлено спустя 30 минут 43 секунды:ну хорошо, а как перевести значение из строки в тип?
скажем есть S = 'tlabel';
И затем это значение S использовать в (findcomponent(component) as <значение из S>).caption := componentcaption
Re: установить caption компоненту не зная его типа
Добавлено: 26.12.2011 19:33:06
wavebvg
А почему просто не попробовать рекурсивно обойти все компоненты по child-ам начиная с формы, каждый опрашивая имя компонента (что-то типа control.name=somecomp). Как только имя найдено или все компоненты закончились - выходим. Если нашли контрол с указанным именем, спрашиваем, есть ли у него свойство caption и, если есть, назначаем.
Re: установить caption компоненту не зная его типа
Добавлено: 26.12.2011 19:53:57
debi12345
Если нашли контрол с указанным именем, спрашиваем, есть ли у него свойство caption
А как это спросить чтобы программа не вылетела ?
Эксэпшен тут не перехватишь, AFAIK.
Пока что просматривается все-таки вариант проверять на тип - в идеале самый низовой в иерерхии наследования имеющий свойство CAPTION, после приведения типа к этом низовому типу. Ну и этот тип может быть интерфейсом, в котором...
Re: установить caption компоненту не зная его типа
Добавлено: 26.12.2011 21:14:12
v-t-l
debi12345 писал(а):А как это спросить чтобы программа не вылетела ?
Только через RTTI. Попробуйте адаптировать мой пример выше. У меня сейчас не на чем сделать это самому.
Re: установить caption компоненту не зная его типа [решено]
Добавлено: 02.03.2012 21:17:01
minoshi
v-t-l писал(а):debi12345 писал(а):А как это спросить чтобы программа не вылетела ?
Только через RTTI. Попробуйте адаптировать мой пример выше. У меня сейчас не на чем сделать это самому.
C caption вроде разобрался (черновой вариант) :
Код: Выделить всё
uses
...
typinfo;
....
procedure tmainfo.on_change(const sender: TObject);
var prop : propinfopoarty;
po1 : ppropinfo;
i : integer;
newcaption : string;
begin
prop := getpropinfoar(tobject(findcomponent('tbutton1'))); //вместо 'tbutton1' ставим имя существующего объекта
newcaption := tstringedit1.value; // новый caption
for i := 0 to high(prop) do
begin
po1 := prop[i];
with po1^ do
begin
case proptype^.kind of
{$ifdef FPC}
tkustring: setunicodestrprop(findcomponent('tbutton1'),po1,newcaption); //собственно присвоение нового caption
{$endif}
end; //case
end;//with
end;
end;
или еще проще (как и советовал
v-t-l) :
Код: Выделить всё
uses
...
typinfo;
function HasProperty(Obj: TObject; PropName: String; PropKinds: TTypeKinds = []): boolean;
begin
Result := (GetPropInfo(Obj,PropName,PropKinds) <> nil);
end;
procedure tmainfo.on_change(const sender: TObject);
begin
if HasProperty(tobject(findcomponent('tbutton1')),'caption') then
SetStrProp(tobject(findcomponent('tbutton1')),'caption','1111');
end;
осталось разобраться с frame.caption :-/
Re: установить caption компоненту не зная его типа [решено]
Добавлено: 05.03.2012 21:48:51
minoshi
ну а вот так меняется frame.caption
Код: Выделить всё
procedure tmainfo.on_change3(const sender: TObject);
var ob : Tobject;
begin
newcaption := 'LLLL';
if HasProperty(tobject(findcomponent('tbutton1')),'frame') then
begin
ob := GetObjectProp(tobject(findcomponent('tbutton1')),'frame');
if HasProperty(ob,'caption') then SetStrProp(ob,'caption',newcaption);
end;
end;