感谢Jesse Good的分享,我现在了解到Windows 7团队做出了一些糟糕的设计决策。我暂时不接受自己的答案,因为如果其他人想到了一种在Windows 7中使用这个隐藏字体功能的方法,即使注册表键不存在(例如通过使用未记录的API或其他诡计),并且他们的答案有效,我将接受它。
这种过滤是通过在Windows 7控制面板中实际“隐藏”字体来完成的。默认情况下,隐藏了其他语言环境的字体,但用户可以将它们显示出来。至少,这是这个想法。以下是讨论此功能的MSDN页面:国际字体管理。
以下是来自此页面和MSDN附近页面的一些关键摘录(也请参见Windows 7兼容性手册中的http://msdn.microsoft.com/en-us/library/windows/desktop/dd371704(v=vs.85).aspx):
从Windows 7开始,字体管理基础设施支持隐藏不适合用户字体选择列表的字体。......这个功能意味着用户不再需要面对不合适的字体列表。
在Windows 7中,没有直接查询隐藏字体或设置字体隐藏的API [我的强调]。如果您今天使用Windows ChooseFont API(字体常规对话框)启用字体选择,则会免费获得新行为。 Windows Scenic Ribbon(字体控件)在Windows 7中引入,也支持此行为,并提供了另一个理由“Ribbonize”您的应用程序。
当字体被选入设备上下文中时,字体隐藏不会影响绘图。 EnumFontFamiliesEx函数继续枚举设置为隐藏的字体。 [突出显示是我的; 显然无法使用EnumFontFamiliesEx区分隐藏和可见的字体]
请注意,字符集是与Unicode字符集之前相对应的传统概念。 [突出显示是我的]
ChooseFont仅列出显示的字体并过滤掉隐藏的字体,同时在列表框中显示字体。 CHOOSEFONT结构的标志成员中的附加标志(CF_INACTIVEFONTS)被添加以允许您在字体列表中显示所有已安装的字体,与Windows 7之前的ChooseFont行为相同。
换句话说,除非您使用ChooseFont公共对话框或官方的Windows功能区控件(仅适用于Windows Vista/7),否则您根本没有支持的方式可以过滤隐藏的字体。任何想隐藏Windows 7控制面板中的字体的用户都感到惊讶或疑惑吗?(我之前错误地发布了MS Word 2010过滤隐藏字体的消息。看起来它并没有,因为他们使用自己的自定义功能区控件而不是Windows内置的功能区。有趣的是,Windows 7字体控制面板不兼容Microsoft的旗舰产品之一,如果不删除Office中更强大的功能区,则无法使其兼容。)
根据Jesse Good发布的链接,我了解到隐藏的字体存储在一个不公开的注册表键中。通过这个链接,以及使用Process Monitor进行的一些实验和分析(查看栈跟踪和注册表访问),我了解到以下内容:
- 功能区控件调用FMS.DLL(字体管理服务)中的一个未公开函数FmsGetFilteredFontList。它的目的显而易见。真遗憾他们没能公开记录和维护它。
- 设置存储在一个不公开的注册表键中,FMS.DLL可以访问该键。
- 如果注册表键被删除,则由FmsGetFilteredFontList重新创建带有默认设置的注册表键,这些设置是隐藏与当前输入语言无关的字体。
- 在干净的Windows安装中创建的全新用户配置文件不包含任何与隐藏字体有关的注册表键。
因此,Jesse Good发布的链接可能适用于许多/大多数情况,但不是100%可靠。如果这些注册表键不存在,您需要一种可靠地重新创建这些键(或至少假定默认值)的方法。即使注册表键消失(例如在新用户配置文件上),默认行为仍然是隐藏某些字体。
ChooseFont
对话框等方面也是这样做的。 - James JohnstonScript
下拉菜单可能对应于ENUMLOGFONTEX
结构的elfScript
成员(http://msdn.microsoft.com/en-us/library/dd162627(VS.85).aspx)-我已经检查过了,大多数有问题的字体都有“西方”脚本。(即使需要对此进行某些过滤,也不清楚我应该从哪里获取要比较的字符串,因为我想知道用户当前的文化)。 - James Johnston