Jump to content

Recommended Posts

Posted

Hello,

I have a gui consisting of two listviews.
I have attached both programmes as attachments

In the first programme "listview changing colours", I can change the colours of individual fields.
In the second programme ‘listview changing and doublclick’, I can move a line between the listviews and see via double-click which line I have clicked.

The idea is to make 1 programme out of it, where I can therefore both colour individual items, make the contents visible via double-click and transfer the line to another listview via ‘drag and drop’.
Because my main programme uses about 40 individual listviews, some speed is important.

After several days of searching and trying, I still get stuck every time.
Anyone have any idea how I can solve this?

Many thanks in advance for your reactions,

Albert

Listview changing colors.au3 Listview changing and doubleclick.au3

Posted (edited)

Here a working example of one listview with color and double click.  You can add as many listviews as you want.  I included a map to register all the colors of the different listviews.

#include <GUIConstants.au3>
#include <GuiListView.au3>

Opt("MustDeclareVars", True)

Global $idListView, $mColor[]

Example()

Func Example()
  Local $hGUI = GUICreate("Colored ListView", 350, 250)
  $idListView = GUICtrlCreateListView("Number|Number|Number", 5, 5, 300, 150)
  Local $hListView = GUICtrlGetHandle($idListView)
  Local $idButton = GUICtrlCreateButton("Change", 5, 180, 100, 20)

  GUIRegisterMsg($WM_NOTIFY, WM_NOTIFY)
  GUISetState()

  For $i = 1 To 50
    GUICtrlCreateListViewItem($i & '|' & $i & '|' & $i, $idListView)
  Next
  ;init background colors for ListView 1 (could be many of these)
  Local $aColor[ControlListView($hGUI, "", $idListView, "GetItemCount")][ControlListView($hGUI, "", $idListView, "GetSubItemCount")]
  $aColor[0][1] = 0xFFAAFF
  $aColor[1][2] = 0x00AA00
  $aColor[2][0] = 0xCCCCCC
  $mColor[$idListView] = $aColor

  While True
    Switch GUIGetMsg()
      Case $GUI_EVENT_CLOSE
        Exit
      Case $idButton
        $aColor = $mColor[$idListView]
        $aColor[5][1] = 0xFF
        $mColor[$idListView] = $aColor
        _WinAPI_RedrawWindow($hListView)
    EndSwitch
  WEnd

EndFunc   ;==>Example

Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)
  Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)

  Switch $tNMHDR.IDFrom
    Case $idListView
      Switch $tNMHDR.Code
        Case $NM_CUSTOMDRAW
          Local $tCustDraw = DllStructCreate($tagNMLVCUSTOMDRAW, $lParam)
          Local $iDrawStage = $tCustDraw.dwDrawStage
          If $iDrawStage = $CDDS_PREPAINT Then Return $CDRF_NOTIFYITEMDRAW
          If $iDrawStage = $CDDS_ITEMPREPAINT Then Return $CDRF_NOTIFYSUBITEMDRAW

          ; Paint item and subitem
          Local $iSubItem = $tCustDraw.iSubItem
          Local $iItem = $tCustDraw.dwItemSpec
          If ControlListView($hWnd, "", $tNMHDR.hWndFrom, "IsSelected", $iItem) Then Return $CDRF_DODEFAULT

          $tCustDraw.clrTextBk = ($mColor[$tCustDraw.IDFrom])[$iItem][$iSubItem] ? ($mColor[$tCustDraw.IDFrom])[$iItem][$iSubItem] : 0xFFFFFF
          Return $CDRF_NEWFONT

        Case $NM_DBLCLK
          Local $tItem = DllStructCreate($tagNMITEMACTIVATE, $lParam)
          ConsoleWrite("Double click for ListView : " & $tItem.IDFrom & " on item : " & $tItem.Index & " on subitem : " & $tItem.SubItem & @CRLF)
      EndSwitch
  EndSwitch
  Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

 

Edited by Nine
added change color
Posted

Thank you very much for the quick response.
I managed to create 2 listview side by side with different colours in the cells.
Also, the double-click works quite well

I still fail to move a row from listview[1] to listview[2].

 I tried: $idListView[1] = GUICtrlCreateListView("Number|Number|Number", 5, 5, 300, 150) to expand with:

  $idListView[1] = GUICtrlCreateListView("Number|Number|Number", 5, 5, 300, 150,BitOR($LVS_SHOWSELALWAYS, $LVS_REPORT, $WS_BORDER))
  _GUICtrlListView_SetExtendedListViewStyle($idListView[1], $LVS_EX_FULLROWSELECT)

(As in the previous program), but that gives no result.
Should I add something in the WM_Notify ?

Posted
#include <GUIConstants.au3>
#include <GuiListView.au3>
#include <GUIListViewEx.au3>
#include <GuiStatusBar.au3>



Opt("MustDeclareVars", True)

Global $idListView[28]
global $hListView[28]
global $mColor[28]
global $g_hStatus


Example()

Func Example()
  Local $hGUI = GUICreate("Colored ListView", 750, 250)
  $idListView[1] = GUICtrlCreateListView("Number|Number|Number", 5, 5, 300, 150,BitOR($LVS_SHOWSELALWAYS, $LVS_REPORT, $WS_BORDER))
  _GUICtrlListView_SetExtendedListViewStyle($idListView[1], $LVS_EX_FULLROWSELECT)
   $hListView[1] = GUICtrlGetHandle($idListView[1])
  $idListView[2] = GUICtrlCreateListView("Number|Number|Number", 305, 5, 300, 150,BitOR($LVS_SHOWSELALWAYS, $LVS_REPORT, $WS_BORDER))
  _GUICtrlListView_SetExtendedListViewStyle($idListView[2], $LVS_EX_FULLROWSELECT)
   $hListView[2] = GUICtrlGetHandle($idListView[2])

  GUIRegisterMsg($WM_NOTIFY, WM_NOTIFY)

  GUISetState()

  For $i = 1 To 50
    GUICtrlCreateListViewItem($i & '|' & $i & '|' & $i, $idListView[1])
    GUICtrlCreateListViewItem($i & '|' & "OK" & '|' & $i, $idListView[2])
  Next

  ;init background colors for ListView 1 (could be many of these)
  Local $aColor[ControlListView($hGUI, "", $idListView[1], "GetItemCount")][ControlListView($hGUI, "", $idListView[1], "GetSubItemCount")]
  $aColor[0][1] = 0xFFAAFF
  $aColor[1][2] = 0x00AA00
  $aColor[2][0] = 0xCCCCCC
  $mColor[$idListView[1]] = $aColor

  ;init background colors for ListView 2 (could be many of these)
  Local $bColor[ControlListView($hGUI, "", $idListView[2], "GetItemCount")][ControlListView($hGUI, "", $idListView[2], "GetSubItemCount")]
  $bColor[0][1] = 0xCCCCCC
  $bColor[1][2] = 0x00AA00
  $bColor[2][0] = 0xFFAAFF
  $mColor[$idListView[2]] = $bColor

  While True
    Switch GUIGetMsg()
      Case $GUI_EVENT_CLOSE
        Exit
    EndSwitch
  WEnd

EndFunc   ;==>Example

Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)
  Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)

  Switch $tNMHDR.IDFrom
    Case $idListView[1]
      Switch $tNMHDR.Code
        Case $NM_CUSTOMDRAW
          Local $tCustDraw = DllStructCreate($tagNMLVCUSTOMDRAW, $lParam)
          Local $iDrawStage = $tCustDraw.dwDrawStage
          If $iDrawStage = $CDDS_PREPAINT Then Return $CDRF_NOTIFYITEMDRAW
          If $iDrawStage = $CDDS_ITEMPREPAINT Then Return $CDRF_NOTIFYSUBITEMDRAW

          ; Paint item and subitem
          Local $iSubItem = $tCustDraw.iSubItem
          Local $iItem = $tCustDraw.dwItemSpec
          If ControlListView($hWnd, "", $tNMHDR.hWndFrom, "IsSelected", $iItem) Then Return $CDRF_DODEFAULT

          $tCustDraw.clrTextBk = ($mColor[$tCustDraw.IDFrom])[$iItem][$iSubItem] ? ($mColor[$tCustDraw.IDFrom])[$iItem][$iSubItem] : 0xFFFFFF
          Return $CDRF_NEWFONT

        Case $NM_DBLCLK
          Local $tItem = DllStructCreate($tagNMITEMACTIVATE, $lParam)
          ConsoleWrite("Double click for ListView : " & $tItem.IDFrom & " on item : " & $tItem.Index & " on subitem : " & $tItem.SubItem & @CRLF)
      EndSwitch

    Case $idListView[2]
      Switch $tNMHDR.Code
        Case $NM_CUSTOMDRAW
          Local $tCustDraw = DllStructCreate($tagNMLVCUSTOMDRAW, $lParam)
          Local $iDrawStage = $tCustDraw.dwDrawStage
          If $iDrawStage = $CDDS_PREPAINT Then Return $CDRF_NOTIFYITEMDRAW
          If $iDrawStage = $CDDS_ITEMPREPAINT Then Return $CDRF_NOTIFYSUBITEMDRAW

          ; Paint item and subitem
          Local $iSubItem = $tCustDraw.iSubItem
          Local $iItem = $tCustDraw.dwItemSpec
          If ControlListView($hWnd, "", $tNMHDR.hWndFrom, "IsSelected", $iItem) Then Return $CDRF_DODEFAULT

          $tCustDraw.clrTextBk = ($mColor[$tCustDraw.IDFrom])[$iItem][$iSubItem] ? ($mColor[$tCustDraw.IDFrom])[$iItem][$iSubItem] : 0xFFFFFF
          Return $CDRF_NEWFONT

        Case $NM_DBLCLK
          Local $tItem = DllStructCreate($tagNMITEMACTIVATE, $lParam)
          ConsoleWrite("Double click for ListView : " & $tItem.IDFrom & " on item : " & $tItem.Index & " on subitem : " & $tItem.SubItem & @CRLF)

      EndSwitch

  EndSwitch
  Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

 

Posted (edited)

Here one simple way.  You can make it more and more complex as you wish to.  Not all exceptions are verified BTW.

ps. requires latest version (because of the map)

#include <GUIConstants.au3>
#include <GuiListView.au3>
#include <WinAPISysWin.au3>

Opt("MustDeclareVars", True)

Global $mColor[], $bDragging, $tDragItem = DllStructCreate($tagNMHDR)

Example()

Func Example()
  Local $hGUI = GUICreate("Colored ListView", 700, 250)
  Local $idListView1 = GUICtrlCreateListView("Number|Number|Number", 5, 5, 300, 150)
  Local $idListView2 = GUICtrlCreateListView("Number|Number|Number", 350, 5, 300, 150)

  Local $idButton = GUICtrlCreateButton("Change", 5, 180, 100, 20)

  GUIRegisterMsg($WM_NOTIFY, WM_NOTIFY)
  GUIRegisterMsg($WM_LBUTTONUP, WM_LBUTTONUP)
  GUISetState()

  For $i = 1 To 10
    GUICtrlCreateListViewItem($i & '|' & $i & '|' & $i, $idListView1)
    GUICtrlCreateListViewItem($i & '|' & "OK" & '|' & $i, $idListView2)
  Next

  ;init background colors for ListView 1 (could be many of these)
  Local $aColor[ControlListView($hGUI, "", $idListView1, "GetItemCount")][ControlListView($hGUI, "", $idListView1, "GetSubItemCount")]
  $aColor[0][1] = 0xFFAAFF
  $aColor[1][2] = 0x00AA00
  $aColor[2][0] = 0xCCCCCC
  $mColor[$idListView1] = $aColor

  Local $aColor[ControlListView($hGUI, "", $idListView2, "GetItemCount")][ControlListView($hGUI, "", $idListView2, "GetSubItemCount")]
  $aColor[2][1] = 0xFFAAFF
  $aColor[3][2] = 0x00AA00
  $aColor[4][0] = 0xCCCCCC
  $mColor[$idListView2] = $aColor

  While True
    Switch GUIGetMsg()
      Case $GUI_EVENT_CLOSE
        Exit
      Case $idButton
        $aColor = $mColor[$idListView1]
        $aColor[5][1] = 0xFF
        $mColor[$idListView1] = $aColor
        _WinAPI_RedrawWindow(GUICtrlGetHandle($idListView1))

        $aColor = $mColor[$idListView2]
        $aColor[6][1] = 0xFF
        $mColor[$idListView2] = $aColor
        _WinAPI_RedrawWindow(GUICtrlGetHandle($idListView2))
    EndSwitch
  WEnd

EndFunc   ;==>Example

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
  Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)

  If _WinAPI_GetClassName($tNMHDR.hWndFrom) <> "SysListView32" Then Return $GUI_RUNDEFMSG
  Switch $tNMHDR.Code
    Case $NM_CUSTOMDRAW
      Local $tCustDraw = DllStructCreate($tagNMLVCUSTOMDRAW, $lParam)
      Local $iDrawStage = $tCustDraw.dwDrawStage
      If $iDrawStage = $CDDS_PREPAINT Then Return $CDRF_NOTIFYITEMDRAW
      If $iDrawStage = $CDDS_ITEMPREPAINT Then Return $CDRF_NOTIFYSUBITEMDRAW

      ; Paint item and subitem
      Local $iSubItem = $tCustDraw.iSubItem
      Local $iItem = $tCustDraw.dwItemSpec
      If ControlListView($hWnd, "", $tNMHDR.hWndFrom, "IsSelected", $iItem) Then Return $CDRF_DODEFAULT

      $tCustDraw.clrTextBk = ($mColor[$tCustDraw.IDFrom])[$iItem][$iSubItem] ? ($mColor[$tCustDraw.IDFrom])[$iItem][$iSubItem] : 0xFFFFFF
      Return $CDRF_NEWFONT

    Case $NM_DBLCLK
      Local $tItem = DllStructCreate($tagNMITEMACTIVATE, $lParam)
      ConsoleWrite("Double click for ListView : " & $tItem.IDFrom & " on item : " & $tItem.Index & " on subitem : " & $tItem.SubItem & @CRLF)

    Case $LVN_BEGINDRAG
      Local $tDrag = DllStructCreate($tagNMLISTVIEW, $lParam)

      $tDragItem.hWndFrom = $tDrag.hWndFrom
      $tDragItem.IDFrom = $tDrag.IDFrom
      $tDragItem.Code = $tDrag.Item
      $bDragging = True
  EndSwitch
  Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

Func WM_LBUTTONUP($hWnd, $iMsg, $wParam, $lParam)
  If Not $bDragging Then Return $GUI_RUNDEFMSG
  $bDragging = False

  Local $tPoint = _WinAPI_GetMousePos()
  Local $hPoint = _WinAPI_WindowFromPoint($tPoint)
  If Not $hPoint Then Return $GUI_RUNDEFMSG
  If _WinAPI_GetClassName($hPoint) <> "SysListView32" Then Return $GUI_RUNDEFMSG
  If $hPoint = $tDragItem.hWndFrom Then Return $GUI_RUNDEFMSG
  Local $aColorSrc = $mColor[$tDragItem.IDFrom]
  Local $idDest = _WinAPI_GetDlgCtrlID($hPoint)
  Local $aColorDest = $mColor[$idDest]
  If UBound($aColorSrc, 2) <> UBound($aColorDest, 2) Then Return $GUI_RUNDEFMSG

  _GUICtrlListView_CopyItems($tDragItem.hWndFrom, $hPoint, True)

  Local $nDest = UBound($aColorDest) + 1
  ReDim $aColorDest[$nDest][UBound($aColorDest, 2)]
  For $i = 0 To UBound($aColorSrc, 2) - 1
    $aColorDest[$nDest - 1][$i] = $aColorSrc[$tDragItem.Code][$i]
  Next
  _ArrayDelete($aColorSrc, $tDragItem.Code)
  $mColor[$tDragItem.IDFrom] = $aColorSrc
  $mColor[$idDest] = $aColorDest

  Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_LBUTTONUP

 

Edited by Nine
Posted

Hello Nine,

Sorry to bother you again, but I'm running into a limit(?).
The attached code is an extension of your last code.
Here I am using 24 listviews (30 rows and 2 columns ) side by side (no problems)
If I fill some listviews (less then 15) with data everything goes fine.
But as soon as I go above 15 listviews (sometimes even less), I get an error message from the WM_NOTIFY:

$tCustDraw.clrTextBk = ($mColor[$tCustDraw.IDFrom])[$iItem][$iSubItem] ? ($mColor[$tCustDraw.IDFrom])[$iItem][$iSubItem] : 0xFFFFFF
$tCustDraw.clrTextBk = ($mColor[$tCustDraw.IDFrom])^ ERROR

#include <GUIConstants.au3>
#include <GuiListView.au3>
#include <WinAPISysWin.au3>

Opt("MustDeclareVars", True)

Global $mColor[], $bDragging, $tDragItem = DllStructCreate($tagNMHDR)
Global $idListview_secties[25]; voorgaand $cLv_secties
global $i_listview_number,$left,$cel_info_1,$cel_info_2

Example()

Func Example()
  Local $MainGui = GUICreate("Colored ListView", 1600, 600)
  $left =5
  for $i_listview_number=0 to 23
    $idListview_secties[$i_listview_number] = GUICtrlCreateListView("Number|Number", $left, 30, 60, 480)
    _GUICtrlListView_SetColumnWidth($idListview_secties[$i_listview_number], 0, 50)
    _GUICtrlListView_SetColumnWidth($idListview_secties[$i_listview_number], 1, 1000)
    $left=$left+65
  next

  Local $idButton = GUICtrlCreateButton("Change", 5, 550, 100, 20)

  GUIRegisterMsg($WM_NOTIFY, WM_NOTIFY)
  GUIRegisterMsg($WM_LBUTTONUP, WM_LBUTTONUP)
  GUISetState()

    For $i_listview_number = 0 To 20;
        for $i_positie=0 to 29
            GUICtrlCreateListViewItem($i_positie & '|' & "y" , $idListview_secties[$i_listview_number])
        next
    Next

    ;init background colors for ListView 1 (could be many of these)
    for $i_listview_number = 0 To 20;
        Local $aColor[ControlListView($MainGui, "", $idListview_secties[$i_listview_number], "GetItemCount")][ControlListView($MainGui, "", $idListview_secties[$i_listview_number], "GetSubItemCount")]
        $aColor[2+$i_listview_number][0] = 0xFFFF00;
        $mColor[$idListview_secties[$i_listview_number]] = $aColor
    Next


  While True
    Switch GUIGetMsg()
      Case $GUI_EVENT_CLOSE
        Exit
      Case $idButton
        $aColor = $mColor[$idListview_secties[1]]
        $aColor[5][0] = 0xFF
        $mColor[$idListview_secties[1]] = $aColor
        _WinAPI_RedrawWindow(GUICtrlGetHandle($idListview_secties[1]))

        $aColor = $mColor[$idListview_secties[2]]
        $aColor[6][0] = 0xFF
        $mColor[$idListview_secties[2]] = $aColor
        _WinAPI_RedrawWindow(GUICtrlGetHandle($idListview_secties[2]))
    EndSwitch
  WEnd

EndFunc   ;==>Example

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
  Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)

  If _WinAPI_GetClassName($tNMHDR.hWndFrom) <> "SysListView32" Then Return $GUI_RUNDEFMSG
  Switch $tNMHDR.Code
    Case $NM_CUSTOMDRAW
      Local $tCustDraw = DllStructCreate($tagNMLVCUSTOMDRAW, $lParam)
      Local $iDrawStage = $tCustDraw.dwDrawStage
      If $iDrawStage = $CDDS_PREPAINT Then Return $CDRF_NOTIFYITEMDRAW
      If $iDrawStage = $CDDS_ITEMPREPAINT Then Return $CDRF_NOTIFYSUBITEMDRAW

      ; Paint item and subitem
      Local $iSubItem = $tCustDraw.iSubItem
      Local $iItem = $tCustDraw.dwItemSpec
      If ControlListView($hWnd, "", $tNMHDR.hWndFrom, "IsSelected", $iItem) Then Return $CDRF_DODEFAULT

      $tCustDraw.clrTextBk = ($mColor[$tCustDraw.IDFrom])[$iItem][$iSubItem] ? ($mColor[$tCustDraw.IDFrom])[$iItem][$iSubItem] : 0xFFFFFF
      Return $CDRF_NEWFONT

    Case $NM_DBLCLK
      Local $tItem = DllStructCreate($tagNMITEMACTIVATE, $lParam)
      ConsoleWrite("Double click for ListView : " & $tItem.IDFrom & " on item : " & $tItem.Index & " on subitem : " & $tItem.SubItem & @CRLF)

    Case $LVN_BEGINDRAG
      Local $tDrag = DllStructCreate($tagNMLISTVIEW, $lParam)

      $tDragItem.hWndFrom = $tDrag.hWndFrom
      $tDragItem.IDFrom = $tDrag.IDFrom
      $tDragItem.Code = $tDrag.Item
      $bDragging = True
  EndSwitch
  Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

Func WM_LBUTTONUP($hWnd, $iMsg, $wParam, $lParam)
  If Not $bDragging Then Return $GUI_RUNDEFMSG
  $bDragging = False

  Local $tPoint = _WinAPI_GetMousePos()
  Local $hPoint = _WinAPI_WindowFromPoint($tPoint)
  If Not $hPoint Then Return $GUI_RUNDEFMSG
  If _WinAPI_GetClassName($hPoint) <> "SysListView32" Then Return $GUI_RUNDEFMSG
  If $hPoint = $tDragItem.hWndFrom Then Return $GUI_RUNDEFMSG
  Local $aColorSrc = $mColor[$tDragItem.IDFrom]
  Local $idDest = _WinAPI_GetDlgCtrlID($hPoint)
  Local $aColorDest = $mColor[$idDest]
  If UBound($aColorSrc, 2) <> UBound($aColorDest, 2) Then Return $GUI_RUNDEFMSG

  _GUICtrlListView_CopyItems($tDragItem.hWndFrom, $hPoint, True)

  Local $nDest = UBound($aColorDest) + 1
  ReDim $aColorDest[$nDest][UBound($aColorDest, 2)]
  For $i = 0 To UBound($aColorSrc, 2) - 1
    $aColorDest[$nDest - 1][$i] = $aColorSrc[$tDragItem.Code][$i]
  Next
  _ArrayDelete($aColorSrc, $tDragItem.Code)
  $mColor[$tDragItem.IDFrom] = $aColorSrc
  $mColor[$idDest] = $aColorDest

  Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_LBUTTONUP

Do you perhaps have a solution?

Posted (edited)

@albertmaathuis Good job on your script. But you should learn how to debug your own code.  By putting ConsoleWrite to check the evolution path of the script you would have learned where the issue is.  BTW it is quite an obvious problem.  On the side note, you should always try to eliminate global variables when possible and you should never hardcode constants when you can use a function that will provide it to you (e.g. UBound).  It is just good programming practices.

Back to your issue, I will not give you the answer.  I will let you debug it by yourself.  But I will give you a hint, since the AutoIt error tells you that the color arrays are incorrectly created, you should search in that direction.  Put some ConsoleWrite as I already told you and you should discover the nasty culprit rapidly...

 

Edited by Nine
Posted

Hello Nine,

Of course, I agree with you about debugging myself. (I always try to do that too)
But underneath that, I'm still not getting anywhere.
Among other things, I found that the ID of my listviews doesn't start at 0, but at 3
But unfortunately I still can't get it to work.
I have taken your first version and adapted it in many places, but no real success is achieved
For testing, I used an extra variable ($idLV_start), so I can be sure I'm using the right id.
The for next loop (starting on line 33) works if I keep it below 19 (so 20 listviews) and then also don't put more than 20 fields in each listview.
Another peculiarity is the consolewrite on line 39. If I activate it, execution stops immediately.

Perhaps you would be kind enough to take another look?

#include <GUIConstants.au3>
#include <GuiListView.au3>
#include <WinAPISysWin.au3>

Opt("MustDeclareVars", True)

Global $mColor[], $bDragging, $tDragItem = DllStructCreate($tagNMHDR)

Example()

Func Example()
  Local $MainGui = GUICreate("Colored ListView", 1700, 600)
  local $idListview_secties[24];
  local $left

  $left =5
  for $i_listview_number= 0 to 23
    $idListview_secties[$i_listview_number] = GUICtrlCreateListView("Number|Number", $left, 30, 60, 480)
    _GUICtrlListView_SetColumnWidth($idListview_secties[$i_listview_number], 0, 50)
    _GUICtrlListView_SetColumnWidth($idListview_secties[$i_listview_number], 1, 1000)
    $left=$left+65
;   ConsoleWrite($idListview_secties[$i_listview_number]&" ")
  next

  Local $idButton = GUICtrlCreateButton("Change", 5, 550, 100, 20)


  GUIRegisterMsg($WM_NOTIFY, WM_NOTIFY)
  GUIRegisterMsg($WM_LBUTTONUP, WM_LBUTTONUP)
  GUISetState()

    local $idLV_start=0
    For $i_listview_number = 0 To 19;
        for $i_positie=0 to 20
            GUICtrlCreateListViewItem($i_positie & '|' & "y" , $idListview_secties[$idLV_start])
        next
ConsoleWrite ($idLV_start&"  "&$i_listview_number&" "&$i_positie&@CRLF)
        Local $aColor[ControlListView($MainGui, "", $idListview_secties[$idLV_start], "GetItemCount")][ControlListView($MainGui, "", $idListview_secties[$idLV_start], "GetSubItemCount")]
;ConsoleWrite ($idLV_start&"  "&$i_listview_number&" "&$i_positie&@CRLF)
        $aColor[0][0] = 0xFFFF00;
        $mColor[$idListview_secties[$idLV_start]] = $aColor
        $idLV_start=$idLV_start+1
    Next


  While True
    Switch GUIGetMsg()
      Case $GUI_EVENT_CLOSE
        Exit
      Case $idButton
        $aColor = $mColor[$idListview_secties[1]]
        $aColor[5][0] = 0xFF
        $mColor[$idListview_secties[1]] = $aColor
        _WinAPI_RedrawWindow(GUICtrlGetHandle($idListview_secties[1]))

        $aColor = $mColor[$idListview_secties[2]]
        $aColor[6][0] = 0xFF
        $mColor[$idListview_secties[2]] = $aColor
        _WinAPI_RedrawWindow(GUICtrlGetHandle($idListview_secties[2]))
    EndSwitch
  WEnd

EndFunc   ;==>Example

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
;   ConsoleWrite ($iMsg&" "&$wParam&" "&$lParam&@CRLF)

  Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)

  If _WinAPI_GetClassName($tNMHDR.hWndFrom) <> "SysListView32" Then Return $GUI_RUNDEFMSG
  Switch $tNMHDR.Code
    Case $NM_CUSTOMDRAW
      Local $tCustDraw = DllStructCreate($tagNMLVCUSTOMDRAW, $lParam)
      Local $iDrawStage = $tCustDraw.dwDrawStage
      If $iDrawStage = $CDDS_PREPAINT Then Return $CDRF_NOTIFYITEMDRAW
      If $iDrawStage = $CDDS_ITEMPREPAINT Then Return $CDRF_NOTIFYSUBITEMDRAW

      ; Paint item and subitem
      Local $iSubItem = $tCustDraw.iSubItem
      Local $iItem = $tCustDraw.dwItemSpec
;  ConsoleWrite ($iItem&" "&$iSubItem&@CRLF)
      If ControlListView($hWnd, "", $tNMHDR.hWndFrom, "IsSelected", $iItem) Then Return $CDRF_DODEFAULT

      $tCustDraw.clrTextBk = ($mColor[$tCustDraw.IDFrom])[$iItem][$iSubItem] ? ($mColor[$tCustDraw.IDFrom])[$iItem][$iSubItem] : 0xFFFFFF
      Return $CDRF_NEWFONT

    Case $NM_DBLCLK
      Local $tItem = DllStructCreate($tagNMITEMACTIVATE, $lParam)
      ConsoleWrite("Double click for ListView : " & $tItem.IDFrom & " on item : " & $tItem.Index & " on subitem : " & $tItem.SubItem & @CRLF)

    Case $LVN_BEGINDRAG
      Local $tDrag = DllStructCreate($tagNMLISTVIEW, $lParam)

      $tDragItem.hWndFrom = $tDrag.hWndFrom
      $tDragItem.IDFrom = $tDrag.IDFrom
      $tDragItem.Code = $tDrag.Item
      $bDragging = True
  EndSwitch
  Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

Func WM_LBUTTONUP($hWnd, $iMsg, $wParam, $lParam)
  If Not $bDragging Then Return $GUI_RUNDEFMSG
  $bDragging = False

  Local $tPoint = _WinAPI_GetMousePos()
  Local $hPoint = _WinAPI_WindowFromPoint($tPoint)
  If Not $hPoint Then Return $GUI_RUNDEFMSG
  If _WinAPI_GetClassName($hPoint) <> "SysListView32" Then Return $GUI_RUNDEFMSG
  If $hPoint = $tDragItem.hWndFrom Then Return $GUI_RUNDEFMSG
  Local $aColorSrc = $mColor[$tDragItem.IDFrom]
  Local $idDest = _WinAPI_GetDlgCtrlID($hPoint)
  Local $aColorDest = $mColor[$idDest]
  If UBound($aColorSrc, 2) <> UBound($aColorDest, 2) Then Return $GUI_RUNDEFMSG

  _GUICtrlListView_CopyItems($tDragItem.hWndFrom, $hPoint, True)

  Local $nDest = UBound($aColorDest) + 1
  ReDim $aColorDest[$nDest][UBound($aColorDest, 2)]
  For $i = 0 To UBound($aColorSrc, 2) - 1
    $aColorDest[$nDest - 1][$i] = $aColorSrc[$tDragItem.Code][$i]
  Next
  _ArrayDelete($aColorSrc, $tDragItem.Code)
  $mColor[$tDragItem.IDFrom] = $aColorSrc
  $mColor[$idDest] = $aColorDest

  Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_LBUTTONUP

 

Posted

A few more additions to the above problem.
Maybe there is a limit somewhere that I can't find after all.
In the attached code, you can crash the program simply by naming an extra variable (see line 20)
The crash then occurs if line 26 runs to 605, no crash if line 26 runs to 604
No extra variable? then always a crash if line 26 runs to 606.
The code is stripped down as much as possible and all tests are described in the code.

Anybody any ideas?

#include <GUIConstants.au3>
#include <GuiListView.au3>
#include <WinAPISysWin.au3>

Opt("MustDeclareVars", True)

Global $mColor[],$bDragging,$tDragItem = DllStructCreate($tagNMHDR)

; Something strange is going on here. As soon as I split the global variable, I immediately get the error message
;Global $mColor[],$bDragging
;global $tDragItem = DllStructCreate($tagNMHDR)


Example()

Func Example()
  Local $hGUI = GUICreate("Colored ListView", 700, 800,600,10);  Changing does not affect the error
  GUISetFont(6)

;  local $test  ;As soon as I activate this rule (local variable $test) then the error message occurs at 605 occurs (changing to 604 works again)
  Local $idListView1 = GUICtrlCreateListView("Number|Number|Number", 5, 5, 300, 400);  Changing does not affect the error

  GUIRegisterMsg($WM_NOTIFY, WM_NOTIFY)
  GUISetState()

  For $i = 1 To 605;If this is changed to 606 the error message follows
    GUICtrlCreateListViewItem($i & '|' & $i & '|' & $i, $idListView1)
  Next

  Local $aColor[ControlListView($hGUI, "", $idListView1, "GetItemCount")][ControlListView($hGUI, "", $idListView1, "GetSubItemCount")]
;  local $aColor[1000][3];Expanding the number of lines in this way also produces no effect; the error remains when 605 goes to 606.

  $aColor[2][0] = 0xFFAAFF;Removing this line gives no effect (except that no cell is colored) the error remains as 605 goes to 606.

  $mColor[$idListView1] = $aColor
;   $mColor[3] = $aColor;The id of the listview=3, also this way the error remains if 605 goes to 606.


  While True
    Switch GUIGetMsg()
      Case $GUI_EVENT_CLOSE
        Exit
    EndSwitch
  WEnd

EndFunc   ;==>Example

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
     ConsoleWrite("hWnd= "&$hWnd&" "&"iMsg= "&$iMsg&" "&"wParam= "&$wParam&" "&"lParam= "&$lParam&" "&@CRLF)
  Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)

  If _WinAPI_GetClassName($tNMHDR.hWndFrom) <> "SysListView32" Then Return $GUI_RUNDEFMSG
  Switch $tNMHDR.Code
    Case $NM_CUSTOMDRAW
      Local $tCustDraw = DllStructCreate($tagNMLVCUSTOMDRAW, $lParam)
      Local $iDrawStage = $tCustDraw.dwDrawStage
      If $iDrawStage = $CDDS_PREPAINT Then Return $CDRF_NOTIFYITEMDRAW
      If $iDrawStage = $CDDS_ITEMPREPAINT Then Return $CDRF_NOTIFYSUBITEMDRAW

      ; Paint item and subitem
      Local $iSubItem = $tCustDraw.iSubItem
      Local $iItem = $tCustDraw.dwItemSpec
 ;ConsoleWrite("IItem= "&$iItem&" ")
      If ControlListView($hWnd, "", $tNMHDR.hWndFrom, "IsSelected", $iItem) Then Return $CDRF_DODEFAULT

      $tCustDraw.clrTextBk = ($mColor[$tCustDraw.IDFrom])[$iItem][$iSubItem] ? ($mColor[$tCustDraw.IDFrom])[$iItem][$iSubItem] : 0xFFFFFF
      Return $CDRF_NEWFONT

    Case $NM_DBLCLK
      Local $tItem = DllStructCreate($tagNMITEMACTIVATE, $lParam)
      ConsoleWrite("Double click for ListView : " & $tItem.IDFrom & " on item : " & $tItem.Index & " on subitem : " & $tItem.SubItem & @CRLF)

    Case $LVN_BEGINDRAG
      Local $tDrag = DllStructCreate($tagNMLISTVIEW, $lParam)

      $tDragItem.hWndFrom = $tDrag.hWndFrom
      $tDragItem.IDFrom = $tDrag.IDFrom
      $tDragItem.Code = $tDrag.Item
      $bDragging = True
  EndSwitch
  Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

 

  • Solution
Posted (edited)
1 hour ago, albertmaathuis said:

Anybody any ideas?

Ok, I'll finally post something in this thread, though we had a solution for 2 days ("we" = me and a helpful tester via PM, for confirmation on a different OS)

But the sentence "Back to your issue, I will not give you the answer." refrained us for posting anything, to avoid creating new tensions.

Just have a look at this post above, then

1) Change this line...

For $i = 1 To 10

...to

For $i = 1 To 500

Now the script throws the error you reported :

$tCustDraw.clrTextBk = ($mColor[$tCustDraw.IDFrom])[$iItem][$iSubItem] ? ($mColor[$tCustDraw.IDFrom])[$iItem][$iSubItem] : 0xFFFFFF
$tCustDraw.clrTextBk = ($mColor[$tCustDraw.IDFrom])^ ERROR

2) Then move this block of 3 lines...

GUIRegisterMsg($WM_NOTIFY, WM_NOTIFY)
GUIRegisterMsg($WM_LBUTTONUP, WM_LBUTTONUP)
GUISetState()

...and place it just before While True :

GUIRegisterMsg($WM_NOTIFY, WM_NOTIFY)
GUIRegisterMsg($WM_LBUTTONUP, WM_LBUTTONUP)
GUISetState()

While True

...now everything should work fine.

It seems that after a few hundreds of list items added, then WM_NOTIFY is always triggered (the listview needs to be redrawn). So if you place the block of 3 lines too early, then the script will crash because the array $aColor is not defined (when map is encountered within the WM_NOTIFY function)

Moving the 3 lines just before the main loop should fix it.
Please tell us if this solution works for you.

Edited by pixelsearch
typo

"I think you are searching a bug where there is no bug... don't listen to bad advice."

Posted

Thank you very much, it works.
I have put the version I will continue with in my project below.

#include <GUIConstants.au3>
#include <GuiListView.au3>
#include <WinAPISysWin.au3>

Opt("MustDeclareVars", True)

Global $mColor[], $bDragging, $tDragItem = DllStructCreate($tagNMHDR)

Example()

Func Example()
  Local $MainGui = GUICreate("Colored ListView", 1700, 800)
  local $idListview_secties[24];
  local $left

  $left =5
  for $i_listview_number= 0 to 23
    $idListview_secties[$i_listview_number] = GUICtrlCreateListView("Number|Number", $left, 30, 60, 480)
    _GUICtrlListView_SetColumnWidth($idListview_secties[$i_listview_number], 0, 50)
    _GUICtrlListView_SetColumnWidth($idListview_secties[$i_listview_number], 1, 1000)
    $left=$left+65
  next
  Local $idButton = GUICtrlCreateButton("Change", 5, 550, 100, 20)



    global $idLV_start=0
    For $i_listview_number = 2 To 25;
        for $i_positie=0 to 29
            GUICtrlCreateListViewItem($i_positie & '|' & "y" , $idListview_secties[$idLV_start])
        next
        Local $aColor[ControlListView($MainGui, "", $idListview_secties[$idLV_start], "GetItemCount")][ControlListView($MainGui, "", $idListview_secties[$idLV_start], "GetSubItemCount")]
        $aColor[0][0] = 0xFFFF00;
        $aColor[29][0] = 0xFFFF00;
        $mColor[$idListview_secties[$idLV_start]] = $aColor
        $idLV_start=$idLV_start+1
    Next

  GUIRegisterMsg($WM_NOTIFY, WM_NOTIFY)
  GUIRegisterMsg($WM_LBUTTONUP, WM_LBUTTONUP)
  GUISetState()

  While True
    Switch GUIGetMsg()
      Case $GUI_EVENT_CLOSE
        Exit
      Case $idButton
        $aColor = $mColor[$idListview_secties[1]]
        $aColor[5][0] = 0xFF
        $mColor[$idListview_secties[1]] = $aColor
        _WinAPI_RedrawWindow(GUICtrlGetHandle($idListview_secties[1]))

        $aColor = $mColor[$idListview_secties[2]]
        $aColor[6][0] = 0xFF
        $mColor[$idListview_secties[2]] = $aColor
        _WinAPI_RedrawWindow(GUICtrlGetHandle($idListview_secties[2]))
    EndSwitch
  WEnd

EndFunc   ;==>Example

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
  Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)

  If _WinAPI_GetClassName($tNMHDR.hWndFrom) <> "SysListView32" Then Return $GUI_RUNDEFMSG
  Switch $tNMHDR.Code
    Case $NM_CUSTOMDRAW
      Local $tCustDraw = DllStructCreate($tagNMLVCUSTOMDRAW, $lParam)
      Local $iDrawStage = $tCustDraw.dwDrawStage
      If $iDrawStage = $CDDS_PREPAINT Then Return $CDRF_NOTIFYITEMDRAW
      If $iDrawStage = $CDDS_ITEMPREPAINT Then Return $CDRF_NOTIFYSUBITEMDRAW

      ; Paint item and subitem
      Local $iSubItem = $tCustDraw.iSubItem
      Local $iItem = $tCustDraw.dwItemSpec
       If ControlListView($hWnd, "", $tNMHDR.hWndFrom, "IsSelected", $iItem) Then Return $CDRF_DODEFAULT

      $tCustDraw.clrTextBk = ($mColor[$tCustDraw.IDFrom])[$iItem][$iSubItem] ? ($mColor[$tCustDraw.IDFrom])[$iItem][$iSubItem] : 0xFFFFFF
      Return $CDRF_NEWFONT

    Case $NM_DBLCLK
      Local $tItem = DllStructCreate($tagNMITEMACTIVATE, $lParam)
      ConsoleWrite("Double click for ListView : " & $tItem.IDFrom & " on item : " & $tItem.Index & " on subitem : " & $tItem.SubItem & @CRLF)

    Case $LVN_BEGINDRAG
      Local $tDrag = DllStructCreate($tagNMLISTVIEW, $lParam)

      $tDragItem.hWndFrom = $tDrag.hWndFrom
      $tDragItem.IDFrom = $tDrag.IDFrom
      $tDragItem.Code = $tDrag.Item
      $bDragging = True
  EndSwitch
  Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

Func WM_LBUTTONUP($hWnd, $iMsg, $wParam, $lParam)
  If Not $bDragging Then Return $GUI_RUNDEFMSG
  $bDragging = False

  Local $tPoint = _WinAPI_GetMousePos()
  Local $hPoint = _WinAPI_WindowFromPoint($tPoint)
  If Not $hPoint Then Return $GUI_RUNDEFMSG
  If _WinAPI_GetClassName($hPoint) <> "SysListView32" Then Return $GUI_RUNDEFMSG
  If $hPoint = $tDragItem.hWndFrom Then Return $GUI_RUNDEFMSG
  Local $aColorSrc = $mColor[$tDragItem.IDFrom]
  Local $idDest = _WinAPI_GetDlgCtrlID($hPoint)
  Local $aColorDest = $mColor[$idDest]
  If UBound($aColorSrc, 2) <> UBound($aColorDest, 2) Then Return $GUI_RUNDEFMSG

  _GUICtrlListView_CopyItems($tDragItem.hWndFrom, $hPoint, True)

  Local $nDest = UBound($aColorDest) + 1
  ReDim $aColorDest[$nDest][UBound($aColorDest, 2)]
  For $i = 0 To UBound($aColorSrc, 2) - 1
    $aColorDest[$nDest - 1][$i] = $aColorSrc[$tDragItem.Code][$i]
  Next
  _ArrayDelete($aColorSrc, $tDragItem.Code)
  $mColor[$tDragItem.IDFrom] = $aColorSrc
  $mColor[$idDest] = $aColorDest

  Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_LBUTTONUP

 

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
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...