Сделайте диалоги совместимыми с большими шрифтами.

Как вы думаете, какие методы лучше всего подходят для создания диалогового окна Windows, совместимого как со стандартными шрифтами (96 точек на дюйм), так и с настройкой «крупных шрифтов» (120 точек на дюйм), чтобы объекты не перекрывались и не обрезались?

Кстати: на всякий случай, если это уместно, я заинтересован в том, чтобы сделать это для диалогов Delphi.

Заранее спасибо!


person Narcís Calvet    schedule 31.03.2010    source источник
comment
11 голосов и еще ни одного ответа! Звучит как неплохой вопрос.   -  person Mason Wheeler    schedule 31.03.2010
comment
Вопрос немного неконкретный. Было бы проще ответить на конкретную проблему. Таким образом, ответы также широки.   -  person merula    schedule 31.03.2010
comment
Проблема также широка по своему охвату. Я предпочитаю иметь решение, которое работает во всех ситуациях, а не несколько небольших решений для конкретных проблем, которые могут не сочетаться друг с другом.   -  person Uwe Raabe    schedule 01.04.2010
comment
Возраст вопроса не имеет значения, когда решается, является ли что-то дубликатом или нет. Единственное, что должно иметь значение, — это качество вопросов/ответов (в данном случае я не имею права что-либо говорить по этому поводу).   -  person Ben    schedule 04.01.2015


Ответы (5)


В файле справки D2007 есть довольно хорошая статья в разделе "Соображения при динамическом изменении размеров форм и Элементы управления" (обратите внимание, что URL-адрес указывает на сам файл справки, а не на веб-страницу как таковую).

Эту же тему под тем же названием можно найти в файле справки D2010 (то же предостережение относительно URL, что и выше) или на docwiki.

Также стоит (хотя бы немного) изучить TForm.Scaled и TForm.ScaleBy.

person Ken White    schedule 31.03.2010

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

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

person merula    schedule 31.03.2010
comment
Я думаю, что короткий ответ - это ОГРОМНОЕ слабое место Delphi. XAML делает это лучше. Java/Swing делает это лучше. Честно говоря, все остальное делает это лучше, чем Delphi. Даже продукты с открытым исходным кодом, такие как Glade, основанные на менеджере компоновки, делают это лучше. - person Warren P; 01.04.2010
comment
В современных версиях Delphi есть компоненты управления компоновкой, по крайней мере, в FireMonkey: Стратегии компоновки FireMonkey. Однако для VCL доступны сторонние компоненты компоновки. - person Remy Lebeau; 29.06.2017

Вот как я пытаюсь работать с пикселями Delphi VCL независимо от настройки размера шрифта в Window.

unit App.Screen;

interface

uses Controls;

type
  TAppScreen = class(TObject)
  private
    FDefaultPixelsPerInch: integer;
    FPixelsPerInch: integer;
    function GetPixelsPerInch: integer;
    procedure SetPixelsPerInch(const Value: integer);
  public
    procedure AfterConstruction; override;
    function DefaultPixelsPerInch: integer;
    function InAcceptableRange(const aPPI: integer): boolean;
    procedure ScaleControl(const aControl: TWinControl);
    property PixelsPerInch: integer read GetPixelsPerInch write SetPixelsPerInch;
  end;

  TAppScreenHelper = class helper for TAppScreen
  private
    class var FInstance: TAppScreen;
    class function GetInstance: TAppScreen; static;
  public
    class procedure Setup;
    class procedure TearDown;
    class property Instance: TAppScreen read GetInstance;
  end;

implementation

uses
  TypInfo, Windows, SysUtils, Forms, Graphics;

type
  TScreenEx = class(TScreen)
  published
    property PixelsPerInch;
  end;

  TScreenHelper = class helper for TScreen
  public
    procedure SetPixelsPerInch(Value: integer);
  end;

procedure TScreenHelper.SetPixelsPerInch(Value: integer);
begin
  PInteger(Integer(Self) + (Integer(GetPropInfo(TScreenEx, 'PixelsPerInch').GetProc) and $00FFFFFF))^ := Value;
end;

procedure TAppScreen.AfterConstruction;
begin
  inherited;
  FDefaultPixelsPerInch := Screen.PixelsPerInch;
  FPixelsPerInch := FDefaultPixelsPerInch;
end;

function TAppScreen.DefaultPixelsPerInch: integer;
begin
  Result := FDefaultPixelsPerInch;
end;

function TAppScreen.GetPixelsPerInch: integer;
begin
  Result := FPixelsPerInch;
end;

function TAppScreen.InAcceptableRange(const aPPI: integer): boolean;
begin
  if DefaultPixelsPerInch > aPPI then
    Result := DefaultPixelsPerInch * 0.55 < aPPI
  else if DefaultPixelsPerInch < aPPI then
    Result := DefaultPixelsPerInch * 1.55 > aPPI
  else
    Result := True;
end;

procedure TAppScreen.ScaleControl(const aControl: TWinControl);
begin
  aControl.ScaleBy(PixelsPerInch, DefaultPixelsPerInch);
end;

procedure TAppScreen.SetPixelsPerInch(const Value: integer);
begin
  FPixelsPerInch := Value;
  Screen.SetPixelsPerInch(FPixelsPerInch);
end;

class function TAppScreenHelper.GetInstance: TAppScreen;
begin
  if FInstance = nil then
    FInstance := TAppScreen.Create;
  Result := FInstance;
end;

class procedure TAppScreenHelper.Setup;
begin
  TAppScreen.Instance;
end;

class procedure TAppScreenHelper.TearDown;
begin
  FInstance.Free;
  FInstance := nil;
end;

initialization
  TAppScreen.Setup;
finalization
  TAppScreen.TearDown;
end.

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

TAppScreen.Instance.PixelsPerInch := 120;
TAppScreen.Instance.PixelsPerInch := 96;
TAppScreen.Instance.PixelsPerInch := 150;

Вы должны изменить PixelsPerInch перед созданием экземпляра потомка TForm, включая диалоги Delphi VCL.

person Chau Chee Yang    schedule 01.04.2010
comment
Почему вы используете class helper для своего собственного класса TAppScreen? Все члены class должны принадлежать самому классу TAppScreen. Нет необходимости использовать class helper вместо TAppScreen вообще. Что касается получения доступа к члену TScreen.FPixelsPerInch, рассмотрите возможность использования Enhanced RTTI через модуль System.Rtti, который может получить доступ к частным и общедоступным полям, а не только к опубликованным свойствам, как с Legacy RTTI из модуля TypInfo. - person Remy Lebeau; 29.06.2017

  • Никогда не размещайте элемент управления и метку его описания рядом, всегда ставьте метку поверх него.

Но помимо этого? Может быть:

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

Я никогда не пробовал использовать TLabeledEdit в этом сценарии, может быть, они делают это автоматически?

person dummzeuch    schedule 31.03.2010

Есть предполагаемые коммерческие решения (Developer Express VCL Layout Manager). Но я не доверяю никому из них. Я подозреваю, что Embarcadero следует устранить это как критическую слабость в текущем наборе компонентов пользовательского интерфейса (VCL).

Я думаю, что сторонний набор компонентов может быть вашим самым быстрым решением прямо сейчас. Он коммерческий, но не очень дорогой.

http://www.devexpress.com/products/VCL/ExLayoutControl/

person Warren P    schedule 31.03.2010
comment
Есть ли уже поддержка этой темы в современных версиях Delphi? (ХЕ и выше) - person EProgrammerNotFound; 09.04.2014
comment
Не для дисплеев с высоким DPI, что является основной проблемой, большие размеры шрифта на самом деле означают дисплеи с разрешением выше 96 DPI, а также хак DPI, используемый Microsoft (Fake DPI для увеличения шрифтов). - person Warren P; 09.04.2014