Jump to content

GUICtrlCreateListViewItem and WM_NOTIFY Bug


Recommended Posts

Hey,

i think i found a bug. When i add listview items with GUICtrlCreateListViewItem and there is a empty subitem in the subitem chain and WM_NOTIFY is present, the GUI freezes. Adding items with UDF works. Bug or wrong usage of GUICtrlCreateListViewItem?

 

Edit: Sorry, forget to say that OwnerDraw mode is on.

#include <GuiListView.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <ColorConstants.au3>


Global Const $ODT_LISTVIEW = 102
Global Const $ODA_DRAWENTIRE = 0x1
Global Const $ODA_SELECT = 0x2
Global Const $ODA_FOCUS = 0x4
Global Const $ODS_SELECTED = 0x0001


Global $GUI_main = GUICreate("", 300, 300, -1, -1)
Global $hGUI_tab_listview[2][10]


$hGUI_tab_listview[0][0] = GUICtrlCreateListView("A|B|C", 15, 10, 250, 280, _
  BitOR($LVS_REPORT, $LVS_SHOWSELALWAYS, $LVS_OWNERDRAWFIXED, $WS_BORDER, $WS_CLIPCHILDREN), 0) ; + $LVS_EX_CHECKBOXES + $LVS_SINGLESEL
_GUICtrlListView_SetExtendedListViewStyle($hGUI_tab_listview[0][0], $LVS_EX_DOUBLEBUFFER)


For $i = 0 To 50
;~  _GUICtrlListView_AddItem(-1, "test " & $i)
;~  _GUICtrlListView_AddSubItem(-1, $i, $i, 1)
    If $i = 5 Then
        GUICtrlCreateListViewItem("|" & "sdfdsfs" & "|" & "", $hGUI_tab_listview[0][0]) ; if empty slot is present, gui gets freezed ; comment this lines out for check
        ContinueLoop
    EndIf
    GUICtrlCreateListViewItem("|" & "sdfdsfs" & "|" & $i, $hGUI_tab_listview[0][0])
Next

GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM")
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUISetState(@SW_SHOW)


; Loop until the user exits.
While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE, $idOK
            ExitLoop
    EndSwitch
WEnd


Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    Return $GUI_RUNDEFMSG
EndFunc     ;==>WM_NOTIFY


Func WM_DRAWITEM($hWnd, $Msg, $wParam, $lParam)
    Local $tagDRAWITEMSTRUCT, $iBrushColor, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC, $bSelected
    $tagDRAWITEMSTRUCT = DllStructCreate( _
       "uint cType;" & _
       "uint cID;" & _
       "uint itmID;" & _
       "uint itmAction;" & _
       "uint itmState;" & _
       "hwnd hItm;" & _
       "handle hDC;" & _
       "long itmRect[4];" & _
       "ulong_ptr itmData" _
       , $lParam)
    If DllStructGetData($tagDRAWITEMSTRUCT, "cType") <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG
    $cID = DllStructGetData($tagDRAWITEMSTRUCT, "cID")
    $itmID = DllStructGetData($tagDRAWITEMSTRUCT, "itmID")
    $itmAction = DllStructGetData($tagDRAWITEMSTRUCT, "itmAction")
    $itmState = DllStructGetData($tagDRAWITEMSTRUCT, "itmState")
    $hItm = DllStructGetData($tagDRAWITEMSTRUCT, "hItm")
    $hDC = DllStructGetData($tagDRAWITEMSTRUCT, "hDC")
    $bSelected = BitAND($itmState, $ODS_SELECTED)
    Switch $cID ; will look for ControlID, not window handle.
      Case $hGUI_tab_listview[0][0]
       Switch $itmAction
        Case $ODA_DRAWENTIRE
         ; don't forget, this is BGR, not RGB
         If $itmState = $bSelected Then ; item is not selected
          $iBrushColor = 0xEEDDBB
         Else ; item is selected
          $iBrushColor = $COLOR_RED
         EndIf
         Local $aBrush = _WinAPI_CreateSolidBrush($iBrushColor)
         Local $aBrushOld = _WinAPI_SelectObject($hDC, $aBrush)
         Local $iLeft = DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 1)
         DllStructSetData($tagDRAWITEMSTRUCT, "itmRect", $iLeft + 1, 1) ; rectangle coordinates for coloring
         ; +1 is the left margin
         _WinAPI_FillRect($hDC, DllStructGetPtr($tagDRAWITEMSTRUCT, "itmRect"), $aBrush)
         _WinAPI_SelectObject($hDC, $aBrushOld)
         _WinAPI_DeleteObject($aBrush)

         ; for all columns of the row:
         $local_alignment = $DT_LEFT
         For $i = 0 To _GUICtrlListView_GetColumnCount($hGUI_tab_listview[0][0]) - 1
          ; 1. get subitem text:
          Local $iSubItmText = _GUICtrlListView_GetItemText($hGUI_tab_listview[0][0], $itmID, $i)
          If $iSubItmText = "" Then ContinueLoop ;ConsoleWrite("hier")
          ; 2. get subitem coordinates for drawing its respective text
          Local $aSubItmRect = _GUICtrlListView_GetSubItemRect($hGUI_tab_listview[0][0], $itmID, $i)
          ; the function above accepts not only subitems (one-based index), but also main item (index=0)
          ; 3. pass the coordinates to a DLL struct
          Local $iSubItmRect = DllStructCreate("long[4]")
          DllStructSetData($iSubItmRect, 1, $aSubItmRect[0] + 6, 1) ; +6 is left margin (X)
          DllStructSetData($iSubItmRect, 1, $aSubItmRect[1] + (-2), 2) ; + (-2) is upper margin (Y)
          DllStructSetData($iSubItmRect, 1, $aSubItmRect[2], 3)
          DllStructSetData($iSubItmRect, 1, $aSubItmRect[3], 4)
          _WinAPI_SetTextColor($hDC, $COLOR_RED)

          DllCall("user32.dll", "int", "DrawTextW", "hwnd", $hDC, "wstr", $iSubItmText, "int", StringLen($iSubItmText), _
            "ptr", DllStructGetPtr($iSubItmRect), "int", $local_alignment)
         Next
         ;#ce
       EndSwitch
    EndSwitch
Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_DRAWITEM
Edited by Trolleule
Link to comment
Share on other sites

  • Moderators

Trolleule,

Your code runs fine for me with no "freezing" - whether I comment the "empty item" line or not - in both v3.3.12.0 and 3.3.13.19. :)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see 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

 

Link to comment
Share on other sites

  • Moderators

Trolleule,

I did scroll the ListView several times - how many do you feel I need to do? :huh:

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see 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

 

Link to comment
Share on other sites

  • Moderators

Trolleule,

I can get the GUI to freeze if I adjust the width of the columns - I am investigating further. :wacko:

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see 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

 

Link to comment
Share on other sites

  • Moderators

Trolleule,

The problem seems to be this line:

If $iSubItmText = "" Then ContinueLoop
If I comment it out then you can use empty subitems without problem. I imagine that missing out the call for an empty item confused the overall drawing process - but that is just a my guess and is probably wrong (as someone will tell me shortly). ;)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see 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

 

Link to comment
Share on other sites

I noticed that even when the display of the LV is frozen, the WM_NOTIFY function is still active and responding. I put a consolewrite in the WM_NOTIFY function and could see writing after the listview display froze. Surprisingly, minimizing the GUI unfreezes the listview and all controls on the GUI.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

Will someone report that?

Feel free, the link to the bug tracker is at the top of every page.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

  • 2 months later...

hey,

Jpm has closed the ticket: 

 

I agree with M23 remark your WM_DRAWITEM has a pb so go to the forum to get help to locate it

 

The problem is still present and i can't figure out why. I have commented the relevant lines. Can someone help me please?

#include <GuiListView.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <ColorConstants.au3>


Global Const $ODT_LISTVIEW = 102
Global Const $ODA_DRAWENTIRE = 0x1
Global Const $ODA_SELECT = 0x2
Global Const $ODA_FOCUS = 0x4
Global Const $ODS_SELECTED = 0x0001

Global $GUI_main = GUICreate("", 300, 300, -1, -1)
Global $idLV = GUICtrlCreateListView("A|B|C", 15, 10, 250, 280, BitOR($LVS_REPORT, $LVS_SHOWSELALWAYS, $LVS_OWNERDRAWFIXED), 0) ; + $LVS_EX_CHECKBOXES + $LVS_SINGLESEL

For $i = 0 To 50
    ; if you comment out these lines, you can easily resize the columns and scroll without a freeze!
    If $i = 5 Then
        GUICtrlCreateListViewItem("|" & "sdfdsfs" & "|" & "", $idLV) ; if empty slot is present, gui gets freezed ; comment these lines out for check
        ContinueLoop
    EndIf
    GUICtrlCreateListViewItem("|" & "sdfdsfs" & "|" & $i, $idLV)
Next

GUIRegisterMsg($WM_DRAWITEM, "WM_DRAWITEM")
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") ; if you do not comment out line 20-23 you can comment out this line and it will work too!
GUISetState(@SW_SHOW)


; Loop until the user exits.
While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE, $idOK
            ExitLoop
    EndSwitch
WEnd


Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    Return $GUI_RUNDEFMSG
EndFunc     ;==>WM_NOTIFY


Func WM_DRAWITEM($hWnd, $Msg, $wParam, $lParam)
    Local $tagDRAWITEMSTRUCT, $iBrushColor, $cID, $itmID, $itmAction, $itmState, $hItm, $hDC, $bSelected
    $tagDRAWITEMSTRUCT = DllStructCreate( _
       "uint cType;" & _
       "uint cID;" & _
       "uint itmID;" & _
       "uint itmAction;" & _
       "uint itmState;" & _
       "hwnd hItm;" & _
       "handle hDC;" & _
       "long itmRect[4];" & _
       "ulong_ptr itmData" _
       , $lParam)
    If DllStructGetData($tagDRAWITEMSTRUCT, "cType") <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG
    $cID = DllStructGetData($tagDRAWITEMSTRUCT, "cID")
    $itmID = DllStructGetData($tagDRAWITEMSTRUCT, "itmID")
    $itmAction = DllStructGetData($tagDRAWITEMSTRUCT, "itmAction")
    $itmState = DllStructGetData($tagDRAWITEMSTRUCT, "itmState")
    $hItm = DllStructGetData($tagDRAWITEMSTRUCT, "hItm")
    $hDC = DllStructGetData($tagDRAWITEMSTRUCT, "hDC")
    $bSelected = BitAND($itmState, $ODS_SELECTED)
    Switch $cID ; will look for ControlID, not window handle.
        Case $idLV
            Switch $itmAction
                Case $ODA_DRAWENTIRE
                    ; don't forget, this is BGR, not RGB
                    If $itmState = $bSelected Then ; item is not selected
                        $iBrushColor = 0xEEDDBB
                    Else ; item is selected
                        $iBrushColor = $COLOR_RED
                    EndIf
                    Local $aBrush = _WinAPI_CreateSolidBrush($iBrushColor)
                    Local $aBrushOld = _WinAPI_SelectObject($hDC, $aBrush)
                    Local $iLeft = DllStructGetData($tagDRAWITEMSTRUCT, "itmRect", 1)
                    DllStructSetData($tagDRAWITEMSTRUCT, "itmRect", $iLeft + 1, 1) ; rectangle coordinates for coloring
                    ; +1 is the left margin
                    _WinAPI_FillRect($hDC, DllStructGetPtr($tagDRAWITEMSTRUCT, "itmRect"), $aBrush)
                    _WinAPI_SelectObject($hDC, $aBrushOld)
                    _WinAPI_DeleteObject($aBrush)

                    ; for all columns of the row:
                    $local_alignment = $DT_LEFT
                    For $i = 0 To _GUICtrlListView_GetColumnCount($idLV) - 1
                        ; 1. get subitem text:
                        Local $iSubItmText = _GUICtrlListView_GetItemText($idLV, $itmID, $i)
                        ; If $iSubItmText = "" Then ContinueLoop ;ConsoleWrite("hier")
                        ; 2. get subitem coordinates for drawing its respective text
                        Local $aSubItmRect = _GUICtrlListView_GetSubItemRect($idLV, $itmID, $i)
                        ; the function above accepts not only subitems (one-based index), but also main item (index=0)
                        ; 3. pass the coordinates to a DLL struct
                        Local $iSubItmRect = DllStructCreate("long[4]")
                        DllStructSetData($iSubItmRect, 1, $aSubItmRect[0] + 6, 1) ; +6 is left margin (X)
                        DllStructSetData($iSubItmRect, 1, $aSubItmRect[1] + (-2), 2) ; + (-2) is upper margin (Y)
                        DllStructSetData($iSubItmRect, 1, $aSubItmRect[2], 3)
                        DllStructSetData($iSubItmRect, 1, $aSubItmRect[3], 4)
                        _WinAPI_SetTextColor($hDC, $COLOR_RED)

                        DllCall("user32.dll", "int", "DrawTextW", "hwnd", $hDC, "wstr", $iSubItmText, "int", StringLen($iSubItmText), _
                            "ptr", DllStructGetPtr($iSubItmRect), "int", $local_alignment)
                    Next
                    ;#ce
            EndSwitch
    EndSwitch
Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_DRAWITEM
Link to comment
Share on other sites

I can confirm the freezing. May I ask why you are using an owner drawn listview, when a listview supports custom drawn items?

Take a look at Custom drawn TreeViews and ListViews. No freezing here.

Link to comment
Share on other sites

Because i use a custom row height:

Func WM_MEASUREITEM($hWnd, $Msg, $wParam, $lParam)
    Local $tMEASUREITEMS = DllStructCreate("uint cType;uint cID;uint itmID;uint itmW;uint itmH;ulong_ptr itmData", $lParam)
    If DllStructGetData($tMEASUREITEMS, "cType") <> $ODT_LISTVIEW Then Return $GUI_RUNDEFMSG
    DllStructSetData($tMEASUREITEMS, "itmH", $nListView_row_height) ; set row height
    Return 1
EndFunc     ;==>WM_MEASUREITEM

And this requires Ownerdraw! If you know a alternative solution to use a custom row height without Ownerdraw i could rewrite my code'?!

Link to comment
Share on other sites

Hypothesis: Not a bug! It's a combination of lacking documentation in MSDN's listview part, and a bit of your carelessness when working with listview item/subitem

Local $iSubItmText = _GUICtrlListView_GetItemText($hGUI_tab_listview[0][0], $itmID, $i)

Change to this (testing-purpose only)

Local $iSubItmText = 'Dummy Text'

Now do your GUI still freeze or not?

Edited by binhnx

99 little bugs in the code

99 little bugs!

Take one down, patch it around

117 little bugs in the code!

Link to comment
Share on other sites

Maybe a clue, the gui (on my pc) doesn't freeze if

If $i = 5 Then
        GUICtrlCreateListViewItem("|" & "sdfdsfs" & "|" & " ", $hGUI_tab_listview[0][0])  ; whitespace in the 'empty' subitem

or using the udf

If $i = 5 Then _GUICtrlListView_AddSubItem($hListView, $i - 1, "", 1)  ; force creation of empty subitem
Edited by mikell
Link to comment
Share on other sites

@binhnx where is the solution? I already tested this but there is not the problem!

@mikell Thank you but only a workaround.

My first post:

 

i think i found a bug. When i add listview items with GUICtrlCreateListViewItem and there is a empty subitem in the subitem chain and WM_NOTIFY is present, the GUI freezes. Adding items with UDF works
Edited by Trolleule
Link to comment
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
 Share

  • Recently Browsing   0 members

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