Jump to content
Sign in to follow this  
Spiff59

Trapping $NM_RETURN in a ListView via WM_NOTIFY

Recommended Posts

Spiff59

I'm wanting to modify an existing ListView to trap pressing {ENTER} and treat it the same as an $NM_DBLCLK. I've found a few examples out in the forums, but none of them work, I can't seen to trap a ListView $NM_RETURN event via NM_NOTIFY. Trapping all the other events works great, but not the enter key. Has something changed in newer versions of Autoit that has made the examples not function?

Thanks.

Share this post


Link to post
Share on other sites
mmavipc

I'm wanting to modify an existing ListView to trap pressing {ENTER} and treat it the same as an $NM_DBLCLK. I've found a few examples out in the forums, but none of them work, I can't seen to trap a ListView $NM_RETURN event via NM_NOTIFY. Trapping all the other events works great, but not the enter key. Has something changed in newer versions of Autoit that has made the examples not function?

Thanks.

Can you post some of the examples?

[size="10"]Pure Au3 crypt funcs(I'm currently also working on making a dll from this)[/size][Y] Be more active in the community[Y] Get 200 posts[N] Get 300 posts[N] Make a Topic in the example scripts forum with at least 50 replies.People who currently hate me:ValikSmOke_N

Share this post


Link to post
Share on other sites
Achilles

I'm wanting to modify an existing ListView to trap pressing {ENTER} and treat it the same as an $NM_DBLCLK. I've found a few examples out in the forums, but none of them work, I can't seen to trap a ListView $NM_RETURN event via NM_NOTIFY. Trapping all the other events works great, but not the enter key. Has something changed in newer versions of Autoit that has made the examples not function?

Thanks.

I think that might actually be a bug with AutoIt. The example script for _GUICtrlListView_Create has the $NM_RETURN but it doesn't work.

My Programs[list][*]Knight Media Player[*]Multiple Desktops[*]Daily Comics[*]Journal[/list]

Share this post


Link to post
Share on other sites
rasim

Spiff59

After searching in the Google i think that this solution will be right:

#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <Constants.au3>

Global Const $VK_RETURN = 0x0D ;Enter key

$hGUI = GUICreate("Test GUI", 300, 200)

$hListView = _GUICtrlListView_Create($hGUI, "Items|SubItems", 10, 10, 280, 180)

For $i = 1 To 10
    _GUICtrlListView_AddItem($hListView, "Item " & $i)
Next

GUISetState()

$wProcHandle = DllCallbackRegister("_WindowProc", "int", "hwnd;uint;wparam;lparam")
$wProcOld = _WinAPI_SetWindowLong($hListView, $GWL_WNDPROC, DllCallbackGetPtr($wProcHandle))

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

_WinAPI_SetWindowLong($hListView, $GWL_WNDPROC, $wProcOld)
DllCallbackFree($wProcHandle)
GUIDelete($hGui)

Func _WindowProc($hWnd, $Msg, $wParam, $lParam)
    Switch $hWnd
        Case $hListView
            Switch $Msg
                Case $WM_GETDLGCODE
                    Switch $wParam
                        Case $VK_RETURN
                            ConsoleWrite("Enter key is pressed" & @LF)
                            Return 0
                    EndSwitch
            EndSwitch
    EndSwitch
    
    Return _WinAPI_CallWindowProc($wProcOld, $hWnd, $Msg, $wParam, $lParam)
EndFunc

:mellow:

Share this post


Link to post
Share on other sites
Spiff59

That does seem to do the trick. Thanks, Rasim.

I'm not having any luck so far incorporating that into the WM_Notify routine, so that a single routine can process both the return character and mouse double-clicks from a ListView. But I am still trying...

Share this post


Link to post
Share on other sites
rasim

Spiff59

so that a single routine can process both the return character and mouse double-clicks from a ListView

Example:

#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <Constants.au3>

Global Const $VK_RETURN = 0x0D ;Enter key

$hGUI = GUICreate("Test GUI", 300, 200)

$hListView = _GUICtrlListView_Create($hGUI, "Items|SubItems", 10, 10, 280, 180)

For $i = 1 To 10
    _GUICtrlListView_AddItem($hListView, "Item " & $i)
Next

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

GUISetState()

$wProcHandle = DllCallbackRegister("_WindowProc", "int", "hwnd;uint;wparam;lparam")
$wProcOld = _WinAPI_SetWindowLong($hListView, $GWL_WNDPROC, DllCallbackGetPtr($wProcHandle))

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

_WinAPI_SetWindowLong($hListView, $GWL_WNDPROC, $wProcOld)
DllCallbackFree($wProcHandle)
GUIDelete($hGui)

Func _WindowProc($hWnd, $Msg, $wParam, $lParam)
    Switch $hWnd
        Case $hListView
            Switch $Msg
                Case $WM_GETDLGCODE
                    Switch $wParam
                        Case $VK_RETURN
                            ConsoleWrite("Enter key is pressed" & @LF)
                            Return 0
                    EndSwitch
            EndSwitch
    EndSwitch
   
    Return _WinAPI_CallWindowProc($wProcOld, $hWnd, $Msg, $wParam, $lParam)
EndFunc

Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)
    Local $hWndListView, $tNMHDR, $hWndFrom, $iCode
    
    $hWndListView = $hListView
    If Not IsHWnd($hWndListView) Then $hWndListView = GUICtrlGetHandle($hListView)
    
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iCode = DllStructGetData($tNMHDR, "Code")
    
    Switch $hWndFrom
        Case $hWndListView
            Switch $iCode
                Case $NM_DBLCLK
                    ConsoleWrite("Double click!" & @LF)
            EndSwitch
    EndSwitch
    
    Return $GUI_RUNDEFMSG
EndFunc

:mellow:

Share this post


Link to post
Share on other sites
Spiff59

I guess both procedures can't be combined into one, but I could live with seperate procedures. But with this code, I can't seem to determine which line of the ListView was either clicked on or had the enter key pressed. GuiCtrlRead seems to be returning 0 in all cases.

Share this post


Link to post
Share on other sites
wraithdu

None of the built-in AutoIt GUI functions will work in the new window procedure of your subclassed control, since it's window procedure is no longer under AutoIt's "supervision". You'll have to use the _GuiCtrlListView_*** UDF functions in that window procedure.

Edited by wraithdu

Share this post


Link to post
Share on other sites
rasim

Spiff59

#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <Constants.au3>

Global Const $VK_RETURN = 0x0D ;Enter key

$hGUI = GUICreate("Test GUI", 300, 200)

$hListView = _GUICtrlListView_Create($hGUI, "Items|SubItems", 10, 10, 280, 180)

For $i = 1 To 10
    _GUICtrlListView_AddItem($hListView, "Item " & $i)
Next

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

GUISetState()

$wProcHandle = DllCallbackRegister("_WindowProc", "int", "hwnd;uint;wparam;lparam")
$wProcOld = _WinAPI_SetWindowLong($hListView, $GWL_WNDPROC, DllCallbackGetPtr($wProcHandle))

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

_WinAPI_SetWindowLong($hListView, $GWL_WNDPROC, $wProcOld)
DllCallbackFree($wProcHandle)
GUIDelete($hGui)

Func _WindowProc($hWnd, $Msg, $wParam, $lParam)
    Switch $hWnd
        Case $hListView
            Switch $Msg
                Case $WM_GETDLGCODE
                    Switch $wParam
                        Case $VK_RETURN
                            ConsoleWrite(_GUICtrlListView_GetItemText($hListView, _
                                         _GUICtrlListView_GetSelectedIndices($hListView)) & @LF)
                            Return 0
                    EndSwitch
            EndSwitch
    EndSwitch
   
    Return _WinAPI_CallWindowProc($wProcOld, $hWnd, $Msg, $wParam, $lParam)
EndFunc

Func WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)
    Local $hWndListView, $tNMHDR, $hWndFrom, $iCode
   
    $hWndListView = $hListView
    If Not IsHWnd($hWndListView) Then $hWndListView = GUICtrlGetHandle($hListView)
   
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iCode = DllStructGetData($tNMHDR, "Code")
   
    Switch $hWndFrom
        Case $hWndListView
            Switch $iCode
                Case $NM_DBLCLK
                    ConsoleWrite("Double click!" & @LF)
            EndSwitch
    EndSwitch
   
    Return $GUI_RUNDEFMSG
EndFunc

Share this post


Link to post
Share on other sites
WeMartiansAreFriendly

@rasim, OP hasn't replied, but it works quite as advertised, I would def. prefer $NM_RETURN method though.

I think that might actually be a bug with AutoIt. The example script for _GUICtrlListView_Create has the $NM_RETURN but it doesn't work.

Do the devs know of this.. maybe you should file a bug report?

Edited by RockemSockem

Don't bother, It's inside your monitor!------GUISetOnEvent should behave more like HotKeySet()

Share this post


Link to post
Share on other sites
drever44

$NM_RETURN is very disappointing.

this seams to have been a problem for some time now, so i don’t suppose that it will be corrected any time soon, looked for a work around for several hours and found nothing that will work correctly with my script.

after putting all this time into my project and only to find out that i cant use the enter key on a list-view is overwhelmingly sad. is there possibly a UDF out there that will correct this issue or am i just not seeing this correctly. perhaps in the bata version this will be corrected.

Simply want to left click an item in the list-view and hit return to open an edit window/gui how hard can that be.

and also having a little trouble with double left click and left click defined at the same time. no mater how fast you double click left click always happens. is this not possible also same with right click and double right click. if not i can live with out the doubles.

any help would be greatly appreciated

Share this post


Link to post
Share on other sites
major4579

$NM_RETURN is very disappointing.

this seams to have been a problem for some time now, so i don’t suppose that it will be corrected any time soon, looked for a work around for several hours and found nothing that will work correctly with my script.

after putting all this time into my project and only to find out that i cant use the enter key on a list-view is overwhelmingly sad. is there possibly a UDF out there that will correct this issue or am i just not seeing this correctly. perhaps in the bata version this will be corrected.

Simply want to left click an item in the list-view and hit return to open an edit window/gui how hard can that be.

and also having a little trouble with double left click and left click defined at the same time. no mater how fast you double click left click always happens. is this not possible also same with right click and double right click. if not i can live with out the doubles.

any help would be greatly appreciated

I am using a different approach (probably has it's own problems.. be kind), This is combined with the Double-Click trap mentioned previously. Basically $fDblClk is set to true if an item is Double-Clicked or selected with the Enter key.

GUISetState()
    
    HotKeySet ('{Enter}', '_Enter_Pressed')
    
    While 1
        Switch GUIGetMsg()
            Case $_GUI_EVENT_CLOSE
                $Selected = -1
                ExitLoop

            Case $hExit
                $Selected = -1
                ExitLoop
            EndSwitch

        If ($fDblClk = True) Then ; If Item is Double-Clicked -or- ENTERed
            For $i = 0 To GUICtrlSendMsg($hListView, $_LVM_GETITEMCOUNT, 0, 0)
                If GUICtrlSendMsg($hListView, $_LVM_GETITEMSTATE, $i, 0x2) Then
                    $Selected = $i
                    EndIf
                Next
            $fDblClk = False
            ExitLoop
            Endif
        WEnd
    GUIDelete($hGUI)

    HotKeySet ('{Enter}')

    Return $Selected
EndFunc   ;==>_ArrayDisplay

Func _Enter_Pressed()
    $fDblClk = True
    Return
    EndFunc

Share this post


Link to post
Share on other sites
Jayson

@drever44 : I made this script some time ago (with some help) and maybe you can make a work around with this. Double click an item so you can edit it and then press enter.

#include <GuiConstantsEx.au3>
#include <GuiListView.au3>
#include <WindowsConstants.au3>
#include <Misc.au3>

Global $aLV_Click_Info, $hTmp_Edit = 0, $fDblClk = False

$hGUI = GUICreate("Test GUI", 300, 200)

$hListView = _GUICtrlListView_Create($hGUI, "Items|SubItems", 10, 10, 280, 180)

For $i = 1 To 10
    _GUICtrlListView_AddItem($hListView, "Item " & $i)
    _GUICtrlListView_AddSubItem($hListView, $i - 1, "SubItems" & $i, 1)
Next

GUISetState()
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

While 1
    If $hTmp_Edit <> 0 Then ; If a temporary edit exists
        If _IsPressed("0D") Then ; If ENTER pressed
            $sText = GUICtrlRead($hTmp_Edit) ; Set label to edit content
            _GUICtrlListView_SetItemText($hListView, $aLV_Click_Info[0], $sText, $aLV_Click_Info[1])
            GUICtrlDelete($hTmp_Edit) ; Delete temporary edit
            $hTmp_Edit = 0
        EndIf
    EndIf

    If $fDblClk Then ; If an item was double clicked
        $fDblClk = False
        GUICtrlDelete($hTmp_Edit) ; Delete any existing temporary edits
        $sTmp_Text = _GUICtrlListView_GetItemText($hListView, $aLV_Click_Info[0], $aLV_Click_Info[1]) ; Read current text of clicked label

        Switch $aLV_Click_Info[1] ; Get label position
            Case 0 ; On Item
                $aLV_Rect_Info = _GUICtrlListView_GetItemRect($hListView, $aLV_Click_Info[0], 2)
            Case Else ; On SubItem
                $aLV_Rect_Info = _GUICtrlListView_GetSubItemRect($hListView, $aLV_Click_Info[0], $aLV_Click_Info[1])
            EndSwitch

        $hTmp_Edit = GUICtrlCreateEdit($sTmp_Text, $aLV_Rect_Info[0] + 13, $aLV_Rect_Info[1] + 10, $aLV_Rect_Info[2] - $aLV_Rect_Info[0], $aLV_Rect_Info[3] - $aLV_Rect_Info[1], 0) ; Create temporary edit
        GUICtrlSetState($hTmp_Edit, $GUI_FOCUS)
    EndIf
WEnd

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    Local $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    Local $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    Local $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hListView
            Switch $iCode
                Case $NM_DBLCLK
                    $aLV_Click_Info = _GUICtrlListView_SubItemHitTest($hListView)
                    If $aLV_Click_Info[0] <> -1 Then $fDblClk = True
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY
Edited by Jayson

Share this post


Link to post
Share on other sites
Hawk

@rasim, OP hasn't replied, but it works quite as advertised, I would def. prefer $NM_RETURN method though.

I think that might actually be a bug with AutoIt. The example script for _GUICtrlListView_Create has the $NM_RETURN but it doesn't work.

Do the devs know of this.. maybe you should file a bug report?

Sorry for digging out such an old thread, but here is the problem exactly written down already. The $NM_RETURN trap seems to not work at all. In my program it just didn't work, so I tried the _GUICtrlListView_Create example script and there it also just doesn't respond to pressing the return key.

Share this post


Link to post
Share on other sites
Melba23

Hawk,

Hello again - keeping me busy this evening! ;)

Use an Accelerator key and a flag like this: ;)

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GUIListView.au3>

Global $fDbl_Click = False, $hListView

Example_UDF_Created()

Func Example_UDF_Created()
    Local $GUI, $sHeader = "Full header of any width at all"

    $GUI = GUICreate("(UDF Created) ListView Get Item Param", 400, 300)
    $hListView = _GUICtrlListView_Create($GUI, "", 2, 2, 394, 268)
    ConsoleWrite($hListView & @CRLF)

    _GUICtrlListView_AddColumn($hListView, $sHeader)
    _GUICtrlListView_AddColumn($hListView, "")

    ; Add items
    _GUICtrlListView_AddItem($hListView, "Item 1")
    _GUICtrlListView_AddItem($hListView, "Item 2")
    _GUICtrlListView_AddItem($hListView, "Item 3")

    _GUICtrlListView_SetColumnWidth($hListView, 0, $LVSCW_AUTOSIZE_USEHEADER)
    _GUICtrlListView_SetColumnWidth($hListView, 1, 0)

    Local $hDummy = GUICtrlCreateDummy() ; <<<<<<<<<<<<<<<<<<<<<<<<<<

    GUISetState()

    Local $aAccelKeys[1][2] = [["{ENTER}", $hDummy]]
    GUISetAccelerators($aAccelKeys)

    GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                Exit
            Case $hDummy ; <<<<<<<<<<<<<<<<<<<<<<<<<<
                $iIndex = _GUICtrlListView_GetSelectedIndices($hListView)
                $fDbl_Click = $iIndex
        EndSwitch

        If $fDbl_Click Then ; <<<<<<<<<<<<<<<<<<<<<<<<<<
            $sText = _GUICtrlListView_GetItemText($hListView, $fDbl_Click)
            MsgBox(0, "Hi", "You either double-clicked or" & @CRLF & "you pressed 'Enter'" & @CRLF & "on " & $sText)
            $fDbl_Click = False
        EndIf

    WEnd

    GUIDelete()
EndFunc   ;==>Example_UDF_Created


Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam

    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hListView
            Switch $iCode
                Case $NM_DBLCLK
                    $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
                    $fDbl_Click = DllStructGetData($tInfo, "Index")
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

Please ask if anything is not clear. :)

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______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

 

Share this post


Link to post
Share on other sites
Yashied

In order to use the return key in ListView, you must replace its default WindowProc procedure as follows.

Func _WindowProc($hWnd, $iMsg, $wParam, $lParam)
    Switch $iMsg
        Case $WM_GETDLGCODE
            Switch $wParam
                Case $VK_RETURN
                    Return $DLGC_WANTALLKEYS
            EndSwitch
    EndSwitch
    Return _WinAPI_CallWindowProc($pDefWindowProc, $hWnd, $iMsg, $wParam, $lParam)
EndFunc   ;==>_WindowProc

But unfortunately DllCallbackRegister() will not work properly here. But you can write your own DLL.

Global Comctl32.l = OpenLibrary(#PB_Any, "comctl32.dll")

ProcedureDLL.i SubclassProc(*HWnd, Msg.l, *WParam, *LParam, *ID, *IParam)
    Select Msg
        Case #WM_GETDLGCODE
            Select *WParam
                Case #VK_RETURN
                    ProcedureReturn #DLGC_WANTALLKEYS
            EndSelect
    EndSelect
    ProcedureReturn CallFunction(Comctl32, "DefSubclassProc", *HWnd, Msg, *WParam, *LParam)
EndProcedure

WSP.dll

And a simple example.

#Include <APIConstants.au3>
#Include <GUIListView.au3>
#Include <GUIConstantsEx.au3>
#Include <ListViewConstants.au3>
#Include <WinAPIEx.au3>

OnAutoItExitRegister('AutoItExit')

$hForm = GUICreate('MyGUI', 300, 300)
$hLV = GUICtrlGetHandle(GUICtrlCreateListView('Name', 0, 0, 300, 300, -1, 0))
For $i = 1 To 4
    _GUICtrlListView_AddItem($hLV, 'Item' & $i)
Next
$hDll = _WinAPI_LoadLibrary(@ScriptDir & 'WSP.dll')
If $hDll Then
    $pSubclassProc = _WinAPI_GetProcAddress($hDll, 'SubclassProc')
    If Not @error Then
        _WinAPI_SetWindowSubclass($hLV, $pSubclassProc, 1000)
    Else
        _WinAPI_FreeLibrary($hDll)
    EndIf
EndIf
$Dummy = GUIctrlCreateDummy()
GUIRegisterMsg($WM_NOTIFY, 'WM_NOTIFY')
GUISetState()

While 1
    Switch GUIGetMsg()
        Case 0
            ContinueLoop
        Case $GUI_EVENT_CLOSE
            Exit
        Case $Dummy
            MsgBox(0, '', _GUICtrlListView_GetItemText($hLV, GUICtrlRead($Dummy)) & ' is activated.')
    EndSwitch
WEnd

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    Local $tNMIA = DllStructCreate($tagNMITEMACTIVATE, $lParam)
    Local $hTarget = DllStructGetData($tNMIA, 'hWndFrom')
    Local $ID = DllStructGetData($tNMIA, 'Code')
    Switch $hTarget
        Case $hLV
            Switch $ID
                Case $LVN_ITEMACTIVATE
                    Local $Item = DllStructGetData($tNMIA, 'Index')
                    If _GUICtrlListView_GetItemSelected($hLV, $Item) Then
                        GUICtrlSendToDummy($Dummy, $Item)
                    EndIf
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

Func AutoItExit()
    If $pSubclassProc Then
        _WinAPI_RemoveWindowSubclass($hLV, $pSubclassProc, 1000)
    EndIf
EndFunc   ;==>AutoItExit

@Melba23

Yes it works, but it has several drawbacks:

  • _GUICtrlListView_GetSelectedIndices() may be too slow for a large number of items.
  • You should check the current focus.

Share this post


Link to post
Share on other sites
Hawk

Thanks to you two for your input, I am thinking of which method to implement.

@Melba23: I get the idea and can use this. I am just figuring out, how to use this with a $BS_DEFPUSHBUTTON-style button that reacts in all my GUI to pressing ENTER. As it seems, the accelerator catches the ENTER key and does not allow the other msges connected with pressing it to be sent. But I think I can send that message to the default push button within $hDummy as a workaround. As soon as I have time I will work on that.

Edit: As I write this, the idea came to me that because I track every ENTER keytroke anyways due to the default pushbutton, I can just add checks in that buttons script to check if the listview has focus and if items are selected. Then I can just do what I intended with the listview items as well as what I wanted with the button. Will check that method soon when I find time.

@Yashied: Your method works flawlessly, I just wanted to have an executable file without additional DLLs. So I tried to figure out why it doesn't work with code implementation and failed. I didn't understand:

1) How would DllCallbackRegister() work here anyways? I think it can only be used when you call DLL functions manually, like with DllCall.

2) _WinAPI_GetProcAddress() just returns an address if I am right. So how does _WinAPI_SetWindowSubclass() know to take the function at pointer $pSubClassProc IN WSP.dll and not from any other DLL? Or does _WinAPI_GetProcAddress() return more than just a number?

Is it the only way to change the callback function of listviews?

TIA,

Hawk

Edited by Hawk

Share this post


Link to post
Share on other sites
Melba23

Hawk,

Here is an amended script which solves your BS_DEFPUSHBUTTON problem and also addresses Yashied's comment about requiring focus on the ListView:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <ButtonConstants.au3>
#include <GUIListView.au3>
#include <WinAPI.au3>

Global $hListView, $hDummy

Example_UDF_Created()

Func Example_UDF_Created()
    Local $GUI, $sHeader = "Full header of any width at all"

    $GUI = GUICreate("Test", 400, 300)
    $hListView = _GUICtrlListView_Create($GUI, "", 10, 10, 200, 200)
    ConsoleWrite($hListView & @CRLF)

    _GUICtrlListView_AddColumn($hListView, $sHeader)
    _GUICtrlListView_AddColumn($hListView, "")

    ; Add items
    _GUICtrlListView_AddItem($hListView, "Item 1")
    _GUICtrlListView_AddItem($hListView, "Item 2")
    _GUICtrlListView_AddItem($hListView, "Item 3")

    _GUICtrlListView_SetColumnWidth($hListView, 0, $LVSCW_AUTOSIZE_USEHEADER)
    _GUICtrlListView_SetColumnWidth($hListView, 1, 0)

    $hDummy = GUICtrlCreateDummy()

    Local $hButton = GUICtrlCreateButton("Test", 10, 260, 80, 30, $BS_DEFPUSHBUTTON) ; <<<<<<<<<<<<<<<<<<<<<<<<<<

    GUISetState()

    GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                Exit
            Case $hButton
                If _WinAPI_GetFocus() = $hListView Then ; <<<<<<<<<<<<<<<<<<<<<<<<<<
                    ; Move to next section
                    ContinueCase ; <<<<<<<<<<<<<<<<<<<<<<<<<<
                Else
                    ; Action the DEFPUSHBUTTON
                    MsgBox(0, "Aha", "Button pressed") ; <<<<<<<<<<<<<<<<<<<<<<<<<<
                EndIf
            Case $hDummy
                ; We get here if the handler fired the control or if the ListView had focus when enter was pressed
                $iIndex = _GUICtrlListView_GetSelectedIndices($hListView)
                $sText = "Selected in ListView : " & _GUICtrlListView_GetItemText($hListView, $iIndex)
                MsgBox(0, "Hi", $sText)
                ; Reset focus away from listview
                GUICtrlSetState($hButton, $GUI_FOCUS)
        EndSwitch

    WEnd

    GUIDelete()
EndFunc   ;==>Example_UDF_Created


Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam

    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hListView
            Switch $iCode
                Case $NM_DBLCLK
                    $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam)
                    ; Fire dummy control
                    GUICtrlSendToDummy($hDummy)
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

Please ask if you have any questions. :)

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______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

 

Share this post


Link to post
Share on other sites
Hawk

It seems that trapping $NM_DBLCLK is not necessary because after double clicking we will receive a $LVN_ITEMACTIVATE notification anyways.

Is there a way to _SendMessage() this notification upon pressing ENTER?

I fiddled around with it and googled quite long about it but only made the script crash.

_SendMessage(?, $WM_NOTIFY, wparam, lparam, 0, "wparam", "lparam") is the puzzle.

Puzzle pieces amongst others are:

GUICtrlGetHandle($GUI) or $GUI

GUICtrlGetHandle($hListView) or $hListView

$LVN_ITEMACTIVATE

Edited by Hawk

Share this post


Link to post
Share on other sites
Yashied

#Include <APIConstants.au3>
#Include <GUIListView.au3>
#Include <GUIConstantsEx.au3>
#Include <ListViewConstants.au3>
#Include <WinAPIEx.au3>

Opt('MustDeclareVars', 1)

Global $Accel[1][2] = [['{ENTER}', 0]]
Global $hForm, $hLV, $Dummy
Global $Item = -1

$hForm = GUICreate('MyGUI', 300, 300)
$hLV = GUICtrlGetHandle(GUICtrlCreateListView('Name', 0, 0, 300, 300, -1, 0))
For $i = 1 To 4
    _GUICtrlListView_AddItem($hLV, 'Item' & $i)
Next
$Dummy = GUIctrlCreateDummy()
$Accel[0][1] = GUIctrlCreateDummy()
GUISetAccelerators($Accel)
GUIRegisterMsg($WM_NOTIFY, 'WM_NOTIFY')
GUISetState()

While 1
    Switch GUIGetMsg()
        Case 0
            ContinueLoop
        Case $GUI_EVENT_CLOSE
            Exit
        Case $Dummy
            MsgBox(0, '', _GUICtrlListView_GetItemText($hLV, GUICtrlRead($Dummy)) & ' is activated.')
        Case $Accel[0][1]
            Switch _WinAPI_GetFocus()
                Case 0

                Case $hLV
                    If (Not _SCAW()) And ($Item <> -1) Then
                        GUICtrlSendToDummy($Dummy, $Item)
                    EndIf
                    ContinueCase
            EndSwitch
            GUISetAccelerators(0, $hForm)
            Send('{ENTER}')
            GUISetAccelerators($Accel, $hForm)
        Case Else

    EndSwitch
WEnd

Func _SCAW()

    Local $aData[5] = [0x10, 0x11, 0x12, 0x5B, 0x5C]
    Local $tData = _WinAPI_GetKeyboardState()

    If Not @error Then
        For $i = 0 To 4
            If BitAND(DllStructGetData($tData, 1, $aData[$i] + 1), 0xF0) Then
                Return $aData[$i]
            EndIf
        Next
    EndIf
    Return 0
EndFunc   ;==>_SCAW

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)

    Static $Flag = False

    Local $tNMIA = DllStructCreate($tagNMITEMACTIVATE, $lParam)
    Local $hTarget = DllStructGetData($tNMIA, 'hWndFrom')
    Local $ID = DllStructGetData($tNMIA, 'Code')

    Switch $hWnd
        Case 0

        Case $hForm
            Switch $hTarget
                Case $hLV
                    Switch $ID
                        Case $LVN_BEGINDRAG
                            Return 0
                        Case $LVN_ITEMACTIVATE
                            GUICtrlSendToDummy($Dummy, DllStructGetData($tNMIA, 'Index'))
                        Case $LVN_ITEMCHANGED
                            If (BitAND(DllStructGetData($tNMIA, 'Changed'), $LVIF_STATE)) And (BitXOR(DllStructGetData($tNMIA, 'NewState'), DllStructGetData($tNMIA, 'OldState'))) Then
                                If BitAND(DllStructGetData($tNMIA, 'NewState'), $LVIS_SELECTED) Then
                                    $Item = DllStructGetData($tNMIA, 'Index')
                                    $Flag = 0
                                Else
                                    If BitAND(DllStructGetData($tNMIA, 'OldState'), $LVIS_FOCUSED) Then
                                        $Flag = 1
                                    Else
                                        If Not $Flag Then
                                            $Item = -1
                                        EndIf
                                        $Flag = 0
                                    EndIf
                                EndIf
                            EndIf
                        Case $NM_CLICK, $NM_DBLCLK, $NM_RCLICK, $NM_RDBLCLK
                            Return 0
                    EndSwitch
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

Share this post


Link to post
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
Sign in to follow this  

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.