News:

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

GetCurrentPositionEx; DrawText

Started by raleeper, June 14, 2007, 10:03:40 AM

Previous topic - Next topic

raleeper

    1.  I think I have learned the dismal answer to the question:

    How can you use DrawText to draw a string and then find out where the last character was drawn
    in order to drawtext (or textout) another string that appears to continue the first string
    (but with different attributes, etc.)?

The answer - No Way.

But I would appreciate it if someone could confirm my conclusions.

I would like to use DrawText in at least some places in my code, in order to take advantage of the builtin formatting - ie & maybe eg, wordbreak & tab processing.

I can do my own text formatting - the code is ready & just needs to be adapted - 16-bit DOS -> 32-bit windows - but all these marvelous new windows functions ought to be good for something [ed. - save it for the Soapbox] and I am not quite ready to give up on DrawText.

    2.  GetCurrentPositionEx always rets 0,0 after a series of drawtext's, or it might ret the cpos after the last textout, but that means:

    3.  There is Noway to find out where Drawtext has left off so as to "append" something there - using Movetoex or other.  So there is Noway to use the text formatting capabilities of Drawtext and then "append", eg. a char with a different text/background color.

    4.  So I am going to have to do my own text formatting and use Textout.

    5.  I realize I might be able to use an edit control to do this but I am not quite ready for that.

Is this pretty much right?

Thanks.

ramguru

You haven't learned much about WinApi yet (to make conclusions such as yours  :wink ). There are many ways to append text, but unfortunately you'll have to use your brains. The first way is to use DrawText in WM_PAINT once: you simply accumulate strings in one big buffer, use szMultiCat to append those strings that you need to show...and specify in DrawText to show that final buffer. Another way is to determine width & heigth of single character (if you use monospace font), when figure out where the last char sits. Also there are functions to determine width & height of whole string (for non-monospace font), but as long as your text is wordwrapped that can be tricky. Also you can simply specify different rect coordinates if you use DrawText multiple times, so it would look like new paragraph each time you use that API...

raleeper

Quote from: ramguru on June 14, 2007, 11:01:01 AM
You haven't learned much about WinApi yet (to make conclusions such as yours  :wink ).

    Yes. Which is why ...

There are many ways to append text, but unfortunately you'll have to use your brains.

    Damn!  I was hoping to use somebody else's

The first way is to use DrawText in WM_PAINT once:

    OK.

you simply accumulate strings in one big buffer,

    Whoa! - What TF does that mean?


use szMultiCat to append those strings that you need to show...and specify in DrawText to show that final buffer. Another way is to determine width & heigth of single character (if you use monospace font), when figure out where the last char sits. Also there are functions to determine width & height of whole string (for non-monospace font), but as long as your text is wordwrapped that can be tricky. Also you can simply specify different rect coordinates if you use DrawText multiple times, so it would look like new paragraph each time you use that API...

    And this is all giibberish.


Tedd

ramguru's suggestion is not draw any strings, until you have the complete set of strings you want to draw, then stick them all together in one big line, and draw the whole line at once - thus, they will be appended correctly. Of course, this works only if you want them all in the same colour - so it's not the correct solution for you.

But, there is an alternative! While DrawText doesn't tell you where it left off, and it doesn't set the current position (a la MoveTo; because this position is meant for line/shape drawing, not for text - which is arguably just a collection of lines and curves, but they're treated differently), what you can do is find out how long the drawn text will be. There is a function - GetTextExtentPoint32 - which will return the width and height of the given string if it were to be drawn in the given DC (which is what specifies the font and its properties.)
No snowflake in an avalanche feels responsible.

zooba

If you call DrawText with DT_CALCRECT as the last parameter it will modify the RECT passed to fully enclose the text. You will have to call it a second time (without DT_CALCRECT) to actually draw the text, but I have found the results of this method to be much more consistent than any others.

Cheers,

Zooba :U

raleeper

Quote from: raleeper on June 14, 2007, 11:27:00 AM
Quote from: ramguru on June 14, 2007, 11:01:01 AM
You haven't learned much about WinApi yet (to make conclusions such as yours  :wink ).

    Yes. Which is why ...

There are many ways to append text, but unfortunately you'll have to use your brains.

    Damn!  I was hoping to use somebody else's

The first way is to use DrawText in WM_PAINT once:

    OK.

you simply accumulate strings in one big buffer,

    Whoa! - What TF does that mean?


use szMultiCat to append those strings that you need to show...and specify in DrawText to show that final buffer. Another way is to determine width & heigth of single character (if you use monospace font), when figure out where the last char sits. Also there are functions to determine width & height of whole string (for non-monospace font), but as long as your text is wordwrapped that can be tricky. Also you can simply specify different rect coordinates if you use DrawText multiple times, so it would look like new paragraph each time you use that API...

    And this is all giibberish.

Yes.

I apologize, ramguru.



raleeper

Zooba - DT_CalcRect will not do what I want.  Although I do need to know the vertical size of the rect, I do not need to know the horizontal size.  What I need to know is the horizontal size of the space from where drawtext leaves off, to the right limit of the rect, eg:

   0123456789abcdef
0  This is some
1  text<-    ?   ->
       123456789abc


Drawtext,...,DT_CalCrect will tell me I need a 0C*n by 2*m rect for this string (in a rect 10*n wide).  But it will not tell me there are 0C places unfilled on the last line.

Tedd - GetTextExtentPoint32 likewise appears to give the size ot the rectangle needed to enclose the string, although I don't understand how it can do that without knowing the horizontal size of the rect in which the string is to be drawn, assuming a string that will be wrapped at least once.

Or am I again making some dumb mistake?

Thanks.

raleeper

Quote from: raleeper on June 14, 2007, 11:23:57 PM
Tedd - GetTextExtentPoint32 likewise appears to give the size ot the rectangle needed to enclose the string, although I don't understand how it can do that without knowing the horizontal size of the rect in which the string is to be drawn, assuming a string that will be wrapped at least once.


OK, I call gettextextent32 once to get the size of the string if it were drawn on a single line, then DT_MODIFYSTRING can be used to find out how many spaces were added for word break, then I need gettextextent32 again to find out the hsize of a string of that many spaces, add that to the first value from gettextextent32, divide by rect.right-rect.left, and the remainder is the hsize of the partial last line.  The quotient rounded up is the number of lines.

I may have the details of this not quite right, but it looks as if it should work!

Thanks.

zooba

GetTextExtentPoint32 assumes that the text is on a single line.

You may be best to manually handle the wrapping in this case. GetTextExtentExPoint (note the 'Ex' just before 'Point') can give you the number of characters of your string which will fit within a certain number of pixels. You can use this to write each line manually and use DT_CALCRECT to give you the width of the current line.

Cheers,

Zooba :U

raleeper

Quote from: zooba on June 15, 2007, 09:03:05 AM
GetTextExtentPoint32 assumes that the text is on a single line.

You may be best to manually handle the wrapping in this case. GetTextExtentExPoint (note the 'Ex' just before 'Point') can give you the number of characters of your string which will fit within a certain number of pixels. You can use this to write each line manually and use DT_CALCRECT to give you the width of the current line.

Cheers,

Zooba :U

I believe you are right about manually wrapping.

But I am 3/4 thru coding the implementation of the caculate-using-drawtextex/modify-gettextextentex method.  It is more complicated than I had thought, but I like to finish what I start.

GetTextExtentExPoint looks [I mean just judging from your description] to be potentially VERY useful, although for my peculiar purposes, not precisely in the way you suggest.

On second thought, I think I will postpone any further work on the calc... method above and investigate this.

Thanks!

Tedd

Check out the similarly named functions to "GetTextExtent..." and see which suits you best - there is one which will tell you how much of the given string will fit into a specified width, thus aiding wrapping.
No snowflake in an avalanche feels responsible.

raleeper

Zooba - It appears that GetTextExtentExPoint ("gteep" for short) will also not do what I want.  I should have realized this because gteep does not take an [in] parameter for formatting (DT_WORDBREAK or DT_EXPANDTABS or ...).

Using an earlier simplified example:

   0123456789abcdef
0  This is some
1  text<-    ?   ->
       123456789abc


   invoke   gteep, hdc, esi, edi, eax, ADDR ccln, 0, OF mbuf

edi = cchString   [in] Count of chars in string = 11
   0123456789abcdef01
   This is some text


eax = nMaxExtent [in] max allowed width, ..., of formatted string = 100
   (using the selected font, etc., the width of a character cell is
   calculated to be 10. 10*10 = 100)

Now the return from gteep in [ccln] is 10, the count of chars that would fit on the line *without formatting*, which I knew already.  What I wanted was the count of chars that would fit *with formatting*.  The return I wanted was *0D*, because when the string is drawn with DT_WORDBREAK, all that will fit on the first line is:

   0123456789abcdef
0  This is some#   (# = space)


I realize I that could probably use the array of partial extents returned in the final parameter (here mbuf) to do further calculations and eventually arrive at what I need.

But since I am using a fixed font, I can calculate all the extents in advance, without gteep or any other API function.

So - implementing this sugestion was a useful exercise and I certainly appreciate the suggestion.  I understand the API, especially the GDI, much better now.

But I see (I think) that I am going to have to do my own formatting and use textout line by line.

Thanks!