Jump to content

Truncate GUICtrlCreateEdit data if too long


Recommended Posts

I have an Edit that I send file names with their full paths to, and sometimes those paths are too long, and you can not see the file name, so I hacked out a way to cut out some info from the middle of the string so the file name is visible. I am hoping there is an optimized, built-in way to do this instead, my way seems inefficient and also doesn't fill the Edit consistently since some characters (like i) are skinnier than others (like w). My code is:

$statusinfo = GUICtrlCreateEdit("", 16, 96, 320, 21, BitOR($ES_AUTOVSCROLL,$ES_AUTOHSCROLL,$ES_READONLY))

.
.
.

$statusinfoshow=stringlen($formattedfile2)
if $statusinfoshow<=52 Then GUICtrlSetData($statusinfo, $formattedfile2)
if $statusinfoshow>52 Then 
    GUICtrlSetData($statusinfo, StringMid($formattedfile2,1,10)&"........."&StringMid($formattedfile2,$statusinfoshow-34,35))
EndIf

Is there a function to do that better? You have no idea how happy I was when I found _StringAddThousandsSep, my way SUCKED but worked, I am hoping the same can happen here.

Thanks!!

Ian

My projects:

  • IP Scanner - Multi-threaded ping tool to scan your available networks for used and available IP addresses, shows ping times, resolves IPs in to host names, and allows individual IPs to be pinged.
  • INFSniff - Great technicians tool - a tool which scans DriverPacks archives for INF files and parses out the HWIDs to a database file, and rapidly scans the local machine's HWIDs, searches the database for matches, and installs them.
  • PPK3 (Persistent Process Killer V3) - Another for the techs - suppress running processes that you need to keep away, helpful when fighting spyware/viruses.
  • Sync Tool - Folder sync tool with lots of real time information and several checking methods.
  • USMT Front End - Front End for Microsoft's User State Migration Tool, including all files needed for USMT 3.01 and 4.01, 32 bit and 64 bit versions.
  • Audit Tool - Computer audit tool to gather vital hardware, Windows, and Office information for IT managers and field techs. Capabilities include creating a customized site agent.
  • CSV Viewer - Displays CSV files with automatic column sizing and font selection. Lines can also be copied to the clipboard for data extraction.
  • MyDirStat - Lists number and size of files on a drive or specified path, allows for deletion within the app.
  • 2048 Game - My version of 2048, fun tile game.
  • Juice Lab - Ecigarette liquid making calculator.
  • Data Protector - Secure notes to save sensitive information.
  • VHD Footer - Add a footer to a forensic hard drive image to allow it to be mounted or used as a virtual machine hard drive.
  • Find in File - Searches files containing a specified phrase.
Link to comment
Share on other sites

NB: You can't open a file, Or Use Run() or do anything, becoz it's all fake!!

$FullPath    = "C:\WINDOWS\system32\IME\CINTLGNT\MORE\M\SOME.TXT"
$StringLeft  = StringLeft($FullPath, 10); 10, The number of characters to get
$StringRight = StringRight($FullPath, 10);10, The number of characters to get
;
MsgBox(0, "ShortPath", $StringLeft & "\..\" & $StringRight)
Link to comment
Share on other sites

I have an Edit that I send file names with their full paths to, and sometimes those paths are too long, and you can not see the file name, so I hacked out a way to cut out some info from the middle of the string so the file name is visible. I am hoping there is an optimized, built-in way to do this instead, my way seems inefficient and also doesn't fill the Edit consistently since some characters (like i) are skinnier than others (like w). My code is:

$statusinfo = GUICtrlCreateEdit("", 16, 96, 320, 21, BitOR($ES_AUTOVSCROLL,$ES_AUTOHSCROLL,$ES_READONLY))

.
.
.

$statusinfoshow=stringlen($formattedfile2)
if $statusinfoshow<=52 Then GUICtrlSetData($statusinfo, $formattedfile2)
if $statusinfoshow>52 Then 
    GUICtrlSetData($statusinfo, StringMid($formattedfile2,1,10)&"........."&StringMid($formattedfile2,$statusinfoshow-34,35))
EndIf

Is there a function to do that better? You have no idea how happy I was when I found _StringAddThousandsSep, my way SUCKED but worked, I am hoping the same can happen here.

Thanks!!

Ian

Well, that something like this.

#Include <EditConstants.au3>
#Include <WinAPI.au3>
#Include <WindowsConstants.au3>

Global Const $Path = @MyDocumentsDir & '\My Music\My Playlists\Muse - Glastonbury Festival (2004).ts'

GUICreate('MyGUI', 400, 200)
$Edit1 = GUICtrlCreateEdit('', 10, 10, 380, 85, BitOR($ES_AUTOVSCROLL, $ES_AUTOHSCROLL, $ES_READONLY))
$Edit2 = GUICtrlCreateEdit('', 10, 105, 380, 85, BitOR($ES_AUTOVSCROLL, $ES_AUTOHSCROLL, $ES_READONLY))
GUISetState()

GUICtrlSetData($Edit1, _StringCut($Edit1, $Path, 0))
GUICtrlSetData($Edit2, _StringCut($Edit2, $Path, 1))

Do
Until GUIGetMsg() = -3

Func _StringCut($hWnd, $sText, $iFlag)

    If Not IsHWnd($hWnd) Then
        $hWnd = GUICtrlGetHandle($hWnd)
        If $hWnd = 0 Then
            Return ''
        EndIf
    EndIf

    Local $Width = _WinAPI_GetWindowWidth($hWnd)
    Local $Count = StringLen($sText)

    While ($Count > 0) And (_StringWidth($hWnd, $sText) > ($Width - 4))
        If $iFlag Then
            $sText = StringTrimRight($sText, 4) & '...'
        Else
            $sText = '...' & StringTrimLeft($sText, 4)
        EndIf
        $Count -= 1
    WEnd
    Return $sText
EndFunc   ;==>_StringCut

Func _StringWidth($hWnd, $sText)

    Local $hDC, $hFont, $hOld, $tSize

    $hDC = _WinAPI_GetDC($hWnd)
    $hFont = _SendMessage($hWnd, $WM_GETFONT)
    $hOld = _WinAPI_SelectObject($hDC, $hFont)
    $tSize = _WinAPI_GetTextExtentPoint32($hDC, $sText)
    _WinAPI_SelectObject($hDC, $hOld)
    _WinAPI_ReleaseDC($hWnd, $hDC)
    Return DllStructGetData($tSize, 1)
EndFunc   ;==>_StringWidth
Link to comment
Share on other sites

  • Moderators

llewxam,

In response to the PM, it is easy to truncate labels:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

$spath = "C:\I am a very long path\Which needs to be\Shortened to fit\In the label.txt"

$hGUI = GUICreate("Test", 500, 500)

GUICtrlCreateLabel($sPath, 10,  10, 300, 30, $DT_PATH_ELLIPSIS)
GUICtrlCreateLabel($sPath, 10,  50, 300, 30, $DT_END_ELLIPSIS)

GUISetState()

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch

WEnd

But this style does not seem to be applicable to edit controls - sorry! :)

M23

Edit:

But this code will do the job without the style:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Array.au3>
#include <StringSize.au3>

$sPath = "C:\I am a very long path\Which needs to be\Shortened to fit\In the control.txt"
$iMax_Size = 285  ; to allow for the vertical scroll bar

$aInfo = _StringSize($sPath)
If $aInfo[2] > $iMax_Size Then

    $aSections = StringSplit($sPath, "\")

    $sSmall_Part = "\" & $aSections[$aSections[0]]
    $sBig_Part = StringReplace($spath, $sSmall_Part, "")

    Do
        $sBig_Part = StringTrimRight($sBig_Part, 1)
        $aInfo = _StringSize($sBig_Part & "..." & $sSmall_Part)
    Until $aInfo[2] < $iMax_Size

    $sTrimmed_Path = $sBig_Part & "..." & $sSmall_Part

EndIf


$hGUI = GUICreate("Test", 500, 500)

GUICtrlCreateLabel($sPath, 10,  10, 300, 30, $DT_PATH_ELLIPSIS)
GUICtrlCreateLabel($sPath, 10,  50, 300, 30, $DT_END_ELLIPSIS)

GUICtrlCreateEdit($sTrimmed_Path, 10, 100, 300, 100)

GUISetState()

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch

WEnd

You will need my StringSize UDF as an include file:

#include-once

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

; #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

#cs

; StringSize Test example ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

; This Test code includes the fully commented StringSize code
; Hence the need for these include files
#include <WindowsConstants.au3>
#include <SendMessage.au3>
#include <WinAPI.au3>
; These include lines are contained in the code of the UDF itself

Global $aFont[4] = ["Arial", "Tahoma", "Courier New", "Comic Sans MS"]
Global $aSize[4] = [9, 12, 10, 15]
Global $aWeight[4] = [200, 400, 600, 800]
Global $aAttrib[4] = [0, 2, 4, 0]
Global $aMaxWidth[4] = [250, 300, 400, 500]
Global $aColour[4] = [0xFFFF88, 0xBBFF88, 0xBB88FF, 0xFF88FF]
Global $aButMsg[4] = ["Press for next example", "Click here", "Please push", "And the next one please..."]

$sLabelMsg  = "This is a message with very long lines which are unlikely to fit within the maximum width specified.  " & _
"This UDF will return the size of rectangle needed to display it in a selected font and size." & @CRLF & @CRLF & _
"The GUI can then be sized to fit and accurately placed on screen.  Other controls, such as the automatically " & _
"sized button under this label, can also be accurately positioned relative to the text."

GUICreate("String Sizing Test", 500, 500)
GUISetState()

While 1
    
    $sFont = $aFont[Random(0, 3, 1)]
    $iSize = $aSize[Random(0, 3, 1)]
    $iWeight = $aWeight[Random(0, 3, 1)]
    $iAttrib = $aAttrib[Random(0, 3, 1)]
    $iMaxWidth = Random(200, 850, 1)
    $iColour = $aColour[Random(0, 3, 1)]
    $sButMsg = $aButMsg[Random(0, 3, 1)]
    
    $aButReturn = _StringSize($sButMsg)
    $aMsgReturn = _StringSize($sLabelMsg, $iSize, $iWeight, $iAttrib, $sFont, $iMaxWidth)
    $iError = @error
    
    If IsArray($aMsgReturn) = 1 Then
        
        WinMove("String Sizing Test", "", (@DesktopWidth - ($aMsgReturn[2] + 25)) / 2, (@DesktopHeight - ($aMsgReturn[3] + 85)) / 2, $aMsgReturn[2] + 25, $aMsgReturn[3] + 85 )
        
        $hLabel = GUICtrlCreateLabel($aMsgReturn[0], 10, 10, $aMsgReturn[2], $aMsgReturn[3], 1)
            GUICtrlSetFont(-1, $iSize, $iWeight, $iAttrib, $sFont)
            GUICtrlSetBkColor(-1, $iColour)
        $hNext = GUICtrlCreateButton($sButMsg, ($aMsgReturn[2] - $aButReturn[2]) / 2, $aMsgReturn[3] + 20, $aButReturn[2] + 20, 30)
        
        While 1
    
        $iMsg = GUIGetMsg()
        
        If $iMsg = -3 Then Exit
        
        If $iMsg = $hNext Then ExitLoop
    
        WEnd

        GUICtrlDelete($hNext)
        GUICtrlDelete($hLabel)
    Else
        MsgBox(0, "Error", "Code = " & $iError)
    EndIf

WEnd

Exit

; End of example ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#ce

Have fun,

M23

Another Edit:

One thing. The styles leave the original path untouched - as you can see by using GuiCtrlRead on the labels - whereas my code actually truncates the string. So you would have to have some method of retrieving the original path later on - perhaps a 2D array of original/truncated and then use _ArraySearch?

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

llewxam,

In response to the PM, it is easy to truncate labels:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

$spath = "C:\I am a very long path\Which needs to be\Shortened to fit\In the label.txt"

$hGUI = GUICreate("Test", 500, 500)

GUICtrlCreateLabel($sPath, 10,  10, 300, 30, $DT_PATH_ELLIPSIS)
GUICtrlCreateLabel($sPath, 10,  50, 300, 30, $DT_END_ELLIPSIS)

GUISetState()

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch

WEnd

But this style does not seem to be applicable to edit controls - sorry! :)

M23

Edit:

But this code will do the job without the style:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Array.au3>
#include <StringSize.au3>

$sPath = "C:\I am a very long path\Which needs to be\Shortened to fit\In the control.txt"
$iMax_Size = 285  ; to allow for the vertical scroll bar

$aInfo = _StringSize($sPath)
If $aInfo[2] > $iMax_Size Then

    $aSections = StringSplit($sPath, "\")

    $sSmall_Part = "\" & $aSections[$aSections[0]]
    $sBig_Part = StringReplace($spath, $sSmall_Part, "")

    Do
        $sBig_Part = StringTrimRight($sBig_Part, 1)
        $aInfo = _StringSize($sBig_Part & "..." & $sSmall_Part)
    Until $aInfo[2] < $iMax_Size

    $sTrimmed_Path = $sBig_Part & "..." & $sSmall_Part

EndIf


$hGUI = GUICreate("Test", 500, 500)

GUICtrlCreateLabel($sPath, 10,  10, 300, 30, $DT_PATH_ELLIPSIS)
GUICtrlCreateLabel($sPath, 10,  50, 300, 30, $DT_END_ELLIPSIS)

GUICtrlCreateEdit($sTrimmed_Path, 10, 100, 300, 100)

GUISetState()

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch

WEnd

You will need my StringSize UDF as an include file:

#include-once

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

; #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

#cs

; StringSize Test example ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

; This Test code includes the fully commented StringSize code
; Hence the need for these include files
#include <WindowsConstants.au3>
#include <SendMessage.au3>
#include <WinAPI.au3>
; These include lines are contained in the code of the UDF itself

Global $aFont[4] = ["Arial", "Tahoma", "Courier New", "Comic Sans MS"]
Global $aSize[4] = [9, 12, 10, 15]
Global $aWeight[4] = [200, 400, 600, 800]
Global $aAttrib[4] = [0, 2, 4, 0]
Global $aMaxWidth[4] = [250, 300, 400, 500]
Global $aColour[4] = [0xFFFF88, 0xBBFF88, 0xBB88FF, 0xFF88FF]
Global $aButMsg[4] = ["Press for next example", "Click here", "Please push", "And the next one please..."]

$sLabelMsg  = "This is a message with very long lines which are unlikely to fit within the maximum width specified.  " & _
"This UDF will return the size of rectangle needed to display it in a selected font and size." & @CRLF & @CRLF & _
"The GUI can then be sized to fit and accurately placed on screen.  Other controls, such as the automatically " & _
"sized button under this label, can also be accurately positioned relative to the text."

GUICreate("String Sizing Test", 500, 500)
GUISetState()

While 1
    
    $sFont = $aFont[Random(0, 3, 1)]
    $iSize = $aSize[Random(0, 3, 1)]
    $iWeight = $aWeight[Random(0, 3, 1)]
    $iAttrib = $aAttrib[Random(0, 3, 1)]
    $iMaxWidth = Random(200, 850, 1)
    $iColour = $aColour[Random(0, 3, 1)]
    $sButMsg = $aButMsg[Random(0, 3, 1)]
    
    $aButReturn = _StringSize($sButMsg)
    $aMsgReturn = _StringSize($sLabelMsg, $iSize, $iWeight, $iAttrib, $sFont, $iMaxWidth)
    $iError = @error
    
    If IsArray($aMsgReturn) = 1 Then
        
        WinMove("String Sizing Test", "", (@DesktopWidth - ($aMsgReturn[2] + 25)) / 2, (@DesktopHeight - ($aMsgReturn[3] + 85)) / 2, $aMsgReturn[2] + 25, $aMsgReturn[3] + 85 )
        
        $hLabel = GUICtrlCreateLabel($aMsgReturn[0], 10, 10, $aMsgReturn[2], $aMsgReturn[3], 1)
            GUICtrlSetFont(-1, $iSize, $iWeight, $iAttrib, $sFont)
            GUICtrlSetBkColor(-1, $iColour)
        $hNext = GUICtrlCreateButton($sButMsg, ($aMsgReturn[2] - $aButReturn[2]) / 2, $aMsgReturn[3] + 20, $aButReturn[2] + 20, 30)
        
        While 1
    
        $iMsg = GUIGetMsg()
        
        If $iMsg = -3 Then Exit
        
        If $iMsg = $hNext Then ExitLoop
    
        WEnd

        GUICtrlDelete($hNext)
        GUICtrlDelete($hLabel)
    Else
        MsgBox(0, "Error", "Code = " & $iError)
    EndIf

WEnd

Exit

; End of example ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#ce

Have fun,

M23

Another Edit:

One thing. The styles leave the original path untouched - as you can see by using GuiCtrlRead on the labels - whereas my code actually truncates the string. So you would have to have some method of retrieving the original path later on - perhaps a 2D array of original/truncated and then use _ArraySearch?

M23

My thanks again to you as always, I decided to use the StringSize method and it looks good visually, but my app is now freezing. The app is a data backup tool (posted code to the forums previously, much has changed since. No need for the array to get the original file name back, I just do "$sPath=$formattedfile2" and off we go. On my first freeze after implementing your suggestion I got an error about an undeclared variable, so set a global for all variables just in case, but the freezing persists. Not yet sure what to make of that, but will get back to you when/if I find out why.

Thanks again though, the script looks very promising!

Ian

Edit-looks like it copies 874 files every time now, repeatable. Could it be a function calling itself too many times?

Edit2 - I take that back, get this - the smaller I set $iMax_Size the SOONER it freeses! I swear, I set to to 50, it bonks right away, I set it to 500 and it went further, I set it to 800 and it went further yet......I'll check StringSize for variables I have in use or anythign like that but doubt I'll find the answer there.....

Edited by llewxam

My projects:

  • IP Scanner - Multi-threaded ping tool to scan your available networks for used and available IP addresses, shows ping times, resolves IPs in to host names, and allows individual IPs to be pinged.
  • INFSniff - Great technicians tool - a tool which scans DriverPacks archives for INF files and parses out the HWIDs to a database file, and rapidly scans the local machine's HWIDs, searches the database for matches, and installs them.
  • PPK3 (Persistent Process Killer V3) - Another for the techs - suppress running processes that you need to keep away, helpful when fighting spyware/viruses.
  • Sync Tool - Folder sync tool with lots of real time information and several checking methods.
  • USMT Front End - Front End for Microsoft's User State Migration Tool, including all files needed for USMT 3.01 and 4.01, 32 bit and 64 bit versions.
  • Audit Tool - Computer audit tool to gather vital hardware, Windows, and Office information for IT managers and field techs. Capabilities include creating a customized site agent.
  • CSV Viewer - Displays CSV files with automatic column sizing and font selection. Lines can also be copied to the clipboard for data extraction.
  • MyDirStat - Lists number and size of files on a drive or specified path, allows for deletion within the app.
  • 2048 Game - My version of 2048, fun tile game.
  • Juice Lab - Ecigarette liquid making calculator.
  • Data Protector - Secure notes to save sensitive information.
  • VHD Footer - Add a footer to a forensic hard drive image to allow it to be mounted or used as a virtual machine hard drive.
  • Find in File - Searches files containing a specified phrase.
Link to comment
Share on other sites

  • Moderators

llewxam,

Sorry, but I am off on holiday for a week early tomorrow and AutoIt definitely does not figure in my better half's plans. :)

My UDF does no file copying whatsoever - so I have no idea where that is coming from. All it does is measure the length of a string, nothing more. And as for freezing with smaller maximums..... I did not include any error-checking in the code - are you sure the StringSplit array is valid? I feel the problem must lie within the code you are feeding the UDF - but then I would say that, wouldn't I? :)

If you still have problems towards the end of next week, by all means let me have the complete code you are working on at that point and I will look at it after I get back.

Good luck,

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

llewxam,

Sorry, but I am off on holiday for a week early tomorrow and AutoIt definitely does not figure in my better half's plans. :)

My UDF does no file copying whatsoever - so I have no idea where that is coming from. All it does is measure the length of a string, nothing more. And as for freezing with smaller maximums..... I did not include any error-checking in the code - are you sure the StringSplit array is valid? I feel the problem must lie within the code you are feeding the UDF - but then I would say that, wouldn't I? :)

If you still have problems towards the end of next week, by all means let me have the complete code you are working on at that point and I will look at it after I get back.

Good luck,

M23

hehehe, enjoy the time off. No worries man, tell ya what - I just tried the $DT_END_ELLIPSIS suggestion and changed the Edit to a Label, no big deal and it works great, backup job finished with no problems. So, if you want to investigate this further when you get back let me know, I'll try any modification to the UDF you would like, but for now I'm making life easy. You do the same for the next week!

Thanks again

Ian

My projects:

  • IP Scanner - Multi-threaded ping tool to scan your available networks for used and available IP addresses, shows ping times, resolves IPs in to host names, and allows individual IPs to be pinged.
  • INFSniff - Great technicians tool - a tool which scans DriverPacks archives for INF files and parses out the HWIDs to a database file, and rapidly scans the local machine's HWIDs, searches the database for matches, and installs them.
  • PPK3 (Persistent Process Killer V3) - Another for the techs - suppress running processes that you need to keep away, helpful when fighting spyware/viruses.
  • Sync Tool - Folder sync tool with lots of real time information and several checking methods.
  • USMT Front End - Front End for Microsoft's User State Migration Tool, including all files needed for USMT 3.01 and 4.01, 32 bit and 64 bit versions.
  • Audit Tool - Computer audit tool to gather vital hardware, Windows, and Office information for IT managers and field techs. Capabilities include creating a customized site agent.
  • CSV Viewer - Displays CSV files with automatic column sizing and font selection. Lines can also be copied to the clipboard for data extraction.
  • MyDirStat - Lists number and size of files on a drive or specified path, allows for deletion within the app.
  • 2048 Game - My version of 2048, fun tile game.
  • Juice Lab - Ecigarette liquid making calculator.
  • Data Protector - Secure notes to save sensitive information.
  • VHD Footer - Add a footer to a forensic hard drive image to allow it to be mounted or used as a virtual machine hard drive.
  • Find in File - Searches files containing a specified phrase.
Link to comment
Share on other sites

  • 7 months later...

Sorry for not asking again about this a long time ago, but I am working on a totally different app now (code is HUGE and irrelevant anyway...) and still have issues with both posted solutions. The solution by Yashied will frequently have large amounts of white space to the right while truncating strings, and Melba23's will cause the script to lock up every time, after several successful trims. $DT_End_Ellipsis was SUCH an awesome solution but required I change my Edit to a Label, which then removed the box around that control, which I then had to create a Graphic control and use GUICtrlSetGraphic to hand-craft the lines, but the look is different on XP vs. Vista/7........jeeeeeez these workarounds become tedious!!! :)

So to sum up, do either of you guys see anything in your solutions to cause the issues I mentioned? If you must see some code for the examples I gave I could bang something out to demonstrate rather than post my current project, but what I am working on now is written from scratch sharing nothing from the app I was working on when I originally posted this question. I really doubt it is something I goofed up twice :( and besides all I am doing here is asking a function to trim a long path, kinda not something I can do wrong.

My Edit control shows files names/paths, some quite long, and the app deals with anywhere from 3,000 to 20,000 or more files, so each of your solutions gets banged on a lot during a single run.

Thanks for any suggestions, unfortunately I couldn't find anything in them myself to correct.

Ian

My projects:

  • IP Scanner - Multi-threaded ping tool to scan your available networks for used and available IP addresses, shows ping times, resolves IPs in to host names, and allows individual IPs to be pinged.
  • INFSniff - Great technicians tool - a tool which scans DriverPacks archives for INF files and parses out the HWIDs to a database file, and rapidly scans the local machine's HWIDs, searches the database for matches, and installs them.
  • PPK3 (Persistent Process Killer V3) - Another for the techs - suppress running processes that you need to keep away, helpful when fighting spyware/viruses.
  • Sync Tool - Folder sync tool with lots of real time information and several checking methods.
  • USMT Front End - Front End for Microsoft's User State Migration Tool, including all files needed for USMT 3.01 and 4.01, 32 bit and 64 bit versions.
  • Audit Tool - Computer audit tool to gather vital hardware, Windows, and Office information for IT managers and field techs. Capabilities include creating a customized site agent.
  • CSV Viewer - Displays CSV files with automatic column sizing and font selection. Lines can also be copied to the clipboard for data extraction.
  • MyDirStat - Lists number and size of files on a drive or specified path, allows for deletion within the app.
  • 2048 Game - My version of 2048, fun tile game.
  • Juice Lab - Ecigarette liquid making calculator.
  • Data Protector - Secure notes to save sensitive information.
  • VHD Footer - Add a footer to a forensic hard drive image to allow it to be mounted or used as a virtual machine hard drive.
  • Find in File - Searches files containing a specified phrase.
Link to comment
Share on other sites

Maybe you could do something like this.

#include <GUIConstantsEx.au3>
#include <staticconstants.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <FontConstants.au3>
#include <editconstants.au3>

$spath = "C:\I am a very long path\Which needs to be\Shortened to fit\In the label.txt"
$spath2 = "D:\This is the other\longstruing\which needs to be \shorter.doc"
$hGUI = GUICreate("Test", 500, 500)
$ed = GUICtrlCreateEdit("",10,10,300,300,$ES_READONLY)
GUICtrlSetBkColor(-1,0xffffff)

GUISetState()


Global $tRECT, $hFont, $hOldFont, $hDC

HotKeySet("{ESC}", "_Exit")

$tRECT = DllStructCreate($tagRect)
DllStructSetData($tRECT, "Left", 5)
DllStructSetData($tRECT, "Top", 5)
DllStructSetData($tRECT, "Right", 290);
DllStructSetData($tRECT, "Bottom", 50)

$hDC = _WinAPI_GetDC(GUICtrlGetHandle($ed))
$hFont = _WinAPI_CreateFont(14, 0, 0, 0, 400, False, False, False, $DEFAULT_CHARSET, _
        $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $DEFAULT_QUALITY, 0, 'Arial')
$hOldFont = _WinAPI_SelectObject($hDC, $hFont)
$itextht = _WinAPI_GetTextExtentPoint32($hDC,"{")
$itextht = DllStructGetData($iTextht,2)
$iLineSpace = $iTextHt * 1.2
ConsoleWrite($itextht & @CRLF)
    _WinAPI_DrawText($hDC, $spath , $tRECT, BitOr($DT_PATH_ELLIPSIS,$DT_MODIFYSTRING))
DllStructSetData($tRECT, "Top", 5 + $iLineSpace)
_WinAPI_DrawText($hDC, $spath2 , $tRECT, BitOr($DT_PATH_ELLIPSIS,$DT_MODIFYSTRING))
While 1

    Switch GUIGetMsg()
    Case $GUI_EVENT_CLOSE
    Exit
    EndSwitch

WEnd

Func _Exit()
    _WinAPI_SelectObject($hDC, $hOldFont)
    _WinAPI_DeleteObject($hFont)
    _WinAPI_ReleaseDC(0, $hDC)
    _WinAPI_InvalidateRect(0, 0)
    $tRECT = 0
    Exit
EndFunc ;==>_Exit

Though you won't be able to scroll the edit. If you have more lines than will fit in the edit you will need to draw all the text again to make it looks like it has scrolled up. But it's better than a label I guess.

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

  • Moderators

llewxam,

You could make your "own" edit style control using labels and so continue to use the "ellipsis" styles. You have to have a bit more code of course, but this gives an idea of what you could do: :(

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#Include <GuiScrollBars.au3>
#include <ScrollBarConstants.au3>

Global $iItems = 100000, $iNumLabels
Global $hScroller, $iScrollPos = 0, $iCurrScrollPos = 0, $iCurrentTopIndex = 0
Global $aData[$iItems][2], $iSelection

; Fill array with data
SplashTextOn("Test", "Filling Data Array")
$sPath1 = "C:\I am a very long path\Which needs to be\Shortened to fit\In the label."
$sPath2 = "D:\This is the other\Long string\Which needs to be\Shorter."
For $i = 0 To $iItems - 1 Step 2
    $aData[$i][0] = $sPath1 & StringFormat("%03i", $i)
    $aData[$i + 1][0] = $sPath2 & StringFormat("%03i", $i + 1)
Next
SplashOff()

; create GUI
$hGui = GUICreate("Test", 400, 400)

$aTruncEdit = _TruncEdit($hGui, 10, 10, 270, 300)

$hButton = GUICtrlCreateButton("Clear", 10, 360, 80, 30)

GUISetState(@SW_SHOW, $hGui)

ConsoleWrite((100 / ($iItems - $iNumLabels)) & @CRLF)

While 1

    $iMsg = GUIGetMsg()

    Switch $iMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $aTruncEdit[1] To $aTruncEdit[$aTruncEdit[0]]
            $aData[$iCurrentTopIndex + $iMsg - 1][1] = Not($aData[$iCurrentTopIndex + $iMsg - 1][1])
            If $aData[$iCurrentTopIndex + $iMsg - 1][1] = 1 Then
                GUICtrlSetBkColor($iMsg, 0x0000FF)
                GUICtrlSetColor($iMsg, 0xFFFFFF)
            Else
                GUICtrlSetBkColor($iMsg, Default)
                GUICtrlSetColor($iMsg, Default)
            EndIf

        Case $hButton
            For $i = $aTruncEdit[1] To $aTruncEdit[$aTruncEdit[0]]
                GUICtrlSetBkColor($i, Default)
                GUICtrlSetColor($i, Default)
            Next
            For $i = 0 To $iItems - 1
                $aData[$i][1] = 0
            Next
    EndSwitch
WEnd

Func _TruncEdit($hWnd, $iLeft, $iTop, $iWidth, $iHeight)

    GUICtrlCreateGraphic($iLeft - 2, $iTop - 2, $iWidth - 16 , $iHeight + 4, $SS_BLACKFRAME)

    $iNumLabels = Int($iHeight / 20)
    Local $aGuiData[$iNumLabels + 1]
    $aGuiData[0] = $iNumLabels

    For $i = 0 To $iNumLabels - 1
        $aGuiData[$i + 1] = GUICtrlCreateLabel($aData[$i][0], $iLeft, $iTop + ($i * 20), $iWidth - 20, 20, $DT_END_ELLIPSIS)
    Next

    ; Create Scrollbar
    $hScroller = GUICreate("", 17, $iNumLabels * 20, $iLeft + $iWidth - 17, $iTop, $WS_CHILD, -1, $hGUI)
    GUISetState(@SW_SHOW, $hScroller)
    GUISwitch($hWnd)

    ; Set scroll bar to run from 1 to 100
    _GUIScrollBars_Init($hScroller)
    _GUIScrollBars_ShowScrollBar($hScroller, $SB_HORZ , False)
    _GUIScrollBars_SetScrollInfoPos($hScroller, $SB_VERT, 100)
    _GUIScrollBars_SetScrollRange($hScroller, $SB_VERT, 0, (200 - _GUIScrollBars_GetScrollInfoPos($hScroller, $SB_VERT)))
    _GUIScrollBars_SetScrollInfoPos($hScroller, $SB_VERT, 0)

    GUIRegisterMsg($WM_VSCROLL, "WM_VSCROLL")

    Return $aGuiData

EndFunc

; This function comes from the _GUIScrollBars_Init example - with a few changes

Func WM_VSCROLL($hWnd, $Msg, $wParam, $lParam)
    #forceref $Msg, $wParam, $lParam
    Local $nScrollCode = BitAND($wParam, 0x0000FFFF)
    Local $index = -1, $yChar, $yPos
    Local $Min, $Max, $Page, $Pos, $TrackPos

    For $x = 0 To UBound($aSB_WindowInfo) - 1
        If $aSB_WindowInfo[$x][0] = $hWnd Then
            $index = $x
            $yChar = $aSB_WindowInfo[$index][3]
            ExitLoop
        EndIf
    Next
    If $index = -1 Then Return 0

    ; Get all the vertial scroll bar information
    Local $tSCROLLINFO = _GUIScrollBars_GetScrollInfoEx($hWnd, $SB_VERT)
    $Min = DllStructGetData($tSCROLLINFO, "nMin")
    $Max = DllStructGetData($tSCROLLINFO, "nMax")
    $Page = DllStructGetData($tSCROLLINFO, "nPage")
    ; Save the position for comparison later on
    $yPos = DllStructGetData($tSCROLLINFO, "nPos")
    $Pos = $yPos
    $TrackPos = DllStructGetData($tSCROLLINFO, "nTrackPos")

    Switch $nScrollCode
        Case $SB_TOP ; user clicked the HOME keyboard key
            DllStructSetData($tSCROLLINFO, "nPos", $Min)
        Case $SB_BOTTOM ; user clicked the END keyboard key
            DllStructSetData($tSCROLLINFO, "nPos", $Max)
        Case $SB_LINEUP ; user clicked the top arrow
            DllStructSetData($tSCROLLINFO, "nPos", $Pos - 1)
        Case $SB_LINEDOWN ; user clicked the bottom arrow
            DllStructSetData($tSCROLLINFO, "nPos", $Pos + 1)
        Case $SB_PAGEUP ; user clicked the scroll bar shaft above the scroll box
            DllStructSetData($tSCROLLINFO, "nPos", $Pos - $Page)
        Case $SB_PAGEDOWN ; user clicked the scroll bar shaft below the scroll box
            DllStructSetData($tSCROLLINFO, "nPos", $Pos + $Page)
        Case $SB_THUMBTRACK ; user dragged the scroll box
            DllStructSetData($tSCROLLINFO, "nPos", $TrackPos)
    EndSwitch

;~    // Set the position and then retrieve it.  Due to adjustments
;~    //   by Windows it may not be the same as the value set.

    DllStructSetData($tSCROLLINFO, "fMask", $SIF_POS)
    _GUIScrollBars_SetScrollInfo($hWnd, $SB_VERT, $tSCROLLINFO)
    _GUIScrollBars_GetScrollInfo($hWnd, $SB_VERT, $tSCROLLINFO)
    ;// If the position has changed, scroll the window and update it
    $Pos = DllStructGetData($tSCROLLINFO, "nPos")

    If ($Pos <> $yPos) Then
        _GUIScrollBars_ScrollWindow($hWnd, 0, $yChar * ($yPos - $Pos))
        $yPos = $Pos
        $iScrollPos = Round(($iItems - $iNumLabels) * $Pos / 100)
        If $iScrollPos <> $iCurrScrollPos Then
            $iIndex = $iCurrentTopIndex + $iScrollPos - $iCurrScrollPos
            For $i = 1 To $iNumLabels
                ; Write the labels to match the required data
                GUICtrlSetData($aTruncEdit[$i], $aData[$iIndex + $i - 1][0])
                If $aData[$iIndex + $i - 1][1] = 1 Then
                    GUICtrlSetBkColor($i, 0x0000FF)
                    GUICtrlSetColor($i, 0xFFFFFF)
                Else
                    GUICtrlSetBkColor($i, Default)
                    GUICtrlSetColor($i, Default)
                EndIf
            Next
            $iCurrScrollPos = $iScrollPos
            $iCurrentTopIndex = $iIndex
        EndIf
    EndIf

    Return $GUI_RUNDEFMSG

EndFunc   ;==>WM_VSCROLL

I have used a 10000 element array to show it does work for large numbers. At the moment you can multiple select/unselect and clear - the items will stay highlighted (highlit?) as you scroll. You will no doubt need further functions, but I am fairly sure we could develop them farly easily.

Let me know what you think - I do not want to spend time on development if you would prefer another route. :)

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

llewxam,

You could make your "own" edit style control using labels and so continue to use the "ellipsis" styles. You have to have a bit more code of course, but this gives an idea of what you could do: :(

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#Include <GuiScrollBars.au3>
#include <ScrollBarConstants.au3>

Global $iItems = 100000, $iNumLabels
Global $hScroller, $iScrollPos = 0, $iCurrScrollPos = 0, $iCurrentTopIndex = 0
Global $aData[$iItems][2], $iSelection

; Fill array with data
SplashTextOn("Test", "Filling Data Array")
$sPath1 = "C:\I am a very long path\Which needs to be\Shortened to fit\In the label."
$sPath2 = "D:\This is the other\Long string\Which needs to be\Shorter."
For $i = 0 To $iItems - 1 Step 2
    $aData[$i][0] = $sPath1 & StringFormat("%03i", $i)
    $aData[$i + 1][0] = $sPath2 & StringFormat("%03i", $i + 1)
Next
SplashOff()

; create GUI
$hGui = GUICreate("Test", 400, 400)

$aTruncEdit = _TruncEdit($hGui, 10, 10, 270, 300)

$hButton = GUICtrlCreateButton("Clear", 10, 360, 80, 30)

GUISetState(@SW_SHOW, $hGui)

ConsoleWrite((100 / ($iItems - $iNumLabels)) & @CRLF)

While 1

    $iMsg = GUIGetMsg()

    Switch $iMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $aTruncEdit[1] To $aTruncEdit[$aTruncEdit[0]]
            $aData[$iCurrentTopIndex + $iMsg - 1][1] = Not($aData[$iCurrentTopIndex + $iMsg - 1][1])
            If $aData[$iCurrentTopIndex + $iMsg - 1][1] = 1 Then
                GUICtrlSetBkColor($iMsg, 0x0000FF)
                GUICtrlSetColor($iMsg, 0xFFFFFF)
            Else
                GUICtrlSetBkColor($iMsg, Default)
                GUICtrlSetColor($iMsg, Default)
            EndIf

        Case $hButton
            For $i = $aTruncEdit[1] To $aTruncEdit[$aTruncEdit[0]]
                GUICtrlSetBkColor($i, Default)
                GUICtrlSetColor($i, Default)
            Next
            For $i = 0 To $iItems - 1
                $aData[$i][1] = 0
            Next
    EndSwitch
WEnd

Func _TruncEdit($hWnd, $iLeft, $iTop, $iWidth, $iHeight)

    GUICtrlCreateGraphic($iLeft - 2, $iTop - 2, $iWidth - 16 , $iHeight + 4, $SS_BLACKFRAME)

    $iNumLabels = Int($iHeight / 20)
    Local $aGuiData[$iNumLabels + 1]
    $aGuiData[0] = $iNumLabels

    For $i = 0 To $iNumLabels - 1
        $aGuiData[$i + 1] = GUICtrlCreateLabel($aData[$i][0], $iLeft, $iTop + ($i * 20), $iWidth - 20, 20, $DT_END_ELLIPSIS)
    Next

    ; Create Scrollbar
    $hScroller = GUICreate("", 17, $iNumLabels * 20, $iLeft + $iWidth - 17, $iTop, $WS_CHILD, -1, $hGUI)
    GUISetState(@SW_SHOW, $hScroller)
    GUISwitch($hWnd)

    ; Set scroll bar to run from 1 to 100
    _GUIScrollBars_Init($hScroller)
    _GUIScrollBars_ShowScrollBar($hScroller, $SB_HORZ , False)
    _GUIScrollBars_SetScrollInfoPos($hScroller, $SB_VERT, 100)
    _GUIScrollBars_SetScrollRange($hScroller, $SB_VERT, 0, (200 - _GUIScrollBars_GetScrollInfoPos($hScroller, $SB_VERT)))
    _GUIScrollBars_SetScrollInfoPos($hScroller, $SB_VERT, 0)

    GUIRegisterMsg($WM_VSCROLL, "WM_VSCROLL")

    Return $aGuiData

EndFunc

; This function comes from the _GUIScrollBars_Init example - with a few changes

Func WM_VSCROLL($hWnd, $Msg, $wParam, $lParam)
 #forceref $Msg, $wParam, $lParam
 Local $nScrollCode = BitAND($wParam, 0x0000FFFF)
 Local $index = -1, $yChar, $yPos
 Local $Min, $Max, $Page, $Pos, $TrackPos

 For $x = 0 To UBound($aSB_WindowInfo) - 1
 If $aSB_WindowInfo[$x][0] = $hWnd Then
 $index = $x
 $yChar = $aSB_WindowInfo[$index][3]
 ExitLoop
 EndIf
 Next
 If $index = -1 Then Return 0

 ; Get all the vertial scroll bar information
 Local $tSCROLLINFO = _GUIScrollBars_GetScrollInfoEx($hWnd, $SB_VERT)
 $Min = DllStructGetData($tSCROLLINFO, "nMin")
 $Max = DllStructGetData($tSCROLLINFO, "nMax")
 $Page = DllStructGetData($tSCROLLINFO, "nPage")
 ; Save the position for comparison later on
 $yPos = DllStructGetData($tSCROLLINFO, "nPos")
 $Pos = $yPos
 $TrackPos = DllStructGetData($tSCROLLINFO, "nTrackPos")

 Switch $nScrollCode
 Case $SB_TOP ; user clicked the HOME keyboard key
 DllStructSetData($tSCROLLINFO, "nPos", $Min)
 Case $SB_BOTTOM ; user clicked the END keyboard key
 DllStructSetData($tSCROLLINFO, "nPos", $Max)
 Case $SB_LINEUP ; user clicked the top arrow
 DllStructSetData($tSCROLLINFO, "nPos", $Pos - 1)
 Case $SB_LINEDOWN ; user clicked the bottom arrow
 DllStructSetData($tSCROLLINFO, "nPos", $Pos + 1)
 Case $SB_PAGEUP ; user clicked the scroll bar shaft above the scroll box
 DllStructSetData($tSCROLLINFO, "nPos", $Pos - $Page)
 Case $SB_PAGEDOWN ; user clicked the scroll bar shaft below the scroll box
 DllStructSetData($tSCROLLINFO, "nPos", $Pos + $Page)
 Case $SB_THUMBTRACK ; user dragged the scroll box
 DllStructSetData($tSCROLLINFO, "nPos", $TrackPos)
 EndSwitch

;~ // Set the position and then retrieve it. Due to adjustments
;~ // by Windows it may not be the same as the value set.

 DllStructSetData($tSCROLLINFO, "fMask", $SIF_POS)
 _GUIScrollBars_SetScrollInfo($hWnd, $SB_VERT, $tSCROLLINFO)
 _GUIScrollBars_GetScrollInfo($hWnd, $SB_VERT, $tSCROLLINFO)
 ;// If the position has changed, scroll the window and update it
 $Pos = DllStructGetData($tSCROLLINFO, "nPos")

 If ($Pos <> $yPos) Then
 _GUIScrollBars_ScrollWindow($hWnd, 0, $yChar * ($yPos - $Pos))
 $yPos = $Pos
 $iScrollPos = Round(($iItems - $iNumLabels) * $Pos / 100)
 If $iScrollPos <> $iCurrScrollPos Then
 $iIndex = $iCurrentTopIndex + $iScrollPos - $iCurrScrollPos
 For $i = 1 To $iNumLabels
 ; Write the labels to match the required data
 GUICtrlSetData($aTruncEdit[$i], $aData[$iIndex + $i - 1][0])
                If $aData[$iIndex + $i - 1][1] = 1 Then
                    GUICtrlSetBkColor($i, 0x0000FF)
                    GUICtrlSetColor($i, 0xFFFFFF)
                Else
                    GUICtrlSetBkColor($i, Default)
                    GUICtrlSetColor($i, Default)
                EndIf
 Next
            $iCurrScrollPos = $iScrollPos
 $iCurrentTopIndex = $iIndex
 EndIf
 EndIf

 Return $GUI_RUNDEFMSG

EndFunc ;==>WM_VSCROLL

I have used a 10000 element array to show it does work for large numbers. At the moment you can multiple select/unselect and clear - the items will stay highlighted (highlit?) as you scroll. You will no doubt need further functions, but I am fairly sure we could develop them farly easily.

Let me know what you think - I do not want to spend time on development if you would prefer another route. :)

M23

That works well Melba23 :)

I would have preferred to do it slighlty differently, so that you have the child window, then create a child for that which is high enough to hold all the labels, then you create all the labels on that and when you scroll just move the grandchild up or down rather than rewrite all the labels. But I'm not going to do it, though I did a similar thing here.

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

Melba23, you again came up with an awesome answer! But, it actually helped me in a round-about way. When I did what you showed above it worked fine, but I am using a color scheme that $SS_BLACKFRAME looked bad with, and bad without too. So I was bummed out, thinking I was back in the same boat as before - a working solution but it was breaking the look of what I was doing. Then I thought about what you were doing, and it gave me a dirty little thought - keep my Edit control where I had it, put a Label control overtop of it but shrink it just enough that the Edit's borders were showing, and just write to the Label!! :( Yeah, I feel very dirty doing that, but hey - should I???? It works great because it is just using $DT_END_ELLIPSIS to truncate the string, and no user could possibly ever know that there are 2 controls stacked on top of each other there! hahahahaha

$statusInfo = GUICtrlCreateEdit("", 16, 96, 347, 21, $ES_READONLY)
GUICtrlSetBkColor(-1, 0xdce8ff)
$shadow = GUICtrlCreateLabel("", 20, 99, 335, 15, $DT_End_Ellipsis)
GUICtrlSetBkColor(-1, 0xdce8ff)

I thank you again for your time devoted to helping me out!

Ian

My projects:

  • IP Scanner - Multi-threaded ping tool to scan your available networks for used and available IP addresses, shows ping times, resolves IPs in to host names, and allows individual IPs to be pinged.
  • INFSniff - Great technicians tool - a tool which scans DriverPacks archives for INF files and parses out the HWIDs to a database file, and rapidly scans the local machine's HWIDs, searches the database for matches, and installs them.
  • PPK3 (Persistent Process Killer V3) - Another for the techs - suppress running processes that you need to keep away, helpful when fighting spyware/viruses.
  • Sync Tool - Folder sync tool with lots of real time information and several checking methods.
  • USMT Front End - Front End for Microsoft's User State Migration Tool, including all files needed for USMT 3.01 and 4.01, 32 bit and 64 bit versions.
  • Audit Tool - Computer audit tool to gather vital hardware, Windows, and Office information for IT managers and field techs. Capabilities include creating a customized site agent.
  • CSV Viewer - Displays CSV files with automatic column sizing and font selection. Lines can also be copied to the clipboard for data extraction.
  • MyDirStat - Lists number and size of files on a drive or specified path, allows for deletion within the app.
  • 2048 Game - My version of 2048, fun tile game.
  • Juice Lab - Ecigarette liquid making calculator.
  • Data Protector - Secure notes to save sensitive information.
  • VHD Footer - Add a footer to a forensic hard drive image to allow it to be mounted or used as a virtual machine hard drive.
  • Find in File - Searches files containing a specified phrase.
Link to comment
Share on other sites

  • Moderators

llewxam,

I feel very dirty doing that, but hey - should I????

Certainly not! Nice example of lateral thinking. :(

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

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...