Jump to content

OnEvent not called with dynamically built child window


jchd
 Share

Recommended Posts

Hi all,

Here's a situation where I'm really stuck.

My [fairly complex and still bloating] application uses a main GUI with no problem and now I'm developping code for a given action triggered by an OnEvent function. I'm using the event mode for handling messages.

For this new code, I need a child GUI which is built dynamically: the controls heavily depend on style and number of currently processed data. Building this bunch of controls "on the fly" is no problem, but I can't find a way to have the OnEvent functions (those registered for these new controls) to work at all.

I've made a short version without any complexity and it behaves the same: OnEvent functions for the child window' controls are never called. And NO, I can't get out of the first OnEvent function without having done complex things with the data collected from the child window. And NO, I just can't build the child window along with the main GUI, because its desired control content can only be determined after complex processing done within the first OnEvent function.

I've also tried to force the event mode off for the child window, but without more success: I keep getting inconsistant messages.

Here is the exerpt which I'd like to make working:

#include <GUIConstantsEx.au3>

Opt("GUIOnEventMode", 1)  ; Change to OnEvent mode 
$mainwindow = GUICreate("Hello World", 200, 100)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")
GUICtrlCreateLabel("Hello world! How are you?", 30, 10)
$okbutton = GUICtrlCreateButton("OK", 70, 50, 60)
GUICtrlSetOnEvent($okbutton, "OKButton")

$dummywindow = GUICreate("Dummy window for testing ", 200, 100)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")

GUISwitch($mainwindow)
GUISetState(@SW_SHOW)

While 1
  Sleep(1000)  ; Idle around
WEnd

Global $instr, $notdone
Global $okbutton, $but, $inp

Func OKButton()
    ;Note: at this point @GUI_CTRLID would equal $okbutton
    MsgBox(0, "GUI Event", "You pressed OK!")
    ; here I process SQLite data which will determine which controls needs to be built in the child GUI below
    ; this has been simplified here
    Local $gui2 = GUICreate("second GUI", 400, 300, -1, -1, -1, -1, $mainwindow)
    Local $inp = GUICtrlCreateInput("your input", 100, 100, 200, 20)
    Local $but = GUICtrlCreateButton("OK (2)", 170, 200, 60, 25)
    GUICtrlSetOnEvent($but, "OKButton2")
if @error Then ConsoleWrite('error is set to ' & @error & @LF)
    ; function registered without error, so it should work, no?
    GUISwitch($gui2)
    GUISetState(@SW_SHOW)
    $notdone = 1
ConsoleWrite('Enter loop ')
    while $notdone = 1
        ; how should I wait for event(s)?
        Sleep(200)
ConsoleWrite('.')
    WEnd
ConsoleWrite(' end of loop' & @LF)

    ; perform more tasks with user input data
    ConsoleWrite($instr & @lf)
EndFunc


Func OKButton2()
    ; we don't even get there. Why?
    ; do something really useful here with user data...
    $instr = GUICtrlRead($inp)
ConsoleWrite('Input read is ' & $instr & @lf)
    $notdone = 0
ConsoleWrite('$notdone set to 0' & @lf)
EndFunc


Func CLOSEClicked()
  ;Note: at this point @GUI_CTRLID would equal $GUI_EVENT_CLOSE,
  ;@GUI_WINHANDLE will be either $mainwindow or $dummywindow
  If @GUI_WINHANDLE = $mainwindow Then 
    MsgBox(0, "GUI Event", "You clicked CLOSE in the main window! Exiting...")
    Exit
  EndIf 
EndFunc

This comes from the help file with additional child window defined during one OnEvent treatment for the main GUI. (Yes, I know, it's dirty).

Thank you for your help.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

try this code:

#include <GUIConstantsEx.au3>

Opt("GuiOnEventMode", 1)  ; Change to OnEvent mode 
$mainwindow = GUICreate("Hello World", 200, 100)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")
GUICtrlCreateLabel("Hello world! How are you?", 30, 10)
$okbutton = GUICtrlCreateButton("OK", 70, 50, 60)
GUICtrlSetOnEvent($okbutton, "OKButton")

$gui2 = GUICreate("second GUI", 400, 300, -1, -1, -1, -1, $mainwindow)
$inp = GUICtrlCreateInput("your input", 100, 100, 200, 20)
$but = GUICtrlCreateButton("OK (2)", 170, 200, 60, 25)
;GUICtrlSetOnEvent($but, "OKButton2")

GuiSetState(@sw_show, $mainwindow)

While 1
  Sleep(1000)  ; Idle around
WEnd

Global $instr, $notdone
Global $okbutton, $but, $inp

Func OKButton()
    ;Note: at this point @GUI_CTRLID would equal $okbutton
    MsgBox(0, "GUI Event", "You pressed OK!")
    ; here I process SQLite data which will determine which controls needs to be built in the child GUI below
    ; this has been simplified here
if @error Then ConsoleWrite('error is set to ' & @error & @LF)
    ; function registered without error, so it should work, no?
    Opt("GuiOnEventMode", 0)
    GuiSetState(@sw_show, $gui2)
    $notdone = 1
ConsoleWrite('Enter loop ')
    while $notdone = 1
        ; how should I wait for event(s)?
        if GUIGetMsg() = $but then 
        $instr = ""
        OKButton2()
        $notdone = 0
        endif
        Sleep(200)
ConsoleWrite('.')
    WEnd
    Opt("GuiOnEventMode", 1)
ConsoleWrite(' end of loop' & @LF)

    ; perform more tasks with user input data
    ConsoleWrite($instr & @lf)
EndFunc


Func OKButton2()
    ; we don't even get there. Why?
    ; do something really useful here with user data...
    $instr = GUICtrlRead($inp)
ConsoleWrite('Input read is ' & $instr & @lf)
    ;$notdone = 0
ConsoleWrite('$notdone set to 0' & @lf)
EndFunc


Func CLOSEClicked()
  ;Note: at this point @GUI_CTRLID would equal $GUI_EVENT_CLOSE,
  ;@GUI_WINHANDLE will be either $mainwindow or $dummywindow
  If @GUI_WINHANDLE = $mainwindow Then 
    MsgBox(0, "GUI Event", "You clicked CLOSE in the main window! Exiting...")
    Exit
    endif
EndFunc
Link to comment
Share on other sites

Help-file says "When the function call is completed the main script is resumed"... in the original source in "Func OKButton()" you're stuck in a loop, the function does not return and thus the next event in the queue will not be executed. Try something like this:

#include <GUIConstantsEx.au3>

Global $instr, $notdone
Global $okbutton, $but, $inp

Global $bSubLoop

Opt("GUIOnEventMode", 1) ; Change to OnEvent mode
$mainwindow = GUICreate("Hello World", 200, 100)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")
GUICtrlCreateLabel("Hello world! How are you?", 30, 10)
$okbutton = GUICtrlCreateButton("OK", 70, 50, 60)
GUICtrlSetOnEvent($okbutton, "OKButton")

$dummywindow = GUICreate("Dummy window for testing ", 200, 100)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")

GUISwitch($mainwindow)
GUISetState(@SW_SHOW)

While 1
    Sleep(10) ; Idle around

    If $bSubLoop = True Then
        $bSubLoop = False
        ;Note: at this point @GUI_CTRLID would equal $okbutton
        MsgBox(0, "GUI Event", "You pressed OK!")
        ; here I process SQLite data which will determine which controls needs to be built in the child GUI below
        ; this has been simplified here
        Local $gui2 = GUICreate("second GUI", 400, 300, -1, -1, -1, -1, $mainwindow)
        Local $inp = GUICtrlCreateInput("your input", 100, 100, 200, 20)
        Local $but = GUICtrlCreateButton("OK (2)", 170, 200, 60, 25)
        GUICtrlSetOnEvent($but, "OKButton2")
        If @error Then ConsoleWrite('error is set to ' & @error & @LF)
        ; function registered without error, so it should work, no?
        GUISwitch($gui2)
        GUISetState(@SW_SHOW)
        $notdone = 1
        ConsoleWrite('Enter loop ')
        While $notdone = 1
            ; how should I wait for event(s)?
            Sleep(200)
            ConsoleWrite('.')
        WEnd
        ConsoleWrite(' end of loop' & @LF)
        GUIDelete($gui2)
        ; perform more tasks with user input data
        ConsoleWrite($instr & @LF)
    EndIf

WEnd

Func OKButton()
    $bSubLoop = True
EndFunc   ;==>OKButton


Func OKButton2()
    ; we don't even get there. Why?
    ; do something really useful here with user data...
    $instr = GUICtrlRead($inp)
    ConsoleWrite('Input read is ' & $instr & @LF)
    $notdone = 0
    ConsoleWrite('$notdone set to 0' & @LF)
EndFunc   ;==>OKButton2


Func CLOSEClicked()
    ;Note: at this point @GUI_CTRLID would equal $GUI_EVENT_CLOSE,
    ;@GUI_WINHANDLE will be either $mainwindow or $dummywindow
    If @GUI_WinHandle = $mainwindow Then
        MsgBox(0, "GUI Event", "You clicked CLOSE in the main window! Exiting...")
        Exit
    EndIf
EndFunc   ;==>CLOSEClicked
Link to comment
Share on other sites

Hi andygo,

It works fine the way you did.

But remember that I only know which controls to put in the child window when I've done very significant processing in the first event. It is impossible to build the child window at the outer (global) scope: it has to be determined on the fly. I will have to do the same kind of "variable" child, which will have up to hundreds of controls (mostly arrays of chekboxes/radios). Each run will have a different layout/composition/labels, ...

If I leave the $GUI2 declaration inside the function, I get a strange bug where $inp is seen as not declared (but it is a global !!!)

BTW there was a mistake in the code example: both $inp and $but shouldn't be preceeded by Local.

Enter loop ...........D:\XL Equit\AutoMAT\Test\bug.au3 (64) : ==> Variable used without being declared.:

$instr = GUICtrlRead($inp)

$instr = GUICtrlRead(^ ERROR

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

Help-file says "When the function call is completed the main script is resumed"... in the original source in "Func OKButton()" you're stuck in a loop, the function does not return and thus the next event in the queue will not be executed. Try something like this:

Well, I was erroneously thinking that ther could be a way to "release" the message being processed, so as to be ready to process the next one in the queue. Or a second message queue.

What you suggest is the easy way for a short script. But I'm using AutoIt as a general programming language and my application will use lots of such "on the fly" dynamically built windows. If I have no solution except put all of the relevant code for those controls, this amounts to having a main loop with 250 to 35000 lines of code. I won't go there!

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

Well... thats the limit of the language... declare needed variables as Global and put the working part in functions for better readability... that's how I've done it with SMF... which currently consits of 10.843 lines of code even without the includes...

#include <GUIConstantsEx.au3>

Global $instr, $notdone
Global $okbutton, $but, $inp

Global $bSubLoop

Global $inp

Opt("GUIOnEventMode", 1) ; Change to OnEvent mode
$mainwindow = GUICreate("Hello World", 200, 100)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")
GUICtrlCreateLabel("Hello world! How are you?", 30, 10)
$okbutton = GUICtrlCreateButton("OK", 70, 50, 60)
GUICtrlSetOnEvent($okbutton, "OKButton")

$dummywindow = GUICreate("Dummy window for testing ", 200, 100)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")

GUISwitch($mainwindow)
GUISetState(@SW_SHOW)

While 1
    Sleep(10) ; Idle around

    If $bSubLoop = True Then
        $bSubLoop = False
        SubFunc1()
    EndIf

WEnd

Func OKButton()
    $bSubLoop = True
EndFunc   ;==>OKButton


Func OKButton2()
    ; we don't even get there. Why?
    ; do something really useful here with user data...
    $instr = GUICtrlRead($inp)
    ConsoleWrite('Input read is ' & $instr & @LF)
    $notdone = 0
    ConsoleWrite('$notdone set to 0' & @LF)
EndFunc   ;==>OKButton2


Func CLOSEClicked()
    ;Note: at this point @GUI_CTRLID would equal $GUI_EVENT_CLOSE,
    ;@GUI_WINHANDLE will be either $mainwindow or $dummywindow
    If @GUI_WinHandle = $mainwindow Then
        MsgBox(0, "GUI Event", "You clicked CLOSE in the main window! Exiting...")
        Exit
    EndIf
EndFunc   ;==>CLOSEClicked

Func SubFunc1()
    ;Note: at this point @GUI_CTRLID would equal $okbutton
    MsgBox(0, "GUI Event", "You pressed OK!")
    ; here I process SQLite data which will determine which controls needs to be built in the child GUI below
    ; this has been simplified here
    Local $gui2 = GUICreate("second GUI", 400, 300, -1, -1, -1, -1, $mainwindow)
    $inp = GUICtrlCreateInput("your input", 100, 100, 200, 20)
    Local $but = GUICtrlCreateButton("OK (2)", 170, 200, 60, 25)
    GUICtrlSetOnEvent($but, "OKButton2")
    If @error Then ConsoleWrite('error is set to ' & @error & @LF)
    ; function registered without error, so it should work, no?
    GUISwitch($gui2)
    GUISetState(@SW_SHOW)
    $notdone = 1
    ConsoleWrite('Enter loop ')
    While $notdone = 1
        ; how should I wait for event(s)?
        Sleep(200)
        ConsoleWrite('.')
    WEnd
    ConsoleWrite(' end of loop' & @LF)
    GUIDelete($gui2)
    ; perform more tasks with user input data
    ConsoleWrite($instr & @LF)

EndFunc   ;==>SubFunc1

Edit: Corrected cut&paste error in script

Edited by KaFu
Link to comment
Share on other sites

Hi andygo,

It works fine the way you did.

But remember that I only know which controls to put in the child window when I've done very significant processing in the first event. It is impossible to build the child window at the outer (global) scope: it has to be determined on the fly. I will have to do the same kind of "variable" child, which will have up to hundreds of controls (mostly arrays of chekboxes/radios). Each run will have a different layout/composition/labels, ...

If I leave the $GUI2 declaration inside the function, I get a strange bug where $inp is seen as not declared (but it is a global !!!)

BTW there was a mistake in the code example: both $inp and $but shouldn't be preceeded by Local.

Enter loop ...........D:\XL Equit\AutoMAT\Test\bug.au3 (64) : ==> Variable used without being declared.:

$instr = GUICtrlRead($inp)

$instr = GUICtrlRead(^ ERROR

ok then try this one:

#include <GUIConstantsEx.au3>

Opt("GUIOnEventMode", 1)  ; Change to OnEvent mode 
$mainwindow = GUICreate("Hello World", 200, 100)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")
GUICtrlCreateLabel("Hello world! How are you?", 30, 10)
$okbutton = GUICtrlCreateButton("OK", 70, 50, 60)
GUICtrlSetOnEvent($okbutton, "OKButton")

$dummywindow = GUICreate("Dummy window for testing ", 200, 100)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")

GUISwitch($mainwindow)
GUISetState(@SW_SHOW)

While 1
  Sleep(1000)  ; Idle around
WEnd

Global $instr, $notdone
Global $okbutton, $but, $inp

Func OKButton()
    ;Note: at this point @GUI_CTRLID would equal $okbutton
    MsgBox(0, "GUI Event", "You pressed OK!")
    ; here I process SQLite data which will determine which controls needs to be built in the child GUI below
    ; this has been simplified here
    Local $gui2 = GUICreate("second GUI", 400, 300, -1, -1, -1, -1, $mainwindow)
    Local $inp = GUICtrlCreateInput("your input", 100, 100, 200, 20)
    Local $but = GUICtrlCreateButton("OK (2)", 170, 200, 60, 25)
    ;GUICtrlSetOnEvent($but, "OKButton2")
if @error Then ConsoleWrite('error is set to ' & @error & @LF)
    ; function registered without error, so it should work, no?
    ;GUISwitch($gui2)
    GUISetState(@SW_SHOW, $gui2)
    $notdone = 1
ConsoleWrite('Enter loop ')
    while $notdone = 1
        ; how should I wait for event(s)?
        Opt("GUIOnEventMode", 0) 
        if GUIGetMsg() = $but then 
        $instr = GUICtrlRead($inp)
        ConsoleWrite('Input read is ' & $instr & @lf)
        $notdone = 0
        ConsoleWrite('$notdone set to 0' & @lf)
        Opt("GUIOnEventMode", 1)
        GUISetState(@SW_HIDE, $gui2)
        endif
        Sleep(200)
ConsoleWrite('.')
    WEnd
ConsoleWrite(' end of loop' & @LF)

    ; perform more tasks with user input data
    ConsoleWrite($instr & @lf)
EndFunc


Func CLOSEClicked()
  ;Note: at this point @GUI_CTRLID would equal $GUI_EVENT_CLOSE,
  ;@GUI_WINHANDLE will be either $mainwindow or $dummywindow
  If @GUI_WINHANDLE = $mainwindow Then 
    MsgBox(0, "GUI Event", "You clicked CLOSE in the main window! Exiting...")
    Exit
  EndIf 
EndFunc
Link to comment
Share on other sites

ok then try this one:

I can't see why a previous try along the same line didn't work. I probably did a mistake somewhere.

Nonetheless, it's probably the way to go for my needs.

Something bothers me anyway: this global variables that gets flagged as undeclared... I'll dig into this some time and probably report elsewhere.

Thank you for your help.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with 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...