Results 1 to 15 of 15

Thread: Measure Character Width (regardless of controls and forms) [Resolved]

  1. #1

    Thread Starter
    Addicted Member
    Join Date
    Sep 2003
    Posts
    160

    Resolved Measure Character Width (regardless of controls and forms) [Resolved]

    is it possible to do that only with api calls without doing printer or something ? because I want to use this function vba and getting form handle.
    I need to specify text font,italic,bold,size and measure the word or character exact width in pixel format to do my customized wrapping text.

    I know it has asked alot in forum and I did a search through all but none could help me.

    thanks in advance.
    Last edited by vbcodec; Apr 2nd, 2005 at 05:02 PM.

  2. #2
    Ex-Super Mod RobDog888's Avatar
    Join Date
    Apr 2001
    Location
    LA, Calif. Raiders #1 AKA:Gangsta Yoda™
    Posts
    60,710

    Re: Measure Character Width (regardless of controls and forms)

    Yes, you can get the width of some text that is using a variable width font.
    You will want to use these APIs in the process:
    1. GetStockObject
    2. GetDC
    3. SelectObject
    4. GetTextExtentPoint32
    5. DeleteObject
    6. ReleaseDC
    VB/Office Guru™ (AKA: Gangsta Yoda®)
    I dont answer coding questions via PM. Please post a thread in the appropriate forum.

    Microsoft MVP 2006-2011
    Office Development FAQ (C#, VB.NET, VB 6, VBA)
    Senior Jedi Software Engineer MCP (VB 6 & .NET), BSEE, CET
    If a post has helped you then Please Rate it!
    Reps & Rating PostsVS.NET on Vista Multiple .NET Framework Versions Office Primary Interop AssembliesVB/Office Guru™ Word SpellChecker™.NETVB/Office Guru™ Word SpellChecker™ VB6VB.NET Attributes Ex.Outlook Global Address ListAPI Viewer utility.NET API Viewer Utility
    System: Intel i7 6850K, Geforce GTX1060, Samsung M.2 1 TB & SATA 500 GB, 32 GBs DDR4 3300 Quad Channel RAM, 2 Viewsonic 24" LCDs, Windows 10, Office 2016, VS 2019, VB6 SP6

  3. #3

    Thread Starter
    Addicted Member
    Join Date
    Sep 2003
    Posts
    160

    Re: Measure Character Width (regardless of controls and forms)

    hi dude, thanks for the reply

    but I don't know anything about api advanced api programming like making object handle to it and stuff like that, do u mind making some sample function code?

    thanks alot

  4. #4
    "Digital Revolution"
    Join Date
    Mar 2005
    Posts
    4,471

    Re: Measure Character Width (regardless of controls and forms)

    A form's .TextWidth function will return the width of a character. For example...

    Width = Form.TextWidth("W")
    Width2 = Form.TextWidth("H")

    They would both return different values (unless you're using a fixed-length font). It returns the number of twips, but that can easily be converted to pixels like this:

    Width = Form.ScaleX(Form.TextWidth("W"), vbTwips, vbPixels)

    And for the height of text, you would use the .TextHeight and .ScaleY methods instead.

  5. #5

    Thread Starter
    Addicted Member
    Join Date
    Sep 2003
    Posts
    160

    Re: Measure Character Width (regardless of controls and forms)

    thanks dude but like I said its gonna ba vba function which can't have access to form and even if does vba form does not have same method like textwidth

    thanks

  6. #6
    Ex-Super Mod RobDog888's Avatar
    Join Date
    Apr 2001
    Location
    LA, Calif. Raiders #1 AKA:Gangsta Yoda™
    Posts
    60,710

    Re: Measure Character Width (regardless of controls and forms)

    You can access a Form in VBA for manipulation through VBA code. I'll see if I can whip up a demo for you
    this weekend when I get some free time.
    VB/Office Guru™ (AKA: Gangsta Yoda®)
    I dont answer coding questions via PM. Please post a thread in the appropriate forum.

    Microsoft MVP 2006-2011
    Office Development FAQ (C#, VB.NET, VB 6, VBA)
    Senior Jedi Software Engineer MCP (VB 6 & .NET), BSEE, CET
    If a post has helped you then Please Rate it!
    Reps & Rating PostsVS.NET on Vista Multiple .NET Framework Versions Office Primary Interop AssembliesVB/Office Guru™ Word SpellChecker™.NETVB/Office Guru™ Word SpellChecker™ VB6VB.NET Attributes Ex.Outlook Global Address ListAPI Viewer utility.NET API Viewer Utility
    System: Intel i7 6850K, Geforce GTX1060, Samsung M.2 1 TB & SATA 500 GB, 32 GBs DDR4 3300 Quad Channel RAM, 2 Viewsonic 24" LCDs, Windows 10, Office 2016, VS 2019, VB6 SP6

  7. #7
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: Measure Character Width (regardless of controls and forms)

    Here's a thread showing several methods of doing this...

    You might be able to use Joacim Anderson's post...

    Wrapping Text

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  8. #8
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Measure Character Width (regardless of controls and forms)

    I've written a class for you that you (and others) might find useful. It only contains a Font property and a TextWidth and a TextHeight method. TextWidth|Height will always return the width/height of the supplied text in pixels. If a multilined text is supplied to the TextWidth method, the return value will be the length of the longest line. TextHeight will return the height needed for all lines to be printed.

    It's very easy to use:
    VB Code:
    1. Dim o As CTextSize
    2. Set o = New CTextSize
    3.  
    4. With o.Font
    5.     .Name = "Times New Roman"
    6.     .Size = 12
    7.     .Bold = True
    8. End With
    9. MsgBox o.TextWidth("Hello World!")
    If no Font has been supplied the class will use MS Sans Serif, 8pt, with normal font style (not bold or italic).

    Enjoy!
    Attached Files Attached Files
    Last edited by Joacim Andersson; Apr 2nd, 2005 at 06:55 PM. Reason: Correcting the spelling of my own class name...

  9. #9

    Thread Starter
    Addicted Member
    Join Date
    Sep 2003
    Posts
    160

    Re: Measure Character Width (regardless of controls and forms)

    thanks alot dude, ur code worked fine
    except that in example it should be "CTextSize" instead of "CfontSize".

    however I found another function around the net in another forum made by somebody else which I thought its not bad to post it here for case somebody else needed it.

    VB Code:
    1. Option Explicit
    2.  
    3. ' ===================================
    4. ' API Declares
    5. '
    6. Private Declare Function CreateDC Lib "gdi32.dll" Alias "CreateDCA" (ByVal lpDriverName As String, ByVal lpDeviceName As String, ByVal lpOutput As String, lpInitData As Long) As Long
    7. Private Declare Function CreateCompatibleBitmap Lib "gdi32.dll" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
    8. Private Declare Function CreateFontIndirect Lib "gdi32.dll" Alias "CreateFontIndirectA" (lpLogFont As LOGFONT) As Long
    9. Private Declare Function SelectObject Lib "gdi32.dll" (ByVal hdc As Long, ByVal hObject As Long) As Long
    10. Private Declare Function DeleteObject Lib "gdi32.dll" (ByVal hObject As Long) As Long
    11. Private Declare Function GetTextExtentPoint32 Lib "gdi32.dll" Alias "GetTextExtentPoint32A" (ByVal hdc As Long, ByVal lpsz As String, ByVal cbString As Long, lpSize As SIZE) As Long
    12. Private Declare Function MulDiv Lib "kernel32.dll" (ByVal nNumber As Long, ByVal nNumerator As Long, ByVal nDenominator As Long) As Long
    13. Private Declare Function GetDC Lib "user32.dll" (ByVal hwnd As Long) As Long
    14. Private Declare Function GetDeviceCaps Lib "gdi32.dll" (ByVal hdc As Long, ByVal nIndex As Long) As Long
    15. Private Declare Function DeleteDC Lib "gdi32.dll" (ByVal hdc As Long) As Long
    16.  
    17. Private Const LOGPIXELSY As Long = 90
    18. Public Type SIZE
    19.     cx As Long
    20.     cy As Long
    21. End Type
    22. Private Type LOGFONT
    23.     lfHeight As Long
    24.     lfWidth As Long
    25.     lfEscapement As Long
    26.     lfOrientation As Long
    27.     lfWeight As Long
    28.     lfItalic As Byte
    29.     lfUnderline As Byte
    30.     lfStrikeOut As Byte
    31.     lfCharSet As Byte
    32.     lfOutPrecision As Byte
    33.     lfClipPrecision As Byte
    34.     lfQuality As Byte
    35.     lfPitchAndFamily As Byte
    36.     lfFaceName As String * 32
    37. End Type
    38. ' ===================================
    39.  
    40. '
    41. ' GetTextSize
    42. ' -> Measures the size in pixels of a string, given a particular font. This uses
    43. '    the GetTextExtentPoint32 API to measure the string. The API is defined as
    44. '    follows:
    45. '
    46. '      GetTextExtendPoint(ByVal hdc As Long, ByVal lpsz As String, ByVal cbString As Long, lpSize As SIZE)
    47. '        hdc:       The device context which is attached to the font to be used
    48. '        lpsz:      The string to measure, based on the font contained in the hdc specified
    49. '        cbString:  The length of the string which was passed in 'lpsz'
    50. '        lpSize:    The SIZE structure which the measurements will be returned to
    51. '
    52. '
    53. Public Function GetTextSize(text As String, font As StdFont) As SIZE
    54.     Dim tempDC As Long
    55.     Dim tempBMP As Long
    56.     Dim f As Long
    57.     Dim lf As LOGFONT
    58.     Dim textSize As SIZE
    59.    
    60.     ' Create a device context and a bitmap that can be used to store a
    61.     ' temporary font object
    62.     tempDC = CreateDC("DISPLAY", vbNullString, vbNullString, ByVal 0)
    63.     tempBMP = CreateCompatibleBitmap(tempDC, 1, 1)
    64.    
    65.     ' Assign the bitmap to the device context
    66.     DeleteObject SelectObject(tempDC, tempBMP)
    67.    
    68.     ' Set up the LOGFONT structure and create the font
    69.     lf.lfFaceName = font.Name & Chr$(0)
    70.     lf.lfHeight = -MulDiv(font.SIZE, GetDeviceCaps(GetDC(0), LOGPIXELSY), 72)
    71.     lf.lfItalic = font.Italic
    72.     lf.lfStrikeOut = font.Strikethrough
    73.     lf.lfUnderline = font.Underline
    74.     If font.Bold Then lf.lfWeight = 800 Else lf.lfWeight = 400
    75.     f = CreateFontIndirect(lf)
    76.    
    77.     ' Assign the font to the device context
    78.     DeleteObject SelectObject(tempDC, f)
    79.    
    80.     ' Measure the text, and return it into the textSize SIZE structure
    81.     GetTextExtentPoint32 tempDC, text, Len(text), textSize
    82.    
    83.     ' Clean up (very important to avoid memory leaks!)
    84.     DeleteObject f
    85.     DeleteObject tempBMP
    86.     DeleteDC tempDC
    87.    
    88.     ' Return the measurements
    89.     GetTextSize = textSize
    90. End Function
    Last edited by vbcodec; Apr 2nd, 2005 at 05:01 PM.

  10. #10
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Measure Character Width (regardless of controls and forms)

    Quote Originally Posted by vbcodec
    thanks alot dude, ur code worked fine
    except that in example it should be "CTextSize" instead of "CfontSize".
    Whoops... Sorry, that's what happens when you type the code directly in the post... I don't even remember what name I gave my class However I've edited my origional post to correct it

  11. #11
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Measure Character Width (regardless of controls and forms) [Resolved]

    Just a little side note on the code you provided. It's using GetTextExtentPoint32 which was also suggested by RobDog888 earlier. During my testing that function returned the font size in logical units rather then pixels, so you have to convert that. My class will return the width and height in pixels and also messure the width and height of a string containing multiple lines.

  12. #12

    Thread Starter
    Addicted Member
    Join Date
    Sep 2003
    Posts
    160

    Re: Measure Character Width (regardless of controls and forms) [Resolved]

    very good note, thank you very much indeed

  13. #13
    Ex-Super Mod RobDog888's Avatar
    Join Date
    Apr 2001
    Location
    LA, Calif. Raiders #1 AKA:Gangsta Yoda™
    Posts
    60,710

    Re: Measure Character Width (regardless of controls and forms) [Resolved]

    Joacim, this is what I came up with. Its not the same?
    This is like autosize textbox code.

    VB Code:
    1. Option Explicit
    2. 'Add 2 textboxes and a command button
    3. Private Type SIZE
    4.     cx As Long
    5.     cy As Long
    6. End Type
    7.  
    8. Private Declare Function GetStockObject Lib "gdi32" (ByVal nIndex As Long) As Long
    9. Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
    10. Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
    11. Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long
    12. Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
    13. Private Declare Function GetTextExtentPoint32 Lib "gdi32" Alias "GetTextExtentPoint32A" (ByVal hdc As Long, _
    14. ByVal lpsz As String, ByVal cbString As Long, lpSize As SIZE) As Long
    15. Private Const ANSI_VAR_FONT As Long = 12
    16.  
    17. Private Sub Command1_Click()
    18.     Dim lWidth As Long
    19.     lWidth = MeasureMe(Text1)
    20.     Text2.Text = lWidth
    21.     Text1.Width = lWidth * 15 + 100 [color=green]'100 compensate for textbox's inner padding[/color]
    22. End Sub
    23.  
    24. Private Sub Form_Load()
    25.     Text1.Text = "This is my variable width text that we are going to measure!"
    26.     Text2.Text = vbNullString
    27. End Sub
    28.  
    29. Private Function MeasureMe(ByVal oText As TextBox) As Long
    30.     Dim hFont As Long
    31.     Dim hFontOrig As Long
    32.     Dim lWidth As Long
    33.     Dim hdc As Long
    34.     Dim sTemp As String
    35.     Dim sz As SIZE
    36.     hdc = GetDC(Form1.hwnd)
    37.     hFont = GetStockObject(ANSI_VAR_FONT)
    38.     hFontOrig = SelectObject(hdc, hFont&)
    39.     GetTextExtentPoint32 hdc, oText.Text, Len(oText.Text), sz
    40.     lWidth = sz.cx
    41.     '<RESET & DELETE>
    42.     SelectObject hdc, hFontOrig
    43.     DeleteObject (hFont)
    44.     ReleaseDC Form1.hwnd, hdc
    45.     MeasureMe = lWidth
    46. End Function
    VB/Office Guru™ (AKA: Gangsta Yoda®)
    I dont answer coding questions via PM. Please post a thread in the appropriate forum.

    Microsoft MVP 2006-2011
    Office Development FAQ (C#, VB.NET, VB 6, VBA)
    Senior Jedi Software Engineer MCP (VB 6 & .NET), BSEE, CET
    If a post has helped you then Please Rate it!
    Reps & Rating PostsVS.NET on Vista Multiple .NET Framework Versions Office Primary Interop AssembliesVB/Office Guru™ Word SpellChecker™.NETVB/Office Guru™ Word SpellChecker™ VB6VB.NET Attributes Ex.Outlook Global Address ListAPI Viewer utility.NET API Viewer Utility
    System: Intel i7 6850K, Geforce GTX1060, Samsung M.2 1 TB & SATA 500 GB, 32 GBs DDR4 3300 Quad Channel RAM, 2 Viewsonic 24" LCDs, Windows 10, Office 2016, VS 2019, VB6 SP6

  14. #14
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: Measure Character Width (regardless of controls and forms) [Resolved]

    OK Rob, it looks fine but if you change the Font used in the TextBox it won't messure the correct length of that will it? You create a stock object using ANSI_VAR_FONT so that will use a standard Ansi font, not the font you're using. At least that is how I read the code. Besides according to MSDN the GetTextExtentPoint32 returns the size in logical units and not in pixels.

    My code creates a LogFont structure out of a StdFont object. It then creates gets a hFont handle from that via a call to CreateFontInderect which is selected into a Device Context that I create directly from the screen. My class doesn't need any visual components or forms. You just select the font you want to use and call the TextWidth/Height methods to get the size in pixels.

  15. #15
    Ex-Super Mod RobDog888's Avatar
    Join Date
    Apr 2001
    Location
    LA, Calif. Raiders #1 AKA:Gangsta Yoda™
    Posts
    60,710

    Re: Measure Character Width (regardless of controls and forms) [Resolved]

    I like your code better. I had done something like this before a couple of years ago. I neve had to change
    the font so I think its close but no cigar.

    So I would have to select the actual font being used and get that object. I thought thats what the ansi var
    constant was for but I guess not.


    I dont want to hijack the thread and it is resolved so I will leave this as it is and use your code

    Thanks for looking at it.
    VB/Office Guru™ (AKA: Gangsta Yoda®)
    I dont answer coding questions via PM. Please post a thread in the appropriate forum.

    Microsoft MVP 2006-2011
    Office Development FAQ (C#, VB.NET, VB 6, VBA)
    Senior Jedi Software Engineer MCP (VB 6 & .NET), BSEE, CET
    If a post has helped you then Please Rate it!
    Reps & Rating PostsVS.NET on Vista Multiple .NET Framework Versions Office Primary Interop AssembliesVB/Office Guru™ Word SpellChecker™.NETVB/Office Guru™ Word SpellChecker™ VB6VB.NET Attributes Ex.Outlook Global Address ListAPI Viewer utility.NET API Viewer Utility
    System: Intel i7 6850K, Geforce GTX1060, Samsung M.2 1 TB & SATA 500 GB, 32 GBs DDR4 3300 Quad Channel RAM, 2 Viewsonic 24" LCDs, Windows 10, Office 2016, VS 2019, VB6 SP6

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