Announcement

Collapse
No announcement yet.

Finding the EXACT width of a line of text

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Finding the EXACT width of a line of text

    Is there anyway to determine the exact width of a line of text that is to be displayed in a dialog box?

    I guess it could be in Dialog units or Pixels cos I can convert it but so far all the methods i have read and tried in Poffs are not exact.

    bu& = GetDialogBaseUnits()
    UnitW = CLNG(LOWRD(bu&)) ' get width of system font
    UnitH = CLNG(HIWRD(bu&)) ' get height of system font

    returns 8 as the "average" system font width. I had to dive that by 2 !!! to get anything close to a real world number.

    Obviously I takes lee space than W. so is it possible to go through the string to be displayed and calculate a sum in pixel i guess, of all the letters that is dead nuts accurate?



    ------------------
    Kind Regards
    Mike

  • #2
    GetTextExtentPoint32()



    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>
    Lance
    mailto:[email protected]

    Comment


    • #3
      Mike;

      AS Lance points out, GetTextExtentPoint32() is the required function.
      Code fragment from working example...

      Code:
              CASE %WM_PAINT
       
                  hdc = BeginPaint(hWnd,ps)
                  Call GetTextMetrics(hdc,tm)
                  linespacing = tm.tmHeight + tm.tmInternalLeading
       
                  For entry = 0 to %NUMENTRIES -1
                      ColStart = 0
                      For i = 0 to %NUMCOLS-1
                          select case i
                                   case 0
                                      sztext = Info(entry).title
                                      exit select
                                   case 1
                                      sztext = Info(entry).author
                                      exit select
                                   case 2
                                      sztext = Info(entry).publisher
                                      exit select
                                   case 3
                                      sztext = Info(entry).date
                                      exit select
                          end select
                   Call GetTextExtentPoint32(hdc,sztext,len(sztext),sz)
       
                  j= 2
                  while ((Columns(i) - %SPACING) < sz.cx)
                        chrs = Columns(i) / tm.tmAveCharWidth
       
                        sOld$=sztext
                        sNew$=left$(sOld$,chrs-j) + "..."
                        sztext=sNew$
         
                        Call GetTextExtentPoint32(hdc,szText,len(szText),sz)
                        incr j
                  wend
       
                  Call TextOut(hdc,ColStart + %SPACING, _
                               HeaderHeight +(entry*linespacing), _
                               sztext,len(sztext))
       
                  ColStart = ColStart + Columns(i)
       
                Next
       
             Next
       
                  Call EndPaint(hWnd, ps)
      HTH
      Regards,
      Jules

      Comment


      • #4
        OK.
        What do i use for hdc befor I have even created a dialog box?

        I need to calculate how big the dlg box is based on a line of text BEFOR i create the dialog.

        I guess I could create it and resize it in the CASE %WM_INITDIALOG. Is that how its done?

        In that case would hdc = CBHNDL ?

        ------------------
        Kind Regards
        Mike

        Comment


        • #5
          One very important thing when it comes to using GetTextExtentPoint32
          is that one must select correct font into DC, otherwise System font
          is used in calculation, which may give wrong result if Ansi font is
          used in control or dialog. Following gives rather good result:
          Code:
          '********************************************************************
          ' Get physical width of text string
          '********************************************************************
          FUNCTION GetTextWidth(BYVAL hWnd AS LONG, BYVAL txt AS STRING) AS LONG
            LOCAL hDc AS LONG, hFont AS LONG, lpSize AS SIZEL
           
            hDc = GetDc(hWnd)                               'get handle for proper device context
              hFont = SendMessage(hWnd, %WM_GETFONT, 0, 0)  'must select hWnd's font into DC,
              hFont = SelectObject(hDC, hFont)              'otherwise System font is used..
              CALL GetTextExtentPoint32(hDc, BYVAL STRPTR(txt), LEN(txt), lpSize)
              SelectObject hDC, hFont                       'select original font back
            ReleaseDC hWnd, hDc                             'and release DC
           
            'FUNCTION = lpSize.cy                           '<- for textheight..
            FUNCTION = lpSize.cx                            '<- function returns the textwidth
          END FUNCTION

          ------------------

          Comment


          • #6
            Resizing dialog or controls can be done in WM_INITDIALOG, or even in
            PBMAIN/WINMAIN, right after dialog/control has been created. Using the
            function above, just send control's handle + text to get textwidth back
            in pixels. Then use DIALOG PIXELS hDlg&, x&, y& TO UNITS xx&, yy&
            if you want use DIALOG SET SIZE.., or return value directly if you use
            MoveWindow or SetWindowPos to resize and position dialog.


            ------------------

            Comment


            • #7
              Thx Borje,
              I get it, but why doesnt this work?

              #COMPILE EXE
              #REGISTER NONE
              #DIM ALL
              #INCLUDE "win32api.INC"
              '-------------------------------------------------------------------------
              CALLBACK FUNCTION DlgProc
              STATIC hFont AS LONG
              LOCAL El AS STRING, lpSize AS SizeL, WdPix AS LONG, HtPix AS LONG, hWnd AS LONG, hdc AS LONG
              El = "***This is a TEST string***"
              SELECT CASE CBMSG
              CASE %WM_INITDIALOG
              CONTROL ADD LABEL, CBHNDL, 100, "", 1, 1, 600, 200
              hWnd = GetDlgItem( CBHNDL, 100 )
              hDC = GetDC(hWnd)
              GetTextExtentPoint32 hdc, BYVAL STRPTR(EL), LEN(El), lpSize
              WdPix = lpSize.cx
              HtPix = lpSize.cy + 60
              DIALOG PIXELS CBHNDL, WdPix, HtPix TO UNITS WdPix, HtPix
              DIALOG SET SIZE CBHNDL, WdPix, HtPix ' should set the Width
              CONTROL SET TEXT CBHNDL, 100, EL + $CRLF + $CRLF + FORMAT$(WdPix) + " Dlg Units"
              ReleaseDC hWnd, hDC
              CASE %WM_DESTROY
              END SELECT
              END FUNCTION

              '-----------------------------------------------------------------------------
              FUNCTION PBMAIN
              LOCAL hDlg AS LONG
              DIALOG NEW 0, "", ,, 600, 200, %WS_CAPTION OR %WS_SYSMENU TO hDlg
              DIALOG SHOW MODAL hDlg CALL DlgProc
              END FUNCTION


              ------------------
              Kind Regards
              Mike

              Comment


              • #8
                Because of the font problem I mentioned. The DC you get via GetDc uses
                System font initially for calculations, but DDT dialogs and controls
                is set to use ANSI font for size calculations, etc. Therefore, one must
                select DDT control's or dialog's font into the DC first. Following in
                %WM_INITDIALOG gives much better result:
                Code:
                            hDC  = GetDC(hWnd)
                               hFont = SendMessage(hWnd, %WM_GETFONT, 0, 0)  'must select hWnd's font into DC,
                               hFont = SelectObject(hDC, hFont)              'otherwise System font is used..
                               GetTextExtentPoint32 hdc, BYVAL STRPTR(EL), LEN(El), lpSize
                               SelectObject hDC, hFont                       'select original font back
                            ReleaseDC hWnd, hDC
                ------------------
                Forgot: If dialog has 3D borders, one need to include those in size.
                Usually 4-5 pixels extra per side, but other border widths may exist.
                If you add like 10 pixels extra to width and height you get from
                GetTextExtentPoint32, size should be enough..


                [This message has been edited by Borje Hagsten (edited May 11, 2001).]

                Comment


                • #9
                  aaaaaaaaaaaaaaaaaaaaaaaaaaaah!

                  I assumed the Dialog used the system font. duh.

                  thx so much Borje

                  ------------------
                  Kind Regards
                  Mike

                  Comment


                  • #10
                    Just for fun: it's actually possible to do this before creating a dialog too,
                    and resize directly at creation by using the desktop's DC. When this can be
                    useful? Well, for own tooltips-like messages, for example. Silly sample:
                    Code:
                    #COMPILE EXE
                    #INCLUDE "win32api.INC"
                    '-------------------------------------------------------------------------
                    CALLBACK FUNCTION DlgProc
                      select case cbmsg
                          CASE %WM_CTLCOLORDLG, %WM_CTLCOLORSTATIC
                             SetBkColor cbwparam, GetSysColor(%COLOR_INFOBK) 'make it look like tooltips..
                             function = GetSysColorBrush(%COLOR_INFOBK)
                     
                          CASE %WM_KEYUP, %WM_SYSKEYUP, %WM_MOUSEMOVE, %WM_KILLFOCUS
                             DIALOG END cbhndl  'kill dialog at these..
                     
                          CASE %WM_DESTROY
                             PostQuitMessage 0  'make sure dialog is destroyed properly at WM_KILLFOCUS..
                     
                       END SELECT
                    END FUNCTION
                     
                    '-----------------------------------------------------------------------------
                    FUNCTION PBMAIN
                       LOCAL hDlg AS LONG, hFont AS LONG, hdc AS LONG, WdPix AS LONG, HtPix AS LONG, _
                             El AS STRING, lpSize AS SIZEL
                     
                       El = "***This is a TEST string***"
                       hDC  = GetDC(%HWND_DESKTOP)
                         hFont = GetStockObject(%ANSI_VAR_FONT)
                         hFont = SelectObject(hDC, hFont)              'otherwise System font is used..
                         GetTextExtentPoint32 hDC, BYVAL STRPTR(EL), LEN(El), lpSize
                         SelectObject hDC, hFont                       'select original font back
                       ReleaseDC %HWND_DESKTOP, hDC
                     
                       WdPix = lpSize.cx + 6
                       HtPix = (lpSize.cy + 1) * 3  'in this sample, make room for three lines
                     
                       DIALOG NEW 0, "", ,, 0, 0, %WS_POPUP or %WS_BORDER TO hDlg
                       DIALOG PIXELS hDlg, WdPix, HtPix TO UNITS WdPix, HtPix
                       DIALOG SET SIZE hDlg, WdPix, HtPix
                     
                       El = El + $CRLF + $CRLF + FORMAT$(WdPix) + " Dlg Units wide"
                       CONTROL ADD LABEL, hDlg, 100, El, -1, 0, WdPix, HtPix, %SS_CENTER
                     
                       DIALOG SHOW MODAL hDlg CALL DlgProc
                    END FUNCTION

                    ------------------

                    Comment


                    • #11
                      Hello Mike,

                      I personally use the DrawText API to figure out the bounding RECT for my text string.

                      Code:
                      DIM rcBound AS RECT
                      DIM szText AS ASCIIZ * 256
                      DIM hDC AS LONG
                       
                      szText = "Here is some example text"
                       
                      DrawText hDC, szText, LEN(szText), rcBound, %DT_CALCRECT or %DT_LEFT
                      rcBound.nTop = 0
                      rcBound.nLeft = 0
                      rcBound.nRight = Text Width
                      rcBound.nBottom = Text Height

                      DT_CALCRECT Determines the width and height of the rectangle. If there are multiple lines of text, DrawText uses the width of the rectangle pointed to by the rcBound parameter and extends the base of the rectangle to bound the last line of text. If there is only one line of text, DrawText modifies the right side of the rectangle so that it bounds the last character in the line. In either case, DrawText returns the height of the formatted text but does not draw the text.

                      ------------------
                      Cheers!



                      [This message has been edited by mark smit (edited May 12, 2001).]

                      Comment


                      • #12
                        THanks Mark,

                        Now that I know the fonts are different I will give it another try.

                        Sometines the simplist things give me the most trouble. These little functions are a minefield. Figuring out these things for the first time often feels like the following test:


                        Time limit: 2 hours. Begin immediately.

                        HISTORY
                        Describe the history of the Papacy from its origins to the present day,
                        concentrating especially , but not exclusively, on its social, political,
                        economic, religious and philosophical impact on Europe, Asia, America, and
                        Africa. Be brief, concise and specific.

                        MEDICINE
                        You have been provided with a razor blade, a piece of gauze, and a bottle of
                        scotch. Remove your appendix. Do not suture until your work has been
                        inspected. You have fifteen minutes.

                        PUBLIC SPEAKING
                        2500 riot-crazed aborigines are storming the classroom. Calm them. You may
                        use any ancient language except Latin or Greek.

                        BIOLOGY
                        Create life. Estimate the differences in subsequent human culture if this
                        form of life had developed 500 million years earlier, with special attention
                        to its affect on the English Parliamentary System. Prove your thesis.

                        MUSIC
                        Write a piano concerto. Orchestrate and perform it with flute and drum.
                        You will find a piano under your seat.

                        PSYCHOLOGY
                        Based on your knowledge of their works, evaluate the emotional stability,
                        degree of adjustment, and the repressed frustrations of each of the
                        following: Alexander of Aphrodisis, Ramses II, Hammurabi. Support your
                        evaluation with quotations from each man's work, making appropriate
                        references. It is not necessary to translate.

                        SOCIOLOGY
                        Estimate the social problems which might accompany the end of the world.
                        Construct an experiment to test your theory.

                        ENGINEERING
                        The disassembled parts of a high-powered rifle have been placed on your
                        desk. You will also find an instruction manual, printed in Swahili. In 10
                        minutes, a hungry Bengal tiger will be admitted to the room Take whatever
                        action you feel necessary. Be prepared to justify your decision.

                        ECONOMICS
                        Develop a realistic plan for refinancing the national debt. Trace the
                        possible effects of your plan in the following areas: Cubism, the Donatist
                        Controversy, and the Wave Theory of Light. Outline a method for preventing
                        these effects. Criticize this method from all possible points of view.
                        Point out the deficiencies in your point of view, as demonstrated in your
                        answer to the last question.

                        POLITICAL SCIENCE
                        There is a red telephone on the desk beside you. Start World War III.
                        Report at length on its socio-political effects, if any.

                        EPISTEMOLOGY
                        Take a position for or against truth. Prove the validity of your stand.

                        PHYSICS
                        Explain the nature of matter. Include in your answer an evaluation of the
                        impact of the development of mathematics on science.

                        PHILOSOPHY
                        Sketch the development of human thought. Estimate its significance. Compare
                        with the development of any other kind of thought.

                        ASTRONOMY
                        You have been given limitless supplies of hydrogen and helium and smaller
                        quantities of the heavy metals. Create the universe. Note: This is a
                        take-home question. Return project in six days.

                        (author unknown)


                        ------------------
                        Kind Regards
                        Mike

                        Comment

                        Working...
                        X