Requires: Direct2D.lg32
Sets the current font for text operations.
D2SetFont D2Font
D2SetFont hFont
D2SetFont fontstring$
D2SetFont fname$ [, height! , weight%][,italic?][,stretch%] [,locale$]
hFont | : integer expression |
fname$, fontstring$, locale$ | : string expression |
height! | : float expression |
weight% | : integer expression |
italic? | : boolean expression |
stretch% | : integer expression |
D2SetFont sets the font to be used with D2Text and D2DrawText.
D2SetFont D2Font takes an object created with D2Font(). For performance reasons it might be useful to cache a D2Font object and later use it with D2SetFont in the drawing operations.
The second form - D2SetFont hFont - D2SetFont takes a GDI font handle and converts it into a D2Font (IDWriteTextFormat) object. hFont may specify a GDI stockfont constant. The properties of the GDI font are converted to Direct2D font-properties that are used then used to create the D2Font object (IDWriteTextFormat). Note that not using the first form a D2Font has to be created each time D2SetFont is executed.
The third form takes a fontstring$ argument containing all the parameters of the current font (similar to _Font$, but the format is different). The format of the string is “fontname, height!, weight%, italic?, strectch%,localename”; all parts are optional (i.e. “,20,400,,10,” is allowed) with the missing parts taken from the current font.
The fourth form requires a font description. The parameters are passed to IDWriteFactory::CreateTextFormat directly. Most parameters use default values, but the application needs to specify the font's name.
The height must be specified in DIPs (1/96 inch == 1 logical pixel) can be a value that's also used for GDI fonts. The parameter is optional and defaults to 11 DIPs, which conforms to the default size of the DEFAULT_GUI_FONT stock font.
The height can be calculated using the D2PointsToDips() function that converts the required size in points to DIPs.
The font weight defaults to a normal font, but it can be one of the following values:
Set the italics boolean parameter to True for an intalics font (default is off).
The default for the stretch parameter is a normal stretch, but it can take one of these values:
The localename$ may specify the locale name, like "en-us".
'
' Samples\Direct2D\D2SetFont.g32 (dpi-aware)
'
$Library "direct2d"
$Library "gfawinx"
DpiAwareness()
OpenW 1, 0, 0, 320, 300, 16 + 32
FormScaleForDpi(Me)
Global Object Win1RT
Set Win1RT = D2GetRT()
Global Float Width1, Height1 ' Use: for DPI change
D2GetSizeRT Win1RT, Width1, Height1
Global Object Fnt, FntBold ' cache the fonts
Set Fnt = D2Font("Gabriola", D2PointsToDIPs(13))
Set FntBold = D2Font("Gabriola", D2PointsToDIPs(13), DWRITE_FONT_WEIGHT_BOLD)
Do
Sleep
Until Me Is Nothing
Sub Win_1_Paint
D2BeginDraw Win1RT, D2C_White
D2SetFont Fnt ' high performance
D2Text 16, 16, "Hello Direct2D (Normal)"
D2SetFont FntBold
D2Text 16, 40, "DirectWrite (Bold)"
D2EndDraw
EndSub
Sub Win_1_ReSize
D2ResizeRT Win1RT, WorkWidth(), WorkHeight() ' size from adjusted window
EndSub
Sub Win_1_MessageProc(hWnd%, Mess%, wParam%, lParam%, retval%, ValidRet?)
Local Int dpi
If Mess% == WM_DPICHANGED
If FormScaleForDpi(Me, wParam%, lParam%) ' scale (resize) form and it's Ocx-es
' Here: Update other Dpi dependent resources (toolbar, bitmaps, Direct2D)
dpi = LoWord(wParam%) ' new Dpi for form
D2SetDpiRT Win1RT, dpi ' update D2 rendertarget's dpi
EndIf
retval% = 0 : ValidRet? = True ' tell OS we handled it
EndIf
EndSub
Function FormScaleForDpi(ByVal frm As Form, Optional newdpi As Int, Optional lParam As Int) As Bool
Local i As Int, c As Control, rc As RECT, prevDpi As Int, newrc As Pointer To RECT, _
tb As Tab, w As Int, h As Int
With frm
' Set initial newdpi for the form and the scale factors for a LoadForm
If .WhatsThisHelpID == 0
If Exist(":{" + .Name) ' a Form-Editor form
.WhatsThisHelpID = WinDpi(0) ' initial dpi is system newdpi
.ScaleWidth = .ScaleWidth * 96 / .WhatsThisHelpID ' set initial scale factors
.ScaleHeight = .ScaleHeight * 96 / .WhatsThisHelpID
Else ' created by OpenW or Form command
.WhatsThisHelpID = 96 ' coord space is 96
EndIf
EndIf
prevDpi = .WhatsThisHelpID
newdpi = LoWord(newdpi)
If newdpi == 0 Then newdpi = WinDpi(.hWnd)
Exit Func If newdpi == prevDpi ' don't continue if equal
' Size the form, except if it is a child window
If !(GetWindowLong(.hWnd, GWL_STYLE) %& WS_CHILD)
If lParam ' size to the OS suggested size
Pointer newrc = lParam ' ptr to RECT in lParam
SizeW .hWnd, newrc.Right - newrc.Left, newrc.Bottom - newrc.Top
Else ' scale based on the current client size
GetClientSize .hWnd, w, h ' can't use _X _Y, they are for ME only
AdjustW .hWnd, Scale(w, newdpi, prevDpi), Scale(h, newdpi, prevDpi)
EndIf
EndIf
.FontSize = .FontSize * newdpi / prevDpi
.ScaleWidth = .ScaleWidth * prevDpi / newdpi
.ScaleHeight = .ScaleHeight * prevDpi / newdpi
' Scale position and size of the Ocx windowed controls
For Each c In frm.Controls
If !(TypeOf(c) Is ImageList || TypeOf(c) Is Timer || _
TypeOf(c) Is CommDlg || TypeOf(c) Is TrayIcon) ' not the windowless OCX-es
' First set fontsize, but not all OCX-es have a Font property
If !(TypeOf(c) Is ProgressBar || TypeOf(c) Is Slider || TypeOf(c) Is Image || TypeOf(c) Is RichEdit)
c.fontsize = c.fontsize * newdpi / prevDpi
ElseIf TypeOf(c) Is RichEdit ' Requires LoadRichEdit50W!
SendMessage c.hwnd, WM_DPICHANGED, MakeLong(newdpi, newdpi), 0
EndIf
' Set new position and size for OCX-controls
GetWinPos(c.hwnd, rc) ' relative to parent
~SetWindowPos(c.hwnd, 0, _
Scale(rc.Left, newdpi, prevDpi), Scale(rc.Top, newdpi, prevDpi), _
Scale(rc.Right - rc.Left, newdpi, prevDpi), _
Scale(rc.Bottom - rc.Top, newdpi, prevDpi), SWP_NOZORDER) ' new pos and size
If TypeOf(c) Is Form ' Scale OCX-es of a child Form Ocx
c.WhatsThisHelpID = prevDpi
~FormScaleForDpi(c, newdpi)
ElseIf TypeOf(c) Is TabStrip ' Scale TabStrip's attached forms
For Each tb In c.Tabs
If TypeOf(tb.Ocx) Is Form
tb.Ocx.WhatsThisHelpID = prevDpi
~FormScaleForDpi(tb.Ocx, newdpi)
EndIf
Next
EndIf
EndIf
Next
.WhatsThisHelpID = newdpi ' store new newdpi
EndWith
FormScaleForDpi = True
EndFunc
NOTE: The above example will not run as it relies on an embedded file which is not present in the syntax. The programme with full resources can be found in GFABASIC/Samples/Direct2D/D2SetFont.g32.
If D2SetFont isn't used D2Text and D2DrawText will use the stock font DEFAULT_GUI_FONT.
A D2Font object does not require a render target and it is not a device-dependent resource like brush and bitmap. In addition, the global font setting isn't released in D2EndDraw. D2SetFont may be used outside the D2BeginDraw/D2EndDraw pair, for instance to calculate the textsize using D2TextSize. There is always one font object the current one; the font last set with D2SetFont.
D2SetFont invokes IDWriteFactory::CreateTextFormat which is part of DirectWrite. The IDWriteTextFormat object is used in the render target object method ID2D1RenderTarget::DrawText (used by D2Text and D2DrawText).
D2FontD2FontSize, D2FontBold, D2FontItalic, D2FontStretch, D2FontName, D2FontLocaleName,, D2GetFontObj, D2RFont, D2Text, D2DrawText, D2TextSize, D2PointsToDips
{Created by Sjouke Hamstra; Last updated: 03/03/2022 by James Gaite}