Известно,что при попытке использовать ф-ию
_ArrayDisplay в ф-ии WM_NOTIFY
возникает зависание скрипта.
Все проблемы из-за наличия в ф-ии цикла обработки сообщений от своего окна
Небольшие изменения в ф-ии _ArrayDisplay
позволяют устранить эту проблему:
Пример и измененная ф-я :
_ArrayDisplay в ф-ии WM_NOTIFY
возникает зависание скрипта.
Все проблемы из-за наличия в ф-ии цикла обработки сообщений от своего окна
Небольшие изменения в ф-ии _ArrayDisplay
позволяют устранить эту проблему:
Пример и измененная ф-я :
Код:
#include <WindowsConstants.au3>
#include <GuiConstantsEx.au3>
#include <GuiListView.au3>
;#include <Array.au3>
$Gui = GUICreate("Test", 200, 250)
$hListView = _GUICtrlListView_Create($GUI, "Items|SubItems", 5, 2, 190, 200, BitOR($LVS_EDITLABELS, $LVS_REPORT))
Dim $aData[4][2]=[["Борис", 44], ["Анна", 55], ["Света", 11], ["Миша",22]]
For $i=0 To 3
$iItem = _GUICtrlListView_AddItem($hListView, "")
For $j=0 To 1
_GUICtrlListView_SetItemText($hListView, $iItem, $aData[$i][$j], $j)
Next
Next
$Label=GUICtrlCreateLabel('',5, 220, 100, 25,0x1000)
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUISetState()
While 1
$msg = GUIGetMsg()
Switch $msg
Case $GUI_EVENT_CLOSE
Exit
EndSwitch
WEnd
;==============================================
Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
;==================================================================
#forceref $hWnd, $iMsg, $iwParam
Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndListView
$hWndListView = $hListView
If Not IsHWnd($hListView) Then $hWndListView = GUICtrlGetHandle($hListView)
$tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
$hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
$iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
$iCode = DllStructGetData($tNMHDR, "Code")
Switch $hWndFrom
Case $hWndListView;, $hWndListView2
Switch $iCode
Case $NM_CLICK
Global $aHit = _GUICtrlListView_SubItemHitTest($hWndFrom)
GUICtrlSetData($Label,_GUICtrlListView_GetItemText($hWndFrom, $aHit [0],$aHit [1]))
__Array_Display($aHit)
EndSwitch
EndSwitch
Return $GUI_RUNDEFMSG
EndFunc ; ===> WM_NOTIFY
; #FUNCTION# ====================================================================================================================
; Name...........: __ArrayDisplay
; 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 = "|"[, $sHeader = ""]]]]]])
; 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
; $sheader - [optional] Header column names
; 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, Zedna, jpm
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: Yes
; ===============================================================================================================================
Func __Array_Display(Const ByRef $avArray, $sTitle = "Array: ListView Display", $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)
Local $sDataSeparatorChar = Opt("GUIDataSeparatorChar", $sSeparator); *** Изменено
Global $iOnEventMode = Opt("GUIOnEventMode", 0) ; *** Изменено
; 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
;Local $hGUI = GUICreate($sTitle, $iWidth, $iHeight, Default, Default, BitOR($_ARRAYCONSTANT_WS_SIZEBOX, $_ARRAYCONSTANT_WS_MINIMIZEBOX, $_ARRAYCONSTANT_WS_MAXIMIZEBOX))
Global $hArrayDisplayGUI = GUICreate($sTitle, $iWidth, $iHeight, Default, Default, BitOR($_ARRAYCONSTANT_WS_SIZEBOX, $_ARRAYCONSTANT_WS_MINIMIZEBOX, $_ARRAYCONSTANT_WS_MAXIMIZEBOX)); *** Изменено
Local $aiGUISize = WinGetClientSize($hArrayDisplayGUI)
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
Local $aItem
For $i = 0 To $iUBound
If GUICtrlCreateListViewItem($avArrayText[$i], $hListView) = 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($hListView, $_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($hListView, $_ARRAYCONSTANT_LVM_SETITEMW, 0, $pItem)
Next
EndIf
Next
; adjust 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
$iWidth += 20
If $iWidth > @DesktopWidth Then $iWidth = @DesktopWidth - 100
WinMove($hArrayDisplayGUI, "", (@DesktopWidth - $iWidth)/2, Default, $iWidth)
; Show dialog
GUISetState(@SW_SHOW, $hArrayDisplayGUI)
#cs
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($hArrayDisplayGUI)
#ce
;Opt("GUIOnEventMode", $iOnEventMode)
Opt("GUIOnEventMode", 1); *** Изменено
Opt("GUIDataSeparatorChar", $sDataSeparatorChar)
GUISetOnEvent($_ARRAYCONSTANT_GUI_EVENT_CLOSE, "_CLOSEClicked"); *** Добавлено и ИЗМЕНЕНО
Return 1
EndFunc ;==>__ArrayDisplay
Func _CLOSEClicked()
GUIDelete($hArrayDisplayGUI)
Opt ("GUIOnEventMode",$iOnEventMode)
EndFunc