调整字体和布局以实现跨 Windows 兼容性






4.07/5 (10投票s)
如何根据操作系统和主题默认值在 Windows 窗体中显示字体
引言
.NET 开发者在设计应用程序时可能会遇到的一个显著问题是,如何使其在任何最近的 Windows 平台(如 Windows 2000、Windows XP 和当前的 Windows Vista)上都能完美显示。在我将 Visual Studio 2005 安装在全新的 Windows Vista 系统上之前,我坦率地认为 .NET 运行时会自动解决这个问题。这确实是真的,但仅限于菜单和状态栏。如果您正在寻求 Windows 2000 和 XP 平台之间的兼容性,实际上并没有问题。然而,如果您希望在 Windows 2000/XP 和 Windows Vista 上实现完全相同的应用程序显示效果,问题会更加棘手。原因是 Windows Vista
- 使用新的默认字体(Segoe UI vs. Tahoma)
- 使用新的默认字体大小(9.25 vs. 8.25)
当然,在大多数情况下,为每个不同的操作系统设计多个不同版本是不可行的。我的目标是找到一种简单的方法来更新我的应用程序,以便根据 Windows 操作系统和主题显示正确的字体和大小,而无需完全重新设计它们。主要困难在于,新的 Vista 操作系统字体具有不同的尺寸和几何形状。
一个简单的方法
第一个想法很明显:如果用户正在运行 Vista,则将任何控件的字体更改为 SegoeUI 字体系列,大小为 9.25 点。比这更好的方法是询问 .NET 运行时,获取当前正在使用的 UI 的默认字体。这样,我们可以确信该解决方案将适用于任何过去和将来的操作系统和主题。因此,为了用正确的默认字体更新应用程序,我们可以使用 .NET 2.0 中引入的 SystemFonts
类。经过一些研究,我发现...
SystemFonts.MessageBoxFont
...在带有 Vista 主题的 Windows Vista 上默认为 Segoe UI 9.25,例如,在带有 XP 主题的 Windows XP 上默认为 Tahoma 8.25。如果我们不想重新设计我们的应用程序,我们可以应用一个初始化后的代码,它只需调整任何控件的字体。我们将其放在 Windows Forms 初始化代码的下方
InitializeComponent();
// Correct font
foreach (Control c in this.Controls)
{
c.Font = new Font(SystemFonts.MessageBoxFont.FontFamily.Name, 8.25f);
}
这种方法的缺点是我们会丢失在设计视图中对控件字体所做的任何修改。因此,例如,如果我们设置 Label 1 的字体为 粗体
,我们就会丢失此设置,而得到的是普通样式。更好的方法是以下方式
foreach (Control c in this.Controls)
{
Font old = c.Font;
c.Font =
new Font(SystemFonts.MessageBoxFont.FontFamily.Name,
8.25f, old.Style);
}
通过这样做,我们保留了关于控件字体的所有信息。我们可以仅修改字体系列,并获得通过 Visual Studio 窗体设计器等定义的字体大小和样式。如果不是因为 Windows Vista 现在默认使用 9.25 点字体大小,这可能是一个最佳解决方案。我们可以这样说:如果用户正在运行 Vista,则调整到 9.25,否则设置为 8.25 字体大小。这个伪算法的问题在于我们坚持使用特定的操作系统 - 在这种情况下是 Vista - 而忽略了用户可能拥有 Windows Vista,但她可能正在使用经典主题。在这种情况下,她的默认字体是 Tahoma 8.25。再次,我们使用 SystemFonts
来获得更通用的解决方案
foreach (Control c in this.Controls)
{
Font old = c.Font;
c.Font =
new Font(SystemFonts.MessageBoxFont.FontFamily.Name,
SystemFonts.MessageBoxFont.Size, old.Style);
}
自定义大小的控件
我们现在已经设计了一个解决方案,通过几行代码,就可以调整我们的应用程序,使其使用适合任何 Windows 操作系统和主题组合的正确默认字体。当我们在同一个窗体中使用不同或自定义字体大小时,会出现一个小问题,因为我们会更改窗体中任何控件的字体和大小。一种建议是将控件的 Tag
属性设置为某个值 - 例如,“custom” - 这样就可以跳过对控件的重新调整大小
foreach (Control c in this.Controls)
{
Font old = c.Font;
float size = c.Font.Size;
if (c.Tag == null)
{
size = SystemFonts.MessageBoxFont.Size;
}
c.Font =
new Font(SystemFonts.MessageBoxFont.FontFamily.Name,
size, old.Style);
}
更简单
上述方法的一个问题是它为窗体中的每个控件分配了一个新的 Font
对象。可能有一种更简单的方法,即设置窗体的默认字体。感谢 Georgi Atanasov 指出这一点
Font sysFont = SystemFonts.MessageBoxFont;
this.Font = new Font(sysFont.Name, sysFont.SizeInPoints, sysFont.Style);
在这种情况下,您窗体中的任何控件都会在任何主题上获得正确的字体并相应地进行更改。如果您不直接在代码或设计视图中修改控件的 Font
属性,此方法将起作用。换句话说,设置了 Font
属性的控件将保留其字体。如果我们只修改我们想要拥有不同于默认字体的控件的字体属性,这可能正是预期的行为。然而,通常情况下 - 尤其是在一个团队中,界面来自设计师而不是程序员时 - 情况并非如此,我们必须在任何主题上进行测试以确保结果。无论如何,这个最新的解决方案显然更优雅。
结论
Windows Vista 操作系统外观的巨大改变严重影响了现有应用程序。问题在于坚持旧的风格还是设计全新的用户界面。我的文章只是提出了一个小小的技巧,以避免重新设计,并提供一个遵循用户操作系统主题的用户界面。当然,这并不完全令人满意。例如,在从 8.25 点更改为 9.25 点大小时,标签的宽度和高度应进行调整,并且还需要进行许多其他小的修复。不过,我认为这可能是一个不错的起点。
历史
- 2007 年 6 月 29 日 -- 发布原文
- 2007 年 7 月 19 日 -- 更新文章