Sign in to follow this  
Followers 0
this-is-me

Gui unresponsive...

20 posts in this topic

#1 ·  Posted (edited)

If you click the close button on this gui, it takes about 3 seconds to go away... If any controls are added, it takes the same time to respond to the control as well. Is this a bug, or did I do something wrong?

#include <GUIConstants.au3>
Opt("Wintitlematchmode", 4)

Opt("GUICoordMode", 1)
Opt("GUIResizeMode", $GUI_DOCKALL)
$ttl = "Testing"

$guihndl = GuiCreate($ttl, 395, 36, -1, -1, -1, 0x00000080)
GUISetBkColor(0xFFFFFF)

AdlibEnable("adlibs")
GUISetState(@SW_SHOW)

func adlibs()
   $msg = GUIGetMsg(1)
   Select
      Case $msg[0] = $GUI_EVENT_CLOSE
         Exit
      Case $msg[0] = 0
        ;;;
   EndSelect
EndFunc

sleep(50000)
Edited by this-is-me

Who else would I be?

Share this post


Link to post
Share on other sites



Well, your code does work, but I need to have other functions running while the gui is open. Is there any workaround to have adlib work in this situation? I have to have the GUI open _at_all_times_ but I also need to be able to have a good response when clicking buttons. Is the guimsg function automatically inserting a pause, since Jon said that he is keeping CPU usage to a minimum when using while loops? If so, can this be disabled by a call to Opt?


Who else would I be?

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

That helps make the code simpler, but since GUICtrlSetOnEvent is controlled by guimsg(), then the same slow timing applies.

Edited by this-is-me

Who else would I be?

Share this post


Link to post
Share on other sites

Run this and then come back and explain what your problem is exactly:

#include <GuiConstants.au3>

$hwnd = GUICreate("Blah", 100, 100)
GUISetState(@SW_SHOWNORMAL)

While WinExists($hWnd)
    $msg = GUIGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then GuiDelete()
    MsgBox(4096, "", "Annoying, aren't I?")
WEnd

Share this post


Link to post
Share on other sites

I mean that I already have a script that works with functions in sequence as they need to be called. The gui I am creating needs to be open all the time and the functions I am calling cannot be called inside a while loop and cannot be called multiple times. They are layed out in a time line. I need the gui to have a few checkboxes that will modify the already-running code if checked. I only need the gui to respond if I ask it to. For instance (modified example of above):

#include <GUIConstants.au3>
Opt("Wintitlematchmode", 4)

Opt("GUICoordMode", 1)
Opt("GUIResizeMode", $GUI_DOCKALL)
$ttl = "Testing"

$guihndl = GuiCreate($ttl, 395, 36, -1, -1, -1, 0x00000080)
$checkbox = GUICtrlCreateCheckbox("Test", 0, 0, 50, 16)
GUISetBkColor(0xFFFFFF)

AdlibEnable("adlibs")
GUISetState(@SW_SHOW)

MsgBox(0,"","Testing")
Sleep(5000)
MsgBox(0,"","Testing")
Sleep(5000)
MsgBox(0,"","Testing")
Sleep(5000)

func adlibs()
  $msg = GUIGetMsg(1)
  Select
      Case $msg[0] = $GUI_EVENT_CLOSE
         Exit
      Case $msg[0] = 0
        ;;;
      Case $msg[0] = $checkbox
         WinMove("handle=" & $guihndl, "", 0, 0)
  EndSelect
EndFunc

If you substitute the msgboxes for the code I need to execute and the checkbox for code that needs to run every once in a while, then you have the problem I now face. I cannot make adjustments to my main functions to allow this gui to interact in anything but a rarely needed basis.


Who else would I be?

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

Thats very simple.

#include <GuiConstants.au3>

$hwnd = GUICreate("Blah", 100, 100)
GUISetState(@SW_SHOWNORMAL)

Global $bEvent1 = 0, $bEvent2 = 0
Global $hTimer = TimerInit()

While WinExists($hWnd)
    $msg = GUIGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then GuiDelete()
        
    If Not $bEvent1 And TimerStop($hTimer) > 5000 Then Event1()
    If Not $bEvent2 And TimerStop($hTimer) > 10000 Then Event2()
WEnd

Func Event1()
    MsgBox(4096, "", "Event1")
    $bEvent1 = 1
EndFunc; Event1()

Func Event2()
    MsgBox(4096, "", "Event2")
    $bEvent2 = 1
EndFunc; Event2()

If it's critical that Event2() start after an exact number of seconds after completion of Event1(), then recycle $hTimer by resetting it in Event1().

Edit: Fixed sentence clarity.

Edited by Valik

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

Thanks, but we are talking about modifying a 2800 line script (optimized, no extraneous lines) to allow it to work in this way, not to mention the fact that while each event() is running, the gui functions are totally unresponsive. I need the gui events to respond WHILE the main script is still running. Any workarounds here? I am not begging or whining, I just don't see yet how it is possible.

Edited by this-is-me

Who else would I be?

Share this post


Link to post
Share on other sites

If this below doesn't help, then you're going to need multi-threading (Which we don't have).

#include <GuiConstants.au3>

$hwnd = GUICreate("Blah", 100, 100)
GUISetState(@SW_SHOWNORMAL)

Global $bEvent1 = 0, $bEvent2 = 0
Global $hTimer = TimerInit()

While WinExists($hWnd)
    $msg = GUIGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then GuiDelete()
        
    If Not $bEvent1 And TimerStop($hTimer) > 5000 Then AdlibEnable("Event1")
    If Not $bEvent2 And TimerStop($hTimer) > 10000 Then AdlibEnable("Event2")
WEnd

Func Event1()
    MsgBox(4096, "", "Event1")
    $bEvent1 = 1
    AdlibDisable()
EndFunc; Event1()

Func Event2()
    MsgBox(4096, "", "Event2")
    $bEvent2 = 1
    AdlibDisable()
EndFunc; Event2()

Share this post


Link to post
Share on other sites

:) Valik just jumped out of the box and ran away...

Unfortunately, I already have a (working) adlib section that I still need to have going (which by itself is 140 lines long). The gui stuff was going to be an addition to that section.

@Jon, any simple way to remove the pause? Something like an Opt("GuiMsgIdle", 0) ?


Who else would I be?

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

Okay, this is getting old. I keep shooting in the dark and just clipping the target. Show me your AdLib section and I can tell you if I have another solution or not.

Edit: Oh, and the pause is 10 ms, that is nothing more than anti-100% CPU.

Edited by Valik

Share this post


Link to post
Share on other sites

:) Valik just jumped out of the box and ran away...

Unfortunately, I already have a (working) adlib section that I still need to have going (which by itself is 140 lines long). The gui stuff was going to be an addition to that section.

@Jon, any simple way to remove the pause? Something like an Opt("GuiMsgIdle", 0) ?

The pause 10ms which is nothing and that's ONLY if the gui has no messages waiting, if there are any messages waiting (which there definately will be unless you poll it constantly) then the pause is 0.

Share this post


Link to post
Share on other sites

The pause 10ms which is nothing and that's ONLY if the gui has no messages waiting, if there are any messages waiting (which there definately will be unless you poll it constantly) then the pause is 0.

One thing to remember as well, currently the mouse movement messages are sent so there may be a large number (well at most 16) waiting in the message queue so if in your adlib you are only doing a single GuiGetMsg then you won't be getting all the messages just the first (and so any button click message could be held up). So try reading GuiGetMsg a number of times (or until it is 0) before moving on.

Actually, this reminds me that I need to add an option to filter out the mouse messages unless they are asked for.

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

OK. Here is the adlib:

removed.
Edited by this-is-me

Who else would I be?

Share this post


Link to post
Share on other sites

#15 ·  Posted (edited)

Okay, I see no loops or anything like that to complicate things, so why don't you place the timer and function calls in that AdLib? Using TimerInit()/TimerDiff() won't cause the AdLib to hang (Except during the actual execution of the function). This will minimize the GUI's latency as much as possible (Blocking-like or functions that take a few moments to complete will make it less responsive).

Basically, something like this:

#include <GuiConstants.au3>

$hwnd = GUICreate("Blah", 100, 100)
GUISetState(@SW_SHOWNORMAL)

Global $bEvent1 = 0, $bEvent2 = 0
Global $hTimer = TimerInit()

While WinExists($hWnd)
    $msg = GUIGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then GuiDelete()
WEnd

Func Event1()
    MsgBox(4096, "", "Event1")
    $bEvent1 = 1
EndFunc; Event1()

Func Event2()
    MsgBox(4096, "", "Event2")
    $bEvent2 = 1
EndFunc; Event2()

Func adlib()
    If Not $bEvent1 And TimerStop($hTimer) > 5000 Then Event1()
    If Not $bEvent2 And TimerStop($hTimer) > 10000 Then Event2()

    If WinExists("classname=#32770", "Deleted a total") Then
        If $delcaught = 0 Then
; Rest of code snipped
EndFunc
Edited by Valik

Share this post


Link to post
Share on other sites

Think I may add multiple adlib support with different timers, then you could run GuiGetMsg() from one on a high refresh rate. Or maybe have the OnEvent stuff seperate from GuiGetMsg(), but that would mean either using the msg mode OR the event mode as synchronization would be a nightmare otherwise.

Share this post


Link to post
Share on other sites

#17 ·  Posted (edited)

I think multiple adlibs would be wonderful especially in my situation. I also think multiple adlibs could be very confusing for noobs. I forsee many good things coming from multiple adlibs in the right hands (I'm sure mine aren't included).

Edited by this-is-me

Who else would I be?

Share this post


Link to post
Share on other sites

I have found a workaround that may work in some circumstances:

AdlibEnable("adlibfunc", 1)

Not that it makes a diff, but it will help in my situation.


Who else would I be?

Share this post


Link to post
Share on other sites

Think I may add multiple adlib support with different timers, then you could run GuiGetMsg() from one on a high refresh rate.  Or maybe have the OnEvent stuff seperate from GuiGetMsg(), but that would mean either using the msg mode OR the event mode as synchronization would be a nightmare otherwise.

<{POST_SNAPBACK}>

Jon, when/if you allow internal events (Closing/minimizing, et all) to be registered with functions, then you could re-add GuiWaitClose() as events would handle all messages. Users could also have the option to use their own loop to keep the GUI active.

Examples:

GuiCreate()
GuiCtrlCreate()
GuiCtrlSetOnEvent()

GuiCtrlCreate()
GuiCtrlSetOnEvent()

GuiSetOnEvent($GUI_EVENT_CLOSE, ...)

GuiWaitClose()

Func OnSomeEvent()
EndFunc

; More OnEvents()

Or:

Examples:

$guiHwnd = GuiCreate()
GuiCtrlCreate()
GuiCtrlSetOnEvent()

GuiCtrlCreate()
GuiCtrlSetOnEvent()

GuiSetOnEvent($GUI_EVENT_CLOSE, ...)

While WinExists($guiHWnd)
    DoStuff()
WEnd

Func OnSomeEvent()
EndFunc

; More OnEvents()

Func DoStuff()
  ; Do stuff, something that maybe could be in an AdLib could go here
Endfunc

Those are two pseudo-examples of what code might look like if internal events could also be placed in the OnEvent system.

Share this post


Link to post
Share on other sites

@Valik, once again you voice the hopes and aspirations of those lowly coders who can't seem to get their acts together like me.

@Jon, Please give more consideration to Valik's idea than that of multiple adlibs. I also say keep the current functions of GuiSetState, so that the gui could remain open at all times.


Who else would I be?

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  
Followers 0