Sign in to follow this  
Followers 0
Melba23

Fun with ListViews and other things!

11 posts in this topic

#1 ·  Posted (edited)

Good afternoon,

I was helping out in the GUI Help forum and came up with this script. I thought it might be of wider interest and so I am posting it here. :graduated:

What does it do?

- The main purpose was to have multiple editable ListView controls held within individual MDI child GUIs. Double-click on a ListView item/subitem to start editing - click outside the small edit sontrol or press "Enter" to stop editing.

- The child GUIs can be moved and resized within the GUI - with a reset function to put them all back to their original position if you get too confused. Placing your mouse over the blue border allows you to drag the GUIs - placing it over the red border allows you to resize them (as the cursor image change suggests :D ).

- The child GUIs are limited in size (max and min) and also limited in position - they cannot move over the tab controls.

The script is liberally commented so I hope you can follow what is going on: :(

;#AutoIt3Wrapper_Au3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <Constants.au3>
#Include <GuiEdit.au3>
#Include <GuiTab.au3>
#include <WinApi.au3>
#include <Date.au3>

; Declare Globals
Global Const $SC_DRAGMOVE = 0xF012
Global $ahChild[6], $ahListView[UBound($ahChild)]
Global $iActive_Index
Global $tPoint = DllStructCreate($tagPoint)
Global $fDblClk = False, $hEdit, $hDC, $hBrush, $aHit

Global $fEdited = False, $iListView_ID, $sItemOrgText, $sItemNewText ; Line only needed for demo ConsoleWrite

; Set distance from edge of window where resizing is possible
Global Const $iMargin = 4
; Set max and min GUI sizes and coords for children
Global Const $iGUIMinX = 50, $iGUIMinY = 50, $iGUIMaxX = 600, $iGUIMaxY = 600

; Create parent GUI
Global $hGUI = GUICreate("Test", 940, 940)

; Create menu
Global $mMainMenu = GUICtrlCreateMenu("File")
Global $mExit = GUICtrlCreateMenuItem("Exit", $mMainMenu)
Global $mResetMenu = GUICtrlCreateMenu("Reset")
Global $mReset = GUICtrlCreateMenuItem("Reset All ListViews", $mResetMenu)
Global $mHelpMenu = GUICtrlCreateMenu("?")
Global $mAbout = GUICtrlCreateMenuItem("About", $mHelpMenu)

; Create tabs
Global $hTab = GUICtrlCreateTab(10, 10, 920, 900, $TCS_MULTILINE)
Global $iTab_Adjust = GUICtrlCreateDummy()
For $i = 1 To 52
    GUICtrlCreateTabItem("Week " & $i)
Next
GUICtrlCreateTabItem("")
GUICtrlSetState(_WeekNumberISO() + $iTab_Adjust, $GUI_SHOW)

; Determine top limit for child GUI movement to prevent covering tabs
Global $aTabPos = ControlGetPos($hGUI, "", $hTab)
Global $aTabClientPos = _GUICtrlTab_GetDisplayRect(ControlGetHandle($hGUI, "", $hTab))
Global $iChild_Min_Y = $aTabClientPos[1] + $aTabPos[1]

; Create Child GUIs
For $i = 0 To UBound($ahChild) - 1
    _CreateMDIChild($i)
Next

GUISetState(@SW_SHOW, $hGUI)

; Register message handlers
GUIRegisterMsg($WM_LBUTTONDOWN, "_WM_LBUTTONDOWN")             ; For Child resize/drag
GUIRegisterMsg($WM_SIZE, "_WM_SIZE")                           ; For LV resize
GUIRegisterMsg($WM_LBUTTONDOWN, "_WM_LBUTTONDOWN")             ; For Child resize/drag
GUIRegisterMsg($WM_MOUSEMOVE, "_WM_MOUSEMOVE")                 ; For active child and cursor type change
GUIRegisterMsg($WM_GETMINMAXINFO, "_WM_GETMINMAXINFO")         ; For GUI size limits
GUIRegisterMsg($WM_WINDOWPOSCHANGING, "_WM_WINDOWPOSCHANGING") ; For keeping tabs clear
GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY")                       ; For doubleclick on ListView
GUIRegisterMsg($WM_COMMAND, "_WM_COMMAND")                     ; For end of ListView edit

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE, $mExit
            Exit
        Case $mReset
            _Reset_All()
        Case $hTab
            ConsoleWrite("Week Selected: " & GUICtrlRead($hTab) + 1 & @CRLF)
        Case $mAbout
            _About()
    EndSwitch

    ; If a ListView was double clicked
    If $fDblClk Then
        $iListView_ID = $iActive_Index ; Line only needed for demo ConsoleWrite
        $aHit = _GUICtrlListView_SubItemHitTest($ahListView[$iActive_Index])
        If $aHit[0] <> -1 Then
            _Start_ItemEdit()
        EndIf
        $fDblClk = False
    EndIf

    If $fEdited Then ; Lines only needed for demo ConsoleWrite
        $fEdited = False
        ConsoleWrite("ListView " & $iListView_ID & " : Row " & $aHit[0] + 1 & " : Col " & $aHit[1] + 1 & " changed from <" & $sItemOrgText & "> to <" & $sItemNewText & ">" & @CRLF)
    EndIf

WEnd

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

Func _CreateMDIChild($iIndex)

    Local $iX, $iY

    ; Set coords
    Switch $iIndex
        Case 0 To 2
            $iX = 10 + (310 * $iIndex)
            $iY = 90
        Case 3 To 5
            $iX = 10 + (310 * ($iIndex - 3))
            $iY = 510
    EndSwitch
    ; Create child
    Local $hChild = GUICreate("", 300, 400, $iX, $iY, BitOr($WS_POPUP, $WS_BORDER))
    ; Set values into array
    $ahChild[$iIndex] = $hChild

    ; This section is for demo purposes only - it colours the Child GUI borders to distinguish the separate resize/drag areas
    GUISetBkColor(0xFFE0E0)
    GUICtrlCreateLabel("", 5, 5, 290, 390)
    GUICtrlSetBkColor(-1, 0xE0E0FF)
    GUICtrlSetState(-1, $GUI_DISABLE)
    GUICtrlSetResizing(-1, 102)
    ; End of demo section - it can be deleted when not required

    ; Add listview
    _Create_ListView($iIndex)
    ; Set main GUI as parent
    _WinAPI_SetParent($hChild, $hGUI)
    ; Show child
    GUISetState()
    Return
EndFunc   ;==>_CreateMDIChild

Func _Create_ListView($iIndex)

    ; Create ListView
    Local $hListView = _GUICtrlListView_Create($ahChild[$iIndex], "Col 1", 10, 10, 300 - 20, 400 - 20, BitOR($LVS_REPORT, $LVS_SINGLESEL, $WS_BORDER), $LVS_EX_FULLROWSELECT)
    _GUICtrlListView_SetExtendedListViewStyle($hListView, $LVS_EX_FULLROWSELECT)
    ; Save handle
    $ahListView[$i] = $hListView
    _GUICtrlListView_AddColumn($hListView, "Col 2")
    _GUICtrlListView_AddColumn($hListView, "Col 3")
    _GUICtrlListView_AddColumn($hListView, "Col 4")
    _GUICtrlListView_SetColumnWidth($hListView, 0, 60)
    _GUICtrlListView_SetColumnWidth($hListView, 1, 60)
    _GUICtrlListView_SetColumnWidth($hListView, 2, 110)
    _GUICtrlListView_SetColumnWidth($hListView, 3, $LVSCW_AUTOSIZE_USEHEADER )

    ; Simulate fill of Listview
    For $k = 1 To 4
        _GUICtrlListView_AddItem($hListView, "" & $i & $k)
        _GUICtrlListView_AddSubItem($hListView, $k - 1, "Sub " & $i & Chr(64 + $k), 1)
        _GUICtrlListView_AddSubItem($hListView, $k - 1, "Sub " & $i & Chr(77 + $k), 2)
    Next

EndFunc   ;==>_Create_ListView

Func _Reset_All()

    Local $iX, $iY

    For $i = 0 To UBound($ahChild) - 1
        ; Determine original coords
        Switch $i
            Case 0 To 2
                $iX = 10 + (310 * $i)
                $iY = 90
            Case 3 To 5
                $iX = 10 + (310 * ($i - 3))
                $iY = 510
        EndSwitch
        ; Move Child GUI
        WinMove($ahChild[$i], "", $iX, $iY, 300, 400) ; Listviews resize automatically via the WM_SIZE handler
        ; Reset original column widths
        _GUICtrlListView_SetColumnWidth($ahListView[$i], 0, 60)
        _GUICtrlListView_SetColumnWidth($ahListView[$i], 1, 60)
        _GUICtrlListView_SetColumnWidth($ahListView[$i], 2, 110)
        _GUICtrlListView_SetColumnWidth($ahListView[$i], 3, $LVSCW_AUTOSIZE_USEHEADER )
    Next

EndFunc   ;==>_Reset_All

Func _SetCursor()

    ; Set cursor to correct resizing form if mouse is over a border
    Local $iCursorID
    Switch _GetBorder()
        Case 0
            $iCursorID = 2
        Case 1, 2
            $iCursorID = 13
        Case 3, 6
            $iCursorID = 11
        Case 5, 7
            $iCursorID = 10
        Case 4, 8
            $iCursorID = 12
    EndSwitch
    GUISetCursor($iCursorID, 1, $ahChild[$iActive_Index])

EndFunc   ;==>_SetCursor

Func _Start_ItemEdit()

    ; Prevent resizing of columns
    ControlDisable($hGUI, "", HWnd(_GUICtrlListView_GetHeader($ahListView[$iActive_Index])))
    ; Get current text
    $sItemOrgText = _GUICtrlListView_GetItemText($ahListView[$iActive_Index], $aHit[0], $aHit[1]) ; Set to Local if no demo ConsoleWrite
    ; Get size of edit box
    Local $aRect = _GUICtrlListView_GetSubItemRect($ahListView[$iActive_Index], $aHit[0], $aHit[1])
    Local $iEdit_Width = _GUICtrlListView_GetColumnWidth($ahListView[$iActive_Index], $aHit[1]) - 7
    Local $iEdit_Height = $aRect[3] - $aRect[1]
    ; Get position of ListView within client area
    Local $aPos = WinGetPos($ahListView[$iActive_Index])
    Local $tPoint = DllStructCreate("int X;int Y")
    DllStructSetData($tPoint, "X", $aPos[0])
    DllStructSetData($tPoint, "Y", $aPos[1])
    _WinAPI_ScreenToClient($hGUI, $tPoint)
    Local $iEdit_X = DllStructGetData($tPoint, "X") + $aRect[0] + 6
    Local $iEdit_Y = DllStructGetData($tPoint, "Y") + $aRect[1]
    ; Create ListView edit control - credit to smashly for this code
    $hEdit = _GUICtrlEdit_Create($hGUI, $sItemOrgText, $iEdit_X, $iEdit_Y, $iEdit_Width, $iEdit_Height, BitOR($WS_CHILD, $WS_VISIBLE, $ES_AUTOHSCROLL, $ES_LEFT))
    _GUICtrlEdit_SetSel($hEdit, 0, -1)
    _WinAPI_SetFocus($hEdit)
    ; Prevent overwrite of edit rectangle
    $hDC = _WinAPI_GetWindowDC($hEdit)
    $hBrush = _WinAPI_CreateSolidBrush(0)
    Local $stRect = DllStructCreate("int;int;int;int")
    DllStructSetData($stRect, 1, $iEdit_Width)
    DllStructSetData($stRect, 2, 0)
    DllStructSetData($stRect, 3, 0)
    DllStructSetData($stRect, 4, $iEdit_Height)
    DllCall("user32.dll", "int", "FrameRect", "hwnd", $hDC, "ptr", DllStructGetPtr($stRect), "hwnd", $hBrush)
    ; Set HotKey to close edit
    HotKeySet("{ENTER}", "_End_SubItemEdit")

EndFunc

Func _End_SubItemEdit()

    $sItemNewText = _GUICtrlEdit_GetText($hEdit) ; Set to Local if no demo ConsoleWrite
    ; Check edit took place
    If $sItemNewText <> $sItemOrgText Then ; Line only needed for demo ConsoleWrite
        _GUICtrlListView_SetItemText($ahListView[$iActive_Index], $aHit[0], $sItemNewText, $aHit[1])
        $fEdited = True ; Line only needed for demo ConsoleWrite
    EndIf ; Line only needed for demo ConsoleWrite
    ; Free edit rectangle
    _WinAPI_DeleteObject($hBrush)
    _WinAPI_ReleaseDC($hEdit, $hDC)
    _WinAPI_DestroyWindow($hEdit)
    ; Clear HotKey
    HotKeySet("{ENTER}")
    ; Re-enable resizing of columns
    ControlEnable($hGUI, "", HWnd(_GUICtrlListView_GetHeader($ahListView[$iActive_Index])))
    ; Clear handle
    ;$hListView = 0

EndFunc

Func _About()

    Local $sMsg = "This script was written by Melba23" & @CRLF & @CRLF & "And he is pretty pleased with it!"

    MsgBox(8192 + 64, "About this script", $sMsg, 0, $hGUI)

EndFunc

; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Func _WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $wParam

    Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    Local $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    Local $iCode = DllStructGetData($tNMHDR, "Code")
    ; Check if a ListView has sent the message
    For $i = 0 To UBound($ahChild) - 1
        If $ahListView[$i] = $hWndFrom Then
            Switch $iCode
                Case $NM_DBLCLK
                    ; Set flag
                    $fDblClk = True
                    ; Force index
                    $iActive_Index = $i
            EndSwitch
            ExitLoop
        EndIf
    Next
    Return $GUI_RUNDEFMSG

EndFunc

Func _WM_COMMAND($hWnd, $Msg, $wParam, $lParam)

    #forceref $hWnd, $Msg, $wParam

    Local $iCode = BitShift($wParam, 16)
    Switch $lParam
        Case $hEdit
            Switch $iCode
                Case $EN_KILLFOCUS
                    _End_SubItemEdit()
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COMMAND

Func _WM_LBUTTONDOWN($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $wParam, $lParam

    ; If cursor not over child
    If $iActive_Index = -1 Then Return

    ; Check cursor type and resize/drag child window as required
    Local $iCursorType = _GetBorder()
    If $iCursorType > 0 Then ; Cursor is set to resizing style
        Local $iResizeType = 0xF000 + $iCursorType
        _SendMessage($ahChild[$iActive_Index], $WM_SYSCOMMAND, $iResizeType, 0)
    Else
        _SendMessage($ahChild[$iActive_Index], $WM_SYSCOMMAND, $SC_DRAGMOVE, 0)
    EndIf

EndFunc   ;==>_WM_LBUTTONDOWN

Func _WM_SIZE($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $wParam, $lParam

    ; Resize listviews to fit child GUIs - do all to cater for reset
    For $i = 0 To UBound($ahChild) - 1
        If $hWnd = $ahChild[$i] Then
            Local $aWinPos = WinGetPos($ahChild[$i])
            _WinAPI_MoveWindow($ahListView[$i], 10, 10, $aWinPos[2] - 20, $aWinPos[3] - 20,  True)
            Return $GUI_RUNDEFMSG
        EndIf
    Next

    Return $GUI_RUNDEFMSG

EndFunc   ;==>MY_WM_SIZE

Func _WM_MOUSEMOVE($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $wParam, $lParam

    ; Determine active child and set index
    DllStructSetData($tPoint, "X", MouseGetPos(0))
    DllStructSetData($tPoint, "Y", MouseGetPos(1))
    Local $hActive = _WinAPI_WindowFromPoint($tPoint)
    $iActive_Index = -1
    For $i = 0 To UBound($ahChild) - 1
        If $ahChild[$i] = $hActive Then
            $iActive_Index = $i
            ExitLoop
        EndIf
    Next

    If $iActive_Index = -1 Then
        Return
    Else
        _SetCursor()
    EndIf

EndFunc

Func _GetBorder()

    ; Check over a child
    If $iActive_Index = -1 Then Return

    ; Determines if mouse cursor over child border
    Local $aCurInfo = GUIGetCursorInfo($ahChild[$iActive_Index])
    Local $aWinPos = WinGetPos($ahChild[$iActive_Index])
    Local $iSide = 0
    Local $iTopBot = 0
    If $aCurInfo[0] < $iMargin Then $iSide = 1
    If $aCurInfo[0] > $aWinPos[2] - $iMargin Then $iSide = 2
    If $aCurInfo[1] < $iMargin Then $iTopBot = 3
    If $aCurInfo[1] > $aWinPos[3] - $iMargin Then $iTopBot = 6

    Return $iSide + $iTopBot

EndFunc   ;==>_GetBorder

Func _WM_GETMINMAXINFO($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $wParam

    ; Set min and max GUI sizes for child GUIs
    Local $tMinMaxInfo = DllStructCreate("int;int;int;int;int;int;int;int;int;int", $lParam)
    DllStructSetData($tMinMaxInfo, 7, $iGUIMinX)
    DllStructSetData($tMinMaxInfo, 8, $iGUIMinY)
    DllStructSetData($tMinMaxInfo, 9, $iGUIMaxX)
    DllStructSetData($tMinMaxInfo, 10, $iGUIMaxY)
    Return 0

EndFunc   ;==>_WM_GETMINMAXINFO

Func _WM_WINDOWPOSCHANGING($hWnd, $iMsg, $wParam, $lParam)

    #forceref $iMsg, $wParam

    ; Ignore main GUI
    If $hWnd = $hGUI Then Return
    ; Set min Y coord for Child GUIs
    Local $stWinPos = DllStructCreate("uint;uint;int;int;int;int;uint", $lParam)
    If DllStructGetData($stWinPos, 4) <  $iChild_Min_Y Then DllStructSetData($stWinPos, 4, $iChild_Min_Y)

EndFunc

As you can see, the script uses a lot of Windows message handlers - if you are unsure of what these do I recommend the GUIRegisterMsg tutorial in the Wiki.

I am not really interested in developing the script any further, but I am happy to answer questions about it if anyone has any. :D

M23

Edit: Typnig!

Edited by Melba23

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______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

 

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

that's kinda cool, this has a Web 2.5 flavorbeat!!!

I really could use this stuff in some projects !!

Edited by hench

Share this post


Link to post
Share on other sites

wow!! not alot of code either, nice implementation of loops! lol (i personally like it even if others don't :graduated: )

Share this post


Link to post
Share on other sites

wow!! not alot of code either, nice implementation of loops! lol (i personally like it even if others don't :graduated: )

Share this post


Link to post
Share on other sites

Melba23,

An interesting script however, I found a bug.

If I select say week 1, then double click the item represented by column 1, row 1, then double click week 2, the script fails with:

C:\AutoItStuff\Interesting\ListViewFun.au3 (252) : ==> Array variable subscript badly formatted.:

ControlEnable($hGUI, "", HWnd(_GUICtrlListView_GetHeader($ahListView[$iActive_Index])))

ControlEnable($hGUI, "", HWnd(_GUICtrlListView_GetHeader($ahListView[^ ERROR

I haven't tried to fix it at this stage.

Regards,

4Eyes

Share this post


Link to post
Share on other sites

Yashied,

it's not really MDI windows

Which, I presume, is why it says in the Help file for $WS_EX_MDICHILD:

"Create a child window included in its parent window (simulation not real MDI)"

But I can live with it! :(

4Eyes,

When I do what you describe, I do not get a crash - so I cannot comment. Anyway, as I said earlier, I am not developing or supporting the script any further - it was just posted for general interest. :graduated:

But if you want to play around with it, please do - anything I post on the forum is for anyone else to do with as they wish.

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______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

 

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

When I do what you describe, I do not get a crash - so I cannot comment. Anyway, as I said earlier, I am not developing or supporting the script any further - it was just posted for general interest. :graduated:

I get the same outcome as 4Eyes.

I know that it will bother you Melba;)

Suppose as I'm being mean I should let you know that I'm running XP SP3 here at work.

Edited by JamesBrooks

Share this post


Link to post
Share on other sites

Yes, I'm running XP with SP3 too.

BTW Melba23, I understand.

4Eyes

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

More fun with ListViews -  _ArrayEdit function.

A cross between M23's "Fun with ListViews" and _ArrayDisplay() from the include file, Array.au3, gives _ArrayEdit().
Unfortunately, I have not made this _ArrayEdit() function a stand alone function as _ArrayDisplay() is.

It does work on my XP SP3.

Double click on an array item/sub-item to start edit. And press "Save" button to save the changed array.

#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <GuiEdit.au3>
#include <Array.au3>

; Combination of  http://www.autoitscript.com/forum/topic/122257-fun-with-listviews-and-other-things/page__view__findpost__p__848651
; and _ArrayDisplay() from include file, Array.au3.

Global $fDblClk = False, $hEdit, $hDC, $hBrush, $aHit, $hGUI, $ahListView, $sItemOrgText, $sItemNewText, $hListView
Global $fEdited = False

Local $aArray[4][5] = [[0, 1, 2, 3, 4],[5, 6, 7, 8, 9],[10, 11, 12, 13, 14],[15, 16, 17, 18, 19]]
;Local $aArray[6] = [0, 1, 2, 3, 4, 5]

_ArrayEdit($aArray)
;_ArrayEdit($aArray, "Array Transposed", -1, 1, "", "|", "Row|Column 1|Column 2|Column 3|Column 4")

_ArrayDisplay($aArray)

; Double click on array item to edit that item.
Func _ArrayEdit(ByRef $avArray, $sTitle = "Array: ListView Edit", $iItemLimit = -1, $iTranspose = 0, $sSeparator = "", $sReplace = "|", $sHeader = "")
    If Not IsArray($avArray) Then Return SetError(1, 0, 0)
    ; Dimension checking
    Local $iDimension = UBound($avArray, 0), $iUBound = UBound($avArray, 1) - 1, $iSubMax = UBound($avArray, 2) - 1
    If $iDimension > 2 Then Return SetError(2, 0, 0)
    ; Separator handling
;~     If $sSeparator = "" Then $sSeparator = Chr(1)
    If $sSeparator = "" Then $sSeparator = Chr(124)
    ;  Check the separator to make sure it's not used literally in the array
    If _ArraySearch($avArray, $sSeparator, 0, 0, 0, 1) <> -1 Then
        For $x = 1 To 255
            If $x >= 32 And $x <= 127 Then ContinueLoop
            Local $sFind = _ArraySearch($avArray, Chr($x), 0, 0, 0, 1)
            If $sFind = -1 Then
                $sSeparator = Chr($x)
                ExitLoop
            EndIf
        Next
    EndIf
    ; Declare variables
    Local $vTmp, $iBuffer = 64
    Local $iColLimit = 250
    Local $iOnEventMode = Opt("GUIOnEventMode", 0), $sDataSeparatorChar = Opt("GUIDataSeparatorChar", $sSeparator)
    ; Swap dimensions if transposing
    If $iSubMax < 0 Then $iSubMax = 0
    If $iTranspose Then
        $vTmp = $iUBound
        $iUBound = $iSubMax
        $iSubMax = $vTmp
    EndIf
    ; Set limits for dimensions
    If $iSubMax > $iColLimit Then $iSubMax = $iColLimit
    If $iItemLimit < 1 Then $iItemLimit = $iUBound
    If $iUBound > $iItemLimit Then $iUBound = $iItemLimit
    ; Set header up
    If $sHeader = "" Then
        $sHeader = "Row  " ; blanks added to adjust column size for big number of rows
        For $i = 0 To $iSubMax
            $sHeader &= $sSeparator & "Col " & $i
        Next
    EndIf
    ; Convert array into text for listview
    Local $avArrayText[$iUBound + 1]
    For $i = 0 To $iUBound
        $avArrayText[$i] = "[" & $i & "]"
        For $j = 0 To $iSubMax
            ; Get current item
            If $iDimension = 1 Then
                If $iTranspose Then
                    $vTmp = $avArray[$j]
                Else
                    $vTmp = $avArray[$i]
                EndIf
            Else
                If $iTranspose Then
                    $vTmp = $avArray[$j][$i]
                Else
                    $vTmp = $avArray[$i][$j]
                EndIf
            EndIf
            ; Add to text array
            $vTmp = StringReplace($vTmp, $sSeparator, $sReplace, 0, 1)
            $avArrayText[$i] &= $sSeparator & $vTmp
            ; Set max buffer size
            $vTmp = StringLen($vTmp)
            If $vTmp > $iBuffer Then $iBuffer = $vTmp
        Next
    Next
    $iBuffer += 1
    ; GUI Constants
    Local Const $_ARRAYCONSTANT_GUI_DOCKBORDERS = 0x66
    Local Const $_ARRAYCONSTANT_GUI_DOCKBOTTOM = 0x40
    Local Const $_ARRAYCONSTANT_GUI_DOCKHEIGHT = 0x0200
    Local Const $_ARRAYCONSTANT_GUI_DOCKLEFT = 0x2
    Local Const $_ARRAYCONSTANT_GUI_DOCKRIGHT = 0x4
    Local Const $_ARRAYCONSTANT_GUI_EVENT_CLOSE = -3
    Local Const $_ARRAYCONSTANT_LVIF_PARAM = 0x4
    Local Const $_ARRAYCONSTANT_LVIF_TEXT = 0x1
    Local Const $_ARRAYCONSTANT_LVM_GETCOLUMNWIDTH = (0x1000 + 29)
    Local Const $_ARRAYCONSTANT_LVM_GETITEMCOUNT = (0x1000 + 4)
    Local Const $_ARRAYCONSTANT_LVM_GETITEMSTATE = (0x1000 + 44)
    Local Const $_ARRAYCONSTANT_LVM_INSERTITEMW = (0x1000 + 77)
    Local Const $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE = (0x1000 + 54)
    Local Const $_ARRAYCONSTANT_LVM_SETITEMW = (0x1000 + 76)
    Local Const $_ARRAYCONSTANT_LVS_EX_FULLROWSELECT = 0x20
    Local Const $_ARRAYCONSTANT_LVS_EX_GRIDLINES = 0x1
    Local Const $_ARRAYCONSTANT_LVS_SHOWSELALWAYS = 0x8
    Local Const $_ARRAYCONSTANT_WS_EX_CLIENTEDGE = 0x0200
    Local Const $_ARRAYCONSTANT_WS_MAXIMIZEBOX = 0x00010000
    Local Const $_ARRAYCONSTANT_WS_MINIMIZEBOX = 0x00020000
    Local Const $_ARRAYCONSTANT_WS_SIZEBOX = 0x00040000
    Local Const $_ARRAYCONSTANT_tagLVITEM = "int Mask;int Item;int SubItem;int State;int StateMask;ptr Text;int TextMax;int Image;int Param;int Indent;int GroupID;int Columns;ptr pColumns"
    Local $iAddMask = BitOR($_ARRAYCONSTANT_LVIF_TEXT, $_ARRAYCONSTANT_LVIF_PARAM)
    Local $tBuffer = DllStructCreate("wchar Text[" & $iBuffer & "]"), $pBuffer = DllStructGetPtr($tBuffer)
    Local $tItem = DllStructCreate($_ARRAYCONSTANT_tagLVITEM), $pItem = DllStructGetPtr($tItem)
    DllStructSetData($tItem, "Param", 0)
    DllStructSetData($tItem, "Text", $pBuffer)
    DllStructSetData($tItem, "TextMax", $iBuffer)
    ; Set interface up
    Local $iWidth = 640, $iHeight = 480
    $hGUI = GUICreate($sTitle, $iWidth, $iHeight, Default, Default, BitOR($_ARRAYCONSTANT_WS_SIZEBOX, $_ARRAYCONSTANT_WS_MINIMIZEBOX, $_ARRAYCONSTANT_WS_MAXIMIZEBOX))
    Local $aiGUISize = WinGetClientSize($hGUI)
    $ahListView = GUICtrlCreateListView($sHeader, 0, 0, $aiGUISize[0], $aiGUISize[1] - 26, 0x40800201);$_ARRAYCONSTANT_LVS_SHOWSELALWAY
    ; 00800005, 00000020
    $hListView = ControlGetHandle($hGUI, "", $ahListView)
    Local $hSave = GUICtrlCreateButton("Save", 3, $aiGUISize[1] - 23, $aiGUISize[0] - 6, 20)
    GUICtrlSetResizing($ahListView, $_ARRAYCONSTANT_GUI_DOCKBORDERS)
    GUICtrlSetResizing($hSave, $_ARRAYCONSTANT_GUI_DOCKLEFT + $_ARRAYCONSTANT_GUI_DOCKRIGHT + $_ARRAYCONSTANT_GUI_DOCKBOTTOM + $_ARRAYCONSTANT_GUI_DOCKHEIGHT)
    GUICtrlSendMsg($ahListView, $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE, $_ARRAYCONSTANT_LVS_EX_GRIDLINES, $_ARRAYCONSTANT_LVS_EX_GRIDLINES)
    GUICtrlSendMsg($ahListView, $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE, $_ARRAYCONSTANT_LVS_EX_FULLROWSELECT, $_ARRAYCONSTANT_LVS_EX_FULLROWSELECT)
    GUICtrlSendMsg($ahListView, $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE, $_ARRAYCONSTANT_WS_EX_CLIENTEDGE, $_ARRAYCONSTANT_WS_EX_CLIENTEDGE)
    ; Fill listview
    Local $aItem
    For $i = 0 To $iUBound
        If GUICtrlCreateListViewItem($avArrayText[$i], $ahListView) = 0 Then
            ; use GUICtrlSendMsg() to overcome AutoIt limitation
            $aItem = StringSplit($avArrayText[$i], $sSeparator)
            DllStructSetData($tBuffer, "Text", $aItem[1])
            ; Add listview item
            DllStructSetData($tItem, "Item", $i)
            DllStructSetData($tItem, "SubItem", 0)
            DllStructSetData($tItem, "Mask", $iAddMask)
            GUICtrlSendMsg($ahListView, $_ARRAYCONSTANT_LVM_INSERTITEMW, 0, $pItem)
            ; Set listview subitem text
            DllStructSetData($tItem, "Mask", $_ARRAYCONSTANT_LVIF_TEXT)
            For $j = 2 To $aItem[0]
                DllStructSetData($tBuffer, "Text", $aItem[$j])
                DllStructSetData($tItem, "SubItem", $j - 1)
                GUICtrlSendMsg($ahListView, $_ARRAYCONSTANT_LVM_SETITEMW, 0, $pItem)
            Next
        EndIf
    Next
    ; adjust window width
    $iWidth = 0
    For $i = 0 To $iSubMax + 1
        $iWidth += GUICtrlSendMsg($ahListView, $_ARRAYCONSTANT_LVM_GETCOLUMNWIDTH, $i, 0)
    Next
    If $iWidth < 250 Then $iWidth = 230
    $iWidth += 20
    If $iWidth > @DesktopWidth Then $iWidth = @DesktopWidth - 100
    WinMove($hGUI, "", (@DesktopWidth - $iWidth) / 2, Default, $iWidth)
    ; Show dialog
    GUISetState(@SW_SHOW, $hGUI)
    GUIRegisterMsg($WM_COMMAND, "_WM_COMMAND") ; For end of ListView edit
    GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY") ; For doubleclick on ListView
    While 1
        Switch GUIGetMsg()
            Case $_ARRAYCONSTANT_GUI_EVENT_CLOSE
                ExitLoop
            Case $hSave
                If $iTranspose <> 0 Then
                    ReDim $avArray[$iUBound + 1][$iSubMax + 1]
                EndIf
                Local $sDisp = "$avArray[" & $iUBound + 1 & "]" & (($iSubMax = 0) ? " = " : "[" & $iSubMax + 1 & "] = ") & @CRLF
                For $x = 0 To $iUBound
                    For $y = 0 To $iSubMax
                        If $iDimension = 1 Then
                            $avArray[$x] = _GUICtrlListView_GetItemText($hListView, $x, $y + 1)
                            $sDisp &= $avArray[$x] & @TAB
                        Else
                            $avArray[$x][$y] = _GUICtrlListView_GetItemText($hListView, $x, $y + 1)
                            $sDisp &= $avArray[$x][$y] & @TAB
                        EndIf
                    Next
                    $sDisp &= @CRLF
                Next
                MsgBox(0, "Edited Array", $sDisp, 5); <========= Delete if not needed ======================
        EndSwitch
        If $fDblClk Then
            $aHit = _GUICtrlListView_SubItemHitTest($hListView)
            If $aHit[0] <> -1 Then
                ;_Start_ItemEdit()
                ControlDisable($hGUI, "", HWnd(_GUICtrlListView_GetHeader($hListView)))
                ; Get current text
                $sItemOrgText = _GUICtrlListView_GetItemText($hListView, $aHit[0], $aHit[1]) ; Set to Local if no demo ConsoleWrite
                ; Get size of edit box
                Local $aRect = _GUICtrlListView_GetSubItemRect($hListView, $aHit[0], $aHit[1])
                Local $iEdit_Width = _GUICtrlListView_GetColumnWidth($hListView, $aHit[1]) - 7
                Local $iEdit_Height = $aRect[3] - $aRect[1]
                ; Get position of ListView within client area
                Local $aPos = WinGetPos($hListView)
                Local $tPoint = DllStructCreate("int X;int Y")
                DllStructSetData($tPoint, "X", $aPos[0])
                DllStructSetData($tPoint, "Y", $aPos[1])
                _WinAPI_ScreenToClient($hGUI, $tPoint)
                Local $iEdit_X = DllStructGetData($tPoint, "X") + $aRect[0] + 6
                Local $iEdit_Y = DllStructGetData($tPoint, "Y") + $aRect[1]
                ; Create ListView edit control - credit to smashly for this code
                $hEdit = _GUICtrlEdit_Create($hGUI, $sItemOrgText, $iEdit_X, $iEdit_Y, $iEdit_Width, $iEdit_Height, BitOR($WS_CHILD, $WS_VISIBLE, $ES_AUTOHSCROLL, $ES_LEFT))
                _GUICtrlEdit_SetSel($hEdit, 0, -1)
                _WinAPI_SetFocus($hEdit)
                ; Prevent overwrite of edit rectangle
                $hDC = _WinAPI_GetWindowDC($hEdit)
                $hBrush = _WinAPI_CreateSolidBrush(0)
                Local $stRect = DllStructCreate("int;int;int;int")
                DllStructSetData($stRect, 1, $iEdit_Width)
                DllStructSetData($stRect, 2, 0)
                DllStructSetData($stRect, 3, 0)
                DllStructSetData($stRect, 4, $iEdit_Height)
                DllCall("user32.dll", "int", "FrameRect", "hwnd", $hDC, "ptr", DllStructGetPtr($stRect), "hwnd", $hBrush)
                ; Set HotKey to close edit
                HotKeySet("{ENTER}", "_End_SubItemEdit")
            EndIf
            $fDblClk = False
        EndIf
        If $fEdited Then ; Lines only needed for demo ConsoleWrite
            $fEdited = False
        EndIf
    WEnd
    GUIDelete($hGUI)
    Opt("GUIOnEventMode", $iOnEventMode)
    Opt("GUIDataSeparatorChar", $sDataSeparatorChar)
    Return 1
EndFunc   ;==>_ArrayEdit

Func _WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam
    Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    Local $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    Local $iCode = DllStructGetData($tNMHDR, "Code")
    ; Check if a ListView has sent the message
    Switch $iCode
        Case $NM_DBLCLK
            ; Set flag
            $fDblClk = True
    EndSwitch
    Return 'GUI_RUNDEFMSG' ; 'GUI_RUNDEFMSG' ; $GUI_RUNDEFMSG from GUIConstantsEx.au3 from GUIConstantsEx.au3
EndFunc   ;==>_WM_NOTIFY

Func _End_SubItemEdit()
    $sItemNewText = _GUICtrlEdit_GetText($hEdit) ; Set to Local if no demo ConsoleWrite
    ; Check edit took place
    If $sItemNewText <> $sItemOrgText Then ; Line only needed for demo ConsoleWrite
        _GUICtrlListView_SetItemText($ahListView, $aHit[0], $sItemNewText, $aHit[1])
        $fEdited = True ; Line only needed for demo ConsoleWrite
    EndIf ; Line only needed for demo ConsoleWrite
    ; Free edit rectangle
    _WinAPI_DeleteObject($hBrush)
    _WinAPI_ReleaseDC($hEdit, $hDC)
    _WinAPI_DestroyWindow($hEdit)
    ; Clear HotKey
    HotKeySet("{ENTER}")
    ; Re-enable resizing of columns
    ControlEnable($hGUI, "", HWnd(_GUICtrlListView_GetHeader($hListView)))
EndFunc   ;==>_End_SubItemEdit

Func _WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    #forceref $hWnd, $Msg, $wParam
    Local $iCode = BitShift($wParam, 16)
    Switch $lParam
        Case $hEdit
            Switch $iCode
                Case $EN_KILLFOCUS
                    _End_SubItemEdit()
            EndSwitch
    EndSwitch
    Return 'GUI_RUNDEFMSG' ; $GUI_RUNDEFMSG from GUIConstantsEx.au3
EndFunc   ;==>_WM_COMMAND

Edit: Replaced _Iif function with ternary conditional operator.

Also "#include <Array.au3>" line deleted.

This also works on Win7.

Edited by Malkey

Share this post


Link to post
Share on other sites

Hello people,

my fun is not that much great because I figured out that !ONLY 16-Childs are possible to set in a ListView! 

Could that be? I tried a lot arround. I got 30 Childs but filling in each a ListView only possible up to count of 16.

Does anybody know why this is so?

Greetings
 

Andrew


Thanks! :bye:

Greetings

Andrew

 

Share this post


Link to post
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
Sign in to follow this  
Followers 0