Debugx.au3
Last modified: Thursday, 5 June 2008
;*******************************************************************************
;
; Function List
; _DebugArrayDisplay()
; _DebugLastErrorMessage()
; _DebugOut()
; _DebugSetup()
;
;*******************************************************************************
#include-once
;===============================================================================
; Name...........: _DebugArrayDisplay
; Description ...: Displays given 1D or 2D array array in a listview.
; Syntax.........: _ArrayDisplay(Const ByRef $avArray[, $sTitle = "Array: ListView Display"[, $iItemLimit = -1[, $iTranspose = 0[, $sSeparator = ""[, $sReplace = "|"]]]]])
; Parameters ....: $avArray - Array to display
; $sTitle - [optional] Title to use for window
; $iItemLimit - [optional] Maximum number of listview items (rows) to show
; $iTranspose - [optional] If set differently than default, will transpose the array if 2D
; $sSeparator - [optional] Change Opt("GUIDataSeparatorChar") on-the-fly
; $sReplace - [optional] String to replace any occurrence of $sSeparator with in each array element
; Return values .: Success - 1
; Failure - 0, sets @error:
; |1 - $avArray is not an array
; |2 - $avArray has too many dimensions (only up to 2D supported)
; Author ........: randallc, Ultima
; Modified.......: Gary Frost (gafrost) / Ultima: modified to be self-contained (no longer depends on "GUIListView.au3")
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......; Yes
;===============================================================================
Func _DebugArrayDisplay(Const ByRef $avArray, $sTitle = "Array: ListView Display", $iItemLimit = -1, $iTranspose = 0, $sSeparator = "", $sReplace = "|")
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)
; Declare variables
Local $i, $j, $vTmp, $aItem, $avArrayText, $sHeader = "Row", $iBuffer = 64
Local $iColLimit = 250, $iLVIAddUDFThreshold = 4000, $iWidth = 640, $iHeight = 480
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 = $iLVIAddUDFThreshold
If $iItemLimit < 1 Then $iItemLimit = $iUBound
If $iUBound > $iItemLimit Then $iUBound = $iItemLimit
If $iLVIAddUDFThreshold > $iUBound Then $iLVIAddUDFThreshold = $iUBound
; Set header up
For $i = 0 To $iSubMax
$sHeader &= $sSeparator & "Col " & $i
Next
; 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_INSERTITEMA = (0x1000 + 7)
Local Const $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE = (0x1000 + 54)
Local Const $_ARRAYCONSTANT_LVM_SETITEMA = (0x1000 + 6)
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("char 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 $hGUI = GUICreate($sTitle, $iWidth, $iHeight, Default, Default, BitOR($_ARRAYCONSTANT_WS_SIZEBOX, $_ARRAYCONSTANT_WS_MINIMIZEBOX, $_ARRAYCONSTANT_WS_MAXIMIZEBOX))
Local $aiGUISize = WinGetClientSize($hGUI)
Local $hListView = GUICtrlCreateListView($sHeader, 0, 0, $aiGUISize[0], $aiGUISize[1] - 26, $_ARRAYCONSTANT_LVS_SHOWSELALWAYS)
Local $hCopy = GUICtrlCreateButton("Copy Selected", 3, $aiGUISize[1] - 23, $aiGUISize[0] - 6, 20)
GUICtrlSetResizing($hListView, $_ARRAYCONSTANT_GUI_DOCKBORDERS)
GUICtrlSetResizing($hCopy, $_ARRAYCONSTANT_GUI_DOCKLEFT + $_ARRAYCONSTANT_GUI_DOCKRIGHT + $_ARRAYCONSTANT_GUI_DOCKBOTTOM + $_ARRAYCONSTANT_GUI_DOCKHEIGHT)
GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE, $_ARRAYCONSTANT_LVS_EX_GRIDLINES, $_ARRAYCONSTANT_LVS_EX_GRIDLINES)
GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE, $_ARRAYCONSTANT_LVS_EX_FULLROWSELECT, $_ARRAYCONSTANT_LVS_EX_FULLROWSELECT)
GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE, $_ARRAYCONSTANT_WS_EX_CLIENTEDGE, $_ARRAYCONSTANT_WS_EX_CLIENTEDGE)
; Fill listview
For $i = 0 To $iLVIAddUDFThreshold
GUICtrlCreateListViewItem($avArrayText[$i], $hListView)
Next
For $i = ($iLVIAddUDFThreshold + 1) To $iUBound
$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($hListView, $_ARRAYCONSTANT_LVM_INSERTITEMA, 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($hListView, $_ARRAYCONSTANT_LVM_SETITEMA, 0, $pItem)
Next
Next
; ajust window width
$iWidth = 0
For $i = 0 to $iSubMax+1
$iWidth += GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_GETCOLUMNWIDTH, $i, 0)
Next
If $iWidth<250 Then $iWidth = 230
WinMove($hGUI,"", Default,Default, $iWidth+20)
; Show dialog
GUISetState(@SW_SHOW, $hGUI)
While 1
Switch GUIGetMsg()
Case $_ARRAYCONSTANT_GUI_EVENT_CLOSE
ExitLoop
Case $hCopy
Local $sClip = ""
; Get selected indices [ _GUICtrlListView_GetSelectedIndices($hListView, True) ]
Local $aiCurItems[1] = [0]
For $i = 0 To GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_GETITEMCOUNT, 0, 0)
If GUICtrlSendMsg($hListView, $_ARRAYCONSTANT_LVM_GETITEMSTATE, $i, 0x2) Then
$aiCurItems[0] += 1
ReDim $aiCurItems[$aiCurItems[0] + 1]
$aiCurItems[$aiCurItems[0]] = $i
EndIf
Next
; Generate clipboard text
If Not $aiCurItems[0] Then
For $sItem In $avArrayText
$sClip &= $sItem & @CRLF
Next
Else
For $i = 1 To UBound($aiCurItems) - 1
$sClip &= $avArrayText[$aiCurItems[$i]] & @CRLF
Next
EndIf
ClipPut($sClip)
EndSwitch
WEnd
GUIDelete($hGUI)
Opt("GUIOnEventMode", $iOnEventMode)
Opt("GUIDataSeparatorChar", $sDataSeparatorChar)
Return 1
EndFunc ;<===>_DebugArrayDisplay
;>> Private Functions <<
Func _DebugBugReportEnv($err=@error, $ext=@extended)
Local $AutoItX64 = ""
If @AutoItX64 then $AutoItX64 = " X64"
Local $AutoItAnsi = " Ansi"
If @AutoItUnicode then $AutoItAnsi = ""
Local $Compiled = ""
If @Compiled then $Compiled= " Compiled"
Local $OsServicePack = ""
If @OSServicePack Then $OsServicePack = "/" & @OSServicePack
Return SetError($err, $ext, "Environment = " & @AutoItVersion & $AutoItX64 & $AutoItAnsi & _
$Compiled & " under " & @OSVersion & $OSServicePack & " " & @ProcessorArch)
EndFunc
;===============================================================================
; Name...........: _DebugLastErrorMessage()
; Description ...: Returns the last error message
; Syntax.........:
; Parameters ....:
; Return values .: Success - Last windows error
; Author ........: Zedna
; Modified.......:
; Remarks .......:
;===============================================================================
;Run('calc2.exe')
;If @error Then MsgBox(16, "Error", "Run() produced and error:" & @CRLF & _GetLastErrorMessage ())
Func _DebugLastErrorMessage($DisplayMsgBox="")
Local $ret,$s
Local $p = DllStructCreate("char[4096]")
Local Const $FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000
If @error Then Return ""
$ret = DllCall("Kernel32.dll","int","GetLastError")
$ret = DllCall("kernel32.dll","int","FormatMessage", _
"int",$FORMAT_MESSAGE_FROM_SYSTEM, _
"ptr",0, _
"int",$ret[0], _
"int",0, _
"ptr",DllStructGetPtr($p), _
"int",4096, _
"ptr",0)
$s = DllStructGetData($p,1)
$p = 0
If $DisplayMsgBox <> "" Then MsgBox(0,"_GetLastErrorMessage",$DisplayMsgBox & @CRLF & $s)
return $s
EndFunc
;===============================================================================
; Name...........: _DebugOut
; Description ...: Outputs a string to the Notepad window setup by _DebugSetup.
; Syntax.........: _DebugOut(Const $sOutput, Const $bActivate)
; Parameters ....: $sOutput = The string (or other printable value) to be output to the Notepad window.
; $bActivate = (Optional) True/False flag that inidicates that the Notepad window should be
; activated before sending characters. This is needed if another window is activated during the main script.
; Return values .: Success - Returns 1.
; Failure - Returns 0 and Sets @Error:
; |0 - No error.
; |1 - $sOutput is an incompatible type.
; |2 - $bActivate is an incompatible type.
; |3 - _DebugSetup() did not run properly. Make sure _DebugSetup() ran properly before calling this function.
; |4 - The Notepad window has been closed. Output can not occur.
; Author ........: David Nuttall (Nutster)
; Modified.......:
; Remarks .......: Before calling this function, _DebugSetup must be called first to create the Notepad window.
; Related .......: _DebugSetup
; Link ..........;
; Example .......; Yes
;===============================================================================
Func _DebugOut(Const $sOutput, Const $bActivate = False, Const $curerr = @error, Const $curext = @extended)
If IsNumber($sOutput) = 0 And IsString($sOutput) = 0 And IsBool($sOutput) = 0 Then
Return SetError(1, 0, 0) ; $sOutput can not be printed
ElseIf IsBool($bActivate) = False And IsNumber($bActivate) = False Then
Return SetError(2, 0, 0) ; The $bActivate flag is set to an invalid type. Must be able to convert to Bool.
ElseIf IsHWnd($g_hWndDbg) = 0 Then
Return SetError(3, 0, 0) ; Window was not assigned.
ElseIf WinExists($g_hWndDbg) = 0 Then
Return SetError(4, 0, 0) ; The Notepad window no longer exists
Else
If $bActivate Then WinActivate($g_hWndDbg)
ControlCommand($g_hWndDbg, "", "Edit1", "EditPaste", String($sOutput) & @CRLF)
Return SetError($curerr, $curext, 1) ; Return @error and @extende as before calling _DebugOut()
EndIf
EndFunc ;==>_DebugOut
;===============================================================================
; Name...........: _DebugSetup
; Description ...: Sets up a debug session using a Microsoft Notepad window as the output target.
; Syntax.........: _DebugSetup(Const $sTitle)
; Parameters ....: $sTitle = (Optional) Title to be displayed on the Notepad window. Default value is "Debug Info".
; $bBugReportInfos = (Optional) Display BugReport infos. Default value is false.
; Return values .: Success - Returns 1.
; Failure - Returns 0 and Sets @Error:
; |0 - No error.
; |1 - $sTitle is an incompatable type.
; |2 - Another debug session is open. Use it instead.
; |3 - Another Untitled MS-Notepad window is already open. Save it or close it before continuing.
; Author ........: David Nuttall (Nutster)
; Modified.......: Jean-Paul Mesnage (jpm)
; Remarks .......: This must be called in your program before any _DebugOut() calls.
; Microsoft Notepad in the %PATH%
; Related .......: _DebugOut
;===============================================================================
Func _DebugSetup(Const $sTitle = "Debug Info", Const $bBugReportInfos = false)
Local $pNotepad ; process ID of the Notepad started by this function
If $g_hWndDbg = 0 And WinExists($sTitle) Then
; notepad started by an another script use it
$g_hWndDbg = WinGetHandle($sTitle)
EndIf
If IsNumber($sTitle) = 0 And IsString($sTitle) = 0 And IsBool($sTitle) = 0 Then
Return SetError(1, 0, 0) ; Not any of the acceptable types.
ElseIf IsHWnd($g_hWndDbg) Then
; Another session already started
If WinExists($g_hWndDbg) Then
Return SetError(2, 0, 0) ; The session is still active
Else
; Reset the session and assign new hWnd.
EndIf
EndIf
$pNotepad = Run("Notepad.exe")
WinWait("[CLASS:Notepad]")
$g_hWndDbg = WinGetHandle("[CLASS:Notepad]")
If $pNotepad <> WinGetProcess($g_hWndDbg) Then
Return SetError(3, 0, 0)
EndIf
WinActivate($g_hWndDbg)
WinSetTitle($g_hWndDbg, "", String($sTitle))
If $bBugReportInfos Then _DebugOut(_DebugBugReportEnv() & @CRLF)
Return 1
EndFunc ;==>_DebugSetup