2

我发现 Win32 ChooseFont() API 的行为有些奇怪,更重要的是不一致。

LOGFONT lf = { 0 };
strcopy(lf.lfFaceName, m_face_name);
const int ppi = GetDeviceCaps(pView, LOGPIXELSY);
lf.lfHeight = -MulDiv(m_font_height, ppi, 72);
CFontDialog fd(&lf);
if (fd.DoModal() != IDOK)
    return;
m_face_name = fd.GetFaceName();
m_font_height = lf.lfHeight;

假设第一次,人脸名称是“Segoe UI”,这是可行的。

但是如果用户将对话框更改为“Segoe UI”、“Light”、“9”、(面部、样式、高度),并且我们再次执行上述操作,则字体选择常用对话框无法选择“ Segoe UI”作为人脸名称。相反,我将 Font: 字段设为空白。

如果用户选择“Regular”、“Italic”、“Bold”、“Bold Italic”的样式,这不是问题,因为这些样式存储在样式位中,并且不会混淆名称。我在第二次运行时丢弃它们,因为我忽略了它们(我会禁用字体样式:如果有一种方法可以轻松做到这一点 - 我不希望为此子类化 CFontDialog - 这是一个完整的“另一个时间级别”和此刻不允许的努力)。

我尝试根据对话框中的先前细节创建一种字体,然后尝试将 LOGFONT 拉出。没有骰子。

同样,我尝试在对话框中查询 FontStyle() - 但它返回空白 - 所以这里没有什么可以从字体名称中删除......

这似乎是 MS 对话框的一个错误 - 它告诉我一件事,但随后无法使用它自己的输出在第二次通过时正确初始化自身(当然,在这种情况下,我只是保留了部分而不是全部 LOGFONT )。

有谁知道 WTH 有这个想法吗?或者我可能会使用的一种方法(在字体名称末尾寻找“Light”的硬编码 - 太糟糕了!)?

4

2 回答 2

4

字体设计的发展已经大大超过了传统 api 跟上的能力。OpenType 发生了,其中之一。除了 LOGFONT 可以支持的字体样式之外,还有其他字体样式。对于 Segoe UI,控制粗体的属性可以是 Light 和 Semibold。对于其他字体,字体拉伸是另一个属性,常见的有 Condensed 和 Expanded。字体能够实现专用的字体文件以使这些样式看起来不错,而不是像过去那样依赖于从现有字体中合成样式。查看 WPF FontStretch 和 FontWeight 枚举类型以获取可能的值。

这些是 LOGFONT 无法表达的属性。有一个兼容性黑客来处理这个问题,类型面孔名称被映射。所以风格为“Light”的“Segoe UI”变成了“Segoe UI Light”。Windows 字体映射器将从这样的名称中选择正确的 true-type 字体文件。然而不起作用的是用“Segoe UI Light”初始化 LOGFONT.lfFaceName。实际上不知道为什么,可能避免不必处理歧义。或者只是简单的失败。一种可能的解决方法是在字体名称中识别这些附加的样式名称,但这也不完美。

GDI 的汽油用完了。很像 User32。

于 2012-06-02T00:57:06.193 回答
-1

首先,当您在 proc 中初始化 LOGFONT 时,不能只将其设置为 0

ala "= { 0 };"

使用类似的东西

memset(&lf, 0, sizeof(lf));

否则你的 lf 在你的 proc 中包含随机废话。其次,不保存LOGFONT结构的所有设置有什么大不了的?如果您使用的是 MFC,这并不是因为它的开销太大。如果修复 lf 的初始化不起作用,只需保存整个 LOGFONT。

于 2012-06-01T19:25:55.000 回答