Jump to content

Custom created ListView problem


PaulIA
 Share

Recommended Posts

I've been looking at this one all afternoon and I'm still stumped as to what I'm doing wrong. I was working on a small script to create a ListView control. I know that GUICreateListView already does this, but I was doing some research for Auto3Lib and wanted to write this for the learning experience. As shown in the code below, I create the ListView control and add 4 columns to it. It appears to work fine, but when I click on any of the column headers, the program crashes.

I did a search on the forum, but I could not find anything that exposes the internal workings of GUICreateListView. This is one of those times that I wish I had access to the AutoIt source. ;)

Google and MSDN say that the code below should work, so I must be missing something pretty simple. Can anybody give me a clue as to what I'm doing wrong?

Regards,

Paul

CODE
#include <GUIConstants.au3>

Global $hGUI
Global $hList

Global Const $LVCOLUMN                          = "int;int;int;ptr;int;int;int;int"

Global Const $LVC_MASK                          = 1
Global Const $LVC_FMT                           = 2
Global Const $LVC_CX                            = 3
Global Const $LVC_PSZTEXT                       = 4
Global Const $LVC_CCHTEXTMAX                    = 5
Global Const $LVC_ISUBITEM                      = 6
Global Const $LVC_IIMAGE                        = 7
Global Const $LVC_IORDER                        = 8

Global Const $LVCF_SUBITEM                      = 0x008
Global Const $LVCF_IMAGE                        = 0x010
Global Const $LVCF_ORDER                        = 0x020

Global Const $LVM_INSERTCOLUMN                  = 0x101B

; =================================================================================================
$hGUI  = GUICreate("ListView Test GUI", 408, 300)
$hList = _ListView_Create($hGUI, 2, 2, 404, 296)
_ListView_InsertColumn($hList, 0, $LVCFMT_LEFT, 100, "Column 1")
_ListView_InsertColumn($hList, 1, $LVCFMT_LEFT, 100, "Column 2")
_ListView_InsertColumn($hList, 2, $LVCFMT_LEFT, 100, "Column 3")
_ListView_InsertColumn($hList, 3, $LVCFMT_LEFT, 100, "Column 4")
GUISetState()

do
  Sleep(10)
until GUIGetMsg() = $GUI_EVENT_CLOSE

; =================================================================================================
Func _ListView_Create($hWnd, $iX, $iY, $iWidth=150, $iHeight=150, $iStyle=0x0D, $iExStyle=0x220)
  $iStyle = BitOR($iStyle, $WS_CHILD, $WS_VISIBLE)
  Return _CreateWindowEx($iExStyle, "SysListView32", "", $iStyle, $iX, $iY, $iWidth, $iHeight, $hWnd)
EndFunc

; =================================================================================================
Func _ListView_InsertColumn($hWnd, $iIndex, $iFmt, $iCX, $sText)
  Local $pBuffer, $rBuffer, $rColumn, $pColumn, $pMemory, $rMemMap, $iResult, $iSize, $pTextPtr

  $rBuffer = DllStructCreate("char[4096]")
  $pBuffer = DllStructGetPtr($rBuffer )
  $rColumn = DllStructCreate($LVCOLUMN)
  $pColumn = DllStructGetPtr($rColumn )
  DllStructSetData($rBuffer, 1, $sText)
  DllStructSetData($rColumn, $LVC_MASK      , BitOR($LVCF_FMT, $LVCF_WIDTH, $LVCF_TEXT))
  DllStructSetData($rColumn, $LVC_FMT       , $iFmt)
  DllStructSetData($rColumn, $LVC_CX        , $iCX )
  DllStructSetData($rColumn, $LVC_CCHTEXTMAX, 4096 )
  DllStructSetData($rColumn, $LVC_PSZTEXT, $pBuffer)
  $iResult = _SendMessage($hWnd, $LVM_INSERTCOLUMN, $iIndex, $pColumn)
  Return $iResult
EndFunc

; =================================================================================================
; UDFs below this line have been used in several of the other Auto3Lib modules, so I'm thinking that
; the problem is probably not in one of these, but...
; =================================================================================================
Func _CreateWindowEx($iExStyle, $sClass, $sName, $iStyle, $iX, $iY, $iWidth, $iHeight, $hParent, _
                     $hMenu=0, $hInstance=0, $pParam=0)
  Local $aResult

  if $hInstance = 0 then $hInstance = _GetModuleHandle("")
  $aResult = DllCall("User32.dll", "hwnd", "CreateWindowEx", "int", $iExStyle, "str", $sClass, _
                     "str", $sName, "int", $iStyle, "int", $iX, "int", $iY, "int", $iWidth, _
                     "int", $iHeight, "hwnd", $hParent, "hwnd", $hMenu, "hwnd", $hInstance, _
                     "ptr", $pParam)
  Return $aResult[0]
EndFunc

; =================================================================================================
Func _GetModuleHandle($sModuleName)
  Local $rBuffer, $pBuffer, $aResult

  if $sModuleName <> "" then
    $rBuffer = DllStructCreate("char[4096]")
    $pBuffer = DllStructGetPtr($rBuffer    )
    DllStructSetData($rBuffer, 1, $sModuleName)
  endif
  $aResult = DllCall("Kernel32.dll", "hwnd", "GetModuleHandle", "ptr", $pBuffer)
  Return "0x" & Hex($aResult[0])
EndFunc

; =================================================================================================
Func _SendMessage($hWnd, $iMsg, $iwParam, $ilParam)
  Local $aResult

  if not IsHWnd($hWnd) then $hWnd = HWnd($hWnd)
  $aResult = DllCall("User32.dll", "int", "SendMessage", "hwnd", $hWnd, "int", $iMsg, "int", $iwParam, "int", $ilParam)
  Return $aResult[0]
EndFunc
Auto3Lib: A library of over 1200 functions for AutoIt
Link to comment
Share on other sites

I had a little more time to work on this problem today. It appears that this may be a "feature" in AutoIt in how it works with ListView controls. When I set up a function to capture messages from the ListView control via GUIRegisterMsg and trap out the LVN_COLUMNCLICK messages, the problem goes away. I'm wondering if AutoIt is internally trapping these messages so that it can fire the GUICtrlRegisterListViewSort function? Below is some code that shows the problem and how to get rid of it by trapping the LVN_COLUMNCLICK message from the ListView:

CODE
#include <GUIConstants.au3>

Global $hGUI
Global $hList

Global Const $LVCOLUMN                          = "int;int;int;ptr;int;int;int;int"

Global Const $LVC_MASK                          = 1
Global Const $LVC_FMT                           = 2
Global Const $LVC_CX                            = 3
Global Const $LVC_PSZTEXT                       = 4
Global Const $LVC_CCHTEXTMAX                    = 5
Global Const $LVC_ISUBITEM                      = 6
Global Const $LVC_IIMAGE                        = 7
Global Const $LVC_IORDER                        = 8

Global Const $LVM_INSERTCOLUMN                  = 0x101B

Global Const $WM_NOTIFY                         = 0x004E

Global Const $LVN_FIRST                         = -100
Global Const $LVN_COLUMNCLICK                   = $LVN_FIRST - 8

; =================================================================================================
$hGUI  = GUICreate("ListView Test GUI", 408, 300)
$hList = _ListView_Create($hGUI, 2, 2, 404, 296)
_ListView_InsertColumn($hList, 0, $LVCFMT_LEFT, 100, "Column 1")
_ListView_InsertColumn($hList, 1, $LVCFMT_LEFT, 100, "Column 2")
_ListView_InsertColumn($hList, 2, $LVCFMT_LEFT, 100, "Column 3")
_ListView_InsertColumn($hList, 3, $LVCFMT_LEFT, 100, "Column 4")
GUISetState()

; Set up to capture notifications.  Comment out line below to see error
;GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

do
  Sleep(10)
until GUIGetMsg() = $GUI_EVENT_CLOSE

; If I trap out the LVN_COLUMNCLICK message, everything works
; =================================================================================================
Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
  Local $rHead     = DllStructCreate("int;int;int", $ilParam)
  Local $hWndFrom  = DllStructGetData($rHead, 1)
  Local $hCtrlFrom = DllStructGetData($rHead, 2)
  Local $iCode     = DllStructGetData($rHead, 3)

  if $hWndFrom = $hList then
    if $iCode = $LVN_COLUMNCLICK then
      ConsoleWrite("LVN_COLUMNCLICK" & @CR)
      Return
    endIf
  endIf
  Return $GUI_RUNDEFMSG
EndFunc

; =================================================================================================
Func _ListView_Create($hWnd, $iX, $iY, $iWidth=150, $iHeight=150, $iStyle=0x0D, $iExStyle=0x220)
  $iStyle = BitOR($iStyle, $WS_CHILD, $WS_VISIBLE)
  Return _CreateWindowEx($iExStyle, "SysListView32", "", $iStyle, $iX, $iY, $iWidth, $iHeight, $hWnd)
EndFunc

; =================================================================================================
Func _ListView_InsertColumn($hWnd, $iIndex, $iFmt, $iCX, $sText)
  Local $pBuffer, $rBuffer, $rColumn, $pColumn, $pMemory, $rMemMap, $iResult, $iSize, $pTextPtr

  $rBuffer = DllStructCreate("char[4096]")
  $pBuffer = DllStructGetPtr($rBuffer )
  $rColumn = DllStructCreate($LVCOLUMN)
  $pColumn = DllStructGetPtr($rColumn )
  DllStructSetData($rBuffer, 1, $sText)
  DllStructSetData($rColumn, $LVC_MASK      , BitOR($LVCF_FMT, $LVCF_WIDTH, $LVCF_TEXT))
  DllStructSetData($rColumn, $LVC_FMT       , $iFmt)
  DllStructSetData($rColumn, $LVC_CX        , $iCX )
  DllStructSetData($rColumn, $LVC_CCHTEXTMAX, 4096 )
  DllStructSetData($rColumn, $LVC_PSZTEXT, $pBuffer)
  $iResult = _SendMessage($hWnd, $LVM_INSERTCOLUMN, $iIndex, $pColumn)
  Return $iResult
EndFunc

; =================================================================================================
Func _CreateWindowEx($iExStyle, $sClass, $sName, $iStyle, $iX, $iY, $iWidth, $iHeight, $hParent, _
                     $hMenu=0, $hInstance=0, $pParam=0)
  Local $aResult

  if $hInstance = 0 then $hInstance = _GetModuleHandle("")
  $aResult = DllCall("User32.dll", "hwnd", "CreateWindowEx", "int", $iExStyle, "str", $sClass, _
                     "str", $sName, "int", $iStyle, "int", $iX, "int", $iY, "int", $iWidth, _
                     "int", $iHeight, "hwnd", $hParent, "hwnd", $hMenu, "hwnd", $hInstance, _
                     "ptr", $pParam)
  Return $aResult[0]
EndFunc

; =================================================================================================
Func _GetModuleHandle($sModuleName)
  Local $rBuffer, $pBuffer, $aResult

  if $sModuleName <> "" then
    $rBuffer = DllStructCreate("char[4096]")
    $pBuffer = DllStructGetPtr($rBuffer    )
    DllStructSetData($rBuffer, 1, $sModuleName)
  endif
  $aResult = DllCall("Kernel32.dll", "hwnd", "GetModuleHandle", "ptr", $pBuffer)
  Return "0x" & Hex($aResult[0])
EndFunc

; =================================================================================================
Func _SendMessage($hWnd, $iMsg, $iwParam, $ilParam)
  Local $aResult

  if not IsHWnd($hWnd) then $hWnd = HWnd($hWnd)
  $aResult = DllCall("User32.dll", "int", "SendMessage", "hwnd", $hWnd, "int", $iMsg, "int", $iwParam, "int", $ilParam)
  Return $aResult[0]
EndFunc
Auto3Lib: A library of over 1200 functions for AutoIt
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...