Jump to content

Recommended Posts

Posted (edited)

Hi, I have problem with $NM_DBLCLK handling for ListView. I need three forms:

Form 1 = base form of app

Form 2 = any listview with ListView event handling

Form 3 = viewing details of selected item from Form 2

After double-click on a item in the listview AutoIt crashes! :)

What's wrong with my script? Can somebody help me with this problem?

AutoIt: 3.2.10.0

#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <ListBoxConstants.au3>
#include <WindowsConstants.au3>

Global $Form1, $Form2, $Form3
Global $List_View
Global $Result

; MAIN GUI 
    $Form1=GUICreate("FORM 1", 600, 400)
    $Button1=GUICtrlCreateButton("Show form 2", 240, 352, 121, 33, 0)
    $Label1=GUICtrlCreateLabel("Text.....", 16, 16, 332, 17)
    GUISetState(@SW_SHOW,$Form1)
    GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") ; <<<< SET EVENTS
    While 1
        $nMsg = GUIGetMsg()
        Switch $nMsg
            Case $GUI_EVENT_CLOSE
                ExitLoop 
            Case $Button1
                _ShowForm2()
        EndSwitch
    WEnd
Exit  

;== SHOW FORM 2 ==============================
Func _ShowForm2()
$Form2=GUICreate("FORM 2", 410, 250)
$Button2=GUICtrlCreateButton("Show form 3", 152, 200, 121, 33, 0)
$List_View=GUICtrlCreateListView("Name", 8, 16, 393, 150)
$item1=GuiCtrlCreateListViewItem("Paul",$List_View)
$item2=GuiCtrlCreateListViewItem("Robert",$List_View)
$item3=GuiCtrlCreateListViewItem("Chris",$List_View)
Local $Label1=GUICtrlCreateLabel("Please, double click on a item...", 16, 170, 200, 17)
GUISetState (@SW_DISABLE, $Form1)
GUISetState(@SW_SHOW,$Form2)
While 1
    $nMsg = GUIGetMsg()
    Select 
        Case $nMsg = $GUI_EVENT_CLOSE
            GUISetState (@SW_ENABLE, $Form1)
            GUIDelete($Form2)
            Return
        Case $nMsg = $Button2
            _ShowForm3() ; test only
    EndSelect
WEnd
EndFunc ;==> SHOW FORM 2 ======================= 

;== SHOW FORM 3 ==============================
Func _ShowForm3()
$Form3=GUICreate("FORM 3", 200, 100)
$Button3=GUICtrlCreateButton("Close", 48, 64, 97, 33, 0)
$Result=GUICtrlCreateLabel("Result:", 16, 16, 100, 17)
GUISetState(@SW_DISABLE,$Form2)
GUISetState(@SW_SHOW,$Form3)
While 1
    $nMsg = GUIGetMsg()
    Select 
        Case $nMsg=$GUI_EVENT_CLOSE Or $nMsg=$Button3
            GUISetState (@SW_ENABLE, $Form2)
            GUIDelete($Form3)
            Return
        Case Else 
    EndSelect
WEnd
EndFunc ;==> SHOW FORM 3 =======================

Func WM_NOTIFY($hWndGUI, $MsgID, $wParam, $lParam)
    #forceref $hWndGUI, $MsgID, $wParam
    Local $tagNMHDR, $event, $hwndFrom, $code
    $tagNMHDR = DllStructCreate("int;int;int", $lParam) ;NMHDR (hwndFrom, idFrom, code)
    If @error Then Return
    $event = DllStructGetData($tagNMHDR, 3)
    Select
    Case $wParam = $List_View
        Select
            Case $event = $NM_DBLCLK ; Crash?
                _ShowForm3() ; + result (in the future)
            EndSelect
    EndSelect
    $tagNMHDR = 0
    $event = 0
    $lParam = 0
EndFunc ;==> WM_Notify_Events
Edited by Logman
  • Moderators
Posted (edited)

You have all 3 gui's using $nMsg, what happens when you change each function to their own Var like $nMsg1 for $Form2 and $nMsg2 for $Form3?

When using functions, you should really declare variables within the function local if they are only to be used in a local scope.

Edit:

Nah, I even changed that and it crashed still, even after changing up the wm_events... guess I'm too tired to debug:

#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <ListBoxConstants.au3>
#include <WindowsConstants.au3>

Global $Form1, $Form2, $Form3
Global $List_View
Global $Result
Global $hForm2

; MAIN GUI
    $Form1=GUICreate("FORM 1", 600, 400)
    $Button1=GUICtrlCreateButton("Show form 2", 240, 352, 121, 33, 0)
    $Label1=GUICtrlCreateLabel("Text.....", 16, 16, 332, 17)
    GUISetState(@SW_SHOW,$Form1)
    While 1
        $nMsg = GUIGetMsg()
        Switch $nMsg
            Case $GUI_EVENT_CLOSE
                ExitLoop
            Case $Button1
                _ShowForm2($Form1)
        EndSwitch
    WEnd
Exit 

;== SHOW FORM 2 ==============================
Func _ShowForm2($hParent)
$Form2=GUICreate("FORM 2", 410, 250, Default, Default, -1, -1, $hParent)
$Button2=GUICtrlCreateButton("Show form 3", 152, 200, 121, 33, 0)
$List_View=GUICtrlCreateListView("Name", 8, 16, 393, 150)
$item1=GuiCtrlCreateListViewItem("Paul",$List_View)
$item2=GuiCtrlCreateListViewItem("Robert",$List_View)
$item3=GuiCtrlCreateListViewItem("Chris",$List_View)
Local $Label1=GUICtrlCreateLabel("Please, double click on a item...", 16, 170, 200, 17)
GUISetState (@SW_DISABLE, $Form1)
GUISetState(@SW_SHOW,$Form2)
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") ; <<<< SET EVENTS
While 1
    $nMsg2 = GUIGetMsg()
    Select
        Case $nMsg2 = $GUI_EVENT_CLOSE
            GUISetState (@SW_ENABLE, $Form1)
            GUIDelete($Form2)
            Return
        Case $nMsg2 = $Button2
            _ShowForm3($Form2) ; test only
    EndSelect
WEnd
EndFunc ;==> SHOW FORM 2 =======================

;== SHOW FORM 3 ==============================
Func _ShowForm3($hParent)
$Form3=GUICreate("FORM 3", 200, 100, Default, Default, -1, -1, $hParent)
$Button3=GUICtrlCreateButton("Close", 48, 64, 97, 33, 0)
$Result=GUICtrlCreateLabel("Result:", 16, 16, 100, 17)
GUISetState(@SW_DISABLE,$Form2)
GUISetState(@SW_SHOW,$Form3)
While 1
    $nMsg3 = GUIGetMsg()
    Select
        Case $nMsg3 = $GUI_EVENT_CLOSE Or $nMsg3 = $Button3
            GUISetState (@SW_ENABLE, $Form2)
            GUIDelete($Form3)
            Return
    EndSelect
WEnd
EndFunc ;==> SHOW FORM 3 =======================
Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam
    Local $iCode, $tNMHDR
    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $iCode
        Case $NM_DBLCLK
            _ShowForm3($Form2)
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc
Edited by SmOke_N

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Posted

Smoke_N, thanks for your reply. I've tried several times to change the wm_events, but still AutoIt crashes. I find it strange. :)

This code is not working too:

#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <GuiListView.au3>
#include <ListBoxConstants.au3>
#include <WindowsConstants.au3>

Global $Form1, $Form2, $Form3
Global $List_View
Global $Result
Global $hForm2

; MAIN GUI
    $Form1=GUICreate("FORM 1", 600, 400)
    $Button1=GUICtrlCreateButton("Show form 2", 240, 352, 121, 33, 0)
    $Label1=GUICtrlCreateLabel("Text.....", 16, 16, 332, 17)
    GUISetState(@SW_SHOW,$Form1)
    While 1
        $nMsg = GUIGetMsg()
        Switch $nMsg
            Case $GUI_EVENT_CLOSE
                ExitLoop
            Case $Button1
                _ShowForm2($Form1)
        EndSwitch
    WEnd
Exit

;== SHOW FORM 2 ==============================
Func _ShowForm2($hParent)
$Form2=GUICreate("FORM 2", 410, 250, Default, Default, -1, -1, $hParent)
$Button2=GUICtrlCreateButton("Show form 3", 152, 200, 121, 33, 0)
$List_View=GUICtrlCreateListView("Name", 8, 16, 393, 150)
$item1=GuiCtrlCreateListViewItem("Paul",$List_View)
$item2=GuiCtrlCreateListViewItem("Robert",$List_View)
$item3=GuiCtrlCreateListViewItem("Chris",$List_View)
Local $Label1=GUICtrlCreateLabel("Please, double click on a item...", 16, 170, 200, 17)
GUISetState (@SW_DISABLE, $Form1)
GUISetState(@SW_SHOW,$Form2)
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") ; <<<< SET EVENTS
While 1
    $nMsg2 = GUIGetMsg()
    Select
        Case $nMsg2 = $GUI_EVENT_CLOSE
            GUISetState (@SW_ENABLE, $Form1)
            GUIDelete($Form2)
            Return
        Case $nMsg2 = $Button2
            _ShowForm3($Form2) ; test only
    EndSelect
WEnd
EndFunc ;==> SHOW FORM 2 =======================

;== SHOW FORM 3 ================================
Func _ShowForm3($hParent)
$Form3=GUICreate("FORM 3", 200, 100, Default, Default, -1, -1, $hParent)
$Button3=GUICtrlCreateButton("Close", 48, 64, 97, 33, 0)
$Result=GUICtrlCreateLabel("Result:", 16, 16, 100, 17)
GUISetState(@SW_DISABLE,$Form2)
GUISetState(@SW_SHOW,$Form3)
While 1
    $nMsg3 = GUIGetMsg()
    Select
        Case $nMsg3 = $GUI_EVENT_CLOSE Or $nMsg3 = $Button3
            GUISetState (@SW_ENABLE, $Form2)
            GUIDelete($Form3)
            Return
    EndSelect
WEnd
EndFunc ;==> SHOW FORM 3 =======================

;== WM_NOTIFY ==================================
Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndListView, $tInfo
    $hWndListView = $List_View
    If Not IsHWnd($List_View) Then $hWndListView = GUICtrlGetHandle($List_View)
    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
      Case $hWndListView
            Switch $iCode
                 Case $NM_DBLCLK 
                _ShowForm3($Form2)
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc ;==>WM_NOTIFY ===========================
Posted (edited)

Don't run the function from the WM_NOTIFY, just set a flag from there.

You need to return from the WM_NOTIFY as quickly as possible.

#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <GuiListView.au3>
#include <ListBoxConstants.au3>
#include <WindowsConstants.au3>

Global $Form1, $Form2, $Form3
Global $List_View, $fLoadForm = False, $hForm2

; MAIN GUI
$Form1 = GUICreate("FORM 1", 600, 400)
$Button1 = GUICtrlCreateButton("Show form 2", 240, 352, 121, 33, 0)
GUICtrlCreateLabel("Text.....", 16, 16, 332, 17)
GUISetState(@SW_SHOW, $Form1)
While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            ExitLoop
        Case $Button1
            _ShowForm2($Form1)
    EndSwitch
WEnd
Exit

;== SHOW FORM 2 ==============================
Func _ShowForm2($hParent)
    $Form2 = GUICreate("FORM 2", 410, 250, Default, Default, -1, -1, $hParent)
    $Button2 = GUICtrlCreateButton("Show form 3", 152, 200, 121, 33, 0)
    $List_View = GUICtrlCreateListView("Name", 8, 16, 393, 150)
    $item1 = GUICtrlCreateListViewItem("Paul", $List_View)
    $item2 = GUICtrlCreateListViewItem("Robert", $List_View)
    $item3 = GUICtrlCreateListViewItem("Chris", $List_View)
    GUICtrlCreateLabel("Please, double click on a item...", 16, 170, 200, 17)
    GUISetState(@SW_DISABLE, $Form1)
    GUISetState(@SW_SHOW, $Form2)
    GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") ; <<<< SET EVENTS
    While 1
        $nMsg2 = GUIGetMsg()
        Select
            Case $nMsg2 = $GUI_EVENT_CLOSE
                GUISetState(@SW_ENABLE, $Form1)
                GUIDelete($Form2)
                Return
            Case $nMsg2 = $Button2
                _ShowForm3($Form2) ; test only
            Case Else
                If $fLoadForm Then
                    $fLoadForm = False
                    _ShowForm3($Form2)
                EndIf
        EndSelect
    WEnd
EndFunc   ;==>_ShowForm2

;== SHOW FORM 3 ================================
Func _ShowForm3($hParent)
    $Form3 = GUICreate("FORM 3", 200, 100, Default, Default, -1, -1, $hParent)
    $Button3 = GUICtrlCreateButton("Close", 48, 64, 97, 33, 0)
    GUICtrlCreateLabel("Result:", 16, 16, 100, 17)
    GUISetState(@SW_DISABLE, $Form2)
    GUISetState(@SW_SHOW, $Form3)
    While 1
        $nMsg3 = GUIGetMsg()
        Select
            Case $nMsg3 = $GUI_EVENT_CLOSE Or $nMsg3 = $Button3
                GUISetState(@SW_ENABLE, $Form2)
                GUIDelete($Form3)
                Return
        EndSelect
    WEnd
EndFunc   ;==>_ShowForm3

;== WM_NOTIFY ==================================
Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndListView, $tInfo
    $hWndListView = $List_View
    If Not IsHWnd($List_View) Then $hWndListView = GUICtrlGetHandle($List_View)
    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hWndListView
            Switch $iCode
                Case $NM_DBLCLK
                    $fLoadForm = True
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY
Edited by GaryFrost

SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

Posted

Don't run the function from the WM_NOTIFY, just set a flag from there.

You need to return from the WM_NOTIFY as quickly as possible.

Huh, I think your solution is very simple and this is extremely useful information. You solved my problem, it's works!

Thank you GaryFrost!

Posted

GaryFrost

Don't run the function from the WM_NOTIFY, just set a flag from there.

You need to return from the WM_NOTIFY as quickly as possible.

Well, but if i need run function from the WM_NOTIFY, possible run function and then exit from function with return?

e.g.:

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndListView, $tInfo
    $hWndListView = $List_View
    If Not IsHWnd($List_View) Then $hWndListView = GUICtrlGetHandle($List_View)
    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hWndListView
            Switch $iCode
                Case $NM_DBLCLK
                    _ShowForm3()
            Return
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
Posted

Think about what this is doing.....

WM_NOTIFY is fired

Function is called from WM_NOTIFY that loads a new form

New form is expecting WM_NOTIFY events but the function hasn't returned to WM_NOTIFY yet and WM_NOTIFY hasn't returned yet.

SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

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
×
×
  • Create New...