Requires: Direct2D.lg32
Draws the text layout (D2Layout) object at the given position using text formatting.
D2TextLayout x!, y!, D2Layout [, format] [, param] [, D2Brush] [, options]
x!, y! | : float expression |
TextLayout | : Object variable |
format, param | : integer expression |
D2brush | : Object variable |
options | : integer expression |
D2TextLayout draws the formatted text described by the specified D2Layout object variable (IDWriteTextLayout object) at position x, y without clipping it to the layout rectangle (D2T_NOCLIP has no meaning to D2TextLayout). By default, if the text layout object extends the boundaries of the dimension specified with D2Layout() function it is drawn without clipping. To overrule the no-clipping behavior specify D2D1_DRAW_TEXT_OPTIONS_CLIP in the options parameter. See below.
The format argument specifies alignment, clipping, trimming, wrapping, text flow, and more. Because IDWriteTextLayout inherits from IDWriteTextFormat, the format parameter specifies the same values as with D2DrawText and can be one or more of the following D2T_* values. Depending on the format value additional information should be specified in the param argument:
D2T_LEFT(= DT_LEFT), D2T_CENTER(=DT_CENTER), D2T_RIGHT(=DT_RIGHT), D2T_JUSTIFIED | Text alignment, only one value can be specified. Invokes the IDWriteTextFormat::SetTextAlignment method. |
D2T_PARTOP, D2T_PARCENTER (= DT_VCENTER), D2T_PARBOTTOM (= DT_BOTTOM) | Paragraph alignment, only one value can be specified. Invokes the IDWriteTextFormat::SetParagraphAlignment method. |
D2T_TABSTOP (= DT_TABSTOP) | Sets tab stops. Set the hi-word of the additional parameter param to the number of pixels for the tab stop. Excludes the use of D2T_TRIMCHAR and D2T_TRIMWORD. Invokes the IDWriteTextFormat::SetIncrementalTabStop method. |
D2T_NOCLIP | Has no meaning to D2TextLayout since the text is drawn without clipping it to the layout rectangle. To overrule the no-clipping behavior specify D2D1_DRAW_TEXT_OPTIONS_CLIP in the options parameter. See below. |
D2T_PATH_ELLIPSES (= DT_PATH_ELLIPSIS) | Replaces characters in the middle of the string with ellipses so that the result fits in the specified rectangle. If the string contains backslash (\) characters, DT_PATH_ELLIPSIS preserves as much as possible of the text after the last backslash. Invokes the IDWriteTextFormat::SetTrimming method. May need to be combined with D2T_NOWRAP. Cannot be combined with another trimming option. |
D2T_END_ELLIPSES (= DT_END_ELLIPSIS) | Replaces characters at the end of the string with ellipses so that the result fits in the specified rectangle. Invokes the IDWriteTextFormat::SetTrimming method. May need to be combined with D2T_NOWRAP. Cannot be combined with another trimming option. |
D2T_TRIMCHAR, D2T_TRIMWORD | Sets trimming for text overflowing the layout rectangle. Additional information must be specified in the extra param. The hi-word specifies the character code to use as the delimiter that signals the beginning of the portion of text to be preserved. The lo-word specifies the delimiter count, counting from the end of the text, to preserve text from. Set the param value using MakeLong(charcode, count). Invokes the IDWriteTextFormat::SetTrimming method. Cannot be combined with D2T_PATH_ELLIPSIS or D2T_END_ELLIPSIS or D2T_LINESPACING or D2T_TABSTOP. |
D2T_READTOLEFT (= DT_RTLREADING), D2T_READTORIGHT | Sets the reading direction from right to left. Only one value can be specified. Invokes the IDWriteTextFormat::SetReadingDirection method. |
D2T_LINESPACING | Sets the linespacing for multiple line text. Actually, sets the line height, the distance between one baseline to another. Set the lo-word of the additional parameter to specify the height in pixels. Invokes the IDWriteTextFormat::SetLineSpacing method. Cannot be combined with D2T_TRIMCHAR or D2_TRIMWORD. |
D2T_NOWRAP (= DT_SINGLELINE) | Disables word wrapping, words are kept within the same line even when it overflows the layout box. Default is to wrap whole words. Invokes the IDWriteTextFormat::SetWordWrapping method. Cannot be combined with D2T_WORDWRAP. |
D2T_WORDWRAP (= DT_WORDBREAK) | Sets the word wrapping option, words are broken across lines to avoid text overflowing the layout box, this is the default behavior. Invokes the IDWriteTextFormat::SetWordWrapping method. Cannot be combined with D2T_NOWRAP. |
D2T_FLOWDOWN, D2T_FLOWUP, D2T_FLOWTOLEFT, D2T_FLOWTORIGHT | Sets the paragraph flow direction. Only one value can be specified. Invokes the IDWriteTextFormat::SetFlowDirection method. |
The optional D2brush argument specifies a brush object to draw with. If omitted, a solid color brush based on the foreground color is used.
The optional options argument can be a combination of the DWRITE_DRAW_TEXT_OPTIONS constants:
D2D1_DRAW_TEXT_OPTIONS_NONE = 0x00000000 (Default for D2TextLayout) | Text is snapped to pixel boundaries and not clipped, the text will be drawn outside the dimension specified with D2Layout(). |
D2D1_DRAW_TEXT_OPTIONS_NO_SNAP = 0x00000001 | Do not snap the baseline of the text vertically. |
D2D1_DRAW_TEXT_OPTIONS_CLIP = 0x00000002 | Clip the text to the content bounds. Specify this when the text layout object must be clipped to dimension specified with D2Layout. D2T_NOCLIP is ignored with D2TextLayout. |
D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT = 0x00000004 | Render color versions of glyphs if defined by the font. |
D2D1_DRAW_TEXT_OPTIONS_DISABLE_COLOR_BITMAP_SNAPPING = 0x00000008 | Bitmap origins of color glyph bitmaps are not snapped. |
'
' Samples\Direct2D\D2TextLayout.g32 (dpi-aware)
'
$Library "direct2d"
$Library "gfawinx"
DpiAwareness()
OpenW 1, 0, 0, 300, 300, 48
FormScaleForDpi(Me)
Global Object RT1
Set RT1 = D2GetRT()
' Build a Text Layout object for a given text
Global Txt1$ = "Hello DirectX" #10 "This is GB" #10 "(GFABASIC 32)"
D2SetFont "Gabriola", 18 ' set a base font for TextLayout
' Obtain TextLayout for text with current font.
' If Txt1 or dimension changes recreate the TextLayout object.
Global oTL1 As Object
Set oTL1 = D2Layout(Txt1$, 100, 60)
' Set font data for text ranges
D2DefLayout oTL1, 0, 5, D2TL_FONTNAME, "Courier New"
D2DefLayout oTL1, 0, 5, D2TL_UNDERLINE, True
D2DefLayout oTL1, 0, 5, D2TL_STRIKETHRU, True
D2DefLayout oTL1, 0, 5, D2TL_FONTSIZE, 12
Do
Sleep
Until Me Is Nothing
Sub Win_1_Paint
D2BeginDraw RT1, D2C_WhiteSmoke
Local w!, h!
D2TextSize oTL1, w!, h!
D2SetFont DEFAULT_GUI_FONT ' for D2Text
D2Text 0, 0, "TextLayout's dimension:" + Str(w!) + " x" + Str(h!)
D2TextLayout 10, 10, oTL1 ' no clipping
D2EndDraw
EndSub
Sub Win_1_ReSize
D2ResizeRT RT1, WorkWidth(), WorkHeight()
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 RT1, 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
Use D2DefLayout to set the formatting on specific text ranges of a D2Layout object.
As with all drawing operations, D2TextLayout must be embedded between D2BeginDraw and D2EndDraw. D2TextLayout invokes the ID2D1RenderTarget::DrawTextLayout method.
For more information on formatting text see here.
D2Layout, D2DefLayout, D2RLayout, D2SetRT, D2GetRT, D2BeginDraw, D2EndDraw, D2Text, D2DrawText
{Created by Sjouke Hamstra; Last updated: 03/03/2022 by James Gaite}