In Win7 funktionieren einige Schriftarten nicht wie in Win2K / XP

Meine Frage ist, wie die Schriftartbehandlung geändert werden muss, um unter Windows 7 ordnungsgemäß zu funktionieren. Ich bin sicher, dass ich eine Annahme über etwas getroffen habe, das zuvor gültig war, aber nicht mehr gültig ist. Aber ich weiß nicht einmal, wo ich anfangen soll zu suchen! Ich bete, dass jemand helfen kann! Hier sind die Details, wie ich sie verstehe (ich habe diese Frage auch in einem Microsoft Windows-Entwicklerforum gepostet, aber sie beantworten sie nicht):

Ja, ich bin hinter der Zeit zurück (zum Teufel, ich schreibe immer noch WIN32-Code in einfachem C!). Ich habe eine 10 Jahre alte DLL geschrieben, die eine noch ältere DOS-Bildschirm-E / A-Bibliothek im Client-Bereich eines Fensters nachahmt. Selbstverständlich können nur Schriftarten mit fester Breite verwendet werden. Wenn einige der Programme, die die DLL verwenden, auf Windows 7 verschoben wurden, tritt ein merkwürdiges Flackern auf, wenn eine TRUE TYPE-Schriftart mit fester Breite verwendet wird (Bitmap-Schriftarten funktionieren immer noch einwandfrei) dass ein einzelnes Zeichen mit geschriebenExtTextOut ist breiter als es sein sollte. Ich habe die Messungen auf drei verschiedene Arten überprüft (mitGetTextExtentPoint32 auf einer Zeichenkette mit 132 Zeichen und Teilen durch 132 durch AufrufenGetTextMetrics und sogar mitGetCharABCWidths für alle 256 Zeichen) und alle stimmen darin überein, dass die Schrift die gleiche Breite hat. AberExtTextOut rendert das Hintergrundrechteck um ein oder zwei Pixel breiter als die Schriftbreite. Entweder als, oder es beginnt der Hintergrund, der ein oder zwei Pixel links von der in den Parametern angegebenen Position rendert [Ich nenne es so:ExtTextOut( hdc, r.left, r.top, ETO_OPAQUE, &r, &ch, 1, NULL ).] Und denken Sie daran, dass dieser EXAKT-Code unter Windows 2000, Windows XP und mit Bitmap-Schriftarten unter Windows 7 einwandfrei funktioniert - unter Windows 7 funktioniert er jedoch nicht mehr ordnungsgemäß mit TrueType-Schriftarten mit fester Breite.

Für alle, die nicht verstehen, was ich tun muss: Stellen Sie sich vor, Sie schreiben ein Zeichen pro Quadrat auf ein Blatt Millimeterpapier. Jedes Quadrat verwendet dieselbe Schriftart, kann jedoch eine andere Vordergrund- und / oder Hintergrundfarbe haben. ich benutzeTA_TOP|TA_LEFT Textausrichtung, da dies die einfachste und konsistent angewendete Ausrichtung ist, sollte für eine Schriftart mit fester Breite funktionieren.

Was ich sehe, ist, dass ExtTextOut ein größeres Hintergrundrechteck ausgibt, als ich in angegeben habeRECT * Parameter. Da das von mir bereitgestellte Rechteck aus der angegebenen Schriftgröße erstellt wird, sollte dies NIEMALS passieren - und dies geschah nie unter Windows XP und früher und nicht bei Bitmap-Schriftarten (dh .FON) unter Windows 7. entweder. Aber es passiert IMMER mit TrueType-Schriften mit fester Breite unter Windows 7. Dies ist der Fall, wenn EXACT SAME EXECUTABLE unter Windows 2000, Windows XP und Windows 7 (32 und 64) ausgeführt wird. Ich bin eher geneigt zu glauben, dass eine fundamentale Annahme, die ich zum Umgang mit Schriftarten unter Windows gemacht habe, nicht mehr zutrifft (nach 20 Jahren, in denen ich Software für Windows geschrieben habe).

Aber ich habe keine Ahnung, wie oder wo ich herausfinden soll, was das sein könnte! Bitte, bitte hilf mir!

--- änderung ---

Für alle Interessierten habe ich es geschafft, das zu umgehen, was ich für einen Fehler halte - bis ich die gegenteilige Dokumentation finde. Meine Problemumgehung besteht aus zwei Änderungen an meiner Bibliothek:

Verwenden Sie die von zurückgegebene GrößeGetTextExtentPoint32() von einem "X" anstelle von Daten ausTEXTMETRICS.Umfassen dieETO_CLIPPING Fahne in allenExtTextOut() Anrufe.

Zuvor habe ich verwendettmHeight+tmExternalLeading für die Anzahl der Pixel zwischen den Spitzen aufeinanderfolgender Textzeilen, wie dokumentiert. Ich entdeckte, dass der size.cy-Wert von derGetTextExtentPoint32() war nicht dasselbe und schien genauer. Das schlechteste Beispiel, das ich gefunden habe, war die OCRB-True-Type-Schriftart. Folgendes habe ich im Debugger für die OCRB-Schriftart gesehen, die ich erstellt hatte (mithilfe des Dialogfelds zur Auswahl der Systemschriftart):

ocrbtm.tmHeight          = 11
ocrbtm.tmExternalLeading =  7

ocrbsize.cy = 11

Aus irgendeinem Grund, den ich noch nicht herausgefunden habe, ignoriert Windows den für die OCRB-Schriftart definierten externen Leitwert. Die Verwendung des Größenwerts anstelle des TM führt zu schönem, ordentlichem, dicht gepacktem Text, genau das, was ich wollte.

DasETO_CLIPPING flag sollte für mich nicht notwendig sein, da ich das Rechteck auf genau die Maße eines einzelnen Zeichens setze und benutzeETO_OPAQUE Um den Hintergrund auszufüllen (und den vorherigen Zelleninhalt zu überschreiben). Ohne das Beschneidungsflag ist ein einzelnes Zeichen jedoch breiter als es die Größe, die Textmetrik oder die ABC-Breite angibt. Dies gilt zumindest für alle die dokumentation habe ich bisher gefunden.

Ich glaube, dass das HEIGHT-Problem schon lange besteht, aber der Rest war unnötig, bis wir unsere Software unter Windows 7 laufen ließen. Ich hänge dies an meine Frage an, um zu sehen, ob jemand erklären kann, was ich offensichtlich nicht verstehe.

- Änderungsantrag 2 -

1: Alle Unterlagen, die ich finden kann, sagen das austmHeight+tmExternalLeading sollte einzelne Textzeilen erzeugen. Zeitraum. Dies ist jedoch nicht immer der Fall, und ich kann keine Dokumentation finden, die angibt, wie Windows die verschiedenen Werte ermittelt, die manchmal von zurückgegeben werdenGetTextExtentPoint32().

2: unter Win7 (vielleicht Vista)ExtTextOut füllte etwas mehr Hintergrund aus, als es sollte (indem ein paar zusätzliche Pixel rechts hinzugefügt wurden), aber nur, wenn eine True Type-Schriftart ausgewählt wurde. Dies geschieht auch dann, wenn das Rechteck istdoppelt Die erwartete Größe des Zeichens (in BEIDEN Dimensionen) DPI / Skalierung mag ein Faktor sein, aber da mein System auf 100% eingestellt ist, scheint es, dass Windows Probleme mit einem 1: 1-Skalierungsfaktor hat und dies scheint sei ein Käfer. Die Tatsache, dass nur TrueType- und keine Bitmap-Schriftarten (.FON) betroffen sind, scheint auch die Skalierung auszuschließen (sofern nicht anders angegeben)ist ein Fehler im Skalierungssystem), da Windows versuchen sollte, den gesamten Text und nicht nur einen Teil davon zu skalieren. Außerdem ist im Dialogfeld "Benutzerdefinierte DPI-Einstellung" die Einstellung "DPI-Skalierung im Windows XP-Stil verwenden" grau (aber aktiviert). Schließlich ist dieses gesamte Problem möglicherweise das Ergebnis meiner Ausführung unter dem Windows Classic-Thema anstelle eines Aero-Themas oder eines anderen nativen Win7-Themas.

- Änderungsantrag 3 -

Das einfache Aufrufen von SetProcessDPIAware () hat keine Auswirkung auf das Problem, das ich habe. Da besteht mein Problem bei der 100% DPI Einstellung (Maßstab 1: 1), wenn mein Problem istist DPI-bezogen, dann muss ich einen Fehler in der DPI-Virtualisierung entdeckt haben, denn so beschreibt Microsoft das Feature:

Diese Funktion stellt der Anwendung "virtualisierte" Systemmetriken und Benutzeroberflächenelemente zur Verfügung, als würde sie mit 96 DPI ausgeführt. Die Anwendung wird dann auf eine Oberfläche außerhalb des Bildschirms mit 96 DPI gerendert, und der Desktop Windows Manager skaliert das resultierende Anwendungsfenster so, dass es mit der DPI-Einstellung übereinstimmt.

Alle meine Einstellungen zeigen, dass ich zu 100% skaliert bin, und ein Blick in das Feld für benutzerdefinierte Einstellungen zeigt deutlich, dass dies 96 DPI bedeutet. Wenn also die DPI-Virtualisierung von 96 DPI auf 96 DPI für meine TrueType-Schriftarten mit fester Breite nicht funktioniert, hat Windows ein Problem, oder? Oder muss ich eine Funktion aufrufen (oder den Anruf beenden?), Damit der DPI-Virtualizer ordnungsgemäß funktioniert?

Ich bin immer noch nicht davon überzeugt, dass das angebliche Skalierungsproblem tatsächlich so viel mit der Schriftgröße zu tun hat, wie ich ursprünglich dachte. Das liegt daran, dass sich das Problem in der. ManifestiertHintergrund Rechteck gefüllt durchExtTextOut() anstelle des gesendeten Textzeichens. Das Hintergrundrechteck wird ein wenig vergrößert, wenn die Schriftart der Typ true ist. Ich habe jetzt auch überprüft, ob dieses Problem bei Verwendung des Windows Classic-Designs oder des Standard-Windows Aero-Designs auftritt. Bauen Sie nun ein vereinfachtes Beispiel auf, damit andere damit experimentieren können.

- Änderungsantrag 4 -

Ich habe ein minimales Demo-Programm erstellt, das zeigt, was ich sehe (und was ich tue). Das Visual Studio 2010-Projekt / die Visual Studio 2010-Quelle kann von heruntergeladen werdenhttp://www.svalli.com/files/fwtt.7z - Ich habe absichtlich keine ausführbaren Dateien hinzugefügt, da ich nicht riskieren möchte, Malware zu verbreiten. Das Programm lässt Sie eine Schriftart mit fester Breite auswählen und schreibt dann zwei 5x5-Zeichenraster in den Client-Bereich, eines, das mit der Taste erstellt wurdeGetTextExtentPoint32 Größe und eine mit derTEXTMETRIC Größe wie von Microsoft dokumentiert. Die Gitter sind in einem schwarz-weißen Schachbrettmuster mit einem gelb-roten Zeichen als letztes in die Mitte geschrieben, um den Überlappungseffekt anzuzeigen (möglicherweise benötigen Sie ein Zoom-Dienstprogramm, um dies klar zu sehen.) Das Programm zeichnet auch eine Zeichenfolge, die mit 5 X beginnt Das Raster, beginnend mit dem gleichen Versatz links, dient als Vergleich für meine Methode zum Platzieren einzelner Zeichen (ich stimme mit der Zeichenfolge überein.) Über das Menü kann das Ein- und Ausschalten des Zuschneidens aktiviert bzw. deaktiviert werdenExtTextOut und Auswahl anderer Schriftarten. Es gibt auch eine Befehlszeilenoptiondpiaware (Groß- und Kleinschreibung beachten), durch die das Programm aufgerufen wirdSetProcessDPIAware() wenn es gestartet wird, so dass die Wirkung dieses Aufrufs auch ausgewertet werden kann.

Durch das Erschaffen habe ich das gelerntExtTextOut füllt das richtige Hintergrundrechteck aus, aber das Zeichen, das mit einem undurchsichtigen Hintergrund gerendert wird, ist möglicherweise breiter als es sein sollte und beginnt möglicherweise nicht einmal an der StelleExtTextOut wurde angewiesen, mit dem Zeichnen zu beginnen! Ich sagte "sollte sein", weil der Zeichenabstand, den ich bekomme, mit dem übereinstimmt, was ich bekomme, wenn ich habeExtTextOut einen ganzen String rendern. Die Überlappung kann sich anscheinend auf einer oder beiden Seiten des angegebenen Rechtecks ​​befinden. Beispielsweise fügt OCRB ein zusätzliches Pixel sowohl auf der linken als auch auf der rechten Seite der Zeichenzelle hinzu, während die anderen von mir ausgewählten TrueType-Schriftarten zwei Pixel rechts hinzufügen Kante.

Ich möchte das wirklich "richtig" machen, aber ich kann keine Dokumentation finden, die zeigt, was ich falsch mache oder was fehlt. Nun, ich vermisse wahrscheinlich etwas für DPI Aware bei anderen Maßstäben als 100%, aber ansonsten bin ich nur verblüfft.

- Änderungsantrag 5 -

Etwas weniger verblüfft ... das Problem wird von ClearType verursacht. Durch das Deaktivieren von ClearType funktionierten alle Schriftarten wieder. Das Aktivieren von ClearType unter XP verursacht dasselbe Problem. Anscheinend kann ClearType im Hintergrund (bis mir jemand sagt, wie man es erkennt) Zeichen horizontal um ein paar Pixel strecken, um Platz für die schattierten Pixel zu schaffen, die es hinzufügt, um die Dinge zu glätten.

Ist Clipping der einzige Weg, um dieses Problem zu umgehen?

- Änderungsantrag 6 -

Teilweise Antwort auf meine Beschneidungsfrage oben: Beim Erstellen einer neuen Schriftart führe ich jetzt Folgendes aus (in Pseudocode):

CreateFontIndirect
SelectFont
GetTextMetrics
if( (tmPitchAndFamily & TMPF_TRUETYPE) && Win6.x or above )
   if( SystemParametersInfo( SPI_GETCLEARTYPE ) )
        lfQuality = NONANTIALIASED_QUALITY
        DeleteObject( font )
        CreateFontIndirect

Ohne dies zu beschneidenfast funktioniert immer mit den von mir verwendeten Schriftgrößen, obwohl ich ein paar gefunden habe, die noch ein zusätzliches Pixel rechts (oder links) von der Zeichenzelle rendern. Glücklicherweise handelt es sich hierbei anscheinend um kostenlose Schriftarten, die im Internet gefunden werden. Daher liegt ihre Gesamtqualität möglicherweise unter den Standards professioneller Schriftgießereien.

Wenn jemand eine bessere Antwort finden kann, würde ich wirklich,JA WIRKLICH liebe es zu hören! Bis dahin denke ich, dass dies so gut ist, wie es nur geht. Vielen Dank fürs Lesen!

Antworten auf die Frage(1)

Ihre Antwort auf die Frage