Jump to content



Photo

UDF: _ArrayBox()


  • Please log in to reply
10 replies to this topic

#1 blindwig

blindwig

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 772 posts

Posted 21 June 2005 - 01:15 AM

I wanted a better way to display an array than _ArrayDisplay. It's 2 biggest limitations were that since it's using a messagebox, really big arrays will be too big to fit the box on the screen, and secondly that it doesn't show 2-dimensional arrays.
My function handles 1d and 2d arrays, and also 0-based and 1-based arrays. It creates a GUI Form (that is sizable and maximizable) with a listview on it that displays the array with the index numbers listed down the side.

CODE

;===============================================================================
;
; Function Name: _ArrayBox()
; Description: Shows an array in a GUI window. Improved version of _ArrayDisplay
; Parameter(s): $Array - An array, 1d or 2d, 0-based or 1-based
; $ArrayBase - 1 or 0 - tells what base the array is
; $sTitle - the title to put on the output window
; $Width, $Height, $Left, $Top - Set the size and position of the output window
; Requirement(s): $Array must be 1d or 2d. If 1-based, then arraysize is assumed to be $Array[0] or $Array[0][0]
; Return Value(s): -1 = $Array is not an array, error=1
; Author(s): Mike Ratzlaff <mike@ratzlaff.org>
; Revision: 20050620A
;
;===============================================================================
;
Func _ArrayBox(ByRef $Array, $ArrayBase = 1, $sTitle = 'Array Box', $Width = 200, $Height = 200, $Left = -1, $Top = -1)
Dim $AllDone = 0, $msg, $i, $j, $ArrayDimensions = UBound($Array, 0)
Dim $hndForm_Main, $hndListView_Display

If $ArrayDimensions = 0 Then
SetError(1)
Return -1
EndIf

;Setup
If $ArrayBase <> 0 Then $ArrayBase = 1
If $ArrayBase Then
Select
Case $ArrayDimensions = 1
$ArrayMax = $Array[0]
Case $ArrayDimensions = 2
$ArrayMax = $Array[0][0]
EndSelect
Else
$ArrayMax = UBound($Array, 1) - 1
EndIf

;Create GUI
If $Height < 100 Then $Height = 100
If $Width < 100 Then $Width = 100
$hndForm_Main = GUICreate($sTitle, $Width, $Height, $Left, $Top, BitOR($WS_POPUP, $WS_CAPTION, $WS_SIZEBOX, $WS_MAXIMIZEBOX, $WS_EX_DLGMODALFRAME))

;Create List Box
If $ArrayDimensions = 1 Then
$sTemp = 'Index|Value'
ElseIf $ArrayDimensions = 2 Then
$sTemp = 'Index'
For $i = 0 To UBound($Array, 2) - 1
$sTemp = $sTemp & '|' & $i
Next
EndIf
$hndListView_Display = GUICtrlCreateListView($sTemp, 0, 0, $Width, $Height-24, BitOR($LVS_SHOWSELALWAYS, $LVS_SINGLESEL))
GUICtrlSetResizing($hndListView_Display, BitOR($GUI_DockLeft, $GUI_DockTop, $GUI_DockRight, $GUI_DockBottom))

;Create Controls, Show GUI
$hndButton_Close = GUICtrlCreateButton('&Close',$Width-80,$Height-24,80,24)
GUICtrlSetResizing($hndButton_Close, BitOR($GUI_DockRight, $GUI_DockBottom, $GUI_DockSize))
GUICtrlSetState($hndButton_Close, $GUI_DefButton)
GUISetState (@SW_SHOW, $hndForm_Main)

;Display Array
Select
Case $ArrayDimensions = 1 ;1-Dimensional Array
For $i = $ArrayBase To $ArrayMax
GUICtrlCreateListViewItem($i & '|' & $Array[$i], $hndListView_Display)
Next ;$i
Case $ArrayDimensions = 2 ;2-Dimensional Array
For $i = $ArrayBase To $ArrayMax
$sTemp=$Array[$i][0]
for $j = 1 To UBound($Array, 2) - 1
$sTemp = $sTemp & '|' & $Array[$i][$j]
Next ;$j
GUICtrlCreateListViewItem('[' & $i & ']|' & $sTemp, $hndListView_Display)
Next ;$i
Case Else ;Unhandled Type

EndSelect

;Wait for user to close box
Do
$msg = GUIGetMsg()
Select
Case $msg = $GUI_EVENT_CLOSE
$AllDone = 1
Case $msg = $hndButton_Close
$AllDone = 1
EndSelect
Until $AllDone
GUIDelete($hndForm_Main)
Return 0
EndFunc

Tell me what you think!





#2 blindwig

blindwig

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 772 posts

Posted 21 June 2005 - 01:18 AM

Oh, I forgot to say - It's called _ArrayBox because it's going to be part of a new UDF set I'm writing for displaying complex types (stuff that doesn't display right in a MsgBox). I'm calling my functions _*Box after the MsgBox and InputBox functions.

#3 blindwig

blindwig

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 772 posts

Posted 21 June 2005 - 01:30 AM

Oh, and here's some sample code so you can see how it looks:
Dim $a=IniReadSectionNames('C:\windows\win.ini') _ArrayBox($a,1,'Windows Settings') Dim $s=$a[random(1,$a[0])], $a=IniReadSection('C:\windows\win.ini',$s) _ArrayBox($a,1,'Windows Settings: ' & $s)


#4 FuryCell

FuryCell

    A cornered fox is more dangerous than a jackal!

  • Active Members
  • PipPipPipPipPipPip
  • 2,437 posts

Posted 22 June 2005 - 02:29 AM

Nice Job. :)
Just tried it with a two dimensional array and it worked perfectly. The list view looks cool too. :evil:

There are two things i think you can do to make it even better though.
1.Make all your variables Local

2.Make $ArrayBase default to 0 so it follows the standards of the other array functions.

Edited by SolidSnake, 22 June 2005 - 02:34 AM.

HKTunes:Softpedia | GoogleCodeLyricToy:Softpedia | GoogleCodeRCTunes:Softpedia | GoogleCodeMichtaToolsProgrammer n. - An ingenious device that turns caffeine into code.

#5 blindwig

blindwig

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 772 posts

Posted 22 June 2005 - 03:13 AM

Nice Job.  :)
Just tried it with a two dimensional array and it worked perfectly. The list view looks cool too.    :D

<{POST_SNAPBACK}>

Great, glad you liked it!

There are two things i think you can do to make it even better though.
1.Make all your variables Local

2.Make $ArrayBase default to 0 so it follows the standards of the other array functions.

<{POST_SNAPBACK}>

1. I think that when you use Dim inside a function, it is automatically a local variable?

2. It's always hard for me to pick the default base when writing array functions. Sometime I think maybe I shouldn't have a default and just make the user specify it everytime. I picked 1 this time because that what most of the arrays I want to display are. Most functions that I use (StringSplit, IniRead*, etc) return 1-based arrays, so that's why I made it the default. And I'm putting this in a UDF library that I'm writing that is focused on 1-based arrays, so for my purposes it's better to make it 1-based by default. But if you need to include it in a project of your own, feel free to change it to suit your needs :evil:

I just found a weird bug - if you give a string for the $ArrayBase, then it will assume that the array is 0-based and will put that string for the "name" of the first index.

I also want to figure out how to make the window modal, so that the GetMsg loop doesn't take away from other GUIs that may be running. But I haven't tested that so I don't even know if it's a problem yet.

I'm also thinking of adding a feature that if you select a line in the listview, the function will return the corresponding array element number.

#6 blindwig

blindwig

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 772 posts

Posted 22 June 2005 - 03:25 AM

Oh, and another bug I forgot to mention:
Obviously if one of your array elements has a '|' character in it, you are going to get un desirable results.
I guess I could run StringReplace on the element before using it...

#7 FuryCell

FuryCell

    A cornered fox is more dangerous than a jackal!

  • Active Members
  • PipPipPipPipPipPip
  • 2,437 posts

Posted 22 June 2005 - 03:50 PM

I just found a weird bug - if you give a string for the $ArrayBase, then it will assume that the array is 0-based and will put that string for the "name" of the first index.

Look at this quote from the helpfile:

If a string is used as a number and it doesn't contain a valid number, it will be assumed to equal 0.  For example,

    10 * "fgh" equals the number 0.


I think that when you use Dim inside a function, it is automatically a local variable?

Yes. Just looked at the help file and you are correct.

Edited by SolidSnake, 22 June 2005 - 04:22 PM.

HKTunes:Softpedia | GoogleCodeLyricToy:Softpedia | GoogleCodeRCTunes:Softpedia | GoogleCodeMichtaToolsProgrammer n. - An ingenious device that turns caffeine into code.

#8 blindwig

blindwig

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 772 posts

Posted 22 June 2005 - 08:40 PM

Yeah, I need to add '$ArrayBase = $ArrayBase * 1' or '$ArrayBase = Int($ArrayBase)' right after the ';setup' line.

I also found another issue - the ListView can only hold 4095 items.

#9 randallc

randallc

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 1,902 posts

Posted 29 July 2005 - 03:19 AM

Hi,
i can't copy the script out of the strange quote box into Scite and retain "cr"s? - can you please post it as an attachment?
Best, Randall

#10 Wus

Wus

    Indentured Servant

  • Active Members
  • PipPipPipPipPipPip
  • 513 posts

Posted 29 July 2005 - 05:45 AM

awsome... I use _arraydisplay alot to debug, and It aalways annoys me when I try to use it with an array with 600 values... this should make it so i dont have to use roundabout methods to use big arrays..
Posted Image

#11 blindwig

blindwig

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 772 posts

Posted 01 August 2005 - 10:38 PM

I guess there are some browsers out there that don't let you copy code out of a CODEBOX on this forums, so here is my latest code in a regular CODE tag:
Plain Text         
;=============================================================================== ; ; Function Name: _Array1Box() ; Description: Shows an array in a GUI window. Improved version of _Array1Display ; Parameter(s): $Array - An array, 1d or 2d, 0-based or 1-based ; $ArrayBase - 1 or 0 - tells what base the array is ; $sTitle - the title to put on the output window ; $Width, $Height, $Left, $Top - Set the size and position of the output window ; Requirement(s): $Array must be 1d or 2d. If 1-based, then arraysize is assumed to be $Array[0] or $Array[0][0] ; Return Value(s): Integer, 0 or more = 0-based index of selected item ;                 -1 = no item was selected ;                 Error=1 = $Array is not an array ; Author(s): Mike Ratzlaff <mike@ratzlaff.org> ; Revision: 20050728A ; ;=============================================================================== ; Func _Array1Box(ByRef $Array, $sTitle = 'Array Box', $ArrayBase = 1, $Width = 200, $Height = 200, $Left = -1, $Top = -1)     Local $AllDone = 0, $msg, $i, $j, $ArrayDimensions = UBound($Array, 0), $ArrayMax, $sTemp     Local $hndForm_Array1Box_Main, $hndListView_Array1Box_Display, $hndButton_Array1Box_Close         If $ArrayDimensions = 0 Then         SetError(1)         Return 'Given variable is not an array'     EndIf     ;Setup     If $ArrayBase <> 0 Then $ArrayBase = 1     If $ArrayBase Then         Select             Case $ArrayDimensions = 1                 $ArrayMax = $Array[0]             Case $ArrayDimensions = 2                 $ArrayMax = $Array[0][0]         EndSelect     Else         $ArrayMax = UBound($Array, 1) - 1     EndIf     ;Create GUI     If $Height < 100 Then $Height = 100     If $Width < 100 Then $Width = 100     $hndForm_Array1Box_Main = GUICreate($sTitle, $Width, $Height, $Left, $Top, BitOR($WS_POPUP, $WS_CAPTION, $WS_SIZEBOX, $WS_MAXIMIZEBOX, $WS_EX_DLGMODALFRAME))     ;Create List Box     If $ArrayDimensions = 1 Then         $sTemp = 'Index|Value'     ElseIf $ArrayDimensions = 2 Then         $sTemp = 'Index'         For $i = 0 To UBound($Array, 2) - 1             $sTemp = $sTemp & '|' & $i         Next     EndIf     If $ArrayBase Then         GUICtrlCreateLabel('size = (' & $ArrayMax & '/' & UBound($Array) & ')', 0, 0, $Width, 16)     Else         GUICtrlCreateLabel('size = (' & UBound($Array) & ')', 0, 0, $Width, 16)     EndIf     GUICtrlSetResizing(-1, BitOR($GUI_DockLeft, $GUI_DockTop, $GUI_DockRight, $GUI_DOCKHEIGHT))     $hndListView_Array1Box_Display = GUICtrlCreateListView($sTemp, 0, 16, $Width, $Height-40, BitOR($LVS_SHOWSELALWAYS, $LVS_SINGLESEL))     GUICtrlSetResizing($hndListView_Array1Box_Display, BitOR($GUI_DockLeft, $GUI_DockTop, $GUI_DockRight, $GUI_DockBottom))     ;Create Controls, Show GUI     $hndButton_Array1Box_Close = GUICtrlCreateButton('&Close',$Width-80,$Height-24,80,24)     GUICtrlSetResizing($hndButton_Array1Box_Close, BitOR($GUI_DockRight, $GUI_DockBottom, $GUI_DockSize))     GUICtrlSetState($hndButton_Array1Box_Close, BitOR($GUI_DefButton, $GUI_FOCUS))     GUISetState (@SW_SHOW, $hndForm_Array1Box_Main)     ;Display Array     Select         Case $ArrayDimensions = 1;1-Dimensional Array             For $i = 0 To $ArrayMax             GUICtrlCreateListViewItem($i & '|' & $Array[$i], $hndListView_Array1Box_Display)             Next;$i         Case $ArrayDimensions = 2;2-Dimensional Array             For $i = 0 To $ArrayMax                 $sTemp=$Array[$i][0]                 for $j = 1 To UBound($Array, 2) - 1                     $sTemp = $sTemp & '|' & $Array[$i][$j]                 Next;$j                 GUICtrlCreateListViewItem('[' & $i & ']|' & $sTemp, $hndListView_Array1Box_Display)             Next;$i         Case Else;Unhandled Type                 EndSelect     ;Wait for user to close box     Do         $msg = GUIGetMsg()         Select             Case $msg = $GUI_EVENT_CLOSE                 $AllDone = 1             Case $msg = $hndButton_Array1Box_Close                 $AllDone = 1         EndSelect     Until $AllDone     ;Destroy GUI, Return index of selected item     $i = ControlListView(WinGetTitle($sTitle), '', $hndListView_Array1Box_Display, "GetSelected")     If $i='' Then $i = -1     GUIDelete($hndForm_Array1Box_Main)     Return $i EndFunc

I've added the feature that if you select an item, that item's index is returned (otherwise -1 is returned)




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users