Страница 1 из 1

установить caption компоненту не зная его типа [решено]

СообщениеДобавлено: 25.12.2011 22:39:40
minoshi
Доброго времени суток!

Собственно сабж.

Есть, например, файл с таким содержанием :
Код: Выделить всё
somecomp = 'caption1'
и т.д.


Как найти компонент с именем 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:10:28
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 11:45:48
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;