gregnottage Posted September 15, 2009 Posted September 15, 2009 Hi guys, I've been wrestling with this all day, and I've reached a point that I can't seem to workaround. I found Melba23's great UDF (_StringSize) to help with resizing text to fit on a GUI window which works fine. However, I can't workout how to write the dynamic window sizing properly. What I want to achieve is a form that has a fixed width, but a height that is dynamically built depending on the amount of the text in the first text label ($hLabel). If the text in the first label ($hLabel) is spread onto several lines (which is taken care of by the _StringSize function), then I want the height of the form to be re-sized accordingly. I also want the other items dynamically placed on the form at the correct height, depending on how big the first text label ($hLabel) is. I'm trying to evenly space everything out on the form automatically without needing the $hLabel text label size to be pre-determined. Hope I've explained this correctly - but please let me know if you need some clarification? Anyway, here's what I've got so far. If any of you gurus out there can shed any light on where I'm going wrong I would really appreciate it ;-) Many thanks, Greg. expandcollapse popup;Set AutoIt options AutoItSetOption("TrayIconDebug", 0); Show debug info in tray icon AutoItSetOption("WinTitleMatchMode", 2); 2 = Match any substring in title AutoItSetOption("TrayIconHide", 1); 0 = do not hide, 1 = hide tray icon #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include-once #include <WindowsConstants.au3> #include <SendMessage.au3> #include <WinAPI.au3> ;Declare Variables $strMsg1 = "This is a long message for testing purposes to push the text onto two lines" ;$strMsg1 = "This is a shorter message for testing" ;$strMsg1 = "This is a very long message for longer testing purposes to push the text onto three lines ...." $strMsg2 = "Next Line" $strMsg3 = "Please wait..." $strFullText = $strMsg1 & @CRLF & @CRLF & $strMsg2 & @CRLF & @CRLF & $strMsg3; Build the message text $sFont = "Arial" $iSize = 14 $iWeight = 400 $iAttrib = 0 $iMaxWidth = 360 $iFrmWidth = 400 $iFrmHeight = 300 $iFrmLeft = 425 $iFrmTop = 15 $iPercent = 0 ;Main Script GUICreate("ScreenMsg", $iFrmWidth, $iFrmHeight, $iFrmLeft, $iFrmTop, BitOR($WS_DLGFRAME,$WS_POPUP,$WS_CLIPSIBLINGS), BitOR($WS_EX_TOPMOST,$WS_EX_WINDOWEDGE)) GUISetBkColor(0x000000) $aMsgReturn = _StringSize($strFullText, $iSize, $iWeight, $iAttrib, $sFont, $iMaxWidth) $hLabel = GUICtrlCreateLabel($aMsgReturn[0], 10, 80, $aMsgReturn[2], $aMsgReturn[3], $SS_CENTER) GUICtrlSetFont(-1, $iSize, $iWeight, $iAttrib, $sFont) GUICtrlSetColor(-1, 0xC0C0C0) $iMidFrm = $iFrmWidth/2; Middle of Form $iMidLbl = $aMsgReturn[2]/2; Middle of Label $iLeftPos = $iMidFrm - $iMidLbl; Left positioning for label GUICtrlSetPos (-1, $iLeftPos, 80) ;Workout where to place the form $iFrmLeft = (@DesktopWidth / 2) - $iMidFrm $aiPos = ControlGetPos("ScreenMsg", "", $hLabel) $iProgTop = $aiPos[1] + $aiPos[3] $iProgTop = $aiPos[1] + $aiPos[3] + 30 $iProgLeft = $iMidFrm - (350/2) $Progress = GUICtrlCreateProgress($iProgLeft, $iProgTop, 350, 21) $iPos = ControlGetPos("ScreenMsg", "", $Progress) $iFrmHeight = $iPos[1] + $iPos[3] + 30 WinMove("ScreenMsg", "", $iFrmLeft, $iFrmTop, $iFrmWidth, $iFrmHeight) GUISetState(@SW_SHOW) While 1 $iPercent = IniRead(@ScriptDir & "\Progress.INI", "ProgressBar", "PercentCompleted", "0") GUICtrlSetData($Progress, $iPercent) $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd ;Define Functions ; #FUNCTION# ======================================================================================= ; ; Name...........: _StringSize ; Description ...: Returns size of rectangle required to display string - width can be chosen ; Syntax ........: _StringSize($sText[, $iSize[, $iWeight[, $iAttrib[, $sName[, $iWidth]]]]]) ; Parameters ....: $sText - String to display ; $iSize - Font size in points - default AutoIt GUI default ; $iWeight - Font weight (400 = normal) - default AutoIt GUI default ; $iAttrib - Font attribute (0-Normal, 2-Italic, 4-Underline, 8 Strike - default AutoIt ; $sName - Font name - default AutoIt GUI default ; $iWidth - [optional] Width of rectangle - default is unwrapped width of string ; Requirement(s) : v3.2.12.1 or higher ; Return values .: Success - Returns array with details of rectangle required for text: ; |$array[0] = String formatted with @CRLF at required wrap points ; |$array[1] = Height of single line in selected font ; |$array[2] = Width of rectangle required to hold formatted string ; |$array[3] = Height of rectangle required to hold formatted string ; Failure - Returns 0 and sets @error: ; |1 - Incorrect parameter type (@extended = parameter index) ; |2 - Failure to create GUI to test label size ; |3 - Failure of _WinAPI_SelectObject ; |4 - Font too large for chosen width - longest word will not fit ; Author ........: Melba23 ; Modified ......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: Yes ;=================================================================================================== Func _StringSize($sText, $iSize = Default, $iWeight = Default, $iAttrib = Default, $sName = Default, $iWidth = 0) Local $hWnd, $hFont, $hDC, $oFont, $tSize, $hGUI, $hText_Label, $sTest_Line Local $iLine_Count, $iLine_Width, $iWrap_Count, $iLast_Word Local $asLines[1], $avSize_Info[4], $aiPos[4] ; Check parameters are correct type If Not IsString($sText) Then Return SetError(1, 1, 0) If Not IsNumber($iSize) And $iSize <> Default Then Return SetError(1, 2, 0) If Not IsInt($iWeight) And $iWeight <> Default Then Return SetError(1, 3, 0) If Not IsInt($iAttrib) And $iAttrib <> Default Then Return SetError(1, 4, 0) If Not IsString($sName) And $sName <> Default Then Return SetError(1, 5, 0) If Not IsNumber($iWidth) Then Return SetError(1, 6, 0) ; Create GUI to contain test labels, set to passed font parameters $hGUI = GUICreate("", 1200, 500, 10, 10) If $hGUI = 0 Then Return SetError(2, 0, 0) GUISetFont($iSize, $iWeight, $iAttrib, $sName) ; Store unwrapped text $avSize_Info[0] = $sText ; Ensure EoL is @CRLF and break text into lines If StringInStr($sText, @CRLF) = 0 Then StringRegExpReplace($sText, "[x0a|x0d]", @CRLF) $asLines = StringSplit($sText, @CRLF, 1) ; Draw label with unwrapped lines to check on max width $hText_Label = GUICtrlCreateLabel($sText, 10, 10) $aiPos = ControlGetPos($hGUI, "", $hText_Label) GUICtrlDelete($hText_Label) ; Store line height for this font size after removing label padding (always 8) $avSize_Info[1] = ($aiPos[3] - 8)/ $asLines[0] ; Store width and height of this label $avSize_Info[2] = $aiPos[2] $avSize_Info[3] = $aiPos[3] - 4 ; Reduce margin ; Check if wrapping is required If $aiPos[2] > $iWidth And $iWidth > 0 Then ; Set returned text element to null $avSize_Info[0] = "" ; Set width element to max allowed $avSize_Info[2] = $iWidth ; Set line count to zero $iLine_Count = 0 ; Take each line in turn For $j = 1 To $asLines[0] ; Size this line unwrapped $hText_Label = GUICtrlCreateLabel($asLines[$j], 10, 10) $aiPos = ControlGetPos($hGUI, "", $hText_Label) GUICtrlDelete($hText_Label) ; Check wrap status If $aiPos[2] < $iWidth Then ; No wrap needed so count line and store $iLine_Count += 1 $avSize_Info[0] &= $asLines[$j] & @CRLF Else ; Wrap needed so need to count wrapped lines ; Create label to hold line as it grows $hText_Label = GUICtrlCreateLabel("", 0, 0) ; Initialise Point32 method $hWnd = ControlGetHandle($hGui, "", $hText_Label) $hFont = _SendMessage($hWnd, $WM_GETFONT) $hDC = _WinAPI_GetDC($hWnd) $oFont = _WinAPI_SelectObject($hDC, $hFont) If $oFont = 0 Then Return SetError(3, 0, 0) ; Zero counter $iWrap_Count = 0 While 1 ; Set line width to 0 $iLine_Width = 0 ; Initialise pointer for end of word $iLast_Word = 0 For $i = 1 To StringLen($asLines[$j]) ; Is this just past a word ending? If StringMid($asLines[$j], $i, 1) = " " Then $iLast_Word = $i - 1 ; Increase line by one character $sTest_Line = StringMid($asLines[$j], 1, $i) ; Place line in label GUICtrlSetData($hText_Label, $sTest_Line) ; Get line length $tSize = _WinAPI_GetTextExtentPoint32($hDC, $sTest_Line) $iLine_Width = DllStructGetData($tSize, "X") ; If too long exit the loop If $iLine_Width >= $iWidth - Int($iSize / 2) Then ExitLoop Next ; End of the line of text? If $i > StringLen($asLines[$j]) Then ; Yes, so add final line to count $iWrap_Count += 1 ; Store line $avSize_Info[0] &= $sTest_Line & @CRLF ExitLoop Else ; No, but add line just completed to count $iWrap_Count += 1 ; Check at least 1 word completed or return error If $iLast_Word = 0 Then GUIDelete($hGUI) Return SetError(4, 0, 0) EndIf ; Store line up to end of last word $avSize_Info[0] &= StringLeft($sTest_Line, $iLast_Word) & @CRLF ; Strip string to point reached $asLines[$j] = StringTrimLeft($asLines[$j], $iLast_Word) ; Trim leading whitespace $asLines[$j] = StringStripWS($asLines[$j], 1) ; Repeat with remaining characters in line EndIf WEnd ; Add the number of wrapped lines to the count $iLine_Count += $iWrap_Count ; Clean up _WinAPI_ReleaseDC($hWnd, $hDC) GUICtrlDelete($hText_Label) EndIf Next ; Convert lines to pixels and add reduced margin $avSize_Info[3] = ($iLine_Count * $avSize_Info[1]) + 4 EndIf ; Clean up GUIDelete($hGUI) ; Return array Return $avSize_Info EndFunc ; => _StringSize ;Script End
Moderators Melba23 Posted September 26, 2009 Moderators Posted September 26, 2009 gregnottage,Sorry about the delay in replying - I was on holiday for the past few weeks.In my opinion, you are overcomplicating things a bit. As you want a fixed width GUI, the only real variable is the height of the label. Once you have that, the rest is simple maths. Take a look at this - I have commented the process:expandcollapse popup;Set AutoIt options AutoItSetOption("TrayIconDebug", 0); Show debug info in tray icon AutoItSetOption("WinTitleMatchMode", 2); 2 = Match any substring in title AutoItSetOption("TrayIconHide", 1); 0 = do not hide, 1 = hide tray icon #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include-once #include <WindowsConstants.au3> #include <SendMessage.au3> #include <WinAPI.au3> ;Declare Variables $strMsg1 = "This is a long message for testing purposes to push the text onto two lines" ;$strMsg1 = "This is a shorter message for testing" ;$strMsg1 = "This is a very long message for longer testing purposes to push the text onto three lines ...." $strMsg2 = "Next Line" $strMsg3 = "Please wait..." $strFullText = $strMsg1 & @CRLF & @CRLF & $strMsg2 & @CRLF & @CRLF & $strMsg3; Build the message text $sFont = "Arial" $iSize = 14 $iWeight = 400 $iAttrib = 0 $iMaxWidth = 360 $iFrmWidth = 400 $iFrmHeight = 300 $iFrmLeft = 425 $iFrmTop = 15 $iPercent = 0 ;Main Script GUICreate("ScreenMsg", $iFrmWidth, $iFrmHeight, $iFrmLeft, $iFrmTop, BitOR($WS_DLGFRAME, $WS_POPUP, $WS_CLIPSIBLINGS), BitOR($WS_EX_TOPMOST, $WS_EX_WINDOWEDGE)) GUISetBkColor(0x000000) $aMsgReturn = _StringSize($strFullText, $iSize, $iWeight, $iAttrib, $sFont, $iMaxWidth) $hLabel = GUICtrlCreateLabel($aMsgReturn[0], 10, 80, $aMsgReturn[2], $aMsgReturn[3], $SS_CENTER) GUICtrlSetFont(-1, $iSize, $iWeight, $iAttrib, $sFont) GUICtrlSetColor(-1, 0xC0C0C0) $iMidFrm = $iFrmWidth / 2; Middle of Form $iMidLbl = $aMsgReturn[2] / 2; Middle of Label $iLeftPos = $iMidFrm - $iMidLbl; Left positioning for label GUICtrlSetPos(-1, $iLeftPos, 80) ;Workout where to place the form $iFrmLeft = (@DesktopWidth / 2) - $iMidFrm $aiPos = ControlGetPos("ScreenMsg", "", $hLabel) $iProgTop = $aiPos[1] + $aiPos[3] $iProgTop = $aiPos[1] + $aiPos[3] + 30 $iProgLeft = $iMidFrm - (350 / 2) $Progress = GUICtrlCreateProgress($iProgLeft, $iProgTop, 350, 21) $iPos = ControlGetPos("ScreenMsg", "", $Progress) $iFrmHeight = $iPos[1] + $iPos[3] + 30 WinMove("ScreenMsg", "", $iFrmLeft, $iFrmTop, $iFrmWidth, $iFrmHeight) GUISetState(@SW_SHOW) ; We know all the widths because you set the max value, so all we are interested in is the height of the message ; First measure the message to get the label height in $aMsgReturn[3] $aMsgReturn = _StringSize($strFullText, $iSize, $iWeight, $iAttrib, $sFont, $iMaxWidth) ; You have set the top of the label at a margin of 80 so we now know that the bottom of the label is $aMsgReturn[3] + 80 ; Assume a further margin of 20 to the progressbar - which must therefore start at $aMsgReturn[3] + 100 ; You have set the progressbar to a height of 21, add another 30 as a final margin below and we get a form height of $aMsgReturn[3] + 151 ; Now we can create the form and place the controls ; Note I have deliberately added 300 to $iFrmTop to get the 2 versions to show together $hGUI = GUICreate("ScreenMsg", $iFrmWidth, $aMsgReturn[3] + 151, -1, $iFrmTop + 300, BitOR($WS_DLGFRAME, $WS_POPUP, $WS_CLIPSIBLINGS), BitOR($WS_EX_TOPMOST, $WS_EX_WINDOWEDGE)) GUISetBkColor(0x000000) $hLabel = GUICtrlCreateLabel($aMsgReturn[0], 20, 80, $iMaxWidth, $aMsgReturn[3], $SS_CENTER) GUICtrlSetFont(-1, $iSize, $iWeight, $iAttrib, $sFont) GUICtrlSetColor(-1, 0xC0C0C0) $Progress = GUICtrlCreateProgress(25, $aMsgReturn[3] + 100, 350, 21) GUISetState(@SW_SHOW) While 1 ;$iPercent = IniRead(@ScriptDir & "\Progress.INI", "ProgressBar", "PercentCompleted", "0") ;GUICtrlSetData($Progress, $iPercent) $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd ;Define Functions ; #FUNCTION# ======================================================================================= ; ; Name...........: _StringSize ; Description ...: Returns size of rectangle required to display string - width can be chosen ; Syntax ........: _StringSize($sText[, $iSize[, $iWeight[, $iAttrib[, $sName[, $iWidth]]]]]) ; Parameters ....: $sText - String to display ; $iSize - Font size in points - default AutoIt GUI default ; $iWeight - Font weight (400 = normal) - default AutoIt GUI default ; $iAttrib - Font attribute (0-Normal, 2-Italic, 4-Underline, 8 Strike - default AutoIt ; $sName - Font name - default AutoIt GUI default ; $iWidth - [optional] Width of rectangle - default is unwrapped width of string ; Requirement(s) : v3.2.12.1 or higher ; Return values .: Success - Returns array with details of rectangle required for text: ; |$array[0] = String formatted with @CRLF at required wrap points ; |$array[1] = Height of single line in selected font ; |$array[2] = Width of rectangle required to hold formatted string ; |$array[3] = Height of rectangle required to hold formatted string ; Failure - Returns 0 and sets @error: ; |1 - Incorrect parameter type (@extended = parameter index) ; |2 - Failure to create GUI to test label size ; |3 - Failure of _WinAPI_SelectObject ; |4 - Font too large for chosen width - longest word will not fit ; Author ........: Melba23 ; Modified ......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: Yes ;=================================================================================================== Func _StringSize($sText, $iSize = Default, $iWeight = Default, $iAttrib = Default, $sName = Default, $iWidth = 0) Local $hWnd, $hFont, $hDC, $oFont, $tSize, $hGUI, $hText_Label, $sTest_Line Local $iLine_Count, $iLine_Width, $iWrap_Count, $iLast_Word Local $asLines[1], $avSize_Info[4], $aiPos[4] ; Check parameters are correct type If Not IsString($sText) Then Return SetError(1, 1, 0) If Not IsNumber($iSize) And $iSize <> Default Then Return SetError(1, 2, 0) If Not IsInt($iWeight) And $iWeight <> Default Then Return SetError(1, 3, 0) If Not IsInt($iAttrib) And $iAttrib <> Default Then Return SetError(1, 4, 0) If Not IsString($sName) And $sName <> Default Then Return SetError(1, 5, 0) If Not IsNumber($iWidth) Then Return SetError(1, 6, 0) ; Create GUI to contain test labels, set to passed font parameters $hGUI = GUICreate("", 1200, 500, 10, 10) If $hGUI = 0 Then Return SetError(2, 0, 0) GUISetFont($iSize, $iWeight, $iAttrib, $sName) ; Store unwrapped text $avSize_Info[0] = $sText ; Ensure EoL is @CRLF and break text into lines If StringInStr($sText, @CRLF) = 0 Then StringRegExpReplace($sText, "[x0a|x0d]", @CRLF) $asLines = StringSplit($sText, @CRLF, 1) ; Draw label with unwrapped lines to check on max width $hText_Label = GUICtrlCreateLabel($sText, 10, 10) $aiPos = ControlGetPos($hGUI, "", $hText_Label) GUICtrlDelete($hText_Label) ; Store line height for this font size after removing label padding (always 8) $avSize_Info[1] = ($aiPos[3] - 8)/ $asLines[0] ; Store width and height of this label $avSize_Info[2] = $aiPos[2] $avSize_Info[3] = $aiPos[3] - 4 ; Reduce margin ; Check if wrapping is required If $aiPos[2] > $iWidth And $iWidth > 0 Then ; Set returned text element to null $avSize_Info[0] = "" ; Set width element to max allowed $avSize_Info[2] = $iWidth ; Set line count to zero $iLine_Count = 0 ; Take each line in turn For $j = 1 To $asLines[0] ; Size this line unwrapped $hText_Label = GUICtrlCreateLabel($asLines[$j], 10, 10) $aiPos = ControlGetPos($hGUI, "", $hText_Label) GUICtrlDelete($hText_Label) ; Check wrap status If $aiPos[2] < $iWidth Then ; No wrap needed so count line and store $iLine_Count += 1 $avSize_Info[0] &= $asLines[$j] & @CRLF Else ; Wrap needed so need to count wrapped lines ; Create label to hold line as it grows $hText_Label = GUICtrlCreateLabel("", 0, 0) ; Initialise Point32 method $hWnd = ControlGetHandle($hGui, "", $hText_Label) $hFont = _SendMessage($hWnd, $WM_GETFONT) $hDC = _WinAPI_GetDC($hWnd) $oFont = _WinAPI_SelectObject($hDC, $hFont) If $oFont = 0 Then Return SetError(3, 0, 0) ; Zero counter $iWrap_Count = 0 While 1 ; Set line width to 0 $iLine_Width = 0 ; Initialise pointer for end of word $iLast_Word = 0 For $i = 1 To StringLen($asLines[$j]) ; Is this just past a word ending? If StringMid($asLines[$j], $i, 1) = " " Then $iLast_Word = $i - 1 ; Increase line by one character $sTest_Line = StringMid($asLines[$j], 1, $i) ; Place line in label GUICtrlSetData($hText_Label, $sTest_Line) ; Get line length $tSize = _WinAPI_GetTextExtentPoint32($hDC, $sTest_Line) $iLine_Width = DllStructGetData($tSize, "X") ; If too long exit the loop If $iLine_Width >= $iWidth - Int($iSize / 2) Then ExitLoop Next ; End of the line of text? If $i > StringLen($asLines[$j]) Then ; Yes, so add final line to count $iWrap_Count += 1 ; Store line $avSize_Info[0] &= $sTest_Line & @CRLF ExitLoop Else ; No, but add line just completed to count $iWrap_Count += 1 ; Check at least 1 word completed or return error If $iLast_Word = 0 Then GUIDelete($hGUI) Return SetError(4, 0, 0) EndIf ; Store line up to end of last word $avSize_Info[0] &= StringLeft($sTest_Line, $iLast_Word) & @CRLF ; Strip string to point reached $asLines[$j] = StringTrimLeft($asLines[$j], $iLast_Word) ; Trim leading whitespace $asLines[$j] = StringStripWS($asLines[$j], 1) ; Repeat with remaining characters in line EndIf WEnd ; Add the number of wrapped lines to the count $iLine_Count += $iWrap_Count ; Clean up _WinAPI_ReleaseDC($hWnd, $hDC) GUICtrlDelete($hText_Label) EndIf Next ; Convert lines to pixels and add reduced margin $avSize_Info[3] = ($iLine_Count * $avSize_Info[1]) + 4 EndIf ; Clean up GUIDelete($hGUI) ; Return array Return $avSize_Info EndFunc ; => _StringSize ;Script EndYou can see that the 2 versions of the GUI are (as near as I can get them) identical. But try using the other versions of $strMsg1 - you will see that my version copes a bit better with the changing size of the label. Please ask if anything is unclear.M23  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 columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Â
gregnottage Posted September 28, 2009 Author Posted September 28, 2009 Hi Melba, Thanks for replying ;-) I did actually devise a workaround, which seems to be working. I'll post all my code below - but the 'magic' that helped me was to use the GUICtrlSetResizing($hLabel, $GUI_DOCKALL)command. This allowed me to resize everything without it all looking weird. expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Res_Comment=Script to display a message on-screen with progress bar #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #cs ---------------------------------------------------------------------------------- AutoIt Version: v3.3.0.0 Script Function: Script to display a message on-screen with progress bar #ce ---------------------------------------------------------------------------------- ;Script Start ;Set AutoIt options AutoItSetOption("TrayIconDebug", 0); Show debug info in tray icon AutoItSetOption("WinTitleMatchMode", 2); 2 = Match any substring in title AutoItSetOption("TrayIconHide", 1); 0 = do not hide, 1 = hide tray icon ;AutoItSetOption("GUIOnEventMode", 1); Enable/disable OnEvent functions notifications. 0 = (default) disable, 1 = enable #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include-once #include <WindowsConstants.au3> #include <SendMessage.au3> #include <WinAPI.au3> #include <Array.au3> ;Declare Variables $strMsg1 = IniRead(@ScriptDir & "\Progress.INI", "Message", "Msg1", "Message1") $strMsg2 = IniRead(@ScriptDir & "\Progress.INI", "Message", "Msg2", "Message2") $strMsg3 = IniRead(@ScriptDir & "\Progress.INI", "Message", "Msg3", "Please wait...") $strFullText = $strMsg1 & @CRLF & @CRLF & $strMsg2 & @CRLF & @CRLF & $strMsg3; Build the message text $sFont = "Arial" $iSize = 12 $iWeight = 551 $iAttrib = 0 $iMaxWidth = 320 $iFrmWidth = 360 $iFrmHeight = 300 $iFrmLeft = 425 $iFrmTop = 15 $iPercent = 0 $iPicWidth = 225 $iPicHeight = 97 ;Main Script GUICreate("ScreenMsg", $iFrmWidth, $iFrmHeight, $iFrmLeft, $iFrmTop, BitOR($WS_DLGFRAME,$WS_POPUP,$WS_CLIPSIBLINGS), $WS_EX_WINDOWEDGE) GUISetBkColor(0x000000) $oPic1 = GUICtrlCreatePic(@ScriptDir & "\logo.bmp", 0, 20, $iPicWidth, $iPicHeight, BitOR($SS_NOTIFY,$WS_GROUP,$WS_CLIPSIBLINGS)) $aMsgReturn = _StringSize($strFullText, $iSize, $iWeight, $iAttrib, $sFont, $iMaxWidth) $hLabel = GUICtrlCreateLabel($aMsgReturn[0], 10, 80, $aMsgReturn[2], $aMsgReturn[3], $SS_CENTER) GUICtrlSetFont(-1, $iSize, $iWeight, $iAttrib, $sFont) GUICtrlSetColor(-1, 0xC0C0C0) $iMidFrm = $iFrmWidth/2; Middle of Form $iMidLbl = $aMsgReturn[2]/2; Middle of Label $iLeftPos = $iMidFrm - $iMidLbl; Left positioning for label GUICtrlSetPos (-1, $iLeftPos, 130) GUICtrlSetResizing($hLabel, $GUI_DOCKALL); so the control will not move during resizing ;Workout where to place the form $iFrmLeft = (@DesktopWidth / 2) - $iMidFrm $aiPos = ControlGetPos("ScreenMsg", "", $hLabel) $iProgTop = $aiPos[1] + $aiPos[3] $iProgTop = $aiPos[1] + $aiPos[3] + 20 $iProgLeft = $iMidFrm - 162; Which is the width of the control/2 ,i.e. (350/2) $Progress = GUICtrlCreateProgress($iProgLeft, $iProgTop, 320, 21, $SS_CENTER) GUICtrlSetResizing($Progress, $GUI_DOCKALL) $iPos = ControlGetPos("ScreenMsg", "", $Progress) $iFrmHeight = $iPos[1] + $iPos[3] + 27 $iMidPic = $iPicWidth/2; Middle of picture $iPicLeft = $iMidFrm - $iMidPic GUICtrlSetPos($oPic1, $iPicLeft, 20, $iPicWidth, $iPicHeight) GUICtrlSetResizing($oPic1, $GUI_DOCKALL) WinMove("ScreenMsg", "", $iFrmLeft, $iFrmTop, $iFrmWidth, $iFrmHeight) GUISetState(@SW_SHOW) While 1 $iPercent = IniRead(@ScriptDir & "\Progress.INI", "ProgressBar", "PercentCompleted", "0") GUICtrlSetData($Progress, $iPercent) $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd ;Define Functions ; #FUNCTION# ======================================================================================= ; ; Name...........: _StringSize ; Description ...: Returns size of rectangle required to display string - width can be chosen ; Syntax ........: _StringSize($sText[, $iSize[, $iWeight[, $iAttrib[, $sName[, $iWidth]]]]]) ; Parameters ....: $sText - String to display ; $iSize - Font size in points - default AutoIt GUI default ; $iWeight - Font weight (400 = normal) - default AutoIt GUI default ; $iAttrib - Font attribute (0-Normal, 2-Italic, 4-Underline, 8 Strike - default AutoIt ; $sName - Font name - default AutoIt GUI default ; $iWidth - [optional] Width of rectangle - default is unwrapped width of string ; Requirement(s) : v3.2.12.1 or higher ; Return values .: Success - Returns array with details of rectangle required for text: ; |$array[0] = String formatted with @CRLF at required wrap points ; |$array[1] = Height of single line in selected font ; |$array[2] = Width of rectangle required to hold formatted string ; |$array[3] = Height of rectangle required to hold formatted string ; Failure - Returns 0 and sets @error: ; |1 - Incorrect parameter type (@extended = parameter index) ; |2 - Failure to create GUI to test label size ; |3 - Failure of _WinAPI_SelectObject ; |4 - Font too large for chosen width - longest word will not fit ; Author ........: Melba23 ; Modified ......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: Yes ;=================================================================================================== Func _StringSize($sText, $iSize = Default, $iWeight = Default, $iAttrib = Default, $sName = Default, $iWidth = 0) Local $hWnd, $hFont, $hDC, $oFont, $tSize, $hGUI, $hText_Label, $sTest_Line Local $iLine_Count, $iLine_Width, $iWrap_Count, $iLast_Word Local $asLines[1], $avSize_Info[4], $aiPos[4] ; Check parameters are correct type If Not IsString($sText) Then Return SetError(1, 1, 0) If Not IsNumber($iSize) And $iSize <> Default Then Return SetError(1, 2, 0) If Not IsInt($iWeight) And $iWeight <> Default Then Return SetError(1, 3, 0) If Not IsInt($iAttrib) And $iAttrib <> Default Then Return SetError(1, 4, 0) If Not IsString($sName) And $sName <> Default Then Return SetError(1, 5, 0) If Not IsNumber($iWidth) Then Return SetError(1, 6, 0) ; Create GUI to contain test labels, set to passed font parameters $hGUI = GUICreate("", 1200, 500, 10, 10) If $hGUI = 0 Then Return SetError(2, 0, 0) GUISetFont($iSize, $iWeight, $iAttrib, $sName) ; Store unwrapped text $avSize_Info[0] = $sText ; Ensure EoL is @CRLF and break text into lines If StringInStr($sText, @CRLF) = 0 Then StringRegExpReplace($sText, "[x0a|x0d]", @CRLF) $asLines = StringSplit($sText, @CRLF, 1) ; Draw label with unwrapped lines to check on max width $hText_Label = GUICtrlCreateLabel($sText, 10, 10) $aiPos = ControlGetPos($hGUI, "", $hText_Label) GUICtrlDelete($hText_Label) ; Store line height for this font size after removing label padding (always 8) $avSize_Info[1] = ($aiPos[3] - 8)/ $asLines[0] ; Store width and height of this label $avSize_Info[2] = $aiPos[2] $avSize_Info[3] = $aiPos[3] - 4 ; Reduce margin ; Check if wrapping is required If $aiPos[2] > $iWidth And $iWidth > 0 Then ; Set returned text element to null $avSize_Info[0] = "" ; Set width element to max allowed $avSize_Info[2] = $iWidth ; Set line count to zero $iLine_Count = 0 ; Take each line in turn For $j = 1 To $asLines[0] ; Size this line unwrapped $hText_Label = GUICtrlCreateLabel($asLines[$j], 10, 10) $aiPos = ControlGetPos($hGUI, "", $hText_Label) GUICtrlDelete($hText_Label) ; Check wrap status If $aiPos[2] < $iWidth Then ; No wrap needed so count line and store $iLine_Count += 1 $avSize_Info[0] &= $asLines[$j] & @CRLF Else ; Wrap needed so need to count wrapped lines ; Create label to hold line as it grows $hText_Label = GUICtrlCreateLabel("", 0, 0) ; Initialise Point32 method $hWnd = ControlGetHandle($hGui, "", $hText_Label) $hFont = _SendMessage($hWnd, $WM_GETFONT) $hDC = _WinAPI_GetDC($hWnd) $oFont = _WinAPI_SelectObject($hDC, $hFont) If $oFont = 0 Then Return SetError(3, 0, 0) ; Zero counter $iWrap_Count = 0 While 1 ; Set line width to 0 $iLine_Width = 0 ; Initialise pointer for end of word $iLast_Word = 0 For $i = 1 To StringLen($asLines[$j]) ; Is this just past a word ending? If StringMid($asLines[$j], $i, 1) = " " Then $iLast_Word = $i - 1 ; Increase line by one character $sTest_Line = StringMid($asLines[$j], 1, $i) ; Place line in label GUICtrlSetData($hText_Label, $sTest_Line) ; Get line length $tSize = _WinAPI_GetTextExtentPoint32($hDC, $sTest_Line) $iLine_Width = DllStructGetData($tSize, "X") ; If too long exit the loop If $iLine_Width >= $iWidth - Int($iSize / 2) Then ExitLoop Next ; End of the line of text? If $i > StringLen($asLines[$j]) Then ; Yes, so add final line to count $iWrap_Count += 1 ; Store line $avSize_Info[0] &= $sTest_Line & @CRLF ExitLoop Else ; No, but add line just completed to count $iWrap_Count += 1 ; Check at least 1 word completed or return error If $iLast_Word = 0 Then GUIDelete($hGUI) Return SetError(4, 0, 0) EndIf ; Store line up to end of last word $avSize_Info[0] &= StringLeft($sTest_Line, $iLast_Word) & @CRLF ; Strip string to point reached $asLines[$j] = StringTrimLeft($asLines[$j], $iLast_Word) ; Trim leading whitespace $asLines[$j] = StringStripWS($asLines[$j], 1) ; Repeat with remaining characters in line EndIf WEnd ; Add the number of wrapped lines to the count $iLine_Count += $iWrap_Count ; Clean up _WinAPI_ReleaseDC($hWnd, $hDC) GUICtrlDelete($hText_Label) EndIf Next ; Convert lines to pixels and add reduced margin $avSize_Info[3] = ($iLine_Count * $avSize_Info[1]) + 4 EndIf ; Clean up GUIDelete($hGUI) ; Return array Return $avSize_Info EndFunc ; => _StringSize ;Script End The progress.ini looks like this: [Message] Msg1=TypeMessage1here Msg2=TypeMessage2here Msg3=Please wait... [ProgressBar] PercentCompleted=0 I also wrote a little app that can increment the progress bar by updating the percentage in the progress.ini file. All you need to do is run it, with a number as the first command line argument - then it will write that number as the percentage in the progres.ini (and thereby increment the progress bar on the message window). expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Res_Comment=Script to update the progress bar INI file #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #cs ---------------------------------------------------------------------------- AutoIt Version: v3.3.0.0 Script Function: Script to update the progress bar INI file with percentage #ce ---------------------------------------------------------------------------- ;Script Start ;Set AutoIt options AutoItSetOption("TrayIconDebug", 1); Show debug info in tray icon AutoItSetOption("WinTitleMatchMode", 2); 2 = Match any substring in title AutoItSetOption("TrayIconHide", 1); 0 = do not hide, 1 = hide tray icon ;_ErrorMsg("") ;Set Variables If $cmdline[0] = 0 Then ;Check if no cmdline params specified, show message _ErrorMsg("No command line parameters specified!") Exit ElseIf $cmdline[0] > 1 Then ;Check number of params - if more than 1, show message _ErrorMsg("Please only use a single command line parameter!") Exit EndIf ;Read percentage specified via command line parameter $intPercent = Number($cmdline[1]) ;Read current percentage in Progress.INI file $intCurProgress = IniRead(@ScriptDir & "\Progress.INI", "ProgressBar", "PercentCompleted", 0) ;Main Script If $intCurProgress <100 Then ;Check cmdline number between 1-100 and do stuff If $intPercent >=1 And $intPercent <=100 Then ;MsgBox(0, "Info", "Percent specified is: " & $intPercent) $intNewPercent = $intPercent + $intCurProgress IniWrite(@ScriptDir & "\Progress.INI", "ProgressBar", "PercentCompleted", $intNewPercent) Exit Else _ErrorMsg("Please specify a number between 1 and 100") EndIf Else ;_ErrorMsg("Progress complete") Exit EndIf ;Define functions Func _ErrorMsg($strErrMsg) MsgBox(262192, "Error", $strErrMsg); Show the error message with topmost window EndFunc; =>__ErrorMsg() ;Script End I'm sure your way is more elegant than my cludgy code, but it seems to work OK for what I need. If you have any recommendations or suggestions on how to improve what I've done, please let me know. Once again, thanks very much for responding! I'd be lost without the kind and helpful support that people share on this forum!!! Many thanks and kind regards, Greg.
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now