Hallo liebe Community,
Ich möchte euch jetzt mein neues Werk vorstellen, eine Custom Message Box.
Ich benötigte für ein Projekt mehr als nur 3 Buttons zur Auswahl für eine Message Box.
Nach einer mehr oder weniger gründlichen aber erfolglosen Suche, habe ich beschlossen,
selbst eine Solche Funktion zu schreiben.
Anbei seht ihr das Ergebnis:
Spoiler anzeigen
#include-once
[/autoit] [autoit][/autoit] [autoit]; #FUNCTION# ===================================================================================================================
; Name...........: CustomMsgBox()
; Description ...: Create a Custom Msgbox
; Syntax ........: CustomMsgBox($sTitle, $sText, $asButtonarray = "", $iTimeout = "", $iIcon = -1, $sIconpath = "shell32.dll")
; Parameters ....: $sTitle - Title for Messagebox
; $sText - [optional] Text for the Messagebox
; $asButtonarray - [optional] Array with Buttonnames to add to MsgBox
; $iTimeout - [optional] Timeout for MsgBox
; $iIcon - [optional] Iconnumber for the Messagebox
; $sIconpath - [optional] Where to find the Icon (Default shell32.dll)
; Return value ..: Button klicked
; Author ........: TheLuBu ([email='LuBu@veytal.com'][/email])
; Modified.......:
; Remarks .......:
; ===============================================================================================================================
Func CustomMsgBox($sTitle, $sText, $asButtonarray = "", $iTimeout = "", $iIcon = -1, $sIconpath = "shell32.dll")
Local $Useopt = Opt("GUIOnEventMode")
Opt("GUIOnEventMode", 0)
Local $h_CMBGUI, $iLeft = 12, $iTop = 25, $Timer, $iMsG, $iButtonTop, $iButtonLeft
Local $iMaxStringWidth = 400, $aSize, $aControlPos, $iUseleft
Local $iDefButton = -1, $cIcon, $avButtonHandleArray
$h_CMBGUI = GUICreate($sTitle, 500, 500, -1, -1, 13107200) ;BitOR($WS_SYSMENU, $WS_CAPTION))
GUISetIcon(@AutoItExe, -2, $h_CMBGUI)
If $iIcon >= 0 And $iIcon <= 3 Then
$iLeft = 25
$cIcon = GUICtrlCreateIcon($sIconpath, $iIcon, $iLeft, $iTop, 32, 32)
GUICtrlSetBkColor($cIcon, 0xFFFFFF)
GUICtrlSetResizing($cIcon, 802)
$iLeft = 65
$iTop = 34
EndIf
If IsArray($asButtonarray) Then
If UBound($asButtonarray) > 6 Then $iMaxStringWidth = Ceiling(UBound($asButtonarray) / 2) * 100 + 100
Local $avButtonHandleArray[UBound($asButtonarray)]
EndIf
$aSize = _StringSize($sText, Default, Default, Default, "", $iMaxStringWidth)
If $aSize[3] > 17 Then $iTop = 25
GUICtrlCreateLabel($aSize[0], $iLeft, $iTop, $aSize[2], $aSize[3])
GUICtrlSetResizing(-1, 802)
GUICtrlSetBkColor(-1, -2)
If Not IsArray($asButtonarray) Then
$iDefButton = GUICtrlCreateButton("Ok", ($iLeft + $aSize[2]) / 2 - 44, $iTop + $aSize[3], 88, 26)
GUICtrlSetResizing(-1, 802)
Else
$iButtonTop = 0
$iButtonLeft = 12
For $i = 0 To UBound($asButtonarray) - 1
$avButtonHandleArray[$i] = GUICtrlCreateButton($asButtonarray[$i], $iButtonLeft, $iTop + $aSize[3] + $iButtonTop, 88, 26)
$iButtonLeft += 100
If $i = Ceiling(UBound($asButtonarray) / 2) - 1 Then
$iButtonTop += 30
$iButtonLeft = 12
EndIf
GUICtrlSetResizing(-1, 802)
Next
EndIf
Local $iIndex
If $iIcon >= 0 And $iIcon <= 3 Then
If IsArray($asButtonarray) Then
$iIndex = Floor(UBound($asButtonarray) / 2)
If IsInt(UBound($asButtonarray)/2) Then $iIndex -= 1
If $iIndex < 0 THen $iIndex = 0
$aControlPos = ControlGetPos($h_CMBGUI, "", $avButtonHandleArray[$iIndex])
If $aControlPos[0] + $aControlPos[2] > $iLeft + $aSize[2] Then
$iUseleft = $aControlPos[0] + $aControlPos[2] + 15
Else
$iUseleft = $iLeft + $aSize[2] + 15
EndIf
EndIf
WinMove($h_CMBGUI, "", Default, Default, $iUseleft, $iTop * 2 + $aSize[3] + 35 + $iButtonTop)
Else
If IsArray($asButtonarray) Then
$iIndex = Floor(UBound($asButtonarray) / 2)
If IsInt(UBound($asButtonarray)/2) Then $iIndex -= 1
If $iIndex < 0 THen $iIndex = 0
$aControlPos = ControlGetPos($h_CMBGUI, "", $avButtonHandleArray[$iIndex])
If $aControlPos[0] + $aControlPos[2] > $aSize[2] Then
$iUseleft = $aControlPos[0] + $aControlPos[2] + 15
Else
$iUseleft = $aSize[2] + 15
EndIf
EndIf
WinMove($h_CMBGUI, "", Default, Default, $iUseleft, $iTop * 2 + $aSize[3] + 35 + $iButtonTop)
EndIf
GUISetState(@SW_SHOW, $h_CMBGUI)
$Timer = TimerInit()
While 1
$iMsG = GUIGetMsg(1)
Switch $iMsG[1]
Case $h_CMBGUI
Switch $iMsG[0]
Case -3
GUIDelete($h_CMBGUI)
Opt("GUIOnEventMode", $Useopt)
Return 0
Case $iDefButton
GUIDelete($h_CMBGUI)
Opt("GUIOnEventMode", $Useopt)
Return 1
Case $avButtonHandleArray[0] To $avButtonHandleArray[UBound($avButtonHandleArray) - 1]
GUIDelete($h_CMBGUI)
Opt("GUIOnEventMode", $Useopt)
Return $iMsG[0] + 1 - $avButtonHandleArray[0]
EndSwitch
EndSwitch
If $iTimeout > 0 Then
If TimerDiff($Timer) > $iTimeout * 1000 Then
GUIDelete($h_CMBGUI)
Opt("GUIOnEventMode", $Useopt)
Return 0
EndIf
EndIf
WEnd
EndFunc ;==>CustomMsgBox
[/autoit] [autoit][/autoit] [autoit]; #INDEX# ============================================================================================================
; Title .........: _StringSize
; AutoIt Version : v3.2.12.1 or higher
; Language ......: English
; Description ...: Returns size of rectangle required to display string - maximum width can be chosen
; Remarks .......:
; Note ..........:
; Author(s) .....: Melba23 - thanks to trancexx for the default DC code
; ====================================================================================================================
;#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
[/autoit] [autoit][/autoit] [autoit]; #CURRENT# ==========================================================================================================
; _StringSize: Returns size of rectangle required to display string - maximum width can be chosen
; ====================================================================================================================
; #INTERNAL_USE_ONLY#=================================================================================================
; _StringSize_Error_Close: Releases DC and deletes font object after error
; _StringSize_DefaultFontName: Determines Windows default font
; ====================================================================================================================
; #FUNCTION# =========================================================================================================
; Name...........: _StringSize
; Description ...: Returns size of rectangle required to display string - maximum permitted width can be chosen
; Syntax ........: _StringSize($sText[, $iSize[, $iWeight[, $iAttrib[, $sName[, $iWidth[, $hWnd]]]]]])
; Parameters ....: $sText - String to display
; $iSize - [optional] Font size in points - (default = 8.5)
; $iWeight - [optional] Font weight - (default = 400 = normal)
; $iAttrib - [optional] Font attribute (0-Normal (default), 2-Italic, 4-Underline, 8 Strike)
; + 1 if tabs are to be expanded before sizing
; $sName - [optional] Font name - (default = Tahoma)
; $iWidth - [optional] Max width for rectangle - (default = 0 => width of original string)
; $hWnd - [optional] GUI in which string will be displayed - (default 0 => normally not required)
; Requirement(s) : v3.2.12.1 or higher
; Return values .: Success - Returns 4-element array: ($iWidth set // $iWidth not set)
; |$array[0] = String reformatted with additonal @CRLF // Original string
; |$array[1] = Height of single line in selected font // idem
; |$array[2] = Width of rectangle required for reformatted // original string
; |$array[3] = Height of rectangle required for reformatted // original string
; Failure - Returns 0 and sets @error:
; |1 - Incorrect parameter type (@extended = parameter index)
; |2 - DLL call error - extended set as follows:
; |1 - GetDC failure
; |2 - SendMessage failure
; |3 - GetDeviceCaps failure
; |4 - CreateFont failure
; |5 - SelectObject failure
; |6 - GetTextExtentPoint32 failure
; |3 - Font too large for chosen max width - a word will not fit
; Author ........: Melba23 - thanks to trancexx for the default DC code
; Modified ......:
; Remarks .......: The use of the $hWnd parameter is not normally necessary - it is only required if the UDF does not
; return correct dimensions without it.
; Related .......:
; Link ..........:
; Example .......: Yes
;=====================================================================================================================
Func _StringSize($sText, $iSize = 8.5, $iWeight = 400, $iAttrib = 0, $sName = "", $iMaxWidth = 0, $hwnd = 0)
; Set parameters passed as Default
If $iSize = Default Then $iSize = 8.5
If $iWeight = Default Then $iWeight = 400
If $iAttrib = Default Then $iAttrib = 0
If $sName = "" Or $sName = Default Then $sName = _StringSize_DefaultFontName()
; Check parameters are correct type
If Not IsString($sText) Then Return SetError(1, 1, 0)
If Not IsNumber($iSize) Then Return SetError(1, 2, 0)
If Not IsInt($iWeight) Then Return SetError(1, 3, 0)
If Not IsInt($iAttrib) Then Return SetError(1, 4, 0)
If Not IsString($sName) Then Return SetError(1, 5, 0)
If Not IsNumber($iMaxWidth) Then Return SetError(1, 6, 0)
If Not IsHWnd($hwnd) And $hwnd <> 0 Then Return SetError(1, 7, 0)
Local $aRet, $hDC, $hFont, $hLabel = 0, $hLabel_Handle
[/autoit] [autoit][/autoit] [autoit]; Check for tab expansion flag
Local $iExpTab = BitAND($iAttrib, 1)
; Remove possible tab expansion flag from font attribute value
$iAttrib = BitAND($iAttrib, BitNOT(1))
; If GUI handle was passed
If IsHWnd($hwnd) Then
; Create label outside GUI borders
$hLabel = GUICtrlCreateLabel("", -10, -10, 10, 10)
$hLabel_Handle = GUICtrlGetHandle(-1)
GUICtrlSetFont(-1, $iSize, $iWeight, $iAttrib, $sName)
; Create DC
$aRet = DllCall("user32.dll", "handle", "GetDC", "hwnd", $hLabel_Handle)
If @error Or $aRet[0] = 0 Then
GUICtrlDelete($hLabel)
Return SetError(2, 1, 0)
EndIf
$hDC = $aRet[0]
$aRet = DllCall("user32.dll", "lparam", "SendMessage", "hwnd", $hLabel_Handle, "int", 0x0031, "wparam", 0, "lparam", 0) ; $WM_GetFont
If @error Or $aRet[0] = 0 Then
GUICtrlDelete($hLabel)
Return SetError(2, _StringSize_Error_Close(2, $hDC), 0)
EndIf
$hFont = $aRet[0]
Else
; Get default DC
$aRet = DllCall("user32.dll", "handle", "GetDC", "hwnd", $hwnd)
If @error Or $aRet[0] = 0 Then Return SetError(2, 1, 0)
$hDC = $aRet[0]
; Create required font
$aRet = DllCall("gdi32.dll", "int", "GetDeviceCaps", "handle", $hDC, "int", 90) ; $LOGPIXELSY
If @error Or $aRet[0] = 0 Then Return SetError(2, _StringSize_Error_Close(3, $hDC), 0)
Local $iInfo = $aRet[0]
$aRet = DllCall("gdi32.dll", "handle", "CreateFontW", "int", -$iInfo * $iSize / 72, "int", 0, "int", 0, "int", 0, _
"int", $iWeight, "dword", BitAND($iAttrib, 2), "dword", BitAND($iAttrib, 4), "dword", BitAND($iAttrib, 8), "dword", 0, "dword", 0, _
"dword", 0, "dword", 5, "dword", 0, "wstr", $sName)
If @error Or $aRet[0] = 0 Then Return SetError(2, _StringSize_Error_Close(4, $hDC), 0)
$hFont = $aRet[0]
EndIf
; Select font and store previous font
$aRet = DllCall("gdi32.dll", "handle", "SelectObject", "handle", $hDC, "handle", $hFont)
If @error Or $aRet[0] = 0 Then Return SetError(2, _StringSize_Error_Close(5, $hDC, $hFont, $hLabel), 0)
Local $hPrevFont = $aRet[0]
; Declare variables
Local $avSize_Info[4], $iLine_Length, $iLine_Height = 0, $iLine_Count = 0, $iLine_Width = 0, $iWrap_Count, $iLast_Word, $sTest_Line
; Declare and fill Size structure
Local $tSize = DllStructCreate("int X;int Y")
DllStructSetData($tSize, "X", 0)
DllStructSetData($tSize, "Y", 0)
; Ensure EoL is @CRLF and break text into lines
$sText = StringRegExpReplace($sText, "((?<!\x0d)\x0a|\x0d(?!\x0a))", @CRLF)
Local $asLines = StringSplit($sText, @CRLF, 1)
; For each line
For $i = 1 To $asLines[0]
; Expand tabs if required
If $iExpTab Then
$asLines[$i] = StringReplace($asLines[$i], @TAB, " XXXXXXXX")
EndIf
; Size line
$iLine_Length = StringLen($asLines[$i])
DllCall("gdi32.dll", "bool", "GetTextExtentPoint32W", "handle", $hDC, "wstr", $asLines[$i], "int", $iLine_Length, "ptr", DllStructGetPtr($tSize))
If @error Then Return SetError(2, _StringSize_Error_Close(6, $hDC, $hFont, $hLabel), 0)
If DllStructGetData($tSize, "X") > $iLine_Width Then $iLine_Width = DllStructGetData($tSize, "X")
If DllStructGetData($tSize, "Y") > $iLine_Height Then $iLine_Height = DllStructGetData($tSize, "Y")
Next
; Check if $iMaxWidth has been both set and exceeded
If $iMaxWidth <> 0 And $iLine_Width > $iMaxWidth Then ; Wrapping required
; For each Line
For $j = 1 To $asLines[0]
; Size line unwrapped
$iLine_Length = StringLen($asLines[$j])
DllCall("gdi32.dll", "bool", "GetTextExtentPoint32W", "handle", $hDC, "wstr", $asLines[$j], "int", $iLine_Length, "ptr", DllStructGetPtr($tSize))
If @error Then Return SetError(2, _StringSize_Error_Close(6, $hDC, $hFont, $hLabel), 0)
; Check wrap status
If DllStructGetData($tSize, "X") < $iMaxWidth - 4 Then
; No wrap needed so count line and store
$iLine_Count += 1
$avSize_Info[0] &= $asLines[$j] & @CRLF
Else
; Wrap needed so zero counter for wrapped lines
$iWrap_Count = 0
; Build line to max width
While 1
; Zero line width
$iLine_Width = 0
; Initialise pointer for end of word
$iLast_Word = 0
; Add characters until EOL or maximum width reached
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)
; Get line length
$iLine_Length = StringLen($sTest_Line)
DllCall("gdi32.dll", "bool", "GetTextExtentPoint32W", "handle", $hDC, "wstr", $sTest_Line, "int", $iLine_Length, "ptr", DllStructGetPtr($tSize))
If @error Then Return SetError(2, _StringSize_Error_Close(6, $hDC, $hFont, $hLabel), 0)
$iLine_Width = DllStructGetData($tSize, "X")
; If too long exit the loop
If $iLine_Width >= $iMaxWidth - 4 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 Return SetError(3, _StringSize_Error_Close(0, $hDC, $hFont, $hLabel), 0)
; 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
EndIf
Next
; Reset any tab expansions
If $iExpTab Then
$avSize_Info[0] = StringRegExpReplace($avSize_Info[0], "\x20?XXXXXXXX", @TAB)
EndIf
; Complete return array
$avSize_Info[1] = $iLine_Height
$avSize_Info[2] = $iMaxWidth
; Convert lines to pixels and add drop margin
$avSize_Info[3] = ($iLine_Count * $iLine_Height) + 4
Else ; No wrapping required
; Create return array (add drop margin to height)
Local $avSize_Info[4] = [$sText, $iLine_Height, $iLine_Width, ($asLines[0] * $iLine_Height) + 4]
EndIf
; Clear up
DllCall("gdi32.dll", "handle", "SelectObject", "handle", $hDC, "handle", $hPrevFont)
DllCall("gdi32.dll", "bool", "DeleteObject", "handle", $hFont)
DllCall("user32.dll", "int", "ReleaseDC", "hwnd", 0, "handle", $hDC)
If $hLabel Then GUICtrlDelete($hLabel)
Return $avSize_Info
[/autoit] [autoit][/autoit] [autoit]EndFunc ;==>_StringSize
[/autoit] [autoit][/autoit] [autoit]; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: _StringSize_Error_Close
; Description ...: Releases DC and deleted font object if required after error
; Syntax ........: _StringSize_Error_Close ($iExtCode, $hDC, $hGUI)
; Parameters ....: $iExtCode - code to return
; $hDC, $hGUI - handles as set in _StringSize function
; Return value ..: $iExtCode as passed
; Author ........: Melba23
; Modified.......:
; Remarks .......: This function is used internally by _StringSize
; ===============================================================================================================================
Func _StringSize_Error_Close($iExtCode, $hDC = 0, $hFont = 0, $hLabel = 0)
If $hFont <> 0 Then DllCall("gdi32.dll", "bool", "DeleteObject", "handle", $hFont)
If $hDC <> 0 Then DllCall("user32.dll", "int", "ReleaseDC", "hwnd", 0, "handle", $hDC)
If $hLabel Then GUICtrlDelete($hLabel)
Return $iExtCode
[/autoit] [autoit][/autoit] [autoit]EndFunc ;==>_StringSize_Error_Close
[/autoit] [autoit][/autoit] [autoit]; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: _StringSize_DefaultFontName
; Description ...: Determines Windows default font
; Syntax ........: _StringSize_DefaultFontName()
; Parameters ....: None
; Return values .: Success - Returns name of system default font
; Failure - Returns "Tahoma"
; Author ........: Melba23, based on some original code by Larrydalooza
; Modified.......:
; Remarks .......: This function is used internally by _StringSize
; ===============================================================================================================================
Func _StringSize_DefaultFontName()
; Get default system font data
Local $tNONCLIENTMETRICS = DllStructCreate("uint;int;int;int;int;int;byte[60];int;int;byte[60];int;int;byte[60];byte[60];byte[60]")
DllStructSetData($tNONCLIENTMETRICS, 1, DllStructGetSize($tNONCLIENTMETRICS))
DllCall("user32.dll", "int", "SystemParametersInfo", "int", 41, "int", DllStructGetSize($tNONCLIENTMETRICS), "ptr", DllStructGetPtr($tNONCLIENTMETRICS), "int", 0)
Local $tLOGFONT = DllStructCreate("long;long;long;long;long;byte;byte;byte;byte;byte;byte;byte;byte;char[32]", DllStructGetPtr($tNONCLIENTMETRICS, 13))
If IsString(DllStructGetData($tLOGFONT, 14)) Then
Return DllStructGetData($tLOGFONT, 14)
Else
Return "Tahoma"
EndIf
EndFunc ;==>_StringSize_DefaultFontName
[/autoit]Beispiel
#include <CMB.au3>
Local $asButtonarray[6] = ["OK", "Abbrechen", "Weiter", "Zurück", "Ignorieren", "Hinzufügen"]
$t = CustomMsgBox("Custom Messagebox", "Ein wenig Text, nur zu Demozwecken" & @CRLF & "Funktionieren die Zeilenumbrüche?" & @CRLF & "Ich denke schon", $asButtonarray, -1, 3)
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $t = ' & $t & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
Ich würde mich sehr über Feedback freuen