Jump to content

Label Automatic Width (Fit Text)


JFee
 Share

Recommended Posts

I just realized what the real problem is...

After I create it, I call GUICtrlSetFont and change the size. How should I go about updating the width/height afterwards?

Regards,Josh

Link to comment
Share on other sites

check the help file for GUICtrlSetPos.

look at the command line tool in my sig... the width of the Label showing the current directory is modified each time the dir changes.

this is not 100% accurate(off by a px or so) but it works ok for me.

1tip. I wouldn't use stringlen(GuiCtrlRead($YourLabel)) to assign width, you'll find out why soon enough muttley

cheers

Edited by Marcuzzo18

[font="Century Gothic"]quisnam est quantum stultus , balatro vel balatro quisnam insistovolubilis in solum rideo risi risum----------------------------------------------------------------------------------------------------------------------------Portable Command Line Tool[/font]

Link to comment
Share on other sites

I just realized what the real problem is...

After I create it, I call GUICtrlSetFont and change the size. How should I go about updating the width/height afterwards?

Here is an example of a function I wrote just about a week ago.

It gets the text and the font used from the specified control and then resizes based on that, so should work for you after reseting font size

I actually tore apart a resize section from the listview UDF and built on that.

#include <GuiConstantsEx.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>


$Gui = GUICreate("resize label to text width")

$label1 = GUICtrlCreateLabel("A label", 5, 5, 350, 15)
GUICtrlSetBkColor(-1, 0x00ff00)
GUICtrlSetFont(-1, 10, 400, 2, "Times New Roman")

$label2 = GUICtrlCreateLabel("A big font label", 5, 30, 350)
GUICtrlSetBkColor(-1, 0x00ff00)
GUICtrlSetFont(-1, 12, 600, 2, "Arial")

$label3 = GUICtrlCreateLabel("A label that will be padded", 5, 60, 350, 15)
GUICtrlSetBkColor(-1, 0x00ff00)
GUICtrlSetFont(-1, 9, 400, 2, "Times New Roman")

$label4 = GUICtrlCreateLabel("A big label that will be padded", 5, 90, 350)
GUICtrlSetBkColor(-1, 0x00ff00)
GUICtrlSetFont(-1, 12, 600, 2, "Arial")

$btn = GUICtrlCreateButton("Do it!", 175, 200)

GUISetState()



While 1
    $msg = GUIGetMsg()
    
    Switch $msg
        Case $GUI_EVENT_CLOSE
            Exit
            
        Case $btn
            _Control_SetWidth2Text($Gui, "", $label1)
            _Control_SetWidth2Text($Gui, "", $label2)
            _Control_SetWidth2Text($Gui, "", $label3, 5);5 pixels of trailing pad
            _Control_SetWidth2Text($Gui, "", $label4, 25);25 pixels of trailing pad
    EndSwitch
WEnd



Func _Control_SetWidth2Text($hWin, $sWinText, $hCtrl, $iPad = 0)
;author: ResNullius, based on PaulIA/GaryFrost (listview udf)
    Local $hWnd, $hDC, $hFont, $iMax, $tSize, $sText, $aCtrlPos, $ctrlX, $ctrlY, $ctrlW, $ctrlH
    If Not IsHWnd($hCtrl) Then
        $hWnd = ControlGetHandle($hWin, $sWinText, $hCtrl)
    Else
        $hWnd = $hCtrl
    EndIf
    If IsHWnd($hWnd) Then
        $hFont = _SendMessage($hWnd, $WM_GETFONT)
        $hDC = _WinAPI_GetDC($hWnd)
        _WinAPI_SelectObject($hDC, $hFont)
        $sText = ControlGetText($hWin, $sWinText, $hCtrl)
        $tSize = _WinAPI_GetTextExtentPoint32($hDC, $sText & " ")
        If DllStructGetData($tSize, "X") > $iMax Then
            $iMax = DllStructGetData($tSize, "X") + $iPad
            $aCtrlPos = ControlGetPos($hWin, $sWinText, $hCtrl)
            $ctrlX = $aCtrlPos[0]
            $ctrlY = $aCtrlPos[1]
            $ctrlW = $aCtrlPos[2]
            $ctrlH = $aCtrlPos[3]
            ControlMove($hWin, $sWinText, $hCtrl, $ctrlX, $ctrlY, $iMax, $ctrlH)
        EndIf
        _WinAPI_SelectObject($hDC, $hFont)
        _WinAPI_ReleaseDC($hWnd, $hDC)
    EndIf
EndFunc;==>_Control_SetWidth2Text
Edited by ResNullius
Link to comment
Share on other sites

I just realized what the real problem is...

After I create it, I call GUICtrlSetFont and change the size. How should I go about updating the width/height afterwards?

When you create the label control without specifying the width and height, it creates the control based on the given text and the GUI font.

So, if possible, change the GUI font and size BEFORE creating the label control.

Link to comment
Share on other sites

@pdaughe... that wouldn't have worked because it gets resized many times with different text and fonts.

I actually changed my method, so now in effect the font and size are changed before creating it.

I have a Child window, and I made a few buttons and inputs so you can add a label to the child and drag it around and stuff, and then later based on a tag you gave it when you created it, the text is changed to a value read from a CSV (well, tab delimited, but its still a CSV muttley ) file. All of the label's information goes into an array, which can later be saved and loaded, etc.

To make a long story short, since I was going to have a separate child window for setup (adding, deleting, dragging) and a separate child window to actually load the text, I just leave the setup labels alone and use the generated array to create another set of labels.

Works how I wanted it to, but thank you to everyone who helped :)

Regards,Josh

Link to comment
Share on other sites

  • 4 months later...

Yes, don't specify a width in the function. Just

GuiCtrlCreateLabel("some text", x, y)

is this a joke ???

helpfile:

width [optional] The width of the control (default is the previously used width).

height [optional] The height of the control (default is the previously used height).

all two quotations are wrong !!!

try it out:

#include <GuiConstantsEx.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>


$Gui = GUICreate("resize label to text width")

$label1 = GUICtrlCreateLabel("A label", 5, 5);, 350, 15)
GUICtrlSetBkColor(-1, 0x00ff00)
GUICtrlSetFont(-1, 10, 400, 2, "Times New Roman")

$label2 = GUICtrlCreateLabel("A big font label", 5, 30);, 350)
GUICtrlSetBkColor(-1, 0x00ff00)
GUICtrlSetFont(-1, 12, 600, 2, "Arial")

$label3 = GUICtrlCreateLabel("A label that will be padded", 5, 60);, 350, 15)
GUICtrlSetBkColor(-1, 0x00ff00)
GUICtrlSetFont(-1, 9, 400, 2, "Times New Roman")

$label4 = GUICtrlCreateLabel("A big label that will be padded", 5, 90);, 350)
GUICtrlSetBkColor(-1, 0x00ff00)
GUICtrlSetFont(-1, 12, 600, 2, "Arial")

$btn = GUICtrlCreateButton("Do it!", 175, 200)

GUISetState()



While 1
    $msg = GUIGetMsg()
    
    Switch $msg
        Case $GUI_EVENT_CLOSE
            Exit
            
        Case $btn
            _Control_SetWidth2Text($Gui, "", $label1)
            _Control_SetWidth2Text($Gui, "", $label2)
            _Control_SetWidth2Text($Gui, "", $label3, 5);5 pixels of trailing pad
            _Control_SetWidth2Text($Gui, "", $label4, 25);25 pixels of trailing pad
    EndSwitch
WEnd



Func _Control_SetWidth2Text($hWin, $sWinText, $hCtrl, $iPad = 0)
;author: ResNullius, based on PaulIA/GaryFrost (listview udf)
    Local $hWnd, $hDC, $hFont, $iMax, $tSize, $sText, $aCtrlPos, $ctrlX, $ctrlY, $ctrlW, $ctrlH
    If Not IsHWnd($hCtrl) Then
        $hWnd = ControlGetHandle($hWin, $sWinText, $hCtrl)
    Else
        $hWnd = $hCtrl
    EndIf
    If IsHWnd($hWnd) Then
        $hFont = _SendMessage($hWnd, $WM_GETFONT)
        $hDC = _WinAPI_GetDC($hWnd)
        _WinAPI_SelectObject($hDC, $hFont)
        $sText = ControlGetText($hWin, $sWinText, $hCtrl)
        $tSize = _WinAPI_GetTextExtentPoint32($hDC, $sText & " ")
        If DllStructGetData($tSize, "X") > $iMax Then
            $iMax = DllStructGetData($tSize, "X") + $iPad
            $aCtrlPos = ControlGetPos($hWin, $sWinText, $hCtrl)
            $ctrlX = $aCtrlPos[0]
            $ctrlY = $aCtrlPos[1]
            $ctrlW = $aCtrlPos[2]
            $ctrlH = $aCtrlPos[3]
            ControlMove($hWin, $sWinText, $hCtrl, $ctrlX, $ctrlY, $iMax, $ctrlH)
        EndIf
        _WinAPI_SelectObject($hDC, $hFont)
        _WinAPI_ReleaseDC($hWnd, $hDC)
    EndIf
EndFunc;==>_Control_SetWidth2Text

so, please don't write things in this forum that are not true !

my question: is it possible to adjust the height, too ?

thx

j.

Edited by jennico
Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Link to comment
Share on other sites

ah, okay i got it myself !

_ControlAdjust2Text:

#include <GuiConstantsEx.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>


$Gui = GUICreate("resize label to text width and height")

$label1 = GUICtrlCreateLabel("A label", 5, 5);, 350, 15)
GUICtrlSetBkColor(-1, 0x00ff00)
GUICtrlSetFont(-1, 90, 400, 2, "Times New Roman")
GUICtrlSetBkColor(-1, 0xF20000)

$label2 = GUICtrlCreateLabel("A big font label", 5, 30);, 350)
GUICtrlSetBkColor(-1, 0x00ff00)
GUICtrlSetFont(-1, 12, 600, 2, "Arial")

$label3 = GUICtrlCreateLabel("A label that will be padded", 5, 60);, 350, 15)
GUICtrlSetBkColor(-1, 0x00ff00)
GUICtrlSetFont(-1, 9, 400, 2, "Times New Roman")

$label4 = GUICtrlCreateLabel("A big label that will be padded", 5, 90);, 350)
GUICtrlSetBkColor(-1, 0x00ff00)
GUICtrlSetFont(-1, 12, 600, 2, "Arial")

$btn = GUICtrlCreateButton("Do it!", 175, 200)

GUISetState()



While 1
    $msg = GUIGetMsg()
    
    Switch $msg
        Case $GUI_EVENT_CLOSE
            Exit
            
        Case $btn
            _ControlAdjust2Text($Gui, "", $label1)
            _ControlAdjust2Text($Gui, "", $label2)
            _ControlAdjust2Text($Gui, "", $label3, 5);5 pixels of trailing pad
            _ControlAdjust2Text($Gui, "", $label4, 25);25 pixels of trailing pad
    EndSwitch
WEnd



Func _ControlAdjust2Text($hWin, $sWinText, $hCtrl, $iPad = 0)
;author: jennico, based on ResNullius, based on PaulIA/GaryFrost (listview udf)
    Local $hWnd, $hDC, $hFont, $iMax, $tSize, $sText, $aCtrlPos, $ctrlX, $ctrlY, $yMax
    If Not IsHWnd($hCtrl) Then
        $hWnd = ControlGetHandle($hWin, $sWinText, $hCtrl)
    Else
        $hWnd = $hCtrl
    EndIf
    If IsHWnd($hWnd) Then
        $hFont = _SendMessage($hWnd, $WM_GETFONT)
        $hDC = _WinAPI_GetDC($hWnd)
        _WinAPI_SelectObject($hDC, $hFont)
        $sText = ControlGetText($hWin, $sWinText, $hCtrl)
        $tSize = _WinAPI_GetTextExtentPoint32($hDC, $sText & " ")
 ;       If DllStructGetData($tSize, "X") > $iMax Then
            $iMax = DllStructGetData($tSize, "X") + $iPad
            $yMax = DllStructGetData($tSize, "Y")
            $aCtrlPos = ControlGetPos($hWin, $sWinText, $hCtrl)
            $ctrlX = $aCtrlPos[0]
            $ctrlY = $aCtrlPos[1]
    ;        $ctrlW = $aCtrlPos[2]
     ;       $ctrlH = $aCtrlPos[3]
            ControlMove($hWin, $sWinText, $hCtrl, $ctrlX, $ctrlY, $iMax, $yMax)
  ;      EndIf
        _WinAPI_SelectObject($hDC, $hFont)
        _WinAPI_ReleaseDC($hWnd, $hDC)
    EndIf
EndFunc;==>_ControlAdjust2Text

very useful function !

j.

Edited by jennico
Spoiler

I actively support Wikileaks | Freedom for Julian Assange ! | Defend freedom of speech ! | Fight censorship ! | I will not silence.OixB7.jpgDon't forget this IP: 213.251.145.96

 

Link to comment
Share on other sites

What ZITAT said is correct. Your script is wrong.

What you did was to create the labels then afterwards, ie after they had been created the correct size to fit the text, you change the font.

The solution is really simple.

#include <GuiConstantsEx.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>

Global $label1, $label2, $label3, $label4
$Gui = GUICreate("resize label to text width")

CreateLabels(0)


$btn = GUICtrlCreateButton("Do it!", 175, 200)

GUISetState()



While 1
    $msg = GUIGetMsg()

    Switch $msg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $btn;change the fonts in the labels
            CreateLabels()
    EndSwitch
    

WEnd


Func CreateLabels($setfonts = 1)
    
        GUICtrlDelete($label1)
        GUICtrlDelete($label2)
        GUICtrlDelete($label3)
        GUICtrlDelete($label4)

    If $setfonts Then GUISetFont(10, 400, 2, "Times New Roman")
    $label1 = GUICtrlCreateLabel("A label", 5, 5);, 350, 15)
    GUICtrlSetBkColor(-1, 0x00ff00)

    If $setfonts Then GUISetFont(12, 600, 2, "Arial")
    $label2 = GUICtrlCreateLabel("A big font label", 5, 30);, 350)
    GUICtrlSetBkColor(-1, 0x00ff00)

    If $setfonts Then GUISetFont(9, 400, 2, "Times New Roman")
    $label3 = GUICtrlCreateLabel("A label that will be padded", 5, 60);, 350, 15)
    GUICtrlSetBkColor(-1, 0x00ff00)

    If $setfonts Then GUISetFont(12, 600, 2, "Arial")
    $label4 = GUICtrlCreateLabel("A big label that will be padded", 5, 90);, 350)
    GUICtrlSetBkColor(-1, 0x00ff00)
EndFunc  ;==>CreateLabels
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

@jennico:

The labels are resized to old width after minimize+restore. Therefore you have to use GUICtrlSetPos then.

#include <GuiConstantsEx.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>


$Gui = GUICreate("resize label to text width and height")

$label1 = GUICtrlCreateLabel("A label", 5, 5);, 350, 15)
GUICtrlSetBkColor(-1, 0x00ff00)
GUICtrlSetFont(-1, 90, 400, 2, "Times New Roman")
GUICtrlSetBkColor(-1, 0xF20000)

$label2 = GUICtrlCreateLabel("A big font label", 5, 30);, 350)
GUICtrlSetBkColor(-1, 0x00ff00)
GUICtrlSetFont(-1, 12, 600, 2, "Arial")

$label3 = GUICtrlCreateLabel("A label that will be padded", 5, 60);, 350, 15)
GUICtrlSetBkColor(-1, 0x00ff00)
GUICtrlSetFont(-1, 9, 400, 2, "Times New Roman")

$label4 = GUICtrlCreateLabel("A big label that will be padded", 5, 90);, 350)
GUICtrlSetBkColor(-1, 0x00ff00)
GUICtrlSetFont(-1, 12, 600, 2, "Arial")

$btn = GUICtrlCreateButton("Do it!", 175, 200)

GUISetState()



While 1
    $msg = GUIGetMsg()
   
    Switch $msg
        Case $GUI_EVENT_CLOSE
            Exit
           
        Case $btn
            _ControlAdjust2Text($Gui, "", $label1)
            _ControlAdjust2Text($Gui, "", $label2)
            _ControlAdjust2Text($Gui, "", $label3, 5);5 pixels of trailing pad
            _ControlAdjust2Text($Gui, "", $label4, 25);25 pixels of trailing pad
    EndSwitch
WEnd



Func _ControlAdjust2Text($hWin, $sWinText, $hCtrl, $iPad = 0)
;author: jennico, based on ResNullius, based on PaulIA/GaryFrost (listview udf)
    Local $hWnd, $hDC, $hFont, $iMax, $tSize, $sText, $aCtrlPos, $ctrlX, $ctrlY, $yMax, $GUICtrl=False
    If Not IsHWnd($hCtrl) Then
        $hWnd = GUICtrlGetHandle($hCtrl)
        Switch $hWnd
            Case 0
                $hWnd = ControlGetHandle($hWin, $sWinText, $hCtrl)
            Case Else
                $GUICtrl=True
        EndSwitch
    Else
        $hWnd = $hCtrl
    EndIf
    If IsHWnd($hWnd) Then
        $hFont = _SendMessage($hWnd, $WM_GETFONT)
        $hDC = _WinAPI_GetDC($hWnd)
        _WinAPI_SelectObject($hDC, $hFont)
        Switch $GUICtrl
            Case True
                $sText = GUICtrlRead($hCtrl)
            Case Else
                $sText = ControlGetText($hWin, $sWinText, $hCtrl)
        EndSwitch
        $tSize = _WinAPI_GetTextExtentPoint32($hDC, $sText & " ")
 ;       If DllStructGetData($tSize, "X") > $iMax Then
            $iMax = DllStructGetData($tSize, "X") + $iPad
            $yMax = DllStructGetData($tSize, "Y")
            $aCtrlPos = ControlGetPos($hWin, $sWinText, $hCtrl)
            $ctrlX = $aCtrlPos[0]
            $ctrlY = $aCtrlPos[1]
    ;        $ctrlW = $aCtrlPos[2]
     ;       $ctrlH = $aCtrlPos[3]
        Switch $GUICtrl
            Case True
                $sText = GUICtrlSetPos($hCtrl,$ctrlX, $ctrlY, $iMax, $yMax)
            Case Else
                ControlMove($hWin, $sWinText, $hCtrl, $ctrlX, $ctrlY, $iMax, $yMax)
        EndSwitch
            
  ;      EndIf
        _WinAPI_SelectObject($hDC, $hFont)
        _WinAPI_ReleaseDC($hWnd, $hDC)
    EndIf
EndFunc;==>_ControlAdjust2Text
Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

  • Moderators

@Jennico and all other contributors,

This is a function I wrote to replace the default centre-screen MsgBox. It uses much the same idea as above to get the label width (making a GUI with the correct size font and then resizing it), but it also tries to reset the depth of the label if the lines have to wrap. Because I wanted to have a maximum width for the GUI, I knew that wrapping would have to take place sometimes.

Basically the function sees how wide the label would have to be and, if wrapping is needed, sees how many times the line would have to wrap to fit the max size of the GUI. It uses StringLen to guesstimate the number of wraps - and I know that this is only an approximation for a proportional font - but it seems to work quite well as long as you do not have only very wide letters in the label text (at least English seems to have enough narrow 'i', 'f', 'j', etc characters to cope). The code in question is at about Line 328 in SciTE.

CODE

#include <GUIConstantsEx.au3>

#include <WindowsConstants.au3>

#include <StaticConstants.au3>

#include <Constants.au3>

#include <WinAPI.au3>

$aDefMsgBoxFont = _GetDefaultFont()

Global $sDef_EMB_Font_Name = $aDefMsgBoxFont[0]

Global $iDef_EMB_Font_Size = $aDefMsgBoxFont[1]

; Declare Global constants

Global Const $MB_IConstop = 16 ; Stop-sign icon

Global Const $MB_ICONQUERY = 32 ; Question-mark icon

Global Const $MB_ICONEXCLAM = 48 ; Exclamation-point icon

Global Const $MB_ICONINFO = 64 ; Icon consisting of an 'i' in a circle

; Declare _ExtMsgBox global variables

Global $iEMB_Centred = 0

Global $iEMB_BkCol = Default

Global $iEMB_Col = Default

Global $sEMB_Font_Name = $sDef_EMB_Font_Name

Global $iEMB_Font_Size = $iDef_EMB_Font_Size

; Example

$hGUI = GUICreate("Main Window",200, 450, 100, 100)

$hButton1 = GUICtrlCreateButton("Test 1", 20, 20, 60, 30)

$hButton2 = GUICtrlCreateButton("Test 2", 120, 20, 60, 30)

$hButton3 = GUICtrlCreateButton("Test 3", 20, 70, 60, 30)

$hButton4 = GUICtrlCreateButton("Test 4", 120, 70, 60, 30)

$hButton5 = GUICtrlCreateButton("Exit", 70, 410, 60, 30)

GUISetState(@SW_SHOW, $hGUI)

While 1

$msg = GUIGetMsg()

Switch $msg

Case $GUI_EVENT_CLOSE, $hButton5

$nTest = _ExtMsgBox(32, "Yes|&No", "Query", "Are you sure you wish to exit?", $hGUI)

ConsoleWrite($nTest & @CRLF)

If $nTest = 1 Then Exit

Case $hButton1

; Set the centred value and change font size

_ExtMsgBoxSet(1, -1, -1, 9)

$msg = "This is centred on 'Main Window' with no icon, 4 buttons and centred text." & @CRLF & @CRLF

$msg &= "The width is set to maximum by the requirement for 4 buttons and the text will wrap if required to fit in" & @CRLF & @CRLF

$msg &= "Button 4 is set as default and will action on 'Enter'" & @CRLF & @CRLF

$msg &= "It will not time out"

$retvalue = _ExtMsgBox (0, "1|2|3|&4", "Test 1", $msg, $hGUI)

ConsoleWrite($retvalue & @CRLF)

; Reset centred value to default

_ExtMsgBoxSet()

Case $hButton2

; Hide the main GUI to centre the message box on screen

GUISetState(@SW_HIDE, $hGUI)

; Change font, leaving colours unchanged

_ExtMsgBoxSet(0, -1, -1, 9, "Arial")

$msg = "As the Main GUI is hidden, this is centred on screen." & @CRLF & @CRLF

$msg &= "It has:" & @CRLF

$msg &= @TAB & "An Info icon," & @CRLF

$msg &= @TAB & "1 offset button and" & @CRLF

$msg &= @TAB & "Left justified text." & @CRLF & @CRLF

$msg &= "The width is set by the maximum line length" & @CRLF

$msg &= "(which is less than max message box width)" & @CRLF & @CRLF

$msg &= "It will time out in 20 seconds"

; Use $MB_ constants and set timeout value

$retvalue = _ExtMsgBox ($MB_ICONASTERISK, $MB_OK, "Test 2", $msg, $hGUI, 20)

ConsoleWrite($retvalue & @CRLF)

; Reset message box colours and font to default

_ExtMsgBoxSet(0, Default, Default, Default, Default)

; Show the main GUI again

GUISetState(@SW_SHOW, $hGUI)

Case $hButton3

; Set the message box colours (yellow text on blue background) and change font

_ExtMsgBoxSet(0, 0x004080, 0xFFFF00, 10, "Comic Sans MS")

$msg = "This is centred on 'Main Window' with an Exclamation icon, "

$msg &= "2 buttons and wrapped left justified coloured text and coloured background." & @CRLF & @CRLF

$msg &= "It will not time out"

; Use $MB_ constant

$retvalue = _ExtMsgBox ($MB_ICONEXCLAMATION, "OK|Finished", "Test 3", $msg, $hGUI)

ConsoleWrite($retvalue & @CRLF)

; Reset message box colours and font to default

_ExtMsgBoxSet(1, Default, Default, Default, Default)

Case $hButton4

; Centre the single button

_ExtMsgBoxSet(2)

$msg = "No window handle was passed, so the message box is centred on screen." & @CRLF & @CRLF

$msg &= "It has a Stop icon, 1 centred button and left justified text." & @CRLF & @CRLF

$msg &= "This is a very long line, so the message box width is set to the default maximum and the text will be forced to wrap as it is much too long to fit." & @CRLF & @CRLF

$msg &= "It will time out in 15 seconds" & @CRLF & @CRLF & @CRLF & @CRLF & @CRLF & @CRLF & @CRLF & @CRLF & @CRLF

$msg &= "Note that the message box varies in depth automatically to display the lines needed, even if they are forced to wrap a number of times!"

$retvalue = _ExtMsgBox (16, "OK", "Test 4", $msg, "", 15)

ConsoleWrite($retvalue & @CRLF)

; Reset centred value to default

_ExtMsgBoxSet()

EndSwitch

WEnd

; #FUNCTION# ====================================================================================================

=====

; Name............: _ExtMsgBoxSet

; Description ....: Sets the centring parameter and colours colours for subsequent _ExtMsgBox function calls

; Syntax..........: _ExtMsgBoxSet([$iCentred, [$iBkCol, [$iCol, [$sFont_Name, [$iFont_Size]]]]])

; Parameters .....: $iCentred -> 0 = Left justified text (Default), 1 = Centred text, 2 = Centred button

; 3 = Centred text and button. Note: multiple buttons are always centred

; $iBkCol -> The colour for the message box background. Default = system colour

; $iCol -> The colour for the message box text. Default = system colour

; Omitting a colour parameter or setting -1 leaves it unchanged

; Setting a colour parameter to Default resets the system message box colour

; $iFont_Size -> The font size in points to use for the Toast

; $sFont_Name -> The font to use for the Toast

; Omitting a font parameter or setting the font size to -1 or the font name to "" leaves them unchanged

; Setting a font parameter to Default resets the system message box font and size

; Requirement(s)..: v3.2.12.1 or higher

; Return values ..: Success: Returns 0

; Author .........: Melba23

; Example.........; Yes

;===================================================================================================

==================

Func _ExtMsgBoxSet($iCentred = 0, $iBkCol = -1, $iCol = -1, $iFont_Size = -1, $sFont_Name = "")

; Set global EMB variables to required values

$iEMB_Centred = $iCentred

Select

Case $iBkCol = Default

$iEMB_BkCol = _WinAPI_GetSysColor($COLOR_WINDOW)

Case $iBkCol >= 0 And $iBkCol <= 0xFFFFFF

$iEMB_BkCol = $iBkCol

Case Else

EndSelect

Select

Case $iCol = Default

$iEMB_Col = _WinAPI_GetSysColor($COLOR_WINDOWTEXT)

Case $iCol >= 0 And $iCol <= 0xFFFFFF

$iEMB_Col = $iCol

Case Else

EndSelect

Select

Case $iFont_Size = Default

$iEMB_Font_Size = $iDef_EMB_Font_Size

Case $iFont_Size > 0

$iEMB_Font_Size = $iFont_Size

Case Else

EndSelect

Select

Case $sFont_Name = Default

$sEMB_Font_Name = $sDef_EMB_Font_Name

Case $sFont_Name = ""

Case Else

$sEMB_Font_Name = $sFont_Name

EndSelect

EndFunc

; #FUNCTION# ====================================================================================================

=====

; Name............: _ExtMsgBox

; Description ....: Generates a Message Box centred on an owner

; Syntax..........: _ExtMsgBox ($iIcon, $iButton, $sTitle, $sText, [$hWin, [$iTimeut]])

; Parameters .....: $iIcon -> The $MB_ICON constant for the icon to use:

; 0 - No icon, 16 - Stop, 32 - Query, 48 - Exclamation, 64 - Information

; Any other value returns -1, error 1

; $iButton -> Button text separated with "|" character. An ampersand (&)before the text indicates

; the default button. Two focus ampersands returns -1, error 2.

; Can also use $MB_ button constants:

; 0 = "OK", 1 = "OK|Cancel", 2 = "Abort|Retry|Ignore", 3 = "Yes|No|Cancel"

; 4 = "Yes|No", 5 = "Retry|Cancel" Incorrect constant returns -1, error 3

; Default max width of 370 gives 1-4 buttons @ width 80, 5 @ width 60, 6 @ width 50

; Min button width set at 50, so 7 buttons returns -1, error 4 unless default changed

; $sTitle -> The title of the message box

; $sText -> The text to be displayed. Long lines will wrap. The box depth is adjusted to fit

; $hWin -> The handle of the window in which the message box is to be centred

; If the window is hidden the message box is centred in the screen

; No handle passed centres message box in the screen (Default)

; $iTimeout -> Timeout delay before message box closes. 0 = no timeout (Default)

; Requirement(s)..: v3.2.12.1 or higher

; Return values ..: Success: Returns the button pressed, starting at 1, counting from the LEFT.

; Returns 0 if closed by a "CloseGUI" event (i.e. click [X] or press Escape) or timed out

; Failure: Returns -1

; - @error 1 - Icon error

; - @error 2 - Multiple default button error

; - @error 3 - Button constant error

; - @error 4 - Too many buttons

; - @error 5 - GUI creation error

; Author .........: Melba23, based on some original code by photonbuddy and YellowLab

; Example.........; Yes

;===================================================================================================

==================

Func _ExtMsgBox($iIcon, $iButton, $sTitle, $sText, $hWin = "", $iTimeout = 0)

Local $nOldOpt = Opt('GUIOnEventMode', 0)

; Set default sizes for message box

Local $iMsgwidth_max = 370, $iMsgwidth_min = 150

Local $iMsgheight_min = 120

Local $iButtonwidth_max = 80, $iButtonwidth_min = 50

; Declare local variables

Local $iMsgwidth_button, $iButtonwidth_req, $iButtonwidth, $iDefbutton, $iButtoncount, $iButtontext, $iButtonxpos

Local $iMsgwidth_text, $iThins, $iLine_len, $iCount, $iTimeout_begin, $iMsg, $iRetvalue

Local $iMsgwidth, $iLabel_height, $iLabel_vert, $hLabel, $iLabel_style

Local $hMsgGUI, $iHpos, $iVpos, $iIcon_reduction, $iIcon_style

; Declare local arrays

Local $aButtonarray[1]

; Check for icon

$iIcon_reduction = 50

Switch $iIcon

Case 0

$iIcon_reduction = 0

Case 16

$iIcon_style = -110

Case 32

$iIcon_style = -24

Case 48

$iIcon_style = -78

Case 64

$iIcon_style = -278

Case Else

$nOldOpt = Opt('GUIOnEventMode', $nOldOpt)

Return SetError(1, 0, -1)

EndSwitch

; Check if using constants or text

If IsNumber($iButton) Then

Switch $iButton

Case 0

$iButton = "OK"

Case 1

$iButton = "OK|Cancel"

Case 2

$iButton = "Abort|Retry|Ignore"

Case 3

$iButton = "Yes|No|Cancel"

Case 4

$iButton = "Yes|No"

Case 5

$iButton = "Retry|Cancel"

Case Else

$nOldOpt = Opt('GUIOnEventMode', $nOldOpt)

Return SetError(2, 0, -1)

EndSwitch

EndIf

; Check if two buttons are seeking focus

If StringInStr($iButton,"&", 0, 2) <> 0 Then

$nOldOpt = Opt('GUIOnEventMode', $nOldOpt)

Return SetError(2, 0, -1)

EndIf

; Get individual button text

$aButtonarray = StringSplit($iButton, "|")

; Get minimum GUI width needed for buttons

$iMsgwidth_button = ($iButtonwidth_max + 10) * $aButtonarray [0] + 10

; If shorter than min width, set to min width and set buttons to max size

If $iMsgwidth_button < $iMsgwidth_min Then

$iMsgwidth_button = $iMsgwidth_min

$iButtonwidth = $iButtonwidth_max

Else

; If longer than max width, check button width needed to fit

$iButtonwidth_req = ($iMsgwidth_max - (($aButtonarray [0] + 1) * 10)) / $aButtonarray [0]

; If more than min button width, set this value

If $iButtonwidth_req < $iButtonwidth_min Then

; Not enough room for the required buttons

$nOldOpt = Opt('GUIOnEventMode', $nOldOpt)

Return SetError(2, 0, -1)

ElseIf $iButtonwidth_req < $iButtonwidth_max Then

; Set box to max width and set button size as required

$iMsgwidth_button = $iMsgwidth_max

$iButtonwidth = $iButtonwidth_req

Else

; Use max button size and keep box sized at $iMsgwidth_button

$iButtonwidth = $iButtonwidth_max

EndIf

EndIf

; Create oversized GUI - will be resized later

$hMsgGUI = GUICreate($sTitle, 500, 500, -1, -1, BitOr($WS_POPUPWINDOW, $WS_CAPTION))

GUISetFont($iEMB_Font_Size, 400, 1, $sEMB_Font_Name)

If $hMsgGUI = 0 Then

$nOldOpt = Opt('GUIOnEventMode', $nOldOpt)

Return SetError(3, 0, -1)

EndIf

If $iEMB_BkCol <> Default Then GUISetBkColor($iEMB_BkCol)

; Count lines in the message to display

$aLines = StringSplit($sText, @CRLF, 1)

$iCount = $aLines[0]

; Now create label with unwrapped lines to check on max width

$hMsgLabel = GUICtrlCreateLabel($sText, 10 + $iIcon_reduction, 10)

If $iEMB_Col <> Default Then GUICtrlSetColor(-1, $iEMB_Col)

GUICtrlSetResizing (-1, $GUI_DOCKALL) ; Label will resize with GUI

; ############################

;GUICtrlSetBkColor(-1, 0x00ff00) ; Only for testing to see label size

; ############################

; Get label size

$aLabel_Pos = ControlGetPos($hMsgGUI, "", $hMsgLabel)

; Get height per line

$iLine_Height = Int(($aLabel_Pos[3] - 8) / $iCount)

; If label wider than max width

If $aLabel_Pos[2] > $iMsgwidth_max - 30 - $iIcon_reduction Then

; Check for longest line

$iLong_Line = 0

For $j = 1 To $aLines[0]

; Get line char count

$iLine_len = StringLen($aLines[$j])

If $iLine_Len > $iLong_Line Then $iLong_Line = $iLine_Len

Next

; Calculate char length to wrap

$iChar_Limit = $iLong_Line * ($iMsgwidth_max - 30 - $iIcon_reduction) / $aLabel_Pos[2]

; Check each line for wrapping

For $j = 1 To $aLines[0]

; Get line char count

$iLine_len = StringLen($aLines[$j])

; If wrapping needed, add additional lines to count

If $iLine_len > $iChar_Limit Then $iCount += Int($iLine_len / $iChar_Limit)

Next

; Calculate new label height

$Text_Height = $iCount * $iLine_Height

; Set label size

$iLabelwidth = $iMsgwidth_max - 30 - $iIcon_reduction

$iLabelheight = $Text_Height

; Set GUI size

$iMsgwidth = $iMsgwidth_max

$iMsgheight = $Text_Height + 90

; If label smaller than min width

ElseIf $aLabel_Pos[2] < $iMsgwidth_min - 30 - $iIcon_reduction Then

; Set label size

$iLabelwidth = $aLabel_Pos[2]

$iLabelheight = $aLabel_Pos[3]

; Set GUI size

$iMsgwidth = $iMsgwidth_min

$iMsgheight = $aLabel_Pos[3] + 90

; Label width determine GUI width

Else

; Set label size

$iLabelwidth = $aLabel_Pos[2]

$iLabelheight = $aLabel_Pos[3]

; Set GUI size

$iMsgwidth = $aLabel_Pos[2] + 30 + $iIcon_reduction

$iMsgheight = $aLabel_Pos[3] + 90

EndIf

; If only 1 line lower label to to centre text on icon

If $aLines[0] = 1 Then

$iLabel_vert = 27

Else

$iLabel_vert = 20

EndIf

; Resize label

GUICtrlSetPos($hMsgLabel, 10 + $iIcon_reduction, $iLabel_vert, $iLabelwidth, $iLabelheight)

; Increase GUI depth if below min

If $iMsgheight < $iMsgheight_min Then $iMsgheight = $iMsgheight_min

; Get parent GUI pos if exists

If BitAND(WinGetState($hWin), 2) Then

Local $aPos = WinGetPos($hWin)

Else

$hWin = ""

EndIf

; Calc position of GUI - centred on screen or parent

If $hWin = "" Then

$iHpos = (@DesktopWidth - $iMsgwidth) / 2

$iVpos = (@DesktopHeight - $iMsgheight) / 2

Else

$iHpos = ($aPos[2] - $iMsgwidth) / 2 + $aPos[0] - 3

$iVpos = ($aPos[3] - $iMsgheight) / 2 + $aPos[1] - 20

; Now check to make sure window is visible on screen

; First horizontally

If $iHpos < 10 Then $iHpos = 10

If $iHpos + $iMsgwidth > @DesktopWidth - 20 Then $iHpos = @DesktopWidth - 20 - $iMsgwidth

; Then vertically

If $iVpos < 10 Then $iVpos = 10

If $iVpos + $iMsgheight > @DesktopHeight - 60 Then $iVpos = @DesktopHeight - 60 - $iMsgheight

EndIf

; Reposition and resize GUI

WinMove($hMsgGUI, "", $ihPos, $iVpos, $iMsgwidth, $iMsgheight)

; Create icon

If $iIcon_reduction Then GUICtrlCreateIcon("shell32.dll", $iIcon_style, 10, 20)

; Create buttons

$iDefbutton = 0

; Calculate button hozizontal start

If $aButtonarray[0] = 1 Then

If BitAND($iEMB_Centred, 2) = 2 Then

; Single centred button

$iButtonxpos = ($iMsgwidth - $iButtonwidth) / 2

Else

; Single offset button

$iButtonxpos = $iMsgwidth - $iButtonwidth - 10

EndIf

Else

; Multiple centred buttons

$iButtonxpos = 10 + ($iMsgwidth - $iMsgwidth_button) / 2

EndIf

; Create dummy to calculate return value

$hButton_start = GUICtrlCreateDummy()

; Work through button list

For $iButtoncount = 0 To $aButtonarray[0] - 1

$iButtontext = $aButtonarray[$iButtoncount + 1]

; See if button is default

If StringLeft($iButtontext, 1) = "&" Then

$iDefbutton = 0x0001

$aButtonarray[$iButtoncount + 1] = StringTrimLeft($iButtontext, 1)

EndIf

; Draw button

GUICtrlCreateButton($aButtonarray[$iButtoncount + 1], _

$iButtonxpos + ($iButtoncount * ($iButtonwidth + 10)), _

$iMsgheight - 60, $iButtonwidth, 25, $iDefbutton)

; Reset default parameter

$iDefbutton = 0

Next

; Set centring parameter

If BitAND($iEMB_Centred, 1) = 1 Then

$iLabel_style = $SS_CENTER

Else

$iLabel_style = 0

EndIf

GUICtrlSetStyle($hMsgLabel, $iLabel_style)

; Show GUI

GUISetState()

$iTimeout_begin = 0

If $iTimeout > 0 Then $iTimeout_begin = TimerInit()

While 1

$iMsg = GUIGetMsg()

Select

Case $iMsg = $GUI_EVENT_CLOSE

$iRetvalue = 0

ExitLoop

Case $iMsg > $hButton_start

;button handle - dummy handle will give button index

$iRetvalue = $iMsg - $hButton_start

ExitLoop

EndSelect

; Timeout if required

If TimerDiff($iTimeout_begin) / 1000 >= $iTimeout And $iTimeout > 0 Then

$iRetvalue = 0

ExitLoop

EndIf

WEnd

$nOldOpt = Opt('GUIOnEventMode', $nOldOpt)

GUIDelete($hMsgGUI)

Return $iRetvalue

EndFunc;==>_ExtMsgBox()

; #FUNCTION# ====================================================================================================

================

; Name...........: _GetDefaultFont

; Description ...: Determines Windows default fonts

; Syntax.........: _GetDefaultFont([$sUsage])

; Parameters ....: $sUsage => Choice of 5 fonts: 'Caption', 'Small Caption', 'Menu', 'Status', 'Message Box' (default)

; Return values .: Success - Returns an array:

; $array[0] = font name

; $array[1] = font size

; Author ........: Melba 23, based on some original code by Larrydalooza

; Related .......:

; Link ..........;

; Example .......; Yes

; ====================================================================================================

===========================

Func _GetDefaultFont($sUsage = "")

Switch $sUsage

Case "Caption"

$iParam = 7

Case "Small Caption"

$iParam = 10

Case "Menu"

$iParam = 13

Case "Status"

$iParam = 14

Case Else ; Default setting will give "Message Box"

$iParam = 15

EndSwitch

; Get default system font data

$nonclientmetrics = DllStructCreate("uint;int;int;int;int;int;byte[60];int;int;byte[60];int;int;byte[60];byte[60];byte[60]")

DLLStructSetData($nonclientmetrics, 1, DllStructGetSize($nonclientmetrics))

DLLCall("user32.dll", "int", "SystemParametersInfo", "int", 41, "int", DllStructGetSize($nonclientmetrics), "ptr", DllStructGetPtr($nonclientmetrics), "int", 0)

Local $aFontData[2]

; Read font data for required font

$dLogFont = DllStructCreate("long;long;long;long;long;byte;byte;byte;byte;byte;byte;byte;byte;char[32]", DLLStructGetPtr($nonclientmetrics, $iParam))

$aFontData[0] = DllStructGetData($dLogFont, 14) ; Font name

$aFontData[1] = Abs(DllStructGetData($dLogFont, 1)) * .75 ; Font size

Return $aFontData

EndFunc ;=>_GetDefaultFont

This took a couple of really wet weekends to get working to my satisfaction, but if anyone has a better or more accurate way to gauge the depth of the label, I would love to see it.

M23

P.S. And if anyone has any comments on the overall _ExtMsgBox function, please feel free!

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

You may get some ideas from this example.

#include <GuiConstantsEx.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#include <GDIPlus.au3>

$Gui = GUICreate("resize label to text width", 500, 500)

$label1 = _GUICtrlCreateLabelEx("A label Ex", 5, 5, $SS_CENTER, 0x00ff00, 10, 400, 2, "Times New Roman")

$label1a = GUICtrlCreateLabel("A label", 90, 5)
GUICtrlSetBkColor(-1, 0x00ff00)
GUICtrlSetFont(-1, 10, 400, 2, "Times New Roman")

$label2 = _GUICtrlCreateLabelEx("A big font label", 5, 30, $SS_CENTER, 0x00ff00, 12, 600, 1, "Arial")
;GUICtrlSetBkColor(-1, 0x00ff00)
;GUICtrlSetFont(-1, 12, 600, 2, "Arial")

$label3 = _GUICtrlCreateLabelEx("A label that will be padded", 5, 60, $SS_CENTER, 0x00ff00, 12, 400, 2, "Times New Roman", 25)
;GUICtrlSetBkColor(-1, 0x00ff00)
;GUICtrlSetFont(-1, 12, 400, 2, "Times New Roman")

$label4 = _GUICtrlCreateLabelEx("A big label that will not be padded", 5, 90, $SS_CENTER, 0x00ff00, 20, 800, 14, "Arial")
$label4 = _GUICtrlCreateLabelEx("A big label that will not be padded", 180, 140, $SS_CENTER, 0x00ff00, 20, 800, 0, "Arial", 0, 101)
GUISetState()

While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd


; ============== _GUICtrlCreateLabelEx ========================================================
;$sText -The text of the control.
;$left - The left side of the control
;$top  - The top of the control.
;$style - $SS_LEFT, $SS_CENTER, $SS_RIGHT from Label/Static Styles
;$BkGndCol - background color The RGB color to use.
;$size   - Fontsize
;$weight - Font weight (default 400 = normal).
;$attribute [optional] To define 0 - Normal weight or thickness  2 underlined:4 strike:
;       8 char format (add together the values of all the styles required, 2+4 = italic and underlined)
;$fontname - The name of the font to use.
;$iPad - Integer, add spaces to string $sText.
;$iMultiLineRectWidth - Will cause multi lines if less than width of string, $sText, rectangle.
;
Func _GUICtrlCreateLabelEx($sText, $left, $top, $style = $SS_CENTER, $BkGndCol = $GUI_BKCOLOR_TRANSPARENT, $size = 10, _
        $weight = 400, $attribute = 0, $fontname = "Arial", $iPad = 0, $iMultiLineRectWidth = @DesktopWidth)
    
    Local $hWin, $hRetLabel, $hGraphic, $hFamily, $hGDIFont, $tLayout, $aInfo, $hWdith, $hHeight
    
    $hWin = WinGetHandle("[ACTIVE]")
    _GDIPlus_Startup()
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWin)
    $hFamily = _GDIPlus_FontFamilyCreate($fontname)
    $hGDIFont = _GDIPlus_FontCreate($hFamily, $size, $attribute)
    $hFormat = _GDIPlus_StringFormatCreate()
    $tLayout = _GDIPlus_RectFCreate($left, $top, $iMultiLineRectWidth, @DesktopHeight)
    $aInfo = _GDIPlus_GraphicsMeasureString($hGraphic, $sText, $hGDIFont, $tLayout, $hFormat)
    $hWdith = DllStructGetData($aInfo[0], 3)
    $hHeight = DllStructGetData($aInfo[0], 4)
    ;ConsoleWrite("$hWdith    " & $hWdith & "  $hHeight  " & $hHeight & @CRLF)
    If Mod($attribute, 2) = 1 Then $attribute = $attribute - 1
    $hRetLabel = GUICtrlCreateLabel($sText, $left, $top, $hWdith + $iPad, $hHeight, $style)
    GUICtrlSetBkColor(-1, $BkGndCol)
    GUICtrlSetFont(-1, $size, $weight, $attribute, $fontname)
    _WinAPI_RedrawWindow($hWin, 0, 0, BitOR($RDW_ERASE, $RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_FRAME, $RDW_ALLCHILDREN))
    _GDIPlus_FontDispose($hGDIFont)
    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_StringFormatDispose($hFormat)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_Shutdown()
    Return $hRetLabel
EndFunc   ;==>_GUICtrlCreateLabelEx

Link to comment
Share on other sites

  • Moderators

@Malkey,

Thanks for that - looks like a pretty definitive answer.

I had not really looked into GDI before. A whole new world to explore! Ah well, the weekend is forecast to be wet and I have collected all the leaves for this year ;-)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Thanks for that - looks like a pretty definitive answer.

Looking at that _GUICtrlCreateLabelEx() function again. Two more parameters could be added.

1/ An $iPad for height; and,

2/ An ExStyles parameter which would be added to the end of the GUICtrlCreateLabel() function within the _GUICtrlCreateLabelEx() function.

I was playing with these ExStyles - $WS_EX_DLGMODALFRAME , $WS_EX_OVERLAPPEDWINDOW, $WS_EX_STATICEDGE, $WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE. Some of them need padding to the height because of the extra pretty border created around the label.

Link to comment
Share on other sites

  • Moderators

@Malkey,

Your GDI example works well if there is only 1 line of text, but as soon as you try to measure multi-line text it sometimes goes awry depending on the font used.

The following code using your GUICtrlCreateLabelEx function on a series of identical labels with different fonts should make it clear:

CODE

#include <GuiConstantsEx.au3>

#include <WinAPI.au3>

#include <WindowsConstants.au3>

#include <StaticConstants.au3>

#include <GDIPlus.au3>

$Gui = GUICreate("GDI label depth anomalies", 600, 400)

GUISetState()

$msg = "This is the first line." & @CRLF & _

"and another" & @CRLF & _

"followed by another" & @CRLF & _

"and another" & @CRLF & _

"and yet another" & @CRLF & _

"and another" & @CRLF & _

"and one more" & @CRLF & _

"and finally the last"

$label0 = _GUICtrlCreateLabelEx($msg, 5, 5, $SS_LEFT, 0x00ff00, 9, 400, 0, "Segoe UI")

$label1 = _GUICtrlCreateLabelEx($msg, 205, 5, $SS_CENTER, 0xffff00, 9, 400, 0, "Times New Roman")

$label2 = _GUICtrlCreateLabelEx($msg, 405, 5, $SS_RIGHT, 0xffff00, 9, 400, 0, "Arial")

$label3 = _GUICtrlCreateLabelEx($msg, 5, 205, $SS_LEFT, 0xffff00, 9, 400, 0, "Georgia")

$label4 = _GUICtrlCreateLabelEx($msg, 205, 205, $SS_CENTER, 0xffff00, 9, 400, 0, "Microsoft Sans Serif")

$label5 = _GUICtrlCreateLabelEx($msg, 405, 205, $SS_RIGHT, 0x00ff00, 9, 400, 0, "Comic Sans MS")

While 1

$msg = GUIGetMsg()

If $msg = $GUI_EVENT_CLOSE Then Exit

WEnd

Exit

; ============== _GUICtrlCreateLabelEx ========================================================

;$sText -The text of the control.

;$left - The left side of the control

;$top - The top of the control.

;$style - $SS_LEFT, $SS_CENTER, $SS_RIGHT from Label/Static Styles

;$BkGndCol - background color The RGB color to use.

;$size - Fontsize

;$weight - Font weight (default 400 = normal).

;$attribute [optional] To define 0 - Normal weight or thickness 2 underlined:4 strike:

; 8 char format (add together the values of all the styles required, 2+4 = italic and underlined)

;$fontname - The name of the font to use.

;$iPad - Integer, add spaces to string $sText.

;$iMultiLineRectWidth - Will cause multi lines if less than width of string, $sText, rectangle.

;

Func _GUICtrlCreateLabelEx($sText, $left, $top, $style = $SS_CENTER, $BkGndCol = $GUI_BKCOLOR_TRANSPARENT, $size = 10, _

$weight = 400, $attribute = 0, $fontname = "Arial", $iPad = 0, $iMultiLineRectWidth = @DesktopWidth)

Local $hWin, $hRetLabel, $hGraphic, $hFamily, $hGDIFont, $tLayout, $aInfo, $hWdith, $hHeight

$hWin = WinGetHandle("[ACTIVE]")

_GDIPlus_Startup()

$hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWin)

$hFamily = _GDIPlus_FontFamilyCreate($fontname)

$hGDIFont = _GDIPlus_FontCreate($hFamily, $size, $attribute)

$hFormat = _GDIPlus_StringFormatCreate()

$tLayout = _GDIPlus_RectFCreate($left, $top, $iMultiLineRectWidth, @DesktopHeight)

$aInfo = _GDIPlus_GraphicsMeasureString($hGraphic, $sText, $hGDIFont, $tLayout, $hFormat)

$hWdith = DllStructGetData($aInfo[0], 3)

$hHeight = DllStructGetData($aInfo[0], 4)

;ConsoleWrite("$hWdith " & $hWdith & " $hHeight " & $hHeight & @CRLF)

If Mod($attribute, 2) = 1 Then $attribute = $attribute - 1

$hRetLabel = GUICtrlCreateLabel($sText, $left, $top, $hWdith + $iPad, $hHeight, $style)

GUICtrlSetBkColor(-1, $BkGndCol)

GUICtrlSetFont(-1, $size, $weight, $attribute, $fontname)

_WinAPI_RedrawWindow($hWin, 0, 0, BitOR($RDW_ERASE, $RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_FRAME, $RDW_ALLCHILDREN))

_GDIPlus_FontDispose($hGDIFont)

_GDIPlus_FontFamilyDispose($hFamily)

_GDIPlus_StringFormatDispose($hFormat)

_GDIPlus_GraphicsDispose($hGraphic)

_GDIPlus_Shutdown()

Return $hRetLabel

EndFunc ;==>_GUICtrlCreateLabelEx

The green labels have all the text displayed - the yellow ones are missing all or part of the bottom line (the font names are from Vista so may need adjusting if you have an earlier Windows version). And even when all the text is displayed there is a significant difference in the added padding at the bottom. The lower left label even wraps itself without being asked to!

Any idea why this is happening? It is a serious hiccup in the label sizing process which looked to have been solved on Monday!

M23

Edit after a bit more Google searching:

Looks as if this is a well known problem. I have found a number of claimed "solutions", but as I am not literate in the various languages used, they unfortunately do not mean much to me. The best advice I found was to 'guesstimate', which is what I was doing before - and not very satisfactory!

Edited by Melba23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Any idea why this is happening? It is a serious hiccup in the label sizing process which looked to have been solved on Monday!

I rewrote the example using the longest line in the label's text to determine the width of the text rectangle. And added a padding parameter for height.

This is what I found.

A problem with fonts, "Georgia" and "Comic Sans MS" was the attribute parameter (regular, 0), used in _GDIPlus_FontCreate(), does not exist for those fonts.

Once the padding is determined for a particular font, the padding works for all different attributes (bold, italics,...) of the font, that the font allows.

The green labels have padding.

#include <GuiConstantsEx.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#include <GDIPlus.au3>

$Gui = GUICreate("GDI label depth anomalies", 600, 400)

GUISetState()

$msg = "This is the first line." & @CRLF & _
        "and another" & @CRLF & _
        "followed by another" & @CRLF & _
        "and another" & @CRLF & _
        "and yet another" & @CRLF & _
        "and another" & @CRLF & _
        "and one more" & @CRLF & _
        "and finally the last"

$label0 = _GUICtrlCreateLabelEx($msg, 5, 5, $SS_LEFT, 0x00ff00, 9, 400, 0, "Segoe UI", 0, -16)

$label1 = _GUICtrlCreateLabelEx($msg, 205, 5, $SS_CENTER, 0x00ff00, 9, 400, 0, "Times New Roman", 0, 2)

$label2 = _GUICtrlCreateLabelEx($msg, 405, 5, $SS_RIGHT, 0xffff00, 9, 400, 0, "Arial")

$label3 = _GUICtrlCreateLabelEx($msg, 5, 205, $SS_LEFT, 0xffff00, 9, 400, 2, "Georgia"); Bold -1, Italics - 2, Bold Italics - 3 only

$label4 = _GUICtrlCreateLabelEx($msg, 205, 205, $SS_CENTER, 0xffff00, 9, 400, 0, "Microsoft Sans Serif")

$label5 = _GUICtrlCreateLabelEx($msg, 405, 205, $SS_RIGHT, 0x00ff00, 9, 400, 3, "Comic Sans MS", -8, -15) ;Bold -1, Bold Italics - 3 only

While 1
    $msg = GUIGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then Exit
WEnd

Exit

; ============== _GUICtrlCreateLabelEx ========================================================
;$sText -The text of the control.
;$left - The left side of the control
;$top - The top of the control.
;$style - $SS_LEFT, $SS_CENTER, $SS_RIGHT from Label/Static Styles
;$BkGndCol - background color The RGB color to use.
;$size - Fontsize
;$weight - Font weight (default 400 = normal).
;$attribute [optional] To define 0 - Normal weight or thickness 2 underlined:4 strike:
; 8 char format (add together the values of all the styles required, 2+4 = italic and underlined)
;$fontname - The name of the font to use.
;$iPadWidth - Integer, add/substract spaces to string $sText width.
;$iPadHeight - Integer, add/substract spaces to string $sText height.
;$iMultiLineRectWidth - Will cause multi lines if less than width of string, $sText, rectangle (when no @CRLF).
;
Func _GUICtrlCreateLabelEx($sText, $left, $top, $style = $SS_CENTER, $BkGndCol = $GUI_BKCOLOR_TRANSPARENT, $size = 10, _
        $weight = 400, $attribute = 0, $fontname = "Arial", $iPadWidth = 0, $iPadHeight = 0, $iMultiLineRectWidth = @DesktopWidth)

    Local $hWin, $hRetLabel, $hGraphic, $hFamily, $hGDIFont, $tLayout, $aInfo, $hWdith, $hHeight, $bFlag = False
    If StringRegExp($sText, "\x0a|\x0d", 0) = 1 Then
        $aText = StringRegExp($sText, "\w.*[^\x0a|\x0d]", 3)
        Local $MavChar = 0
        For $x = 1 To UBound($aText) - 1
            If StringLen($aText[$x]) > StringLen($aText[$MavChar]) Then $MavChar = $x
        Next
        $sMeasure = $aText[$MavChar]
        $bFlag = True
    Else
        $sMeasure = $sText
    EndIf

    $hWin = WinGetHandle("[ACTIVE]")
    _GDIPlus_Startup()
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWin)
    $hFamily = _GDIPlus_FontFamilyCreate($fontname)
    $hGDIFont = _GDIPlus_FontCreate($hFamily, $size, $attribute)
    $hFormat = _GDIPlus_StringFormatCreate()
    $tLayout = _GDIPlus_RectFCreate($left, $top, $iMultiLineRectWidth, @DesktopHeight)
    $aInfo = _GDIPlus_GraphicsMeasureString($hGraphic, $sMeasure, $hGDIFont, $tLayout, $hFormat)
    $hWdith = DllStructGetData($aInfo[0], 3)
    $hHeight = DllStructGetData($aInfo[0], 4)
    If $bFlag Then $hHeight = $hHeight * UBound($aText)
    If Mod($attribute, 2) = 1 Then $attribute = $attribute - 1
    $hRetLabel = GUICtrlCreateLabel($sText, $left, $top, $hWdith + $iPadWidth, $hHeight + $iPadHeight, $style)
    GUICtrlSetBkColor(-1, $BkGndCol)
    GUICtrlSetFont(-1, $size, $weight, $attribute, $fontname)
    _WinAPI_RedrawWindow($hWin, 0, 0, BitOR($RDW_ERASE, $RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_FRAME, $RDW_ALLCHILDREN))
    _GDIPlus_FontDispose($hGDIFont)
    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_StringFormatDispose($hFormat)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_Shutdown()
    Return $hRetLabel
EndFunc   ;==>_GUICtrlCreateLabelEx
Link to comment
Share on other sites

  • Moderators

Hi all,

After a bit of thought I believe I have developed a working function to resize a label holding a multi-line message that needs wrapping - using GDI to get accurate results for proportional fonts. As GDI does not cope very well with the multiline fomat, I went the route of working with single lines at a time and seeing if they needed wrapping. The pseudo code looks like this:

- Create big GUI

- Count the number of lines in the message to display

- Create label without width and depth parameters to get unwrapped size

- Divide the label height by the number of lines to get the height for a single line

- If the label is wider than the maximum required then:

- - Get the pixel length of each line in the text using GDI

- - Divide this length by the max width required to get the number of lines when wrapped

- - Add the Integer part of this result to the number of lines (because the original line is already counted)

- - Calculate the new height by multipying the new line count by the line height determined earlier

- Of course if the label is not too wide

- - The height does not need to be altered

- Resize and relocate label using GUICtrlSetPos()

- Resize and relocate GUI using WinMove()

The actual code extract is here (I think the variable names and comments are clear):

CODE

; Create oversized GUI - will be resized later

$hMsgGUI = GUICreate($sTitle, 500, 500, -1, -1, BitOr($WS_POPUPWINDOW, $WS_CAPTION))

; Set to font required

GUISetFont($iFont_Size, 400, 0, $sFont_Name)

; Count lines in the message to display

$aLines = StringSplit($sText, @CRLF, 1)

$iCount = $aLines[0]

; Now create label with unwrapped lines to check on max width

$hMsgLabel = GUICtrlCreateLabel($sText, 10 + $iIcon_reduction, 10)

; Label MUST resize with GUI

GUICtrlSetResizing (-1, $GUI_DOCKALL)

; Get label size

$aLabel_Pos = ControlGetPos($hMsgGUI, "", $hMsgLabel)

; Get height per line - there is always an 8 pixel pad below and to the side of a label

$iLine_Height = Int(($aLabel_Pos[3] - 8) / $iCount)

; If label wider than max width required

If $aLabel_Pos[2] > $iLabel_Width_Max Then

; Get pixel length for each line

Dim $aLine_Len[$aLines[0] + 1]

_Size_Lines($aLines, $aLine_Len)

; Check each line for wrapping

For $j = 1 To $aLines[0]

; If wrapping needed, add additional lines to count

If $aLine_Len[$j] > $iLabel_Width_Max Then

$iCount += Int($aLine_Len[$j] / $iLabel_Width_Max)

EndIf

Next

; Calculate new depth for label

$iLabelheight = $iCount * $iLine_Height + 8

EndIf

; Then resize label with GUICtrlSetPos()

; And finally reposition and resize GUI with WinMove()

; -------

Func _Size_Lines($aLines, ByRef $aLine_Len)

$hWin = WinGetHandle("[ACTIVE]")

_GDIPlus_Startup()

$hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWin)

$hFamily = _GDIPlus_FontFamilyCreate($sFont_Name)

$hGDIFont = _GDIPlus_FontCreate($hFamily, $iFont_Size, 400)

$hFormat = _GDIPlus_StringFormatCreate()

$tLayout = _GDIPlus_RectFCreate(0, 0, @DesktopWidth, @DesktopHeight)

For $j = 1 To $aLines[0]

$aInfo = _GDIPlus_GraphicsMeasureString($hGraphic, $aLines[$j], $hGDIFont, $tLayout, $hFormat)

$aLine_Len[$j] = Int(DllStructGetData($aInfo[0], 3) + 1) - 8 ; Padding again

Next

_GDIPlus_StringFormatDispose($hFormat)

_GDIPlus_FontDispose($hGDIFont)

_GDIPlus_FontFamilyDispose($hFamily)

_GDIPlus_GraphicsDispose($hGraphic)

_GDIPlus_Shutdown()

Return

EndFunc

I have not been able to get this to fail yet - but I am sure someone will ;-)

Thanks to all who contributed to this topic, I found it most instructive.

M23

Edit:

@Malkey,

Our earlier posts were nearly simultaneous. Thanks for the explanation about the missing attribute parameters for certain fonts. Amazing what you find when you start digging into the workings, isn't it?

M23

Edited by Melba23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

  • 1 year later...

Hi,

although it's been a while, thanks for that little piece of code. Just needed something like this to measure the actual size of a label's text.

But there's a little issue, I'd like to correct. In this line...

$hGDIFont = _GDIPlus_FontCreate($hFamily, $iFont_Size, 400)

... you used the font weight as third parameter, as it is also used in GuiCtrlSetFont().

Because this parameter only accepts the values 0, 1, 2, 4 and 8, 400 or 600 (for bold text) will probably result in 0, which is normal typeface. So, bold text will always be calculated too short. In my case, I used the calculated width for my text label and as a result it always got cut off.

Bottom line:

$hGDIFont = _GDIPlus_FontCreate($hFamily, $iFont_Size, 2)  ;2 is bold typeface

Just wanted to mention it in case another fellow stumbles across this.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...