Announcement

Collapse
No announcement yet.

determining dimensions for LABEL based upon size of text

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

  • determining dimensions for LABEL based upon size of text

    I'd like to create a dialog that includes labels that are sized appropriately according to the size of the text that needs to be displayed. The text is not known at compile time (it's variable).

    How can I determine (programmatically) how large (wide) the label control needs to be assuming I want just one line (no line breaks)?
    Bernard Ertl
    InterPlan Systems

  • #2
    It might not be possible unless you use a monospace font. If using a proportional font, you would have to know the width of every character and know the kerning. You could probably obtain that information from the font. If so, it should be possible albeit a lot of work. If not, you may well be out of luck without a monospace font.
    Erich Schulman (KT4VOL/KTN4CA)
    Go Big Orange

    Comment


    • #3
      I think you might be able to use this: DrawTextEx
      With the dwDTFormat set to DT_CALCRECT
      There might more parameters which need to be set when using the call for determining the size of a string of text, I used either this or something like this somewhere in one of my programs.
      Furcadia, an interesting online MMORPG in which you can create and program your own content.

      Comment


      • #4
        "The GetTextExtentPoint32 function computes the width and height of the specified string of text. "

        ---Windows SDK----
        Michael Mattias
        Tal Systems Inc. (retired)
        Racine WI USA
        [email protected]
        http://www.talsystems.com

        Comment


        • #5
          There is also the DDT GRAPHIC TEXT SIZE STATEMENT, I think that you will need a GRAPHIC WINDOW to it this way. If using drawtextEX, note that you don't actually draw any text when the dt_calcrect flag is used. This fools everyone once.

          Comment


          • #6
            And of course, with any of the SDK functions, you need to have the font you're working with selected into the device context for the function to return the results you're expecting.
            Furcadia, an interesting online MMORPG in which you can create and program your own content.

            Comment


            • #7
              I'm trying DrawTextEx, but it appears to be returning a width that is twice what it should be.

              Code:
              #COMPILE EXE
              #DIM ALL
              
              '--------------------------------------------------------------------------------
              '   ** Includes **
              '--------------------------------------------------------------------------------
              #IF NOT %DEF(%WINAPI)
              	#INCLUDE "WIN32API.INC"
              #ENDIF
              '--------------------------------------------------------------------------------
              
              '--------------------------------------------------------------------------------
              '   ** Constants **
              '--------------------------------------------------------------------------------
              %IDD_DIALOG1   = 101
              %IDC_TEXTBOX1  = 1001
              '--------------------------------------------------------------------------------
              
              '--------------------------------------------------------------------------------
              '   ** Declarations **
              '--------------------------------------------------------------------------------
              DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
              DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
              '--------------------------------------------------------------------------------
              
              '--------------------------------------------------------------------------------
              FUNCTION PBMAIN()
              	ShowDIALOG1 %HWND_DESKTOP
              END FUNCTION
              '--------------------------------------------------------------------------------
              
              '--------------------------------------------------------------------------------
              '   ** CallBacks **
              '--------------------------------------------------------------------------------
              CALLBACK FUNCTION ShowDIALOG1Proc()
              
              	SELECT CASE CBMSG
              		CASE %WM_COMMAND
              			SELECT CASE CBCTL
              				CASE %IDOK
              					IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
              						DIALOG END CB.HNDL, 1
              					END IF
              				CASE %IDCANCEL
              					IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
              						DIALOG END CB.HNDL, 0
              					END IF
              			END SELECT
              	END SELECT
              
              END FUNCTION
              '--------------------------------------------------------------------------------
              
              '--------------------------------------------------------------------------------
              '   ** Dialogs **
              '--------------------------------------------------------------------------------
              FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
              	LOCAL lRslt AS LONG
              	LOCAL hDlg AS DWORD
              
              	LOCAL sTemp AS STRING, sLabel AS STRING
              	LOCAL lRect AS RECT
              
              	LOCAL I AS LONG, J AS LONG
              
              	I = 1
              
              	DIALOG NEW hParent, "Test", , , 255, 47 + I * 20, %WS_POPUP OR _
              						%WS_DLGFRAME OR %WS_CAPTION OR %WS_SYSMENU OR %WS_MINIMIZEBOX OR _
              						%WS_VISIBLE OR %DS_CENTER OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
              						%DS_SETFONT, %WS_EX_WINDOWEDGE OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
              						%WS_EX_RIGHTSCROLLBAR, TO hDlg
              
              	sLabel = "Description:"
              	IF ISFALSE DrawTextEx( GetDC( hDlg), BYVAL STRPTR( sLabel), LEN( sLabel), lRect, %DT_CALCRECT, BYVAL 0) THEN lRect.nRight = 40
              
              	CONTROL ADD LABEL, hDlg, -1, sLabel, 5, 5, lRect.nRight, 13, %WS_CHILD _
              							 OR %WS_VISIBLE, %WS_EX_LEFT OR %WS_EX_LTRREADING
              	CONTROL ADD TEXTBOX, hDlg, %IDC_TEXTBOX1, "", lRect.nRight + 10, 4, 235 - lRect.nRight, 13
              
              	I = 10 + I * 20
              	CONTROL ADD BUTTON, hDlg, %IDOK, "&OK", 10, I, 70, 25
              	CONTROL ADD BUTTON, hDlg, %IDCANCEL, "&Cancel", 180, I, 65, 25
              
              	DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
              
              	FUNCTION = lRslt
              END FUNCTION
              '--------------------------------------------------------------------------------
              Bernard Ertl
              InterPlan Systems

              Comment


              • #8
                DrawTextExt
                ....
                lprc
                [in/out] Pointer to a RECT structure that contains the rectangle, in logical coordinates, in which the text is to be formatted.
                I think "logical units" means pixels. Your dialog is using UNITS (by default).
                Michael Mattias
                Tal Systems Inc. (retired)
                Racine WI USA
                [email protected]
                http://www.talsystems.com

                Comment


                • #9
                  I tried adding:
                  DIALOG PIXELS hDlg, lRect.nRight, lRect.nBottom TO UNITS lRect.nRight, lRect.nBottom
                  to the code and it appears to have reduced the value of lRect.nRight by 1/4, so it's still ~50% too large.
                  Bernard Ertl
                  InterPlan Systems

                  Comment


                  • #10
                    I think you need to fold in the current DDT font... something like this:

                    Code:
                    	DIALOG NEW hParent, "Test", , , 255, 47 + I * 20, %WS_POPUP OR _
                    						%WS_DLGFRAME OR %WS_CAPTION OR %WS_SYSMENU OR %WS_MINIMIZEBOX OR _
                    						%WS_VISIBLE OR %DS_CENTER OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
                    						%DS_SETFONT, %WS_EX_WINDOWEDGE OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
                    						%WS_EX_RIGHTSCROLLBAR, TO hDlg
                    
                    	sLabel = "Description:"
                    	hdc = GetDC(hDlg): sLen = LEN(sLabel)
                       DIALOG SEND hDlg, %WM_GETFONT, 0, 0 TO hFont
                       SelectObject hdc, hFont
                    	n = DrawTextEx(BYVAL hdc, BYVAL VARPTR(sLabel), BYVAL sLen+1, lRect, %DT_CALCRECT, BYVAL 0)
                    	DIALOG PIXELS hDlg, lRect.nRight, lRect.nLeft TO UNITS lRect.nRight, lRect.nLeft
                    	nWidth = lRect.nRight - lRect.nLeft
                    	IF n = 0 THEN lRect.nRight = 40
                    
                    	CONTROL ADD LABEL, hDlg, -1, sLabel, 5, 5, nWidth, 13, %WS_CHILD _
                    							 OR %WS_VISIBLE, %WS_EX_LEFT OR %WS_EX_LTRREADING
                    	CONTROL ADD TEXTBOX, hDlg, %IDC_TEXTBOX1, "", 5 + nWidth, 4, 235 - lRect.nRight, 13

                    Comment


                    • #11
                      You should not need to select the font into the DC, it should already be in the DC because you're getting the DC for the dialog.

                      With that in mind:

                      Don't forget to ReleaseDC when done with the DC.

                      Before releasing any DC, ensure that you put back in the things which you "removed" when you selected them into the DC. That is:

                      Code:
                      hDC = GetDC(hDialog)
                      oldFont = SelectObject(hDC, myFont)
                      ' do stuff
                      SelectObject hDC, oldFont
                      ReleaseDC hDialog, hDC
                      And of course, don't forget to delete any user created GDI objects.
                      Furcadia, an interesting online MMORPG in which you can create and program your own content.

                      Comment


                      • #12
                        All SDK style, but I never had any luck working with a DC until AFTER WM_INITDIALOG

                        You might want to just create that control at some arbitrary size, and post yourself a private message as the last step of WM_INITDIALOG.

                        Then when you get that private message, do all the GetDc and text measuring stuff and resize the control at that time. It's fast enough no one will notice.

                        It's a thought.
                        Michael Mattias
                        Tal Systems Inc. (retired)
                        Racine WI USA
                        [email protected]
                        http://www.talsystems.com

                        Comment


                        • #13
                          Some code I use for self sizing label. You'll have to refer to win32.hlp for the parameters.
                          PB 7.04 and up
                          V_COL# and V_ROW# are calculated elsewhere and hFontCap is a 10 pt Ms Sans Serif font. All variables with no type identifier are long.
                          Code:
                            hDC = GetDC(hdlg)
                            hfont = SelectObject(hDC&,hFontCap)
                            GetTextExtentPoint32 hDC, BYVAL STRPTR(V_CAPTION$), LEN(V_CAPTION$), lpSize
                            SelectObject hDC, hFont
                            ReleaseDC hdlg, hDC
                            WdPix = lpSize.cx + 6
                            HtPix = lpSize.cy + 1
                            DIALOG PIXELS hdlg, WdPix, HtPix TO UNITS WdPix, HtPix
                            V_CAPTIONl# = WdPix
                            V_LBSTYLE& = %SS_LEFT OR %SS_NOPREFIX OR %SS_NOTIFY: V_XLBSTYLE& = %WS_EX_LEFT
                            CONTROL ADD LABEL, hDlg&, V_CAPTIONid% ,V_CAPTION$, V_COL#, V_ROW# + 1, V_CAPTIONl#, V_CAPTIONh#,V_LBSTYLE&,V_XLBSTYLE&
                            CONTROL SEND hDlg, V_CAPTIONid%,%WM_SETFONT, hFontCap, %True
                          BOB MECHLER

                          Comment


                          • #14
                            Bern, I think the code below does what you were wanting... beginning the textbox just behind the label, with no spaces. Hope this helps.

                            Code:
                            #COMPILE EXE
                            #DIM ALL
                            #INCLUDE "WIN32API.INC"
                            #INCLUDE "debug.inc"
                            
                            %IDD_DIALOG1   = 101
                            %IDC_TEXTBOX1  = 1001
                            
                            FUNCTION PBMAIN()
                               ShowDIALOG1 %HWND_DESKTOP
                            END FUNCTION
                            
                            CALLBACK FUNCTION ShowDIALOG1Proc()
                               SELECT CASE CBMSG
                                  CASE %WM_COMMAND
                                     SELECT CASE CBCTL
                                        CASE %IDOK
                                           IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                                              DIALOG END CB.HNDL, 1
                                           END IF
                                        CASE %IDCANCEL
                                           IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                                              DIALOG END CB.HNDL, 0
                                           END IF
                                     END SELECT
                               END SELECT
                            END FUNCTION
                            
                            FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
                               LOCAL lRslt, hdc, sLen, nWidth, hFont AS LONG
                               LOCAL hDlg AS DWORD
                               LOCAL sTemp AS STRING, sLabel AS STRING
                               LOCAL lRect AS RECT
                               LOCAL I AS LONG, J AS LONG
                               
                               I = 1
                               
                               DIALOG NEW hParent, "Test", , , 255, 47 + I * 20, %WS_POPUP OR _
                               					%WS_DLGFRAME OR %WS_CAPTION OR %WS_SYSMENU OR %WS_MINIMIZEBOX OR _
                               					%WS_VISIBLE OR %DS_CENTER OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
                               					%DS_SETFONT, %WS_EX_WINDOWEDGE OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
                               					%WS_EX_RIGHTSCROLLBAR, TO hDlg
                               
                               sLabel = "My New Description:"
                               hdc = GetDC(hDlg): sLen = LEN(sLabel)
                               DIALOG SEND hDlg, %WM_GETFONT, 0, 0 TO hFont
                               SelectObject hdc, hFont
                               DrawTextEx BYVAL hdc, BYVAL STRPTR(sLabel), sLen, lRect, %DT_CALCRECT, BYVAL 0
                               ReleaseDC hDlg, hdc
                               DIALOG PIXELS hDlg, lRect.nRight, lRect.nLeft TO UNITS lRect.nRight, lRect.nLeft
                               nWidth = lRect.nRight - lRect.nLeft
                                 
                               CONTROL ADD LABEL, hDlg, -1, sLabel, 5, 5, nWidth + 1, 13, %WS_CHILD _
                               						 OR %WS_VISIBLE, %WS_EX_LEFT OR %WS_EX_LTRREADING
                               CONTROL ADD TEXTBOX, hDlg, %IDC_TEXTBOX1, "", 5 + nWidth + 1, 4, 235 - lRect.nRight, 13
                               
                               I = 10 + I * 20
                               CONTROL ADD BUTTON, hDlg, %IDOK, "&OK", 10, I, 70, 25
                               CONTROL ADD BUTTON, hDlg, %IDCANCEL, "&Cancel", 180, I, 65, 25
                               
                               DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
                               
                               FUNCTION = lRslt
                            END FUNCTION

                            Comment


                            • #15
                              Originally posted by Michael Mattias View Post
                              All SDK style, but I never had any luck working with a DC until AFTER WM_INITDIALOG
                              Like perhaps with WM_SIZE set a static variable to indicate you set the size, or better yet, use one of the USER variables available with the control itself.
                              Furcadia, an interesting online MMORPG in which you can create and program your own content.

                              Comment


                              • #16
                                I simply do it this way: if the Label is to the left of the text box, I use RIGHT justify and make sure the background is the same color as the dialog background. If on the right side, i use LEFT justify. If above or below, CENTER justify.
                                Barry

                                Comment


                                • #17
                                  >Like perhaps with WM_SIZE set a static variable to indicate you set the size

                                  More like, until that window is first shown (After WM_INITDIALOG), operations with GetDC(hWnd) have been flaky.

                                  I know the sizes of controls stuff works funny until then. This usually comes up when create a resizeable screen. I have a function I will call like "Main_RelocateControls", and that NEVER works until AFTER WM_INITDIALOG or WM_CREATE. (that gets and uses the ClientRect of the hWnd and that RECT is NEVER correct on WM_INITDIALOG/WM_CREATE).

                                  When I create resizeable screens, I usually don't bother initially creating all the controls to fit or even be in the right place, because I can always call the "relocater" function which I have to have to call on WM_SIZE anyway.

                                  Then again, it could be I just coded it wrong the very first time I did it many years ago, then fixed the problem when I recoded it (more carefully?) for the processing of the private message, and just never changed how I did it because "it works now."

                                  MCM
                                  Michael Mattias
                                  Tal Systems Inc. (retired)
                                  Racine WI USA
                                  [email protected]
                                  http://www.talsystems.com

                                  Comment


                                  • #18
                                    Or, if you were a Trial and Error Dummy (watch me make pointy finger and bend wrist inward maximally), you could create a theoretically long string and see how many units/pixels a label needs to hold it. (Will probably take several/many/lots F5's), then use that number of units when creating the final code. (As a "genera"l rule I use 4.5 per character. Seems to work most of the time, depending on font and size, ...)

                                    Kinda crude but Skinning cats yadayada ....

                                    ======================================
                                    "Not only is there no God,
                                    but try finding a plumber on Sunday."
                                    Woody Allen (1935-)
                                    ======================================
                                    Last edited by Gösta H. Lovgren-2; 12 Feb 2009, 08:15 PM.
                                    It's a pretty day. I hope you enjoy it.

                                    Gösta

                                    JWAM: (Quit Smoking): http://www.SwedesDock.com/smoking
                                    LDN - A Miracle Drug: http://www.SwedesDock.com/LDN/

                                    Comment


                                    • #19
                                      Have not had a chance to research (and always wondered), but no time to do it myself at the moment, my hazy memory (and a quick search) turned up what may be the answer.

                                      try a search on "GetTextExtentPoint32" and I will BET you will get PLENTY of info
                                      Engineer's Motto: If it aint broke take it apart and fix it

                                      "If at 1st you don't succeed... call it version 1.0"

                                      "Half of Programming is coding"....."The other 90% is DEBUGGING"

                                      "Document my code????" .... "WHYYY??? do you think they call it CODE? "

                                      Comment


                                      • #20
                                        I found a solution and it doesn't matter if I set the size in the dialog creation or in the callback after initialization:
                                        Code:
                                        #COMPILE EXE
                                        #DIM ALL
                                        
                                        '--------------------------------------------------------------------------------
                                        '   ** Includes **
                                        '--------------------------------------------------------------------------------
                                        #IF NOT %DEF(%WINAPI)
                                        	#INCLUDE "WIN32API.INC"
                                        #ENDIF
                                        '--------------------------------------------------------------------------------
                                        
                                        '--------------------------------------------------------------------------------
                                        '   ** Constants **
                                        '--------------------------------------------------------------------------------
                                        %IDD_DIALOG1   = 101
                                        %IDC_TEXTBOX1  = 1001
                                        %IDC_LABEL1    = 1002
                                        '--------------------------------------------------------------------------------
                                        
                                        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 returns the textwidth + width of left and right borders
                                        	 FUNCTION = lpSize.cx + GetSystemMetrics( %SM_CXEDGE) * 2
                                        
                                        END FUNCTION
                                        
                                        '--------------------------------------------------------------------------------
                                        '   ** CallBacks **
                                        '--------------------------------------------------------------------------------
                                        CALLBACK FUNCTION ShowDIALOG1Proc()
                                        
                                        	LOCAL X AS LONG, Y AS LONG, lWidth AS LONG
                                        	LOCAL sLabel AS STRING
                                        
                                        	SELECT CASE AS LONG CB.MSG
                                        		CASE %WM_COMMAND
                                        			SELECT CASE AS LONG CB.CTL
                                        				CASE %IDOK
                                        					IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                                        						CONTROL GET TEXT CB.HNDL, %IDC_LABEL1 TO sLabel
                                        
                                        						lWidth = GetTextWidth( CB.HNDL, sLabel)
                                        
                                        						DIALOG PIXELS CB.HNDL, lWidth, Y TO UNITS lWidth, Y
                                        
                                        						CONTROL GET SIZE CB.HNDL, %IDC_LABEL1 TO X, Y
                                        						CONTROL SET SIZE CB.HNDL, %IDC_LABEL1, lWidth, Y
                                        
                                        						CONTROL GET LOC CB.HNDL, %IDC_TEXTBOX1 TO X, Y    'Get Y position
                                        						CONTROL SET LOC CB.HNDL, %IDC_TEXTBOX1, lWidth + 10, Y
                                        						CONTROL GET SIZE CB.HNDL, %IDC_TEXTBOX1 TO X, Y   'Get height
                                        						CONTROL SET SIZE CB.HNDL, %IDC_TEXTBOX1, 235 - lWidth, Y
                                        
                                        						CONTROL SET TEXT CB.HNDL, %IDC_LABEL1, sLabel     'Refresh display of label
                                        					END IF
                                        
                                        				CASE %IDCANCEL
                                        					IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                                        						CONTROL GET TEXT CB.HNDL, %IDC_TEXTBOX1 TO sLabel
                                        						CONTROL SET TEXT CB.HNDL, %IDC_LABEL1, sLabel
                                        					END IF
                                        			END SELECT
                                        
                                        	END SELECT
                                        
                                        END FUNCTION
                                        '--------------------------------------------------------------------------------
                                        
                                        '--------------------------------------------------------------------------------
                                        '   ** Dialogs **
                                        '--------------------------------------------------------------------------------
                                        FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
                                        
                                        	LOCAL lResult AS LONG, lWidth AS LONG, Y AS LONG
                                        	LOCAL hDlg AS DWORD
                                        	LOCAL sLabel AS STRING
                                        
                                        	DIALOG NEW hParent, "Test", , , 255, 65, %WS_POPUP OR _
                                        						%WS_DLGFRAME OR %WS_CAPTION OR %WS_SYSMENU OR %WS_MINIMIZEBOX OR _
                                        						%WS_VISIBLE OR %DS_CENTER OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
                                        						%DS_SETFONT, %WS_EX_WINDOWEDGE OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
                                        						%WS_EX_RIGHTSCROLLBAR, TO hDlg
                                        
                                        	sLabel = "Description:"
                                        
                                        	lWidth = GetTextWidth( hDlg, sLabel)
                                        	DIALOG PIXELS hDlg, lWidth, Y TO UNITS lWidth, Y
                                        
                                        	'Include %WS_EX_CLIENTEDGE if you want to see the border on the label
                                        	CONTROL ADD LABEL, hDlg, %IDC_LABEL1, sLabel, 5, 5, lWidth, 13, %WS_CHILD _
                                        							 OR %WS_VISIBLE, %WS_EX_LEFT OR %WS_EX_LTRREADING 'OR %WS_EX_CLIENTEDGE
                                        
                                        	CONTROL ADD TEXTBOX, hDlg, %IDC_TEXTBOX1, "", lWidth + 10, 4, 235 - lWidth, 13
                                        
                                        	CONTROL ADD BUTTON, hDlg, %IDOK, "&Resize", 10, 30, 85, 25
                                        	CONTROL ADD BUTTON, hDlg, %IDCANCEL, "&Change Label", 160, 30, 85, 25
                                        
                                        	DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lResult
                                        
                                        	FUNCTION = lResult
                                        END FUNCTION
                                        '--------------------------------------------------------------------------------
                                        
                                        '--------------------------------------------------------------------------------
                                        FUNCTION PBMAIN()
                                        	ShowDIALOG1 %HWND_DESKTOP
                                        END FUNCTION
                                        '--------------------------------------------------------------------------------
                                        Bernard Ertl
                                        InterPlan Systems

                                        Comment

                                        Working...
                                        X