Delphi: обработка пользовательских шрифтов - PullRequest
10 голосов
/ 30 декабря 2008

Я пришел с вызовом, который получает предпочтение шрифта пользовательского интерфейса пользователя (как в отличие от жестко закодированного выбора Borland «MS Sans Serif»).

Давайте представим, что настройки шрифта пользователя:

Segoe Print, 15pt

Я установил шрифт всех элементов во всех формах во всех приложениях на:

Segoe Print, 15pt

Проблема в том, что все теперь отрезано. Кнопки слишком маленькие - слишком узкие, слишком коротко. Текст в ярлыках обрезается и т.д ..

Форма имеет свойство Scaled, но оно не меняется в зависимости от шрифта размеры. Свойство scaled масштабирует форму при сериализации в высота цифры "0".

Я ничего не могу найти в справке о том, как Борланд намеревался поддержать пользовательские настройки приложения Windows.

Как мне обрабатывать настройки пользовательских шрифтов?

Примечание: Я отправил это сообщение с сервера группы новостей Embargadero, поскольку сервер новостей Embargadero, похоже, умирает, подвергается цензуре, сломан или требует входа в систему.


Обновление 1

Я говорю о настройках шрифта пользователя, а не о настройках DPI. то есть, представьте следующий языковой нейтральный псевдокод:

procedure TForm1.FormCreate(Sender: TObject);
var
    FontFace: string;
    FontHeight: Integer;
begin
    GetUserFontPreference(out FontFace, out FontHeight);
    Self.Font.Name := FontFace;
    Self.Font.Height := FontHeight;
end;

Примечание: Это не мой настоящий код (в конце концов, это не зависящий от языка псевдокод). Но кроме того, вам нужно рекурсивно проходить через каждый элемент управления в форме, изменяя шрифт, когда его нужно изменить. Если для шрифта применяется стиль, отличный от его родителя (например, полужирный), и он больше не наследует от своего родителя, его необходимо установить вручную.


Согласно запросу lkessler , вот код для получения предпочтения шрифта пользовательского интерфейса из Windows:

procedure GetUserFontPreference(out FaceName: string; out PixelHeight: Integer);
var
    lf: LOGFONT;
begin
    ZeroMemory(@lf, SizeOf(lf));
     //Yes IconTitleFont (not SPI_GETNONCLIENTMETRICS MessageFont)
    if SystemParametersInfo(SPI_GETICONTITLELOGFONT, SizeOf(lf), @lf, 0) then
    begin
        FaceName := PChar(Addr(lf.lfFaceName[0]));
        PixelHeight := lf.lfHeight;
    end
    else
    begin
        {
            If we can't get it, then assume the same non-user preferences that
            everyone else does.
        }
        FaceName := 'MS Shell Dlg 2';
        PixelHeight := 8;
    end;
end;

Смежные вопросы

Ответы [ 6 ]

9 голосов
/ 30 декабря 2008

Во-первых, чтобы нам было ясно, Borland больше не владеет Delphi. Embarcadero теперь владеет Delphi, и теперь мы в надежных и надежных руках.

Хорошо, к вашему вопросу.

Хитрость заключается в том, чтобы установить для TForm.AutoScroll значение False и убедиться, что на вашей машине для разработки установлены мелкие шрифты. Оставляя TForm.Scaled в одиночку (по умолчанию используется значение True).

Вот как у нас это делается внутри, и в IDE все прекрасно обрабатывается.

3 голосов
/ 16 января 2009

Мне нравится использовать эту функцию. Он основан на Graphics.GetFontData

procedure SystemFont(Font: TFont);
var
  LogFont: TLogFont;
begin
  if SystemParametersInfo(SPI_GETICONTITLELOGFONT, SizeOf(TLogFont), @LogFont, 0) then
    begin
      Font.Height := LogFont.lfHeight;
      Font.Orientation := LogFont.lfOrientation;
      Font.Charset := TFontCharset(LogFont.lfCharSet);
      Font.Name := PChar(@LogFont.lfFaceName);

      Font.Style := [];

      if LogFont.lfWeight >= FW_BOLD then
        Font.Style := Font.Style + [fsBold];

      if LogFont.lfItalic = 1 then
        Font.Style := Font.Style + [fsItalic];

      if LogFont.lfUnderline = 1 then
        Font.Style := Font.Style + [fsUnderline];

      if LogFont.lfStrikeOut = 1 then
        Font.Style := Font.Style + [fsStrikeOut];

      case LogFont.lfPitchAndFamily and $F of
        VARIABLE_PITCH: Font.Pitch := fpVariable;
        FIXED_PITCH: Font.Pitch := fpFixed;
        else Font.Pitch := fpDefault;
      end;
    end;
end;

Вы просто используете его для всех событий TForm.OnCreate. Альтернативой может быть создание нового класса, который делает это при создании или зацикливании Screen.Forms.

Если вы измените некоторые свойства шрифта по умолчанию любого из элементов управления в форме, они все равно будут использовать старый шрифт. Если вам нужны настраиваемые свойства для некоторых элементов управления, вам придется их настраивать после вызова SystemFont.

Изменение Graphics.DefFontData во время выполнения может помочь, если дизайнер форм записывает только измененные свойства в файлы .dfm.

3 голосов
/ 30 декабря 2008

Я чувствую с тобой. Но, честно говоря: правильная компоновка графического интерфейса просто не может быть создана с помощью механизма компоновки на основе пикселей, который используется в VCL. Необходим динамический механизм компоновки, который выкладывает элементы управления только после

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

  2. текст в элементе управления был переведен в текущую локаль, поскольку это может уменьшить или увеличить пространство, необходимое для элемента управления.

Поскольку все зависит от свойств среды выполнения, создание диалоговых окон путем размещения элементов управления может не работать. Механизмы компоновки, такие как GTK и QT или размерники в wxWidgets, лучше подходят.

Я не знаю ничего подобного для программ на Delphi. В некоторых программах я занимаюсь ручным изменением размеров и позиционированием элементов управления после установки шрифта и перевода текста. Много работы, но в зависимости от вашей аудитории это может стоить.

Вы также можете посмотреть код, который Джордан Рассел написал для Inno Setup. Он не использует свойство Scaled форм, но написал код для пользовательского масштабирования элементов управления. Возможно, это также подойдет для очень больших шрифтов на экранах с высоким разрешением; Я заметил, что, по крайней мере, на моем экране настройки ноутбука с разрешением 124 DPI выглядят неплохо.

2 голосов
/ 31 декабря 2008

Чтобы сделать это правильно, я думаю, вам нужно:

1 - загрузить настройки шрифта пользователя

2 - примените, как вы описали

3 - определите ширину и высоту всех надписей (в пикселях), сравните их с шириной и высотой элемента управления и скорректируйте соответствующим образом.

К сожалению, отрегулировать соответственно сложно. Вы можете расширить кнопку, но затем вам нужно будет проверить, перекрывается ли она с другим элементом управления.

Лучше всего было бы создать слегка увеличенные элементы управления и надеяться, что пользователь не выберет размер шрифта в 32 пункта.

1 голос
/ 31 декабря 2008

У Kogus была правильная идея, но она не использовала нужную вам функцию. Это будет процедура Windows GetTextExtentPoint32 . Вы передаете ему строку, и она вычисляет ширину и высоту строки, используя текущий выбранный шрифт. Вы найдете это в Windows.pas.

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

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

Это было бы хорошо для одного или двух элементов управления, но любой из этих методов будет много работы, если вы пытаетесь сделать это на весь пользовательский интерфейс.

0 голосов
/ 31 декабря 2008

Я бы сказал, что это было похоже на перевод. В нашем приложении мы сделали кнопки, метки, правки, все, что немного больше, чтобы можно было легко разместить более длинные слова, необходимые для некоторых языков. Это не повредит дизайну немного.

...