How to auto-sizing window by longest text line?
;==========================================================================================================================================
;
; 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
;==========================================================================================================================================