In my app “RealCADD”, I add rich text feature via TextArea and StyledText.
All is good except the Font.Leading which is unknown for desktop app.
And I have some offsets between the text drawn and the text edited in a TextArea, example :
Use graphics.TextHeight (the version for wrapped text) to find the height of the block and divide? It’s not perfect. If you have mixed fonts and font sizes, for example, you’ll have to calculate it for the one you are interested in.
It sounds like you want to control this, though, so I think you’ll need to draw each line separately rather than using a wrapped DrawText(). This way you determine the leading by setting the baseline for drawing each line.
Thank you Matthew for your response but it is not what I want.
At the right of the picture above, it is what I draw with RealCADD.
And at the left, the same text in a TextArea.
There is a difference because I don’t know the leading used in the TextArea and, so, this value is missing in my drawing.
If this is macOS then you can probably do it by accessing the CoreText properties.
Here is a very basic example I created using the MBS plugins that should work when all text has the same style.
To use the example code:
• Add a TextArea named TextArea1 onto a window with some text that uses a single style. Make sure the text doesn’t soft wrap as the example code doesn’t handle it.
• Add a Canvas and put this example code into the Paint event.
Dim nsTextViewObj As NSTextViewMBS
Dim nsAttributedStringObj As NSAttributedStringMBS
Dim nsFontObj As NSFontMBS
Dim fontHeight As Double
Dim tempPicture As Picture
Dim stringHeight As Double
nsTextViewObj = TextArea1.NSTextViewMBS
nsAttributedStringObj = nsTextViewObj.layoutManager.attributedString
nsFontObj = nsAttributedStringObj.attributeAtIndex(NSAttributedStringMBS.NSFontAttributeName, 0)
fontHeight = nsFontObj.boundingRectForFont.Height
'determine the height of one line without spacing (for comparison)
tempPicture = New Picture(1, 1)
tempPicture.Graphics.TextFont = TextArea1.StyledText.Font(1, 1)
tempPicture.Graphics.TextSize = TextArea1.StyledText.Size(1, 1)
tempPicture.Graphics.Bold = TextArea1.StyledText.Bold(1, 1)
tempPicture.Graphics.Italic = TextArea1.StyledText.Italic(1, 1)
stringHeight = Ceil(tempPicture.Graphics.StringHeight(Mid(TextArea1.Text, 1, 1), 9999))
'draw each line
Dim i As Integer
Dim textLines(-1) As String
Dim y As Double
g.TextFont = TextArea1.StyledText.Font(1, 1)
g.TextSize = TextArea1.StyledText.Size(1, 1)
g.Bold = TextArea1.StyledText.Bold(1, 1)
g.Italic = TextArea1.StyledText.Italic(1, 1)
textLines = Split(TextArea1.Text, EndOfLine)
For i = 0 To UBound(textLines)
g.DrawString(textLines(i), 0, y + g.TextAscent)
y = y + fontHeight
Next
Getting this to work for multiple styles will obviously be more complex. My gut feeling is that the spacing is based on the font and not a fixed value so you will have to handle different offsets on the same line. I’ll leave this to you how to work out.
Oh, I understand now. The somewhat kludgy but relatively simple way without plugins or declares is to use the TextArea.CharacterPosition(X,Y) method to “walk” vertically down the TextArea (set X to 0 and increment Y). Every time the result changes, you are on a new line of text. You could use this for your use case, as I understand it. If you need more information about the text on each line, use the character position returned and interrogate the style runs.
As I mentioned in my original reply, the idea was for macOS only.
Have you checked to see if the same problem exists on MS-Windows as TextHeight might be good enough. If the problem does exist then I imagine you’ll have to interrogate the TextArea at a lower level using Declares (i’m sure its a Win32 RichEdit field).
If you have the time, I would recommend trying it, you may need to set the background color to transparent and remove the border, but in theory it should give you identical results to what is displayed in the textarea and should be resolution less so it should work for printing also.
On the Mac (don’t know about Windows) I think the Text Area even has a built in print function that you should be able to access with a declare or two.