Перейти к содержанию
Fire Monkey от А до Я

AngryOwl

Пользователи
  • Постов

    394
  • Зарегистрирован

  • Посещение

  • Победитель дней

    45

Сообщения, опубликованные AngryOwl

  1. Друзья!

    Я тут в одной теме выложил юнит для локализации приложений и демо-пример к нему, а также приложение облегчающее создание и редактирование ресурсов для локализации (файлов с переводами на разные языки).

    Потом подумал - может стоит вынести это в отдельную тему?

    Данная проблема (локализации приложений) возникла уже давно. На заре XE2. Потом были все версии, вплоть до текущей. Но лично меня текущие решения так и не  устраивали. Мне нужно было простое и удобное редактирование сразу всех языков приложения, и чтобы быстро работало.

    Тогда и были созданы этот юнит и приложения, с которыми я решил с вами поделиться. Создано это было для себя, для упрощения локализации собственных приложений. Поэтому никакой "красоты" кода прошу не искать - ее там нет. Местами вообще кому-то покажется "кривым"... )

    Очень жаль, что у меня критически мало времени для общения на данном ресурсе, а потому я в некотором смысле извиняюсь - мог бы выложить этот код давно.

    Тем-более, что он очень простой. Все что в нем используется, и как используется, думаю, всем будет доступно и понятно.

     

    Итак.

    Приложение Test_Translator - это дело пример с, непосредственно, самим юнитом uTranslatorFM.pas

    В uTranslatorFM.pas вы увидите, что локализация осуществлена за счет использования INI-файлов, а сам "перевод" осуществляется простым перебором компонент на форме.

    Стоит отметить, что перевод осуществляется использованием свойства компонент HelpContext (integer), а у компонент, что не имеют этого свойства - используется свойство Tag.

    На первый взгляд может показаться неудобным. А если приложение большое - что-то может забыться. Однако, лично я очень быстро привык к такому использованию. И поверьте  - приложение, в котором я использую этот юнит, очень большое! )))

    Кроме того, если есть компоненты, которые не имеют этих свойств, или которые могут менять значение перевода самостоятельно, либо могут быть динамическими - можно использовать нулевой HelpContext, но при этом придавать им значения "вручную".

    Например: если требуется у компонента TLabel динамически менять значение в ходе выполнения программы, подставляя нужные "подстроки" (грубо - используя, например, Format(...)), то можно написать в программе

    Label1.Text := Format( AppTranslator.GetValue(_код_, _значение_по_умолчанию_), [_подставляемое_значение_]);

    где

    _код_ - это значение, которое будет считываться из INI-файла (например 100)

    _значение_по_умолчанию_ - значение строки по умолчанию, на тот случай, если данный текст отсутствует в INI-файле, или файла с таким переводом не существует (этот параметр не обязателен)

    _подставляемое_значение_ - в данном случае это просто пример, допустим - ход выполнения процесса (например 85%)

    А строка в INI-файле может быть такая:

    (файл lang.ru)

    100=Процесс выполнения %d%%

    (файл lang.en)

    100=The progress %d%%

    и также другие языки.

    Думаю тут, в примере, все элементарно и понятно.

    Все работает на любой платформе!

    Как вы будете подключать файлы к приложению - ваше дело. Можно скачивать с инета, можно встроить в качестве ресурсов, задеплоить в проект и т.д.

    Лично я встраиваю в качестве ресурсов (Win) и деплою (Mac и Android). У меня свои причины и аргументы.

    Файлы:

    Lang.ru

    Lang.en

    и другие, это INI-файлы соответствующих переводов где строки с переводами имеют одинаковые индексы

    LangList.ini - вспомогательный файл (разберетесь))

    language.rc - файл для создания ресурса (Win)

     

    С приложением SLLanguage все немного и сложнее и проще, одновременно...

    Не вижу смысла его описывать - оно просто позволяет редактировать описанные выше ресурсы (файлы языков).

    Часть его кода откуда-то позаимствовано (не помню уже).

     

    Для чего все это я отдельно решил написать, в отдельную тему?

    Предлагаю всем пользоваться данным кодом - кому как заблагорассудится! Исправлять, дополнять и делится мыслями и идеями.

    Возможно кто-то решит создать компонент.

    Ну вот вроде все, друзья!

    Если что - спрашивайте! Отвечу по мере возможности.

    P.S. К модераторам - поправьте, если что, - вдруг не в ту тему закинул.

    SLLanguage.zip

    Test_Translator.zip

    P.P.S. Забыл уточнить - дело-пример делал под XE10, а приложение для создания ресурсов под XE7. Не сложно поправить - кому под что нужно.

  2. И еще, друзья! Делалось это все для себя, для личного пользования, а не для "распространения")

    Так-что не обессудьте - если где "говнокод") Сами поправите кому как нравится)

    Заодно может поделитесь интересными мыслями и идеями.

    Если кому что не понятно - подскажу.

  3. Как обещал - приложение для создания, редактирования, автоматического перевода и сохранения Ini-файлов с переводами для локализации своих приложений. Для примера есть два файлики (Lang.en и Lang.ru) и другие файлы, содержание которых всем будет понятно)

    Все, вроде, просто)

    P.S. Все желающие могут использовать как хотят. Можете что-то добавлять, исправлять и т.д. Ну и не забываем делиться с другими...))

    P.P.S. - делалось уже давно, под XE7. Кто захочет под XE10 - думаю все будет крайне просто переделать.

    SLLanguage.zip

  4. В общем я тупо вырезал часть из своего проекта. И создал маленький демо-проект.

    Работает везде!

    Хоть на Винде, хоть на Маке, хоть на Андроиде.

    Думаю - разберетесь. Тем-более, что там все очень просто.

    В демке сделал только два языка (в моем проекте их 11).

    Все в Ini-файлах, работает очень быстро.

    P.S. Все желающие могут использовать как хотят. Можете что-то добавлять, исправлять и т.д. Ну и не забываем делиться с другими...

    P.P.S. Позже выложу приложение (GUI) для редактирования файлов языков. С автоматическим переводчиком и прочими мелочами, упрощающими редактирование.

    Test_Translator.zip

  5. В конкретном случае - речь идет о Android.

    Тут, в некотором смысле, проще - воспользуйтесь замечательными компонентами FGX от автора данного форума. У компонента TfgApplicationEvents есть все события, которые Вам необходимы. А именно - событие ДО отображения формы (и куча других).

    Ну если Вам не хватает отладчика - тупо натыкайте в нужных местах "тостов" (Toast), и смотрите - что будет "последним" событием...

    З.Ы. А зависание программы происходит однозначно из-за того, что Вы пытаетесь что-то изменить в интерфейсе, до момента пока форма еще не стала активной. Решить можно не только синхронизацией, но и каким-нибудь Splash.

  6. В общем можно сделать, конечно, установку шрифта в инсталлере программы. И это будет оптимальным решением.

    Но можно обойтись и без него.

    Не буду расписывать детали, просто закину приложение и фрагменты кода. Думаю разберетесь. Естественно изменив на свои шрифты и т.п.

    Все нижеперечисленное - в файл проекта DPR, перед Application.Initialize;

    const
      CKey = '\Software\Microsoft\Windows NT\CurrentVersion\Fonts';
      CFontFileName = 'spherelive.ttf';
      CFontName = 'spherelive (TrueType)';
    procedure ExecuteWait(const sProgramm: string; const sParams: string = ''; fHide: Boolean = false);
    var
      ShExecInfo: TShellExecuteInfo;
    begin
      FillChar(ShExecInfo, sizeof(ShExecInfo), 0);
      with ShExecInfo do
      begin
        cbSize := sizeof(ShExecInfo);
        fMask := SEE_MASK_NOCLOSEPROCESS;
        lpFile := PChar(sProgramm);
        lpParameters := PChar(sParams);
        lpVerb := 'open';
        if (not fHide) then
          nShow := SW_SHOW
          else
          nShow := SW_HIDE
      end;
      try
        if (ShellExecuteEx(@ShExecInfo) and (ShExecInfo.hProcess <> 0)) then
        try
          WaitForSingleObject(ShExecInfo.hProcess, INFINITE)
        finally
          CloseHandle(ShExecInfo.hProcess);
        end;
      except
        On E : Exception do
          ShowMessage('font install Exception: ' + E.Message);
      end;
    end;
      if not IsFontRegistered(TPath.Combine(ExtractFilePath(ParamStr(0)), CFontFileName), CFontName) then
        if FileExists(TPath.Combine(ExtractFilePath(ParamStr(0)), 'RegFontC.exe')) then
          ExecuteWait(TPath.Combine(ExtractFilePath(ParamStr(0)), 'RegFontC.exe'));
    
      Application.Initialize;

    Где будет лежать файл со шрифтом - это уже ваше дело. Можно его куда угодно поместить. Хоть в ресурсы, хоть файлом просто, хоть с инета скачать.

    P.S. Ну и конечно - это все именно под винду...

    RegFont.zip

  7. Возможно я не прав, но мой личный опыт показывает, что кол-во "задеплоенных" файлов никак не влияет на скорость запуска приложения.

    А вот что очень сильно влияет - кол-во визуальных компонентов на форме(ах). И чем их больше - тем, соответственно, дольше запускается приложение. И это независимо от того - видимы они на главной форме или нет.

    Ну и, конечно, инициализация различных переменных, невизуальных компонентов, инициализации БД и прочего, - это тоже существенно влияет.

    P.S. Ну и сори - что не в тему (какую именно БД использовать)...

  8. 10 часов назад, dmdel сказал:

    Я не говорю, что такое событие есть! Но у TComboEdit есть процедура  DropDown,  после которого появляется список Items  и две кнопки:  Ок или Отмена. Как отследить, какая была нажата? 

    Согласен, виноват, на счет процедуры. Но в данном случае я никак не могу увидеть эти две кнопки... Может у меня что-то не так? Или с версией андроида что-то не так, либо еще что-то. У меня отображается список в виде RadioButtons, где выбор осуществляется просто выбором пункта из списка. А отмена - просто нажатие кнопки "назад".

    Может Вам стоит обрабатывать событие OnKeyDown?

    Ну или детальнее опишите, желательно со скрином примера...

  9. Подобный вопрос уже задавался тут, но ответа так не последовало.

    А вопрос достаточно актуальный, так как решения не удалось найти.

    Как отловить событие изменения размера клавиатуры, когда после первого отображения клавиатуры и попытки набора текста появляется некий дополнительный прямоугольник с подсказками по набору текста?

    Последовательность следующая:

    1. без клавиатуры

    2. появляется клавиатура при получении фокуса компонентом ввода текста (все ОК)

    3. при первом же введенном символе появляется дополнительная область клавиатуры с предлагаемыми вариантами набора текста (баг - клавиатура перекрывает поле ввода)

    4. при последующих вызовах клавиатуры (все ок)

    device-2016-08-25-022432.pngdevice-2016-08-25-022505.pngdevice-2016-08-25-022515.pngdevice-2016-08-25-022532.png

  10. Уточните детали - что Вы хотите получить?

    Еще лучше - скрин того, чего хотите добиться. Можете просто нарисовать.

    Если Вам нужно, чтобы на фоне (одного цвета) был расположен TListView другого цвета, и у этого TListView были "скругленные углы", то этого добиться очень просто. Разместите TLayout, на нем TListView, у которого выравнивание Client, а по углам TLayout поместите TImage с соответствующими PNG.

    Разумеется, нужно установить свойство TListView в Send to back ("под" этими TImage)

    corner_bottom_left.png

    corner_bottom_right.png

    corner_top_left.png

    corner_top_right.png

  11. type
      TForm2 = class(TForm)
        SizeGrip1: TSizeGrip;
        procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    
    ...........
    
    procedure TForm2.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
    begin
      if AWidth > 800 then
        AWidth := 800;
    
      if AWidth < 300 then
        AWidth := 300;
    
      if AHeight > 600 then
        AHeight := 600;
    
      if AHeight < 200 then
        AHeight := 200;
    
      inherited SetBounds(ALeft, ATop, AWidth, AHeight);
    end;

    Пример проекта прилагаю

    SetBounds.zip

    P.S. И старайтесь пользоваться поиском. Здесь это уже обсуждалось.

  12. Только что, mrseagull сказал:

    Каким способом делал? На пальцах если.
    У меня вариант только хранить все надписи в файле, при старте программы узнавать язык и на все контролы грузить эти надписи но это муторно получится.

    Именно так и делал.

    Один раз написал - все прекрасно работает, стабильно и быстро, на всех платформах. Весь юнит 650 строк, с учетом особенностей проекта.

  13. Попробуйте следующий вариант:

    - открываете проект (важно чтобы первой открытой формой в проекте была главная форма)

    - IDE выдает описанную вами ошибку (жмете Ignore All)

    - закрываете проект без сохранения (не закрывая среду)

    - тут же, снова открывате проект - проект должен открыться уже нормально.

    напомню, что первой должна быть главная форма. если не она, то открываете главную форму (игнорируя все предупреждения) и повторяете снова.

    Это не ошибка проекта. Это баг IDE.

    З.Ы. И связано это, скорее-всего, с использованием сторонних компонент, которые используются в вашем стиле.

  14. Не помню как там TListView, но наверняка есть что-то типа TListView(_ваш_список_).VScrollBar.Width

    Точно не буду утверждать, что так. Но получить текущую ширину скрола, думаю, можно. И обойтись без констант.

    З.Ы. Кстати, они все-равно прописаны в константах, где-то в глобальных модулях...

  15. И [brunnengi] и [ZuBy] оба правы.

    В первом случае у TLayout нужно выключить свойсвто HitTest, чтобы сам TLayout не "перекрывал" клики мышь (или тапы) (TLayout  позволит "выравнивать" несколько "кнопок" относительно друг друга проще)

    Во втором случае - все проще (любой лишний компонент на форме, не важно - в составе чего он, - это дополнительная память, а главное - расходы на отрисовку. Порой нам кажется, что вроде на форме и "нет ничего", а если копнуть поглубже - там окажется море того, чего мы не видим, а отрисовывать то их прийдется!). Простой TImage, на мой взгляд, лучше.

    Но, как мне кажется, в данном случае вовсе не обязательно обрабатывать выравнивание в событии OnResize.

    Достаточно в DesignTime разместить TImage (все) где нужно и установить его (их) свойство Anchors = [akRight, akBottom] (для Вашего случая)

  16. Что же касается самой функции, кажется можно чуть проще (где-то на форуме уже вроде был такой код) и он прекрасно работает:

    function GetTextHeight(AText: string; AMaxWidth: Single; AFont: TFont; ATextAlign: TTextAlign): Single;
    var
      txt: TText;
    begin
      txt := TText.Create(nil);
      try
        txt.Align := TAlignLayout.None;
        txt.VertTextAlign := ATextAlign;
        txt.HorzTextAlign := TTextAlign.Leading;
        txt.Font := AFont;
        txt.WordWrap := True;
        txt.Width := AMaxWidth;
        txt.BeginUpdate;
        txt.Text := AText;
        txt.EndUpdate;
        txt.AutoSize := True;
        Result := txt.Height;
      finally
        FreeAndNil(txt);
      end;
    end;

     

×
×
  • Создать...