CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 16
  1. #1
    Join Date
    Mar 2002
    Location
    Australia
    Posts
    198

    GDI+ MeasureString and character width

    Hey Gurus,

    I'm currently writing a subtitle editor for cinemas. I have touched on the problem I have below in another thread previously, but I thought it best to now start its own thread.

    I have run into a problem I can't seem to find a solution for, even though I have trawled this forum quite heavily.

    When a subtitle is generated, each character can have differing attributes, therefore I can't just DrawString the subtitle, I have to do it a character at a time.

    To do this, I need to track the width of the previous character. If I use MeasureString, the resultant value returned has a significant amount of space around it and nothing I do seems to change this. The text appears with large spacing between the letters, as if it had a lot of kerning applied.

    I am currently using GetTextExtent, which seems to be far more accurate, but it is still not correct, even though I set the font, size, weight etc to match my GDI+ font (nor would I expect it to be, it's just a work-around atm).

    Is there an accurate way of calculating the width of a character in GDI+ which returns the pixel accurate size of the character only?

    Is proving to be quite a pain, especially when underlined is enabled, as the line is broken between some (most) of the characters.

    Any help/suggestions would be greatly appreciated.

    Thanks heaps,

    Steve Q.

  2. #2
    Join Date
    Apr 2009
    Posts
    598

    Re: GDI+ MeasureString and character width

    Use GetCharABCWidths()
    and if it fails (if it is not a True Type font), then call GetCharWidth().
    Last edited by olivthill2; June 15th, 2011 at 04:59 AM.

  3. #3
    Join Date
    Mar 2002
    Location
    Australia
    Posts
    198

    Re: GDI+ MeasureString and character width

    Hey olivthill2,

    Thanks for your reply, I'm struggling to understand the parameters to pass to GetCharABCWidths()?

    Here is what I am doing with GetTextExtent():

    Code:
    				SelectObject( dc.m_hDC, CreateFontIndirect( &m_lfont ) );
    
    				// Get the size of the character
    				fontSize = dc.GetTextExtent( strLine.Mid( j, 1 ) );
    How do I equate that to GetCharABCWidths()?

    I don't understand what uFirstChar and uLastChar should be?

    Some examples I've seen pass in hex values such as this: 0xfbfd. How do I use this with the character I am about to display: strLine.Mid( j, 1 )?

    Thanks in advance for you help!

    Steve Q

  4. #4
    Join Date
    Aug 2000
    Location
    New York, NY, USA
    Posts
    5,656

    Re: GDI+ MeasureString and character width

    Quote Originally Posted by steveq View Post
    To do this, I need to track the width of the previous character. If I use MeasureString, the resultant value returned has a significant amount of space around it and nothing I do seems to change this. The text appears with large spacing between the letters, as if it had a lot of kerning applied.
    It sounds like you are trying to perform a manual kerning. Somewhat ambitious task.
    I was following your previous threads but got lost, sorry.
    You may want to check out GetKerningPairs function.
    Then you could use the last char of left string and the first char of right to find their kerning value and subtract it from (or add to, since it is negative) your X coordinate.
    Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
    Convenience and productivity tools for Microsoft Visual Studio:
    FeinWindows - replacement windows manager for Visual Studio, and more...

  5. #5
    Join Date
    Mar 2002
    Location
    Australia
    Posts
    198

    Re: GDI+ MeasureString and character width

    Thanks VladimirF,

    I'll have a look at this call tomorrow... (it's late here in Australia!)

    You are correct, I am try to manually kern, but I don't see I have much choice in the matter given every character could conceivably be different.

    It would be a dream to just DrawString the entire line in one hit. I wish there was a way of preformatting the string and then just writing it to the screen!

    Thanks again for taking the time to help.

    Steve Q.

  6. #6
    Join Date
    Aug 2008
    Location
    Scotland
    Posts
    379

    Re: GDI+ MeasureString and character width

    Hi,

    Have you taken a look at using a RichEdit control to do this?

    Alan

  7. #7
    Join Date
    Mar 2002
    Location
    Australia
    Posts
    198

    Re: GDI+ MeasureString and character width

    Hey Alan,
    Thanks for your suggestion. The text I am drawing on the screen has previously been entered and formatted in a Rich Edit control. I'm now trying to take what the user has entered in this control and display it with all it's formatting over an image in a separate window. It's a way of previewing the subtitle the way it will look on the cinema screen. So far it is working really well, except for the inter-character spacing.
    I need to get this right, especially if a word is underlined. If it is not correct the underline is broken between characters.

    Thanks again,

    Steve Q

  8. #8
    Join Date
    Apr 2009
    Posts
    598

    Re: GDI+ MeasureString and character width

    Quote Originally Posted by steveq View Post
    I'm struggling to understand the parameters to pass to GetCharABCWidths()?

    I don't understand what uFirstChar and uLastChar should be?
    They are ASCII numbers.
    GetCharABCWidths() was designed to fill a table with several widths at once, so that the user might reuse the data in his local table instead of calling the function several times. Nevertheless you can call it to have the size of only one character, by giving the same number to uFirstChar and to uLastChar.
    Quote Originally Posted by steveq View Post
    How do I use this with the character I am about to display: strLine.Mid( j, 1 )?
    You pass the Ascii code of your character, i.e. the Ascii code for strLine.Mid( j, 1 )
    Quote Originally Posted by steveq View Post
    Some examples I've seen pass in hex values such as this: 0xfbfd
    I have never seen such a big value passed to that function. I use it myself to pass values between 0 and 256, because usually, fonts are supposed to contain Ascii characters, but maybe it works also with fonts containing more than 256 characters.

  9. #9
    Join Date
    Mar 2002
    Location
    Australia
    Posts
    198

    Re: GDI+ MeasureString and character width

    Hey All,

    VladmirF: I looked at the kerning pairs call, and got it working, but to be honest I'm not sure what I get back? Where is the result of the call returned?

    olivthill2: Thanks for your help with GetCharABCWidths() I got it working, and the results I got back, when added together, were identical to GetTextExtent().

    I also tried DrawText() and got the same result as GetTextExtent too!

    Alas, I'm no closer!

    I didn't think this would be as big an issue as it seems to be!

    Thanks for your help.

    Steve Q.

  10. #10
    Join Date
    Mar 2008
    Location
    Turin / Italy
    Posts
    178

    Re: GDI+ MeasureString and character width

    A quick idea:
    Can't you copy what's on the DC of the RichEditControl in an image and apply a mask in that image to remove the background? Than you just have to Draw an image over an image preserving all text formatting.

  11. #11
    Join Date
    Mar 2002
    Location
    Australia
    Posts
    198

    Re: GDI+ MeasureString and character width

    Hey SkyNetTo,

    Nice idea although I'm not sure how to implement it. Also the text in the rich edit control is scaled down by about 3 to fit in the control.

    When I draw it at cinema resolution as a preview, it is scaled up 3 times to actual size (the resolution of a 2K cinema frame is 2048x1080). It is then re-scaled by the user as they re-size the window.

    Knowing this, does your idea still apply?

    Thanks for your help,

    Steve Q

  12. #12
    Join Date
    Mar 2008
    Location
    Turin / Italy
    Posts
    178

    Re: GDI+ MeasureString and character width

    Quote Originally Posted by steveq View Post
    Also the text in the rich edit control is scaled down by about 3 to fit in the control.
    If it is scaled I'm afraid you get what is scaled not the actual size. So my idea doesn't apply

  13. #13
    Join Date
    Mar 2002
    Location
    Australia
    Posts
    198

    Re: GDI+ MeasureString and character width

    Bumma! It was a good idea!

    Unfortunately the resolution of the screen at 2K is impractical for a rich edit control

    Thanks anyhow!

  14. #14
    Join Date
    Aug 2000
    Location
    New York, NY, USA
    Posts
    5,656

    Re: GDI+ MeasureString and character width

    Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
    Convenience and productivity tools for Microsoft Visual Studio:
    FeinWindows - replacement windows manager for Visual Studio, and more...

  15. #15
    Join Date
    Nov 2009
    Posts
    45

    Re: GDI+ MeasureString and character width

    Which OS you are testing on?
    Jack
    --------------------------------------------------------------------------------
    HMI/SCADA/CAD/GIS VC++ Source Codes: http://www.code-home.com

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured