;========================================================================================================================================== ; ; How to auto-sizing a window by the longest text line? ; ;------------------------------------------------------------------------------------------------------------------------------------------ ; (c)Detlev Dalitz.20120425. ;========================================================================================================================================== ;------------------------------------------------------------------------------------------------------------------------------------------ #DefineFunction udfGetTextExtent (strText) If strText == "" Then Return Arrayize (0 : ":" : 0, ":") ; Return dim-1 array of two elements: [0]=0, [1]=0. strFileUSER32 = DirWindows (1) : "USER32.DLL" strFileGDI32 = DirWindows (1) : "GDI32.DLL" hdlDC = DllCall (strFileUSER32, long : "GetDC", lpnull) ; Get Device Context. hdlBBSize = BinaryAlloc (8) ; Buffer to receive the SIZE structure. blnResult = DllCall (strFileGDI32, long : "GetTextExtentPoint32A", long : hdlDC, lpstr : strText, long : StrCharCount (strText), lpbinary : hdlBBSize) intTextWidth = BinaryPeek4 (hdlBBSize, 0) ; The width dimension of the given string, in logical units. intTextHeight = BinaryPeek4 (hdlBBSize, 4) ; The height dimension of the given string, in logical units. blnResult = DllCall (strFileUSER32, long : "ReleaseDC", lpnull, long : hdlDC) ; Release Device Context. hdlBBSize = BinaryFree (hdlBBSize) Return Arrayize (intTextWidth : ":" : intTextHeight, ":") ; Return dim-1 array of two elements: [0]=Rectangle width, [1]=Rectangle height. ;.......................................................................................................................................... ; This UDF "udfGetTextExtent" computes the width and height of the specified string of text ... ; and returns both values as a dim-1 array of two elements: [0]=Rectangle width, [1]=Rectangle height. ; ; (c)Detlev Dalitz.20120425. ;.......................................................................................................................................... ; Reference: ; GetTextExtentPoint32 function ; Applies to: desktop apps only ; ; The GetTextExtentPoint32 function computes the width and height of the specified string of text. ; ; Syntax ; Copy ; BOOL GetTextExtentPoint32( ; __in HDC hdc, ; __in LPCTSTR lpString, ; __in int c, ; __out LPSIZE lpSize ; ); ; ; Parameters ; hdc [in] ; A handle to the device context. ; ; lpString [in] ; A pointer to a buffer that specifies the text string. The string does not need to be null-terminated, because the c parameter specifies the length of the string. ; ; c [in] ; The length of the string pointed to by lpString. ; ; lpSize [out] ; A pointer to a SIZE structure that receives the dimensions of the string, in logical units. ; ; Return value ; If the function succeeds, the return value is nonzero. ; If the function fails, the return value is zero. ; ; Remark ; GetTextExtentPoint32 doesn't consider "\n" (new line) or "\r\n" (carriage return and new line) characters when it computes the height of a text string. ;.......................................................................................................................................... ; The SIZE structure specifies the width and height of a rectangle. ; ; Syntax ; Copy ; typedef struct tagSIZE { ; LONG cx; ; LONG cy; ; } SIZE, *PSIZE; ; ; Members ; cx ; Specifies the rectangle's width. The units depend on which function uses this. ; ; cy ; Specifies the rectangle's height. The units depend on which function uses this. ; ; Remarks ; The rectangle dimensions stored in this structure may correspond to viewport extents, window extents, text extents, bitmap dimensions, or the aspect-ratio filter for some extended functions. ;.......................................................................................................................................... ; (c)Detlev Dalitz.20120425. ;.......................................................................................................................................... #EndFunction ;------------------------------------------------------------------------------------------------------------------------------------------ ;------------------------------------------------------------------------------------------------------------------------------------------ #DefineFunction udfGetTextExtentMax (strText) arrResult = Arrayize (0 : @LF : 0, @LF) ; Define dim-1 array of two elements: [0]=0, [1]=0. If strText == "" Then Return arrResult strText = StrReplace (strText, @CRLF, @LF) arrText = Arrayize (strText, @LF) intItems = ArrInfo (arrText, 1) intLast = intItems - 1 intHeigth = 2 << 15 For intI = 0 To intLast arrTE = udfGetTextExtent (arrText[intI]) arrResult[0] = Max (arrResult[0], arrTE[0]) arrResult[1] = arrResult[1] + arrTE[1] If arrTE[1] Then intHeigth = Min (intHeigth, arrTE[1]) Next arrResult[1] = Max (arrResult[1], intItems * intHeigth) Return arrResult #EndFunction ;.......................................................................................................................................... ; This UDF "udfGetTextExtentMax" evaluates a text string, having one or more lines, ... ; and returns a dim-1 array of two elements: [0]=Rectangle max width, [1]=Rectangle max height. ; ; (c)Detlev Dalitz.20120425. ;------------------------------------------------------------------------------------------------------------------------------------------ ;------------------------------------------------------------------------------------------------------------------------------------------ #DefineFunction udfGetCenteredCoordinates (intWidth, intHeight, strDelimiter) ; Convert to 1000x1000 virtual coordinates. intLenX = (10 + intWidth) * 1000 / WinMetrics (0) ; ? Consider window border width. Should be calculated too. intLenY = (28 + intHeight) * 1000 / WinMetrics (1) ; ? Consider window titlebar height. Should be calculated too. ; Calculate upper left corner and lower right corner. intLX = Max (0, (1000 - intLenX) / 2) intLY = Max (0, (1000 - intLenY) / 2) intRX = Min (1000, intLX + intLenX) intRY = Min (1000, intLY + intLenY) Return intLX : strDelimiter : intLY : strDelimiter : intRX : strDelimiter : intRY ;.......................................................................................................................................... ; This UDF "udfGetCenteredCoordinates" returns a string list of coordinates ... ; (upper-left-corner-x, upper-left-corner-y, lower-right-corner-x, lower-right-corner-y) ; ... separated by the given delimiter character. ; ; (c)Detlev Dalitz.20120425. ;.......................................................................................................................................... #EndFunction ;------------------------------------------------------------------------------------------------------------------------------------------ ; Test. DirChange (DirScript ()) strMsgTitle = "Test | Text Extent" strMsgText = "Line 01: Box auto-sizing by longest text line." strMsgText = strMsgText : @LF : @LF : "Line 03: Line with text info. Some more text. Maybe variable length info, but text still fits!" strMsgText = strMsgText : @LF : @LF : "Line 05: Line with text info. Some more text. Some more text." strMsgText = strMsgText : @LF : @LF : "Line 07: " IntControl (0012, 5, 0, 0, 0) ; Suppress OK to close messages. 1 Allow Windows to be exited with no warning. 4 Allow quiet termination. IntControl (1008, 1, 0, 0, 0) ; Enables Close command. BoxTitle (strMsgTitle) arrTextExtent = udfGetTextExtentMax (strMsgText) ; Get width and height of text rectangle in pixels. BoxesUp (udfGetCenteredCoordinates (arrTextExtent[0], arrTextExtent[1], ","), @NORMAL) ; Set the window centered on the screen. BoxTitle (strMsgTitle : " | Width=" : arrTextExtent[0] : " | Height=" : arrTextExtent[1]) BoxDataTag (1, 1) BoxText (strMsgText) BoxDataClear (1, 1) TimeDelay (4) ; Additional tests. ; Test 2. strMsgText = strMsgText : @LF : @LF : "Line 09: " arrTextExtent = udfGetTextExtentMax (strMsgText) ; Get width and height of text rectangle in pixels. WinPlaceSet (@NORMAL, "", udfGetCenteredCoordinates (arrTextExtent[0], arrTextExtent[1], " ")) ; Set the window centered on the screen. BoxTitle (strMsgTitle : " | Width=" : arrTextExtent[0] : " | Height=" : arrTextExtent[1]) BoxDataTag (1, 1) BoxText (strMsgText) BoxDataClear (1, 1) TimeDelay (4) ; Test 3. strMsgText = strMsgText : @LF : @LF : "Line 11: " : StrFill ("i", 70) arrTextExtent = udfGetTextExtentMax (strMsgText) ; Get width and height of text rectangle in pixels. WinPlaceSet (@NORMAL, "", udfGetCenteredCoordinates (arrTextExtent[0], arrTextExtent[1], " ")) ; Set the window centered on the screen. BoxTitle (strMsgTitle : " | Width=" : arrTextExtent[0] : " | Height=" : arrTextExtent[1]) BoxDataTag (1, 1) BoxText (strMsgText) BoxDataClear (1, 1) TimeDelay (4) ; Test 4. strMsgText = strMsgText : @LF : @LF : "Line 13: " : StrFill ("n", 70) arrTextExtent = udfGetTextExtentMax (strMsgText) ; Get width and height of text rectangle in pixels. WinPlaceSet (@NORMAL, "", udfGetCenteredCoordinates (arrTextExtent[0], arrTextExtent[1], " ")) ; Set the window centered on the screen. BoxTitle (strMsgTitle : " | Width=" : arrTextExtent[0] : " | Height=" : arrTextExtent[1]) BoxDataTag (1, 1) BoxText (strMsgText) BoxDataClear (1, 1) TimeDelay (4) ; Test 5. strMsgText = strMsgText : @LF : @LF : "Line 15: " : StrFill ("m", 70) arrTextExtent = udfGetTextExtentMax (strMsgText) ; Get width and height of text rectangle in pixels. WinPlaceSet (@NORMAL, "", udfGetCenteredCoordinates (arrTextExtent[0], arrTextExtent[1], " ")) ; Set the window centered on the screen. BoxTitle (strMsgTitle : " | Width=" : arrTextExtent[0] : " | Height=" : arrTextExtent[1]) BoxDataTag (1, 1) BoxText (strMsgText) BoxDataClear (1, 1) TimeDelay (4) ; Test 6. strMsgText = strMsgText : @LF : @LF : "Line 17: The End is near." arrTextExtent = udfGetTextExtentMax (strMsgText) ; Get width and height of text rectangle in pixels. WinPlaceSet (@NORMAL, "", udfGetCenteredCoordinates (arrTextExtent[0], arrTextExtent[1], " ")) ; Set the window centered on the screen. BoxTitle (strMsgTitle : " | Width=" : arrTextExtent[0] : " | Height=" : arrTextExtent[1]) BoxDataTag (1, 1) BoxText (strMsgText) BoxDataClear (1, 1) TimeDelay (4) ; Test 7. strMsgText = strMsgText : StrFill (@LF, 20) : StrFill ("Truncation may occur ... ", 240) : StrFill (@LF, 20) arrTextExtent = udfGetTextExtentMax (strMsgText) ; Get width and height of text rectangle in pixels. WinPlaceSet (@NORMAL, "", udfGetCenteredCoordinates (arrTextExtent[0], arrTextExtent[1], " ")) ; Set the window centered on the screen. BoxTitle (strMsgTitle : " | Width=" : arrTextExtent[0] : " | Height=" : arrTextExtent[1]) BoxDataTag (1, 1) BoxText (strMsgText) BoxDataClear (1, 1) TimeDelay (6) ; The End. For intI = 16 To 1 By -1 intX = intI * WinMetrics (0) / 16 intY = intI * WinMetrics (1) / 16 WinPlaceSet (@NORMAL, "", udfGetCenteredCoordinates (intX, intY, " ")) ; Set the window centered on the screen. BoxTitle (strMsgTitle : " | Width=" : intX : " | Height=" : intY) TimeDelay (intI / 64.) Next :CANCEL Exit ;==========================================================================================================================================