SetTimer( ,0) blocks script.

Issue #67 closed
Winter Laite created an issue

This issue is difficult to troubleshoot. Two test scripts are below. The intent is to rename the MsgBox buttons by using SetTimer.

working keysharp code
#SingleInstance
SetTimer("ChangeButtonNames", -50)
Result := MsgBox("Choose a button:", "Add or Delete", 4)
if (Result == "Yes")
    MsgBox("You chose Add", "Add something")
else
    MsgBox("You chose Delete", "Delete something")

ChangeButtonNames()
{
    if (!WinExist(, "Choose a button:")) {
        return
    }
    ;SetTimer(, 0)
    FileAppend("Got past timer`r`n", "a_timerlog.txt")
    WinActivate()
    ControlSetText("&Add", "Button1")
    ControlSetText("&Delete", "Button2")
}

Note that ‘SetTimer(, 0) is commented out. The timer is running once only because of the '-50’ passed to SetTimer on line 2. Although this does work, it does not address the issue.

non-working keysharp code

Second script, not working. Positive value for line 2, attempt to turn off timer at line 14. Line 15 is never executed.

#SingleInstance
SetTimer("ChangeButtonNames", 50)
Result := MsgBox("Choose a button:", "Add or Delete", 4)
if (Result == "Yes")
    MsgBox("You chose Add", "Add something")
else
    MsgBox("You chose Delete", "Delete something")

ChangeButtonNames()
{
    if (!WinExist(, "Choose a button:")) {
        return
    }
    SetTimer(, 0)
    FileAppend("Got past timer`r`n", "a_timerlog.txt")
    WinActivate()
    ControlSetText("&Add", "Button1")
    ControlSetText("&Delete", "Button2")
}

For reference, the working script taken from the AHK Script Showcase:

#SingleInstance
SetTimer(ChangeButtonNames, 50)
Result := MsgBox("Choose a button:", "Add or Delete", 4)
if (Result == "Yes")
    MsgBox("You chose Add", "Add something")
else
    MsgBox("You chose Delete", "Delete something")

ChangeButtonNames(*)
{
    if (!WinExist("Add or Delete"))
        return  ; Keep waiting.
    SetTimer( , 0)
    WinActivate()
    ControlSetText("&Add", "Button1")
    ControlSetText("&Delete", "Button2")
}

There is a workaround. Is it perhaps necessary in Keysharp to run 'SetTimer(, 0) as the last line of a function?

#SingleInstance

^!u::
{
SetTimer("ChangeButtonNames", 50)
Result := MsgBox("Choose a button:", "Add or Delete", 4)
if (Result == "Yes")
    MsgBox("You chose Add", "Add something")
else
    MsgBox("You chose Delete", "Delete something")
}

ChangeButtonNames()
{
    if (!WinExist(, "Choose a button:")) {
        return
    }

    FileAppend("Got past timer`r`n", "a_timerlog.txt")
    WinActivate()
    ControlSetText("&Add", "Button1")
    ControlSetText("&Delete", "Button2")
    SetTimer(, 0)
}

Comments (9)

  1. Matt Feemster repo owner

    My previous commit somehow missed the file which fixed this. I’ve committed again, please test.

  2. Winter Laite reporter

    Retested workaround and OP. Neither works. No error thrown. It used to work with a negative value for SetTimer, i.e. ‘SetTimer(, -200)’ and no call to ‘SetTimer(, 0)’, but that no longer works either.

  3. Matt Feemster repo owner

    I had inadvertently introduced a bug in MsgBox(). The timer code was fine. I’ve committed a fix, let’s hope it works so please test one last time.

  4. Winter Laite reporter

    This still does not work. The code at the top works again now, but the workaround with ‘SetTimer(, 0)’ still does not work. The following line never executes.

        FileAppend("Got past timer`r`n", "a_timerlog.txt")
    

  5. Matt Feemster repo owner

    All were working except your last workaround. The problem is that the initial SetTimer() call was being done inside of a hotkey, which of course is running in its own thread. Recall that I recently changed the timers to be forms timers instead of threading timers. Apparently you cannot call timer.Start() in a thread other than the main one. So I’ve done that and it works on my end. Please test.

  6. Winter Laite reporter

    Just to make it clear to anyone else who visits this -

    As of September 9, 2022 this script works in AutoHotkey v2.0-beta.7:

    #SingleInstance
    
    ^!u::
    {
    SetTimer(ChangeButtonNames, 50)
    Result := MsgBox("Choose a button:", "Add or Delete", 4)
    if (Result == "Yes")
        MsgBox("You chose Add", "Add something")
    else
        MsgBox("You chose Delete", "Delete something")
    }
    
    ChangeButtonNames(*)
    {
        if (!WinExist(, "Choose a button:")) {
            return
        }
        SetTimer(, 0)
        FileAppend("Got past timer`r`n", "a_timerlog.txt")
        WinActivate()
        ControlSetText("&Add", "Button1")
        ControlSetText("&Delete", "Button2")
    }
    

    The buttons are renamed.

    This script is nearly identical, the changes being quotes around the function called by SetTimer and the removal of the asterisk from the function ChangeButtonNames().

    #SingleInstance
    
    ^!u::
    {
    SetTimer("ChangeButtonNames", 50)
    Result := MsgBox("Choose a button:", "Add or Delete", 4)
    if (Result == "Yes")
        MsgBox("You chose Add", "Add something")
    else
        MsgBox("You chose Delete", "Delete something")
    }
    
    ChangeButtonNames()
    {
        if (!WinExist(, "Choose a button:")) {
            return
        }
        SetTimer(, 0)
        FileAppend("Got past timer`r`n", "a_timerlog.txt")
        WinActivate()
        ControlSetText("&Add", "Button1")
        ControlSetText("&Delete", "Button2")
    }
    

    This Keysharp also changes the button names.

  7. Log in to comment