c++ - schriftgröße - schriften einbetten word




Zu viele Schriftarten beim Enumerieren mit der EnumFontFamiliesEx-Funktion (3)

Da FmsGetFilteredFontList nicht dokumentiert ist, sind die Optionen zum Abrufen der exakt gleichen Liste, die einem Benutzer in einem Windows 7+ ChooseFont-Dialogfeld angezeigt wird, möglicherweise eingeschränkt. Es ist jedoch möglich, eine gute Annäherung an die Standardschriftartenliste zu erzielen, indem nur dokumentierte APIs verwendet werden.

Ich habe etwas Ähnliches getan, um die Anzahl der Möglichkeiten für einen Algorithmus zu reduzieren, der automatisch eine geeignete Schriftart auswählt.

Mein Ansatz bestand darin, die Unicode-Unterbereichs-Bitmaske in FONTSIGNATURE , die beim Aufzählen der Schriftarten überprüft werden kann. Wenn Sie wissen, welche Unicode-Unterbereiche Sie benötigen, wird die Schriftart-Signatur Ihnen sagen, ob die aktuelle Schriftart es abdeckt. Wenn dies der Fall ist, fügen Sie es in die Liste ein. Wenn nicht, dann überspringen Sie es. Ich vermute, das ist wahrscheinlich ähnlich wie FmsGetFilteredFontList seine Standardliste erstellt.

Der Trick besteht darin, herauszufinden, welche Teilbereiche der Benutzer benötigt. In meinem Fall war es relativ einfach, weil ich genau wusste, welchen Text ich machen musste. Ich erstellte eine Zuordnung von Teilbereichen zu FONTSIGNATURE-Stil Bitmask-Werten basierend auf der documentation .

Ich habe die Codepunkte im zu rendernden Text gescannt, im Mapping nachgeschlagen und eine Zielbitmaske erstellt. Ich habe diese Zielbitmaske bitweise mit der in der Schriftart-Signatur für jede aufgezählte Schriftart verknüpft. Wann immer das Ergebnis der Ziel-Bitmaske entsprach, wusste ich, dass die Schriftart (wahrscheinlich) den Text unterstützen könnte. Für meine Anwendung benötigte ich alle Zielbits, um in der Schriftart vorhanden zu sein. Für Ihre Anwendung, ich denke, Sie möchten eines der Ziel-Bits.

Die Schriftart-Signatur-Bitmaske ist ein guter erster Schnitt bei welchen Zeichen die Schriftart bereitstellt. Sie können GetFontUnicodeRanges ganz sicher verwenden, aber ich fand, dass das nicht notwendig war und es war auch langsamer als nur die Schriftart-Signaturen zu überprüfen.

In Ihrem Fall hätten Sie vielleicht eine repräsentative Textzeichenfolge in der Sprache des Benutzers. Zum Beispiel aus dem Dokument, das sie bearbeiten, oder aus einer UI-Ressource, die übersetzt wurde. Sie könnten diesen Beispieltext scannen, um die Zielschriftart zu erhalten.

Wenn Sie beispielsweise einen englischen Text scannen, werden Sie feststellen, dass sich alle erforderlichen Zeichen im lateinischen Unterbereich befinden. Wenn Sie sich das Schriftarten-Applet in Windows 7 für einen englischen Benutzer ansehen (und zur Detailansicht wechseln), sehen Sie, dass die Spalte Einblenden / Ausblenden stark davon abhängt, ob Latin in der Spalte Designed for aufgeführt ist scheint eine textuelle Darstellung der Unicode-Unterbereichs-Bitmaske der Schriftart-Signatur zu sein.

Update : Ich habe gerade versucht, Zeichensätze mit DirectWrite zu nummerieren. Ich dachte, dass diese neuere API die Funktion zum Ausblenden von Schriftarten verarbeiten könnte. Leider gibt es alles zurück und hat keine Optionen (die ich finden kann), um versteckte Schriften herauszufiltern.

Ich versuche, eine Liste von Schriftarten zu erstellen, aus der der Benutzer auswählen kann. Ich mache das mit der Funktion EnumFontFamiliesEx , aber leider ist die Liste der zurückgegebenen Schriften viel zu lang. Es gibt viele zusätzliche Schriftarten, die frivol erscheinen, doppelt sind, für eine andere Sprache oder auf andere Weise unerwünscht für den Benutzer angezeigt werden. Mein Screenshot zeigt am besten den Müll, den ich herausfiltern möchte.

Mein Code für den Aufruf von EnumFontFamiliesEx sieht EnumFontFamiliesEx aus:

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

Die resultierende Liste sieht folgendermaßen aus, nachdem Sie alphabetisch sortiert und Zeichensätze mit doppelten Gesichtsnamen entfernt haben:

Wie Sie sehen können, zeigt der Dialog ChooseFont font common eine sehr vernünftige Liste von Schriftarten an, die benutzerfreundlich und sinnvoll ist. Auf der anderen Seite zeigt mein Code eine lange Liste von zusätzlichen Schriftarten: Schriftarten, die mit "@" beginnen (warum? Wofür sind sie überhaupt?), 3 zusätzliche Varianten der Arial-Schriftart und einige andere Schriftarten unbekannten Zwecks wie Aheroni, Andalus, Angsana neu, AngsanaUPC und so weiter. Das ist verrückt.

Wie EnumFontFamiliesEx ich die Liste der Schriftarten, die von EnumFontFamiliesEx werden, damit es genau mit der Liste übereinstimmt, die im ChooseFont Dialogfeld ChooseFont ?


Dank Jesse Good habe ich jetzt einige verrückte unglückliche Designentscheidungen des Windows 7-Teams kennengelernt. Ich werde meine eigene Antwort noch nicht akzeptieren, denn wenn jemand anders eine Möglichkeit findet, diese versteckte Schrift in Windows 7 zu verwenden, auch wenn der Registrierungsschlüssel noch nicht existiert (zB durch die undokumentierte API oder andere) Trickie) und ihre Antwort funktioniert, ich werde es akzeptieren.

Diese Filterung erfolgt durch das "Verstecken" von Zeichensätzen in der Windows 7 Systemsteuerung. Standardmäßig sind Schriftarten für andere Ländereinstellungen ausgeblendet, sie können jedoch vom Benutzer angezeigt werden. Zumindest ist das die Idee. Hier ist die MSDN-Seite, die dieses Feature behandelt: International Font Management .

Hier sind einige wichtige Auszüge dieser Seite und anderer naher Seiten in MSDN (siehe auch http://msdn.microsoft.com/en-us/library/windows/desktop/dd371704(v=vs.85).aspx von Windows) 7 Kompatibilitätskochbuch):

Ab Windows 7 unterstützt die Font Management Infrastructure das Ausblenden von Schriften, die nicht für die Schriftenauswahllisten eines Benutzers geeignet sind. ... Diese Funktion bedeutet, dass Benutzer nicht länger mit langen Listen unangemessener Schriftarten konfrontiert werden müssen.

In Windows 7 gibt es keine APIs zum direkten Abfragen, welche Schriftarten ausgeblendet sind, oder zum Festlegen von Schriftarten, die ausgeblendet werden sollen. [Hervorhebung meins] Wenn Sie die Windows ChooseFont API (Font common dialog) verwenden, um die Schriftauswahl heute zu aktivieren, erhalten Sie das neue Verhalten kostenlos. Das neue Windows Scenic Ribbon (Schriftsteuerelemente), das in Windows 7 eingeführt wurde, unterstützt dieses Verhalten ebenfalls und bietet einen weiteren Grund für das "Ribbonisieren" Ihrer Anwendungen.

Wenn eine Schriftart in einem Gerätekontext ausgewählt wird, hat dies keine Auswirkung auf das Zeichnen, da die Schriftart ausgeblendet ist. Die EnumFontFamiliesEx-Funktion zählt weiter Schriftarten, die auf ausgeblendet festgelegt sind. [Hervorhebung meiner; Es gibt anscheinend keine Möglichkeit, versteckte und sichtbare Schriften mit EnumFontFamiliesEx zu unterscheiden]

Beachten Sie, dass Zeichensätze eine ältere Idee sind, die Vor-Unicode-Zeichensätzen entspricht. [Betonung meiner]

ChooseFont listet nur die angezeigten Schriftarten auf und filtert die versteckten Schriftarten heraus, während die Schriftarten im Listenfeld angezeigt werden. Das zusätzliche Flag (CF_INACTIVEFONTS) im Flags-Element der CHOOSEFONT-Struktur wurde hinzugefügt, um Ihnen zu ermöglichen, alle installierten Schriftarten in der Schriftartenliste anzuzeigen, genauso wie ChooseFont sich vor Windows 7 verhielt.

Mit anderen Worten, es sei denn, Sie verwenden den gemeinsamen ChooseFont-Dialog oder das offizielle Windows-Menüband (nur unter Windows Vista / 7 verfügbar). Sie haben also keine Möglichkeit, verborgene Schriftarten herauszufiltern. Ist es eine Überraschung oder ein Wunder, dass sich viele Benutzer im Internet darüber beschweren, dass das Verstecken von Schriften in der Windows 7 Systemsteuerung scheinbar wirkungslos bleibt? (Ich habe vorher falsch gepostet, dass MS Word 2010 versteckte Schriften herausfiltert. Es scheint, dass es nicht, weil sie ihre eigenen benutzerdefinierten Ribbon-Steuerelement und nicht die in Windows integrierte Multifunktionsleiste verwenden. Es ist amüsant, dass die Windows 7 Font Control Panel, von Entwurf ist nicht kompatibel mit einem von Flaggschiff-Produkten von Microsoft und kann nicht kompatibel gemacht werden, ohne das leistungsfähigere Band in Office zu kippen.)

Basierend auf dem Link, den Jesse Good gepostet hat, habe ich gelernt, dass die versteckten Schriften in einem undokumentierten Registrierungsschlüssel gespeichert sind. Über diesen Link und einige Experimente und Analysen mit Process Monitor (mit Blick auf Stack-Traces und Registry-Zugriffe) habe ich Folgendes gelernt:

  • Die Multifunktionsleistensteuerung ruft eine undokumentierte Funktion namens FmsGetFilteredFontList in FMS.DLL (Font Management Services) auf. Ihr Zweck erscheint ziemlich offensichtlich. Es ist wirklich eine Schande, dass sie sich nicht darum kümmern, sie öffentlich zu dokumentieren und zu pflegen.
  • Die Einstellungen werden in einem undokumentierten Registrierungsschlüssel gespeichert, auf den von FMS.DLL zugegriffen wird.
  • Wenn der Registrierungsschlüssel gelöscht wird, wird er mit den Standardeinstellungen von FmsGetFilteredFontList neu erstellt, mit denen die Schriftarten ausgeblendet werden sollen, die sich nicht auf die aktuellen Eingabesprachen beziehen.
  • Ein brandneues Benutzerprofil, das bei einer Neuinstallation von Windows erstellt wird, enthält KEINE Registrierungsschlüssel, die sich darauf beziehen, welche Schriftarten ausgeblendet werden sollten.

Daher könnte der Link von Jesse Good für viele / die meisten Fälle funktionieren, aber nicht zu 100%. Sie benötigen eine Möglichkeit, diese Registrierungsschlüssel zuverlässig wiederherzustellen (oder zumindest Standardwerte zu übernehmen), wenn sie nicht vorhanden sind. Das Standardverhalten besteht weiterhin darin, einige Schriftarten auszublenden, auch wenn die Registrierungsschlüssel nicht mehr vorhanden sind (z. B. bei einem neuen Benutzerprofil).


Ich denke, die gesamte Diskussion hier ist irreführend.

Warum sollte es mich interessieren, welche Schriftarten von Microsoft ausgeblendet werden, wenn ich meinen Benutzern einen Schriftarten-Selektor anbiete? Und warum sollte ich alle Schriftarten ausblenden, die nach Meinung von Microsoft standardmäßig ausgeblendet sein sollten?

Was ist, wenn mein Benutzer nur eine dieser Schriftarten verwenden möchte, die Microsoft versteckt hat? Würde ich meinen Benutzer dazu bringen, zur Systemsteuerung zu gehen, um diese Schriftart zu verstecken?

Was, wenn eines Tages ein chinesischer Benutzer einen chinesischen Text auf einem englischen Windows schreiben möchte und die chinesische Schrift versteckt ist?

Ich denke, es gibt einen viel besseren Weg, um die große Menge von Schriften einzuschränken, die von EnumFontFamiliesEx() .

Ich habe meinen eigenen Schriftarten-Selektor geschrieben, der einen Schriftarten-Filter hat, der es dem Benutzer ermöglicht, die Gruppe von Schriftarten auszuwählen, die er verwenden möchte. Auf diese Weise verbirg ich nichts und gebe dem Benutzer die volle Macht und nicht Microsoft!

Der Benutzer möchte möglicherweise ALLE Schriftarten sehen! Manchmal benötigt man nur Arial Black oder Arial Narrow, obwohl Microsoft der Meinung ist, dass es versteckt sein sollte.

int CALLBACK EnumFontFamExProc(const LOGFONT* pk_Font, 
                               const TEXTMETRIC* pk_Metric, 
                               DWORD e_FontType, 
                               LPARAM lParam)
{
    if (e_FontType & TRUETYPE_FONTTYPE)
    {   
        // u32_Flags128 = DWORD[4] = 4 * 32 bit = 128 bit
        DWORD* u32_Flags128 = ((NEWTEXTMETRICEX*)pk_Metric)->ntmFontSig.fsUsb;

        if (u32_Flags128[13 / 32] & (1 << (13 % 32)))
        {
            // the font contains arabic characters (bit 13)
        }
        if (u32_Flags128[38 / 32] & (1 << (38 % 32)))
        {
            // the font contains mathematical symbols (bit 38)
        }
        if (u32_Flags128[70 / 32] & (1 << (70 % 32)))
        {
            // the font contains tibetan characters (bit 70)
        }
    }

Im Callback erhalten Sie ein 128-Bit-Flag, das genau definiert, welche Unicode-Bereiche von der Schriftart unterstützt werden.

Siehe http://msdn.microsoft.com/en-us/library/dd374090%28v=vs.85%29.aspx

Sie können diese 128 Bits verwenden, um die Anzahl der in der Schriftartenliste angezeigten Schriftarten zu filtern und zu reduzieren:





fonts