27

ユーザーが選択できるフォントのリストを作成しようとしています。関数を使用してこれを行っていEnumFontFamiliesExますが、残念ながら、返されるフォントのリストが長すぎます。別の言語では、取るに足らない、重複している、またはユーザーに表示するのが望ましくないように見える余分なフォントがたくさんあります。私のスクリーンショットは、私が除外しようとしているがらくたを最もよく示しています。

呼び出すための私のコードはEnumFontFamiliesEx次のようになります:

LOGFONT lf;
memset(&lf, 0, sizeof(lf));
lf.lfCharSet = DEFAULT_CHARSET;
// screenDC is result of CreateCompatibleDC(NULL)
EnumFontFamiliesEx(screenDC, &lf, GetFontsCallback, NULL, 0);

アルファベット順に並べ替え、顔の名前が重複しているフォントを削除すると、結果のリストは次のようになります。

ここに画像の説明を入力してください

ご覧のとおり、ChooseFontフォント共通ダイアログには、ユーザーフレンドリーで意味のある非常に合理的なフォントのリストが表示されています。一方、私のコードには、追加のフォントの長いリストが表示されます。「@」で始まるフォント(なぜですか?それらは何のためにあるのですか?)、Arialフォントの3つの追加のバリエーション、およびAheroniのような目的が不明な他のいくつかのフォントです。 Andalus、Angsana New、AngsanaUPCなど。それは非常識です。

ダイアログに表示されるリストと完全に一致するように、EnumFontFamiliesExによって返されるフォントのリストをフィルタリングするにはどうすればよいですか?ChooseFont

4

4 に答える 4

28

Jesse Good のおかげで、Windows 7 チームが行った非常に残念な設計上の決定について知ることができました。レジストリ キーがまだ存在しない場合でも、他の誰かが Windows 7 でこの非表示のフォント機能を使用する方法を思いついた場合 (たとえば、文書化されていない API を使用するなど)、私はまだ自分の答えを受け入れません。策略)そして彼らの答えがうまくいくなら、私はそれを受け入れます。

このフィルタリングは、Windows 7 のコントロール パネルで実際にフォントを「非表示」にすることによって行われます。デフォルトでは、他のロケールのフォントは非表示になっていますが、ユーザーが表示できます。少なくとも、これはアイデアです。この機能について説明している MSDN ページは次のとおりです: International Font Management

このページと MSDN の他の近くのページからの重要な抜粋を次に示します ( Windows のhttp://msdn.microsoft.com/en-us/library/windows/desktop/dd371704(v=vs.85).aspxも参照)。 7 互換クックブック):

Windows 7 以降、フォント管理インフラストラクチャは、ユーザーのフォント選択リストに適していないフォントの非表示をサポートしています。... この機能により、ユーザーは不適切なフォントの長いリストに直面する必要がなくなります。

Windows 7 には、非表示のフォントを直接照会したり、フォントを非表示に設定したりするための API はありません。[私の強調] 現在、Windows ChooseFont API (フォント共通ダイアログ) を使用してフォントの選択を有効にすると、新しい動作が無料で得られます。Windows 7 で導入された新しい Windows Scenic リボン (フォント コントロール) もこの動作をサポートし、アプリケーションを "リボン化" する別の理由を提供します。

フォントがデバイス コンテキストで選択されている場合、フォントが非表示になっているため、描画に影響はありません。EnumFontFamiliesEx 関数は、非表示に設定されているフォントを引き続き列挙します。[鉱山を強調; EnumFontFamiliesEx で隠しフォントと可視フォントを区別する方法はないようです]

文字セットは、Unicode 以前の文字セットに対応する従来の概念であることに注意してください。[鉱山を強調]

ChooseFont は、リスト ボックスにフォントを表示する際に、表示されているフォントのみを一覧表示し、非表示のフォントを除外します。CHOOSEFONT 構造体の flags メンバーに追加のフラグ (CF_INACTIVEFONTS) が追加され、Windows 7 より前の ChooseFont の動作と同じように、インストールされているすべてのフォントをフォント リストに表示できるようになりました。

つまり、ChooseFont 共通ダイアログまたは公式の Windows リボン コントロール (Windows Vista/7 でのみ使用可能) を使用しない限り、非表示のフォントを除外する方法はサポートされていません。インターネット上の多くのユーザーが、Windows 7 のコントロール パネルでフォントを非表示にしても効果がないように見えると不平を言っているのは驚きですか?!? (私は以前、MS Word 2010 が非表示のフォントをフィルター処理するという虚偽の投稿をしました。Windows に組み込まれているリボンではなく、独自のカスタム リボン コントロールを使用しているため、そうではないようです。Windows 7 のフォント コントロール パネルが設計上、は Microsoft の主力製品の 1 つと互換性がなく、Office のより強力なリボンを捨てずに互換性を持たせることはできません。)

Jesse Good が投稿したリンクに基づいて、非表示のフォントが文書化されていないレジストリ キーに格納されていることがわかりました。このリンク、および Process Monitor を使用したいくつかの実験と分析 (スタック トレースとレジストリ アクセスの両方を調べる) を通じて、次のことを学びました。

  • リボン コントロールは、FMS.DLL (Font Management Services) の FmsGetFilteredFontList と呼ばれる文書化されていない関数を呼び出します。その目的は明らかです。彼らが公に文書化して維持することを気にすることができなかったのは本当に残念です.
  • 設定は、FMS.DLL によってアクセスされる文書化されていないレジストリ キーに保存されます。
  • レジストリ キーが削除されると、FmsGetFilteredFontList によって既定の設定で再作成されます。これは、現在の入力言語に関連しないフォントを非表示にするためのものです。
  • Windows のクリーン インストールで作成された新しいユーザー プロファイルには、非表示にするフォントに関連するレジストリ キーは含まれていません。

したがって、Jesse Good によって投稿されたリンクは、多く/ほとんどの場合に機能する可能性がありますが、100% の場合ではありません。これらのレジストリ キーが存在しない場合は、確実に再作成する (または少なくとも既定値を想定する) 方法が必要です。既定の動作では、レジストリ キーがなくなっても (新しいユーザー プロファイルなど)、一部のフォントが非表示になります。

于 2012-06-29T17:17:41.340 に答える