font gui w windows

0

Jak wyciągnąć aktualną nazwę podstawowego fonta gui w windows, czyli tego z okien dialogowych, oznaczanego symbolicznie 'MS shell Dlg'?

1.LOGFONT z GetObject nie działa - podaje nadal face name = 'MS shell Dlg'.
2. OUTLINETextMetrics - to samo...

  1. SystemParametersInfo - chyba też nie ma tam tego:
    https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-systemparametersinfoa

  2. GetSystemMetrics... też nie ma.
    https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsystemmetrics

Kiedyś to znalazłem, ale zapomniałem jaka to funkcja była.

0

Aktualną (Vista+) nazwą podstawowego fonta GUI jest Segoe UI o rozmiarze 9.
Nie trzeba go wyciągać, tak jest i już.

1

GetStockObject + DEFAULT_GUI_FONT

3

Ja może zacytuję oficjalną dokumentację:

a.png

Źródło:

https://docs.microsoft.com/en-us/windows/win32/uxguide/vis-fonts

Polecam poczytanie całych działów "Design basics" i "Guidelines", a wiele się wyjaśni.
Jest też tam link do PDF-a.

2

@Azarien: twoja odpowiedź jest całkowicie merytorycznie poprawna, ale nie jestem pewien, czy OP o to pytał. Moim zdaniem chodziło o coś innego - sytuację, w której uzytkownik zmieni sobie domyślny font systemowy na jakikolwiek inny - wtedy porada z Tahoma albo Segue nie będzie adekwatna.

0

Wiem jaki font jest używany: Segoe UI, co jest bardzo podobne do Tahoma (w XP chyba to było).

Chodzi o to że nie wiemy co w przyszłości wymyślą, np. 5 lat może to być inna czcionka.

Jest mi to potrzebne, bo chcę zmieniać rozmiar tej czcionki;
np. na dużych monitorach te literki są za małe dla słabiej widzących, zwykle dla starszych ludzi.

A gdy próbuję powiększać wprost ten: 'MS shell Dlg', czyli DEFAULT_GUI_FONT, wtedy jakoś źle to działa, niestety.

Np. gdy chcę go powiększyć z 8p na 9, wtedy nic się nie zmienia - zostaje 8.
A dla 10p powiększa poprawnie, ale to może być za duże.
Podobnie z 11 - robi się z tego 10...

Jakoś kulawo to działa: jakby tylko parzyste akceptuje.

1

Pobierz z jakiejś kontrolki statycznej font za pomocą WM_GETFONT.
Dostaniesz uchwyt HFONT.
Dalej GetObject() z tym uchwytem. Dostaniesz wypełnioną strukturę LOGFONT.
W tej strukturze chyba będziesz miał to, czego szukasz.
Możesz zmodyfikować pole lfHeight i wywołać CreateFontIndirect na tej strukturze. Dostaniesz nowy font (np. ze zmieniona wielkością).
Zauważ, że lfHeight może być dodanie i ujemne.

0

Tak nie działa, otrzymasz tam font z nazwą: 'MS shell Dlg'.

przykład:

font = Parent->HandleMessage(WM_GETFONT);

SelectObject(dc, font);
LOGFONT lf;

GetObject(lf);

lf.lfHeight = -MulDiv(9, GetDeviceCaps(dc, LOGPIXELSY), 72);

i tu są bzdury w tej strukturce lf, znacz 'MS shell Dlg', a nie faktyczna nazwa.

1

Aż z ciekawości sprawdziłem to.
I jest jak na zrzucie.

Tylko, że:

  1. Po co to wybierasz w kontekście? (po co SelectObject?). To nie ma nic wspólnego z kontekstem urządzenia. Masz pobrać GetObject() dla hFont.
    https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-getobject
    Może próbujesz GetCurrentObject() dla kontekstu?
  2. Najpierw sprawdź, czy kontrolka coś zwróciła. Użyj jakiejś kontrolki, która używa krojów sama z siebie (listView albo TreeView, mi zadziałało na ListView32).
    screenshot-20200629035758.png
0

Może to zależy od wersji Windowsa... mi na win7 inaczej to działa.

Generalnie GetObject zwraca LOGFONT z informacją, która była użyta do tworzenia fonta, a nie do tego który został utworzony finalnie.

Np. możesz zrobić tak:

lf.lfFaceName = ""; // brak nazwy !
lf.lfHeight = -6;
lf.quality = ,,,
itd.
...

no i CreateFont coś tam z tego i tak utworzy - nazwa będzie ustalona.

1

Ten mój zrzut z ekranu jest z Win7.
Pokaż cały kod, którym próbujesz to zrobić, bo czuję, że po prostu robisz to źle.
Poza tym, jak wiesz jak to działa, to czemu pytasz?

0

Albo niech @Stefan_3N gdzieś wrzuci i udostępni link do swojego EXE. Wtedy będzie pewność, że mamy takie same warunki do prowadzenia eksperymentu, a ewentualne różnice zależą od wersji systemu a nie od inaczej napisanego kodu.

0
  TEXTMETRIC tm;
   LOGFONT lf;

   TClientDC dc(HWindow);
   if( !rFont ) // rFont = new TFont((HFONT)Parent->HandleMessage(WM_GETFONT));
    {
      TFont *f = new TFont((HFONT)Parent->HandleMessage(WM_GETFONT)); // font z dialogu, czyli 'MS Shell Dlg'

//      dc.SelectObject(*f);
      f->GetObject(lf);
      delete f;

      lf.lfHeight = -MulDiv(9, GetDeviceCaps(dc, LOGPIXELSY), 72); // powiększam sobie z 8 na 9, lub 10...

      lf.lfWidth = 0; // szer. standardowa 

      strcpy(lf.lfFaceName, "Segoe UI"); // albo 'Tahoma' -> z tym jest ok, tyle że nie znamy poprawnej nazwy!

      rFont = new TFont(&lf);
    }

   dc.SelectObject(*rFont); // to jest konieczne do uzyskania textMetrics
   dc.GetTextMetrics( tm );

//   OUTLINETEXTMETRIC *po = (OUTLINETEXTMETRIC*)Buf;
//   dc.GetOutlineTextMetrics(1000, *po); tu są nadal bzdury...

   if( !BoldFont ) // wersja pogrubiona
    {
      rFont->GetObject(lf);

//    
      lf.lfWeight = FW_SEMIBOLD; // = 600; bold=700
      lf.lfWidth = 0; // szerokość domyśla 
   
  //    strcpy(lf.lfFaceName, "Tahoma"); z tym będzie ok.

      BoldFont = new TFont(&lf); // tworzy font, ale to jest do dupy...
    }
1

Powinieneś odczytać font z kontrolki, a nie z dialogu.
Wykonaj ten kod (on jest w WINAPI, ale jak wkleisz wprost gdzieś w Twój program, to też powinien się wykonać. hInstance, to globalna HINSTANCE)

HWND test=CreateWindow("SysTreeView32","",WS_POPUP, 0, 0, 800, 600, NULL, NULL, hInstance, NULL); //tworzysz kontrolkę tylko po to, żeby z niej odczytać krój
HFONT hFont=(HFONT)SendMessage(test, WM_GETFONT, 0, 0);
if(hFont){
	LOGFONT lf;
	GetObject(hFont, sizeof(lf), &lf);
	MessageBox(NULL, lf.lfFaceName, "", MB_OK);
}
DestroyWindow(test);
0

Tak też nie działa.

font = HandleMessage(WM_GETFONT); // z samej kontrolki w dialogu

i tu mam: font = 0, czyli nie ma go wcale!

0

Być może ta metoda działa w oknie, do którego jawnie tworzono font + SetFont,
co znaczy że gdzieś w kodzie było użyte jawnie: fontName = Segoe UI i + CreateFont.

Zatem w dialogach to raczej nie zadziała.

1

chyba znalazłem poprawne rozwiązanie - bez zbędnych akrobacji.
https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-getstockobject

"It is not recommended that you employ this method to obtain the current font used by dialogs and windows. Instead, use the SystemParametersInfo function with the SPI_GETNONCLIENTMETRICS parameter to retrieve the current font. SystemParametersInfo will take into account the current theme and provides font information for captions, menus, and message dialogs."

0

To jednak jest bzdura z tym Segoe.

Czcionka w dialogach - etykiety, napisy na przyciskach, itp.,
to nie jest wcale Segoe, ani Tahoma...

nie wiem co to jest - jest trochę inna... chyba Microsoft Sans Serif.

0

A jednak: tam jest faktycznie "Microsoft Sans Serif", a nie żadne Segoe!

przykład:


     lf.lfHeight = MulDiv(-9, GetDeviceCaps(dc, LOGPIXELSY), 72);
     strcpy(lf.lfFaceName, "MS Shell Dlg"); // domyślny font dla dialogów!

     lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;
     lf.lfQuality = PROOF_QUALITY;
//     lf.lfPitchAndFamily = FF_SWISS;
    }

   helvFont = CreateFontIndirect(&lf);

// pobieramy parametry tej czcionki
   dc.SelectObject(helvFont);
   TEXTMETRIC tm;
   dc.GetTextMetrics(tm);

// a teraz wyciskamy z tego faktyczną nazwę czcionki:
   OUTLINETEXTMETRIC *po = (OUTLINETEXTMETRIC*)buf;
   dc.GetOutlineTextMetrics(1024, *po); 

i tam to widać...

1

drobna uwaga: font 'Microsoft Sans Serif' jest zrypany.

https://ibb.co/GT77jRr

litera ł ma błędną szerokość dla rozmiaru: 13 i 19 (pikseli), co tam zaznaczyłem.

2

Nie wiem coś się czepił tego Sans Serif. To jest stary font. Microsoft od dawna zaleca Segoe UI (a wcześniej zalecał Tahomę).
Jeśli gdzieś widzisz Sans Serif to albo

  • źle widzisz
  • patrzysz na stary program
  • patrzysz na program nie stosujący się do zaleceń

W kodzie napisałeś:

strcpy(lf.lfFaceName, "MS Shell Dlg"); // domyślny font dla dialogów!

i się dziwisz że dostałeś Sans Serif. Tylko że jako nazwę fonta trzeba podać Segoe UI, a nie MS Shell Dlg. Widnieje to jak wół na obrazku który wkleiłem powyżej, a który w okrojonej formie przytoczę jeszcze raz:

a.png

Ponadto, Microsoft Sans Serif i MS Sans Serif to nie to samo.

0
#include <Windows.h>

int main()
{
    MessageBox(nullptr, L"Ciekawe co to za font.", L"Test", MB_OK);
}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
	<asmv3:application>
		<asmv3:windowsSettings>
			<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
			<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
		</asmv3:windowsSettings>
	</asmv3:application>
	<dependency>
		<dependentAssembly>
			<assemblyIdentity
				type="win32"
				name="Microsoft.Windows.Common-Controls"
				version="6.0.0.0"
				processorArchitecture="*"
				publicKeyToken="6595b64144ccf1df"
				language="*"
			/>
		</dependentAssembly>
	</dependency>
</assembly>

mb.png

0

screenshot-20200728165132.png

Tu masz porównanie: u góry jest Segoe, a na dole domyślny font dialogowy.

Widzisz różnicę?

1 użytkowników online, w tym zalogowanych: 0, gości: 1