D2TextLayout command

Requires: Direct2D.lg32

Purpose

Draws the text layout (D2Layout) object at the given position using text formatting.

Syntax

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

Description

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.

Example

'

' 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

Remarks

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.

See Also

D2Layout, D2DefLayout, D2RLayout, D2SetRT, D2GetRT, D2BeginDraw, D2EndDraw, D2Text, D2DrawText

{Created by Sjouke Hamstra; Last updated: 03/03/2022 by James Gaite}