使对话框与“大字体”兼容。 [复制]
Posted
技术标签:
【中文标题】使对话框与“大字体”兼容。 [复制]【英文标题】:Make dialogs compatible with "large fonts". [duplicate] 【发布时间】:2011-02-02 21:08:18 【问题描述】:您认为使 Windows 对话框同时兼容标准字体 (96 dpi) 和“大字体”设置 (120 dpi) 以使对象不会重叠或被截断的最佳做法是什么?
顺便说一句:以防万一,我有兴趣为 Delphi 对话框执行此操作。
提前致谢!
【问题讨论】:
11 个赞,还没有答案!听起来是个好问题。 这个问题有点不具体。回答特定问题会更容易。所以答案的范围也很广。 这个问题的范围也很广。我更喜欢有一个适用于所有情况的解决方案,而不是针对可能无法很好地协同工作的特定问题的多个小解决方案。 The age of the question is irrelevant when deciding something is a duplicate or not. 唯一重要的是问题/答案的质量(在这种情况下,我没有资格对此发表任何评论)。 【参考方案1】:一般来说,为此目的应该使用布局管理器。这就是它们的设计目的。
Delphi(很长时间没有使用它)没有这样的管理器,但从那时起就能够处理不同的 dpi。您必须使用组件的 autosize 属性来确保它们具有适合所显示文本的大小。为了防止组件重叠,使用对齐和锚属性将它们排列在表单上。最终,您必须将组件分组到容器中以实现正确的布局。
【讨论】:
我认为简短的回答是“这是一个巨大的德尔福弱点”。 XAML 在这方面做得更好。 Java/Swing 在这方面做得更好。坦率地说,其他一切都比德尔福做得更好。即使是像 Glade 这样基于布局管理器的开源软件也能做得更好。 现代 Delphi 版本确实有布局管理组件,至少在 FireMonkey 中:FireMonkey Layouts Strategies。不过,有可用于 VCL 的 3rd 方布局组件。【参考方案2】:在“Considerations When Dynamically Resizing Forms and Controls”下的 D2007 帮助文件中有一篇很好的文章(请注意,该 URL 指向帮助文件本身,而不是网页本身)。
可以在D2010 help file(与上面的URL 相同的警告)或docwiki 中找到同名的相同主题。
检查 TForm.Scaled 和 TForm.ScaleBy 也是值得的(至少一点点)。
【讨论】:
【参考方案3】:这就是我尝试处理 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;
您应该在实例化 TForm 的后代(包括 Delphi 的 VCL 对话框)之前更改 PixelsPerInch。
【讨论】:
你为什么要为你自己的TAppScreen
类使用class helper
?所有class
成员都应该在TAppScreen
类本身中。根本不需要为TAppScreen
使用class helper
。至于访问TScreen.FPixelsPerInch
成员,请考虑通过System.Rtti
单元使用增强型RTTI,它可以访问私有和公共字段,而不仅仅是来自TypInfo
单元的传统RTTI 等已发布属性。【参考方案4】:
切勿将控件及其描述标签并排放置,始终将标签放在其顶部。
但除此之外呢?也许:
在标签的右侧和底部留出足够的空间,以便在使用大字体时它们不会与其他控件重叠。我从未尝试在那种情况下使用 TLabeledEdit,也许他们会自动这样做?
【讨论】:
【参考方案5】:据称有商业解决方案(Developer Express VCL 布局管理器)。但我不相信他们中的任何一个。我怀疑 Embarcadero 应该将此作为当前 UI 组件集 (VCL) 中的一个关键弱点来解决。
我认为第三方组件集可能是您目前最快的解决方案。它是商业的,但并不昂贵。
http://www.devexpress.com/products/VCL/ExLayoutControl/
【讨论】:
现代 Delphi 版本是否已经支持这个主题? (XE 及以上) 不适用于高 DPI 显示器,这是根本问题,“大字体尺寸”实际上意味着高于 96 DPI 显示器,以及微软使用的“DPI hack”(假 DPI 放大字体)。以上是关于使对话框与“大字体”兼容。 [复制]的主要内容,如果未能解决你的问题,请参考以下文章
如何使 jquery 对话框与 themeroller 主题一起使用?