I have a sinking feeling that I already know how to do this, but does anyone have a more efficient method than using a binary chop on the text string until the legth of the result is just less than the desired pixel length?
Announcement
Collapse
No announcement yet.
Truncate text to pixel length
Collapse
X
-
DrawText with DT_MODIFYSTRING is useful for text or path truncation
Comment
-
I still have not mastered this drawtext API.
It seems to map the string at 0,0 in the GW then display just as much as coincides with the given rect - or maybe I got the options wrong.
Any experts out there?
******* ADDED **********
Sorry, what I should have said is that I want to constrain a string to a certain number of pixels in width, so the leftmost character is always displayed, and the right hand end of the string is truncated.
Code:' to investigate DrawText on a GW #compile exe #dim all #include once "WIN32API.inc" function pbmain () as long local hgw as dword local skey as string local i as long local x, y as long local tempr as rect local hDC as dword local sztitle as asciz * 512 graphic window "DrawText (ESC to end)", 100, 100, 280, 200 to hgw graphic attach hgw, 0, redraw sztitle = "HELLO MOTHER" graphic color %white,%blue graphic get dc to hdc setrect tempr, 30, 5, 130, 20 drawtext hdc, byval varptr(sztitle), len(sztitle), tempr, _ %DT_END_ELLIPSIS or %DT_LEFT or %DT_MODIFYSTRING or %DT_SINGLELINE '? hdc, tempr.nleft, tempr.ntop, tempr.nright, tempr.nbottom graphic color %black, %white graphic redraw graphic waitkey$ to skey graphic window end end function
Comment
-
Unless the point is to get a modified string which WILL fit into the rect supplied - in which case one would also need %DT_CALCRECT to prevent anything being displayed:
Code:' to investigate DrawText on a GW #compile exe #dim all #include "WIN32API.inc" function pbmain () as long local hgw as dword local skey as string local i as long local x, y as long local tempr as rect local hDC as dword local sztitle as asciz * 512 graphic window "DrawText (ESC to end)", 100, 100, 280, 200 to hgw graphic attach hgw, 0, redraw sztitle = "HELLO MOTHER" graphic color %white,%blue graphic get dc to hdc setrect tempr, 30, 5, 90, 20 drawtext hdc, byval varptr(sztitle), len(sztitle), tempr, _ %DT_LEFT or %DT_SINGLELINE or %DT_END_ELLIPSIS or %DT_MODIFYSTRING or %DT_CALCRECT graphic set pos ( 0, 40):graphic print sztitle '? hdc, tempr.nleft, tempr.ntop, tempr.nright, tempr.nbottom graphic color %black, %white graphic redraw graphic waitkey$ to skey graphic window end end function
Comment
-
I don't see how graphic redraw can work, since it has no buffered GRAPHIC statements.
DrawText is coming from "outside the reservation"Michael Mattias
Tal Systems (retired)
Port Washington WI USA
[email protected]
http://www.talsystems.com
Comment
-
This looks promising...
GetTextExtentExPoint
The GetTextExtentExPoint function retrieves the number of characters in a specified string that will fit within a specified space and fills an array with the text extent for each of those characters. (A text extent is the distance between the beginning of the space and a character that will fit in the space.) This information is useful for word-wrapping calculations.Michael Mattias
Tal Systems (retired)
Port Washington WI USA
[email protected]
http://www.talsystems.com
Comment
-
Originally posted by Michael Mattias View PostI don't see how graphic redraw can work
GetTextExtentExPoint loks promising for when I graduate to PS fonts, though.
The technique in my code above does actually seem to work, though it looks rather clumsy.
Comment
-
Chris,
Q. What do you want to do?
A. Modify the text in the string and truncate to a specific pixel width
B. Just display the text truncated to a pixel width, without modifying the string
C. Something else entirely
Comment
-
Leave out DT_MODIFYSTRING and DT_CALCRECT and the text will be clipped exactly to the rectangle you specify. If you need some aspect of the text size before output then you can use GetTextExtentPoint32 or DrawText with DT_CALCRECT.
Note: If you want multiple text outputs clipped in a specific area, then a region is what you need.
Comment
-
Originally posted by Kev Peel View PostLeave out DT_MODIFYSTRING and DT_CALCRECT and the text will be clipped exactly to the rectangle you specify.
Code:' to investigate DrawText on a GW #compile exe #dim all #include "WIN32API.inc" function pbmain () as long local hgw as dword local skey as string local i as long local x, y as long local tempr as rect local hDC as dword local sztitle as asciz * 512 graphic window "DrawText (ESC to end)", 100, 100, 280, 200 to hgw graphic attach hgw, 0, redraw sztitle = "HELLO MOTHER" graphic color %white,%blue graphic get dc to hdc setrect tempr, 30, 5, 90, 20 drawtext hdc, byval varptr(sztitle), len(sztitle), tempr, _ %DT_LEFT or %DT_SINGLELINE or %DT_END_ELLIPSIS 'or %DT_MODIFYSTRING or %DT_CALCRECT graphic waitkey$ to skey graphic window end end function
Comment
-
I don't have any experience (at all) with PB graphics commands, but your earlier example worked, so I added the GRAPHIC REDRAW from that into your latest code and it does work. So I would put a GRAPHIC REDRAW statement after any (or batch of) drawing operations direct to the DC.
If this behaviour is by design then ideally it should be noted in the help file under GRAPHIC GET DC.
Comment
-
I see what you mean. The problem was the default text alignment was not TA_LEFT. Have a gander at this:
Code:#Compile Exe #Dim All #Include Once "WIN32API.inc" Function PBMain () As Long Local hgw As Dword Local skey As String Local i As Long Local x, y As Long Local tempr As rect Local hDC As Dword Local sztitle As Asciz * 512 Graphic Window "DrawText (ESC to end)", 100, 100, 280, 200 To hgw Graphic Attach hgw, 0, ReDraw sztitle = "HELLO MOTHER" Graphic Color %white,%blue Graphic Get DC To hdc ' ----Start of GDI code---------------------------------------------- SaveDC(hDC) SetTextAlign(hDC, %TA_LEFT) setrect tempr, 30, 10, 100, 40 drawtext hdc, ByVal VarPtr(sztitle), Len(sztitle), tempr, _ %DT_LEFT Or %DT_SINGLELINE Or %DT_END_ELLIPSIS RestoreDC(hDC, -1) ' ----End of GDI code---------------------------------------------- Graphic ReDraw Graphic Waitkey$ To skey Graphic Window End End Function
PPS. You might need to restore the DC after the GDI calls, in which case a couple calls to SaveDC/RestoreDC have been added. These stack-like functions will save and restore the exact state of the DC before any changes were made, such as with SetTextAlign, SelectObject, and the like.Last edited by Kev Peel; 18 Nov 2008, 04:55 PM.
Comment
-
Originally posted by Chris Holbrook View PostI will drop support a line re the need for save/restoreDC.is the saveDC/restoreDC necessary?
If you will be changing any of the DC's state then yes.
Just don't tell me you knew all along!
Comment
-
>Just don't tell me you knew all along!
I did not know but Iand found an answer in about five minutes.
However, I would not have even tried to use a WinApi draw technique on the proprietary GRAPHIC window/control. I would have measured the text character by character using the provided intrinsic text measurement functions until "it don't fit no more" and printed a substring which did fit.
Yes, your ultimate solution is more elegant, and it just might work with future versions of the compiler, but my client was back in production yesterday.Michael Mattias
Tal Systems (retired)
Port Washington WI USA
[email protected]
http://www.talsystems.com
Comment
Comment