Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.03.26;
Скачать: CL | DM;

Вниз

Сохранение заголовков всех компонентов формы   Найти похожие ветки 

 
__DATA__   (2006-02-22 08:30) [0]

Хочу сделать потдержку нескольких языков в программе, текущий язык сохраняю так :

procedure SaveDefaultLenguage(Form: TWinControl; FileName: String);
var
 i: Integer;
 ini: TINIFile;
begin
 try
   DeleteFile(FileName);
   INI := TINIFile.Create(FileName);
   for i := 0 to Form.ComponentCount-1 do
   begin
     if (Form.Components[i] is TLabel) then
       ini.WriteString("COMPONENTS",(Form.Components[i] as TLabel).Name,(Form.Components[i] as TLabel).Caption)
     else
     if (Form.Components[i] is TButton) then
       ini.WriteString("COMPONENTS",(Form.Components[i] as TButton).Name,(Form.Components[i] as TButton).Caption)
     else
     if (Form.Components[i] is TGroupBox) then
       ini.WriteString("COMPONENTS",(Form.Components[i] as TGroupBox).Name,(Form.Components[i] as TGroupBox).Caption)
     else
     if (Form.Components[i] is TCheckBox) then
       ini.WriteString("COMPONENTS",(Form.Components[i] as TCheckBox).Name,(Form.Components[i] as TCheckBox).Caption)
     //bsSkin ext
     else
     if (Form.Components[i] is TMenuItem) then
       ini.WriteString("COMPONENTS",(Form.Components[i] as TMenuItem).Name,(Form.Components[i] as TMenuItem).Caption)
     else
     if (Form.Components[i] is TbsSkinCheckRadioBox) then
       ini.WriteString("COMPONENTS",(Form.Components[i] as TbsSkinCheckRadioBox).Name,(Form.Components[i] as TbsSkinCheckRadioBox).Caption)
     else
     if (Form.Components[i] is TbsSkinSpeedButton) then
       ini.WriteString("COMPONENTS",(Form.Components[i] as TbsSkinSpeedButton).Name,(Form.Components[i] as TbsSkinSpeedButton).Caption)
     else
     if (Form.Components[i] is TbsSkinStdLabel) then
       ini.WriteString("COMPONENTS",(Form.Components[i] as TbsSkinStdLabel).Name,(Form.Components[i] as TbsSkinStdLabel).Caption)
     else
     if (Form.Components[i] is TbsSkinButton) then
       ini.WriteString("COMPONENTS",(Form.Components[i] as TbsSkinButton).Name,(Form.Components[i] as TbsSkinButton).Caption)
   end;
 finally
   INI.Free;
 end;
end;


Но при попытки записи заголовка определенного элемента в ini файл выскакивает Access Violation. Код вроде правильный и AV вылетать не должен, что я упустил?


 
antonn ©   (2006-02-22 09:32) [1]

__DATA__   (22.02.06 8:30)
Хочу сделать потдержку нескольких языков в программе, текущий язык сохраняю так :

а зачем так сохранять текущий язык со всех контроллов?
допустим, имеется несколько файлом с различными переводами, запоминаем, какой из файлов был загружен последним, и при запуске программы его и грузим. И сохраняем только имя файла, а не все текста. Сами файлы не нужно перезаписывать.


 
__DATA__   (2006-02-22 11:00) [2]

Я тоже сначало так хотел, только у меня много динамически создаваемых контролов, имя которых и заголовок которых я заранее не знаю, так что приходится при запуске сохранять все текущие имена контролов, а при смене языка востанавливать исходные имена контролов(которые были при запуске), а далее обрабатывать их примерно так :

for i := 0 to ComponentsCount-1 do
 if (Componets[i] is TButton) then
   (Components[i] as TButton).Caption := Translate("C:\Englesh.lng",(Components[i] as TButton).Caption;


где Translate :


function Tanslate(LangFile,World: String): String;
var
 strl,strl2: TStringList;
 i: Integer;
 b: Boolean;
begin
 try
   Result := World;
   strl := TStringList.Create;
   strl2 := TStringList.Create;
   if FileExists(LangFile) then
     strl.LoadFromFile(LangFile)
   else
     Exit;
   b := false;
   i := 0;
   while (i<strl.Count)and(not b) do
   begin
     strl2.Text := ExtractWorlds(strl.Strings[i],"=");
     if strl2.Count > 1 then
     begin
       if LStrCmpI(PChar(strl2.Strings[0]),PChar(World))=0 then
       begin
         Result := strl2.Strings[1];
         b := true;
       end;
     end;
     Inc(i);
   end;
 finally
   strl.Free;
   strl2.Free;
 end;
end;


и содержимое файла C:\Englesh.lng примерно следующее:


Собока=Dog
Кошки=Cats
...


Тоесть в файле с языком я не привязываю конкретному элементу конкретный заголовок, а перевожу все заголовки, также как переводчик

При этом можно без опасений работать с динамически создаваемыми контролами

А ошибку уже нашел, у меня оказывается в некоторых контролах поле Name было пустым, а при вызове WriteString с пустым именем секции как раз и вылетает AV. Так что теперь проверяю, чтобы Name пустым небыло


 
evvcom ©   (2006-02-22 11:16) [3]

[0] - код очень не эффективный и при добавлении компонент других типов автоматом их не распознает. Есть такой unit TypInfo. Обрати внимание, например, на GetStrProp и SetStrProp для получения/записи свойства Caption у контрола. И GetPropInfo для определения есть ли такое свойство у контрола и какого оно типа.


 
Экспериментатор   (2006-02-22 22:11) [4]

Вырезка из кода программы
function TranslateProp(Dict : TIniFile; ASection, AIdent1, AIdent2 : string;
                                               var AValue : string): boolean;
begin
 Result:=False;
 try
   if AIdent1="" then Exit;
   AValue:=Dict.ReadString(ASection, AIdent1+"."+AIdent2, "");
   if AValue="" then Dict.WriteString(ASection, AIdent1+"."+AIdent2, "")
     else Result:=True;
 except
 end;
end;

procedure TranslateFormControls(AForm : TForm; ADictFileName : string;
                             isTranslateCaption : boolean = True);
var Dict : TIniFile;
   I : Integer;
   Obj : TComponent;
   PropInfo1 : PPropInfo;
   PropInfo2 : PPropInfo;
   AValue : string;
begin
 try
   Dict:=TIniFile.Create(ExtractFilePath(ParamStr(0))+ADictFileName);

   if not FileExists(ExtractFilePath(ParamStr(0))+ADictFileName) then Exit;

   if isTranslateCaption and TranslateProp(Dict, AForm.Name ,"Form","Caption", AValue) then
         AForm.Caption:=AValue;

   { Переводим заголовки компонентов формы}
   for I:=0 to AForm.ComponentCount-1 do
   begin
     Obj:=AForm.Components[i];
     PropInfo1:=GetPropInfo(Obj.ClassInfo, "Action");
//      if (PropInfo_Action<>nil) then ShowMessage("Type="+IntToStr(Ord(PropInfo_Action.PropType^.Kind)));
     if (PropInfo1=nil) or
       ((PropInfo1<>nil) and (PropInfo1.PropType^.Kind = tkClass)
         and (GetObjectProp(Obj, "Action", TAction)=nil)) then
     begin
       PropInfo2:=GetPropInfo(Obj.ClassInfo, "Caption");
       if PropInfo2<>nil then
       begin
         if (PropInfo2^.PropType^.Kind=tkLString) and ((GetStrProp(Obj, "Caption")<>"")
         and (GetStrProp(Obj, "Caption")<>"-")) then
          if TranslateProp(Dict, AForm.Name ,Obj.Name, "Caption", AValue) then
            SetStrProp(Obj, PropInfo2, AValue);
       end;

       PropInfo2:=GetPropInfo(Obj.ClassInfo, "Hint");
       if PropInfo2<>nil then
       begin
         if (PropInfo2^.PropType^.Kind=tkLString) and (GetStrProp(Obj, "Hint")<>"")then
          if TranslateProp(Dict, AForm.Name ,Obj.Name,"Hint", AValue) then
            SetStrProp(Obj, PropInfo2, GetTextWithReturn(AValue));
       end;
     end;

     PropInfo2:=GetPropInfo(Obj.ClassInfo, "Title");
     if PropInfo2<>nil then
     begin
       if (PropInfo2^.PropType^.Kind=tkLString) and (GetStrProp(Obj, "Title")<>"")then
        if TranslateProp(Dict, AForm.Name ,Obj.Name,"Title", AValue) then
          SetStrProp(Obj, PropInfo2, AValue);
     end;

     PropInfo2:=GetPropInfo(Obj.ClassInfo, "Filter");
     if PropInfo2<>nil then
     begin
       if (PropInfo2^.PropType^.Kind=tkLString) and (GetStrProp(Obj, "Filter")<>"")then
        if TranslateProp(Dict, AForm.Name ,Obj.Name,"Filter", AValue) then
          SetStrProp(Obj, PropInfo2, AValue);
     end;
   end;
   { Переводим подсказки компонентов формы}
{    for I:=0 to AForm.ComponentCount-1 do
   begin
     Obj:=AForm.Components[i];
     PropInfo2:=GetPropInfo(Obj.ClassInfo, "Hint");
     if PropInfo2<>nil then
     begin
       if (PropInfo2^.PropType^.Kind=tkLString) and (GetStrProp(Obj, "Hint")<>"") then
        if TranslateProp(Dict, AForm.Name ,Obj.Name+".Hint", AValue) then
          SetStrProp(Obj, PropInfo2, AValue);
     end;
   end;}

   Dict.Free;
 except
//    ShowMessage("Language file is not loaded!");
 end;
end;


 
Экспериментатор   (2006-02-22 22:45) [5]

Файл перевода получится типа:

[frm_Main]
menu_File.Caption=Файл
menu_Search.Caption=Поиск
menu_View.Caption=Вид
menu_Options.Caption=Опции
menu_Operations.Caption=Операции
menu_Utility.Caption=Утилиты
menu_About.Caption=?
menu_Alternate.Caption=Альтернатива
menu_Language.Caption=Язык интерфейса
menu_LanguageStandard.Caption=Английский (стандартный перевод)
a_files_item_New.Caption=Новый...
a_files_item_New.Hint=Новый проект
a_files_item_Open.Caption=Открыть...
a_files_item_Open.Hint=Открыть проект
a_files_item_OpenDefault.Caption=Открыть файл по умолчанию
a_files_item_OpenDefault.Hint=Открыть файл по умолчанию
a_files_item_CloseFile.Caption=Закрыть файл

Позиции создаются автоматом
потом меняешь значение на свой вкус
Copyright(c) Экспериментатор


 
QwertyKz ©   (2006-02-23 05:43) [6]

GnuGetText - Хорошая вещь для локализации приложений
http://dybdahl.dk/dxgettext/docs/ -
На DelphiPlus.org была статья на эту тему, советую посмотреть


 
TStas ©   (2006-02-23 18:58) [7]

Я в инишку писал только сам язык, а в SetLanguage все и переводил. ИМХО Удобнее всего



Страницы: 1 вся ветка

Текущий архив: 2006.03.26;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.047 c
15-1141146376
antonn
2006-02-28 20:06
2006.03.26
С первым днем весны, товарищи!


15-1141150109
strannik-ivan
2006-02-28 21:08
2006.03.26
dll+потоки


2-1142161827
Sollo
2006-03-12 14:10
2006.03.26
DBX SimpleDataSet кажется проблемы с кэшированием


4-1136460435
Arazel
2006-01-05 14:27
2006.03.26
Как прочитать/записать MBR из под Win9x


2-1141681419
KILROY
2006-03-07 00:43
2006.03.26
Ссылка в БД...