News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Word-wrap by DrawTextEx

Started by Dark Schneider, May 04, 2011, 04:00:58 PM

Previous topic - Next topic

Dark Schneider

I need to apply word wrap to long strings, width of each line is determined by given 1st string (which is its title, and I want to word wrap its description text).

First I call DrawTextEx on DC of a victim, invisible Edit control with DT_CALCRECT flag to set line width.
Then I call DrawTextEx for the string I wish to break into lines with DT_WORDBREAK and DT_EDITCONTROL flag
and use DRAWTEXTPARAMS.uiLengthDrawn returned to copy and append CR/LF to output string.

It works, each lines are cut to the same width of given title string.
Speed is acceptable but a little too slow if used for big collection of strings.

I can't just use white space to manually break it because the string can appear in languages other than English,
sometimes with over/underhang characters.

To gain more speed, how can I do this without actually drawing in that victim control?
Any other method to do this?

qWord

Quote        ; EBX = hdc
        mov edi,chr$("This is a titel",13,10,"very very long long line",13,10,"123456789")
        mov esi,len(edi)
       
        ; get size of first line
        xor ecx,ecx
        .while CHAR ptr [edi+ecx] != 13
            inc ecx
        .endw
        invoke GetTextExtentPoint32,ebx,edi,ecx,ADDR _size
        mov rect.left,0
        mov rect.top,0
        m2m rect.right,_size.x
        mov rect.bottom,100000
        invoke DrawTextEx,ebx,edi,esi,ADDR rect,DT_CALCRECT or DT_WORDBREAK or DT_EDITCONTROL,0
       
        ; draw for testing purpose
        invoke DrawTextEx,ebx,edi,esi,ADDR rect,DT_WORDBREAK or DT_EDITCONTROL,0
        invoke SelectObject,ebx,rv(GetStockObject,HOLLOW_BRUSH)
        invoke Rectangle,ebx,rect.left,rect.top,rect.right,rect.bottom
FPU in a trice: SmplMath
It's that simple!

Dark Schneider

But what I want is not the result of drawing with word wrap on screen.
I want the word-wrapped string (with CRLFs inside) for use later in another function.
That's why I have to call DrawTextEx in loops  to break each line and insert CRLF.
Just hope there is other way to do it without drawing, or better get formatted string (with CRLF in place) from edit control?

dedndave

i guess you could use GetCharABCWidths or some related function to get character widths
get a table for all characters used and total up pixels until the client width is reached
then, insert your own CR/LF
totalling it up is likely to be faster than drawing clipped text, anyways   :P
although, at some point, you may want to draw it also
and - inserting a CR/LF isn't going to be super-fast, either

what you are describing doesn't make a lot of sense because the user may resize the window, then you're screwed
perhaps, rather than inserting the CR/LF, simply keep track of the string index where wrap occurs
that way, you don't have to move a bunch of string data back and forth
much faster, especially on a large text file

what is this other function you are calling
maybe you can stick that call inside the loop to prevent inserting CR/LF's

http://msdn.microsoft.com/en-us/library/dd144857%28v=VS.85%29.aspx

http://msdn.microsoft.com/en-us/library/dd144821%28v=VS.85%29.aspx

Dark Schneider

Thank you , I'll look into that.

In my program I don't need to draw it at all just prepare the string for use with other program.
In that program it will display this string in a custom drawn tooltip window which resize itself to contain the string.
That's why I need word wrap in the first place.

To think about it again, if the string is in a certain asian language it'll be hard to break words anyway because it has no
space between words and it may end up breaking in the middle of a word.
I wonder how Windows do it in multiline Edit control.

dedndave

i see - well, it sounds like you are stuck inserting
i think all you need is a LF for tootips - not that that helps a lot

dedndave

hey - wait a minute - lol

you can set the maximum tooltip window width and it will line wrap itself   :P

        INVOKE  SendMessage,hTooltip,TTM_SETMAXTIPWIDTH,0,MaxWidthPixels
http://msdn.microsoft.com/en-us/library/bb760408%28v=vs.85%29.aspx

Dark Schneider

It is other people's program I can't set anything. I wish I can.
Well I can live with the old method I have which processes 20MB of text files in 20 seconds on Intel Core2 duo 2.33MHz.

Thank for your advice.

jj2007

Quote from: qWord on May 04, 2011, 05:11:10 PM
        invoke GetTextExtentPoint32,ebx,edi,ecx,ADDR _size

Actually, if you need speed, GetTextExtentExPoint is the right function:

A pointer to an array of integers that receives partial string extents. Each element in the array gives the distance, in logical units, between the beginning of the string and one of the characters that fits in the space specified by the nMaxExtent parameter. This array must have at least as many elements as characters specified by the cchString  parameter because the entire array is used internally. The function fills the array with valid extents for as many characters as are specified by the lpnFit parameter. Any values in the rest of the array should be ignored. If alpDx is NULL, the function does not compute partial string widths.