[WinAPI] Muss man Dialogen Schriftarten mitgeben?

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

[WinAPI] Muss man Dialogen Schriftarten mitgeben?

Beitrag von Krishty »

Hi,

ich habe einem Dialog einen Button hinzugefügt. Nicht über den Ressource Editor, sondern über die minimale DLGITEMTEMPLATE-Datenstruktur. Und so sieht er aus:
dlg bad font.png
dlg bad font.png (1.87 KiB) 5988 mal betrachtet
Windows 95 ftw! Ist das normal so? Ich erreiche nach Google-Copy-Paste das beabsichtigte Verhalten, wenn ich dem Dialog eine Schriftart hinzufüge (DS_SHELLFONT mit 8 pt und MS Shell Dlg).

Nun bin ich aber stutzig, ob man das tatsächlich überall machen muss, oder ob ich was falsch gemacht habe und deshalb leide – und ob DS_SHELLFONT überhaupt eine Lösung ist und das nicht nur durch Zufall funktioniert …?

tl;dr: Wie kriege ich hin, dass mein Button aussieht wie alle anderen auch?
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [WinAPI] Muss man Dialogen Schriftarten mitgeben?

Beitrag von Krishty »

Okay; in der MSDN steht:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644994(v=vs.85).aspx#fonts hat geschrieben:Dialog Box Fonts
The system uses the average character width of the dialog box font to calculate the position and dimensions of the dialog box. By default, the system draws all text in a dialog box using the SYSTEM_FONT font.
Ja; sehen wir.
To specify a font for a dialog box other than the default, […] set the DS_SETFONT or DS_SHELLFONT style and specify a point size and a typeface name. Even if a dialog box template specifies a font in this manner, the system always uses the system font for the dialog box title and dialog box menus.
Mhmm
The system font can vary between different versions of Windows. To have your application use the system font no matter which system it is running on, use DS_SHELLFONT with the typeface MS Shell Dlg,
Det hebick sou jemacht!
and use the DIALOGEX Resource instead of the DIALOG Resource.
Ups.

Ich schreibe meinen Kram auf Extended Dialog Resources um und melde mich dann zurück.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: [WinAPI] Muss man Dialogen Schriftarten mitgeben?

Beitrag von CodingCat »

Ich habe WinAPI schon sehr lange nicht mehr angerührt, aber so hatte ich das früher in meinen Programmen gelöst:

Code: Alles auswählen

HFONT systemFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT);
SendMessage(hWnd, WM_SETFONT, (WPARAM) systemFont, TRUE);
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [WinAPI] Muss man Dialogen Schriftarten mitgeben?

Beitrag von Krishty »

Wiebitte? Lösungen, die ausführbaren Code erfordern? Mach dich nicht lächerlich ;)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Helmut
Establishment
Beiträge: 237
Registriert: 11.07.2002, 15:49
Wohnort: Bonn
Kontaktdaten:

Re: [WinAPI] Muss man Dialogen Schriftarten mitgeben?

Beitrag von Helmut »

Habe grad in nem alten Code von mir geschaut wo ich einen Dialog dynamisch aufbaue. Ich benutze da zwar DS_SETFONT statt DS_SHELLFONT, aber setze den Font auch auf "MS Sans Serif". Warum weiß ich aber nicht... Ich würd das einfach so lassen bis das Projekt groß genug ist um in esoterische Sprachen übersetzt zu werden und dann einfach mal schauen obs Probleme mit dem Font gibt. Würde mich aber wundern, wenn Windows dann nicht automatisch nen anderen Font wählt.
Statt mit DLGITEMTEMPLATE rumzufummeln kann man übrigens auch einfach CreateWindow mit "BUTTON" als Klasse benutzen.
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [WinAPI] Muss man Dialogen Schriftarten mitgeben?

Beitrag von Krishty »

Helmut hat geschrieben:Habe grad in nem alten Code von mir geschaut wo ich einen Dialog dynamisch aufbaue. Ich benutze da zwar DS_SETFONT statt DS_SHELLFONT, aber setze den Font auch auf "MS Sans Serif". Warum weiß ich aber nicht... Ich würd das einfach so lassen bis das Projekt groß genug ist um in esoterische Sprachen übersetzt zu werden und dann einfach mal schauen obs Probleme mit dem Font gibt.
Nein danke. Ich arbeite auf meinem anderen PC mit großen Schriftarten und nachts auch mit anderen Desktop-Themas, und ich habe keine Lust, mein „groß genuges“ Projekt dann wegen so einem Detail halb neu zu schreiben.
Würde mich aber wundern, wenn Windows dann nicht automatisch nen anderen Font wählt.
Tut es sogar mit MS Shell Dlg nicht; ich hab’s eben getestet :)
Statt mit DLGITEMTEMPLATE rumzufummeln kann man übrigens auch einfach CreateWindow mit "BUTTON" als Klasse benutzen.
Schon wieder ausführbarer Code, bah. Außerdem musst du dann noch Dialog Units in Pixel umrechnen usw usf. Ich bastle meine GUI lieber statisch zusammen und rufe zur Laufzeit nur CreateDialogIndirectParamW() auf.
Zuletzt geändert von Krishty am 07.06.2013, 22:07, insgesamt 1-mal geändert.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Helmut
Establishment
Beiträge: 237
Registriert: 11.07.2002, 15:49
Wohnort: Bonn
Kontaktdaten:

Re: [WinAPI] Muss man Dialogen Schriftarten mitgeben?

Beitrag von Helmut »

Okay, eine Suche nach WM_SETFONT hat gerade ergeben, dass ich das auch so wie CodingCat gemacht habe.
Kann übrigens jedem nur raten das dynamische Erstellen von Dialogen zu vermeiden. Das ist einfach nur ne Quälerei.
Helmut
Establishment
Beiträge: 237
Registriert: 11.07.2002, 15:49
Wohnort: Bonn
Kontaktdaten:

Re: [WinAPI] Muss man Dialogen Schriftarten mitgeben?

Beitrag von Helmut »

Krishty hat geschrieben:
Würde mich aber wundern, wenn Windows dann nicht automatisch nen anderen Font wählt.
Tut es sogar mit MS Shell Dlg nicht; ich hab’s eben getestet :)
Soweit ich weiß ersetzt Windows die Schriftart auch nur, wenn man die entsprechende Windowsversion benutzt. Also zB mit einem Font mit arabischen und den üblichen lateinischen Zeichen, wenn man die arabische Sprache in Windows aktiviert hat. Anders geht es nicht, weil kein Font alle Unicodezeichen enthalten kann.

Wenn du deine GUI statisch basteln willst sparst du dir mit dem Resourceneditor viel Nerven.
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [WinAPI] Muss man Dialogen Schriftarten mitgeben?

Beitrag von Krishty »

Helmut hat geschrieben:
Krishty hat geschrieben:
Würde mich aber wundern, wenn Windows dann nicht automatisch nen anderen Font wählt.
Tut es sogar mit MS Shell Dlg nicht; ich hab’s eben getestet :)
Soweit ich weiß ersetzt Windows die Schriftart auch nur, wenn man die entsprechende Windowsversion benutzt. Also zB mit einem Font mit arabischen und den üblichen lateinischen Zeichen, wenn man die arabische Sprache in Windows aktiviert hat. Anders geht es nicht, weil kein Font alle Unicodezeichen enthalten kann.
Ja; du hast recht. Eine Erklärung dafür habe ich auch von jemand Bekanntem auf StackOverflow gefunden:
http://stackoverflow.com/questions/7219213/system-default-dialog-font hat geschrieben:How do you know that your dialog is compatible with the metrics of an unknown font? What if the users font has metrics that result in your template generating a dialog with truncated text? – Raymond Chen Aug 28 '11 at 15:38
Ich suche mal weiter, wie ich die Dinger von der Schriftart unabhängig kriege.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [WinAPI] Muss man Dialogen Schriftarten mitgeben?

Beitrag von Krishty »

Cat, deine Lösung setzt wohl auch den Standard-Windows-GUI-Font und nicht den, den der Benutzer eingestellt hat. Außerdem wird dringend davon abgeraten (The Old New Thing – What are SYSTEM_FONT and DEFAULT_GUI_FONT?). Die bessere Lösung ist wohl

    NONCLIENTMETRICS metrix; metrix.cbSize = sizeof metrix;
    SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &metrix, 0);
    hFont = CreateFontIndirectW(&metrix.lfMessageFont);
Zuletzt geändert von Krishty am 14.05.2014, 11:15, insgesamt 1-mal geändert.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [WinAPI] Muss man Dialogen Schriftarten mitgeben?

Beitrag von Krishty »

Okayokay. Um ein Bisschen Ordnung ins Wirrwarr zu bringen:

Windows 7 selber ist inkohärent in benutzerdefinierten Schriftarten. Manchmal werden sie benutzt, manchmal nicht:
fontwirrwarr.png
Falls man an die benutzerdefinierte Schriftart unbedingt rankommen will:

    NONCLIENTMETRICS metrix; metrix.cbSize = sizeof metrix;
    SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &metrix, 0);
    hFont = CreateFontIndirectW(&metrix.lfMessageFont);


Aber Windows macht es, wie gesagt, meist selber nicht. Es wird davon abgeraten weil man nicht im Voraus alle Dialoge mit allen benutzerdefinierten Schriftarten testen kann.* Heutzutage geht es wohl so, dass man alles mit der symbolischen Schriftart Microsoft Sans Serif füllt. Die wird über Windows’ internes Font Mapping zu Tahoma aufgelöst. So macht es auch Visual Studios Resource Editor, wie Helmut schon erwähnte. Nachtrag: Quatsch; ich habe meine Quelle missverstanden. Siehe weiter unten.

MS Shell Dlg 2 ist für Programme da, die für Windows 2000 bis XP ausgelegt sind**: Im Augenblick und auf westlichen Systemen wird es immer zu Tahoma. Auf Systemen exotischer Sprache wird die nächstbeste Schriftart gewählt (z.B. MS UI Gothic auf japanischen Systemen, weil Tahoma nicht alle Zeichen darstellen kann). Weil die letzten Informationen, die ich dazu finden konnte, von 2006 sind, denke ich, dass es auch heute noch die erste Wahl sein sollte.

MS Shell Dlg war für Programme da, die sowohl unter Windows 95, 98, als auch NT und 2000 liefen**: Unter Windows 95, 98, und NT wird sie zu MS Sans Serif aufgelöst; auf Windows 2000 hingegen zu Tahoma (weil das damals die neue Windows-Standardschriftart wurde). Programme, die das benutzen, sehen also sowohl unter Windows 95 und 98, als auch unter 2000 „aktuell“ aus. Von der Benutzung wird abgeraten, falls das Programm auf Windows 95 und 98 verzichtet.

GetStockObject(DEFAULT_GUI_FONT) war bereits beim Erscheinen von Windows 95 deprecated***.

* How do you know that your dialog is compatible with the metrics of an unknown font? What if the users font has metrics that result in your template generating a dialog with truncated text? – Raymond Chen Aug 28 '11 at 15:38 (http://stackoverflow.com/questions/7219 ... ialog-font)
** Overview of MS Shell DLG and FontSubsitutes (http://support.microsoft.com/kb/282187/en-us)
*** Raymond Chen: What are SYSTEM_FONT and DEFAULT_GUI_FONT? (http://blogs.msdn.com/b/oldnewthing/arc ... 36435.aspx)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [WinAPI] Muss man Dialogen Schriftarten mitgeben?

Beitrag von Krishty »

Sooo; noch mehr zum Thema findet sich bei Michael Kaplan. Leider hat er alles kreuz und quer durcheinandergepostet, aber ich hoffe, dass ich alle wichtigen Dinge gefunden habe:
Quintessenz:

Es ist unmöglich, einen Dialog zu definieren, der sich von Windows 95 bis Windows 8 jeweils dem visuellen Stil anpasst. Man muss entweder für jede Shell-Generation eine eigene Version anlegen, oder ein auf dem kleinsten gemeinsamen Nenner basierendes, völlig eigenständiges Aussehen nutzen (wie z.B. Office).

Man kann mit den logischen Fonts die Symptome aber zumindest lindern (wenn man Benutzereinstellungen ignoriert):
  • DS_SHELLFONT mit MS Shell Dlg wählt auf Windows 95, 98, NT 4.0, ME, und 2000 jeweils die „richtige“ Schriftart.
  • DS_SHELLFONT mit MS Shell Dlg 2 wählt auf Windows 2000 und XP jeweils die „richtige“ Schriftart.
  • Die beiden Flags sorgen außerdem dafür, dass auf asiatischen Systemen eine Schriftart gewählt wird, die mit dem Rest der Shell konsistent ist. Ab Vista könnte das durch die verbesserte Unicode-Unterstützung bedeutungslos sein, aber das mutmaße ich jetzt bloß.
Falls man will, dass seine GUI auf jeder Shell gut aussieht, muss man SystemParametersInfo() bemühen und alle Dialogauslegungen zur Laufzeit anhand der verwendeten Schriftart berechnen. Es ist aber nahezu unmöglich, das für jede Situation zu testen, und darum wird es nicht empfohlen (und von niemandem gemacht).

Die Schriftarten pro Windows-Version sind:

    Windows 3.1    System
    Windows 95     MS Sans Serif
    Windows NT 4   MS Sans Serif
    Windows 98     MS Sans Serif
    Windows ME     MS Sans Serif
    Windows 2000   Tahoma
    Windows XP     Tahoma
    Windows Vista  Segoe UI
    Windows 7      Segoe UI
    Windows 8      Segoe UI 2
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [WinAPI] Muss man Dialogen Schriftarten mitgeben?

Beitrag von Krishty »

Ich bin euch meine endgültige Lösung schuldig geblieben, darum trage ich hier nach:
  • MS Shell Dlg 2 als Dialogschriftart setzen
  • DS_SHELLFONT immer setzen
  • ???
  • PROFIT!!!
13-10-04 Windows dialog fonts.png
Man sieht z.B. beim Vergleich von XP und 7 jeweils mit klassischer Oberfläche (kleines e), dass die Schriftart der restlichen GUI vernünftig angepasst wurde.

Wo ich noch nicht ganz hinter gekommen bin, das ist die Übergabe von ANSI_CHARSET an den Dialog. Ob das so richtig ist, und welche Auswirkungen es auf verschiedenen Windows-Systemen auf die Schriftart hat, kann ich nicht sagen. Auf Windows 7 funktioniert aber z.B. Chinesisch trotzdem ausgezeichnet. Ich benutze ausschließlich die W- (also UTF-16-)Version der WinAPI; vielleicht hat der Zeichensatz ja darauf keine Auswirkung.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
Beiträge: 8238
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [WinAPI] Muss man Dialogen Schriftarten mitgeben?

Beitrag von Krishty »

Falls noch jemand zwischen Pixeln und Dialogeinheiten hin- und herkonvertieren muss und sich dabei in einem Fenster befindet, das kein Dialog ist:
  • GetDialogBaseUnits() war für Windows 3.1 entworfen und liefert dementsprechend die Maße des uralt-System-Fonts
  • MapDialogRect() funktioniert nur mit Dialogen
  • SystemParametersInfo(SPI_GETNONCLIENTMETRICS) ist nutzlos, weil die Textbreite Null ist
  • GetTextMetrics() ist die Funktion der Wahl, aber nur für die Höhe – die Breite ist falsch
  • KB 145994 erklärt, wie’s richtig geht (und man will sich lieber in den Kopf schießen, als das wirklich zu tippen) – via GetTextExtentPoint32()
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Antworten