Fórum RTTI - Saber se a propriedade é um array de componentes #461391

19/11/2013

0

Bom Dia

Pessoal trabalho em uma empresa que tem filiais em outros países e devido a isso tenho que criar uma maneira de traduzir os captions do sistema para a linguagem do país. Como o sistema é antigo e não temos como utilizar a opção multi idiomas do delphi estamos criando uma forma de traduzir os captions em tempo de execução utilizando uma tradução que está no banco de dados, para isso estou utilizando RTTI. Porém estou tendo problemas com os componentes que possuem a propriedade Items.

Nos componentes que possuem essas propriedades eu também tenho que traduzir.

Nesta listagem entram os componentes como TComboBox, TGroupBox e TPopupMenu.

No TComboBox a propriedade Items é uma StringList (não tenho problema), porém no caso do TPopupMenu a propriedade Items é um array de outro componente (onde tenho problemas). Como posso fazer para saber qual das duas situações é utilizando RTTI e como posso fazer para alterar a propriedade caption do item do menu que está na propriedade Items?

Abaixo segue o código que estou utilizando

procedure TSISFR022.FormCreate(Sender: TObject);
var
  iCont: integer;
  PropInfo: PPropInfo;
  vSqlIdioma: string;
  vItens: TStringList;
  vTraduz: Boolean;
begin
    vSqlIdioma := ''SELECT componente, traducao from tabela where form= ''+QuotedStr(''frmNotafiscal'')+'' and idioma = ''+QuotedStr(''es'');

    if cdsTraduz.State = dsBrowse then
      cdsTraduz.Close;
    cdsTraduz.DataRequest(vSqlIdioma);
    cdsTraduz.Open;
    if cdsTraduz.RecordCount > 0 then
    begin
      //busca do banco
      for iCont := 0 to (ComponentCount -1) do
      begin
        PropInfo := GetPropInfo(Components[iCont].ClassInfo, ''Caption'');
        if PropInfo <> nil then
        begin
          if trim(GetPropValue(Components[iCont], ''Caption'')) <> '''' then
          begin
            if cdsTraduz.Locate(''componente'', Components[iCont].Name,[]) then
               SetPropValue(Components[iCont], ''Caption'', cdsTraduz.FieldByName(''traducao'').AsString);
          end;
        end;

        PropInfo := GetPropInfo(Components[iCont].ClassInfo, ''Items'');
        if (PropInfo <> nil) then
        begin
              vItens := TStringList.Create;
              vItens.Text := TStringList(Pointer(strtoint(GetPropValue(Components[iCont], ''Items'')))).Text;
              vTraduz := False;
              for iTotal := 0 to (vItens.Count - 1) do
              begin
                if cdsTraduz.Locate(''componente'', Components[iCont].Name+''_L''+IntToStr(iTotal+1),[]) then
                begin
                  vItens[iTotal] := cdsTraduz.FieldByName(''traducao'').AsString;
                  vTraduz := True;
                end;
              end;
              if vTraduz then
                TStringList(TObject(Pointer(strtoint(GetPropValue(Components[iCont], ''Items''))))).Text:=vItens.Text;
              FreeAndNil(vItens);
        end;
      end;
      if cdsTraduz.State = dsBrowse then
        cdsTraduz.Close;
    end;
end;
Fernando Vicari

Fernando Vicari

Responder

Posts

19/11/2013

Gustavo Bretas

Fernando, no PopUp os Itens estão na lista dele, ok, mas vc consegue acessar o TMenuItem, e ele entra no primeiro FOR, insira o nome do componente na sua tabela de tradução que vai dar certo!

Mas se seu sistema tiver TreeView, complica um pouco! rsrs
Responder

Gostei + 0

19/11/2013

Fernando Vicari

Olá Bretas

Correta a sua observação, porém o problema é que para o componente TPopupMenu entra no segundo IF e não poderia.

Como posso saber quando pode entrar no segundo if e quando não? A única maneira que eu vi foi procurar por uma propriedade que tem no TPopupMenu (Ex.: MenuAnimation) e se existir não entra no segundo if, porém achei uma "gambiarra" fazer isso.

Sobre o TreeView também utilizo esse componente. Você pode me ajudar a tratar isso nele também?

Obrigado.
Responder

Gostei + 0

19/11/2013

Gustavo Bretas

Acho até que foge um pouco do RTTI, mas vc pode colocar um IF verificando a classe dos componentes que vc não quer que verifique os ITEMS!

Por exemplo:
  if (not Components[iCont].InheritsFrom(TTPopupMenu)) then
  begin
    PropInfo := GetPropInfo(Components[iCont].ClassInfo, '' Items '');
    if (PropInfo <> nil) then
    begin
      vItens := TStringList.Create;
      vItens.Text := TStringList(Pointer(strtoint(GetPropValue(Components[iCont], '' Items '')))).Text;
      vTraduz := False;
      for iTotal := 0 to (vItens.Count - 1) do
      begin
        if cdsTraduz.Locate('' componente '', Components[iCont].Name + '' _L '' + IntToStr(iTotal + 1), []) then
        begin
          vItens[iTotal] := cdsTraduz.FieldByName('' traducao '').AsString;
          vTraduz := True;
        end;
      end;
      if vTraduz then
        TStringList(TObject(Pointer(strtoint(GetPropValue(Components[iCont], '' Items ''))))).Text := vItens.Text;
      FreeAndNil(vItens);
    end;
  end;


TreeView não sei ainda como fazer! :(

Enquanto isso da uma olhada nesse tutorial: [url]http://www.sisulizer.com/translation/vcl/VCL.pdf[/url]
Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar