Что нового

Отключения паузы выполнения скрипта при трей меню

VadimKHL

Новичок
Сообщения
155
Репутация
0
Народ, помогите.
Не могу отключить остановку скрипта, когда нажимаешь на трей иконку.
Это опция почему то не работает!
Код:
Opt("TrayAutoPause", 0)   ; Меню трея не останавливает работу скрипта.


Как избавиться от остановки?
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
Всё работает
 
Автор
V

VadimKHL

Новичок
Сообщения
155
Репутация
0
Никуя не работает!
Если не было проблемы, не создавал тему!
Сообщение автоматически объединено:

В чем такая увереность?
Сообщение автоматически объединено:

Щас сделаю видео...
Сообщение автоматически объединено:

Не поленился, сходил видео сделал:


И в каком месте оно работает?
Прошу дать объективное объяснение данного ответа.
 
Последнее редактирование:

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
Щас сделаю видео...
Это не автопауза. Это прерывание работы скрипта для обработки всплывающего меню.

Запустите этот скрипт из SciTE и кликните ПКМ по окну или по иконке в трее. При появлении меню вывод в консоль SciTE будет остановлен. Даже AdlibRegister не работает.
Код:
AdlibRegister("Plus")

HotKeySet("{ESC}", "Quit")

Opt("TrayAutoPause", 0)

GUICreate("")
GUICtrlCreateMenuItem("Test", GUICtrlCreateContextMenu())
GUISetState()

While Sleep(111)
  ConsoleWrite(".")
WEnd

Func Quit()
  Exit
EndFunc

Func Plus()
  ConsoleWrite("+")
EndFunc
 
Последнее редактирование:
Автор
V

VadimKHL

Новичок
Сообщения
155
Репутация
0
Это не автопауза. Это прерывание работы скрипта для обработки всплывающего меню.

Тогда что делает эта автопауза которая управляется через Opt("TrayAutoPause", X) ?

Запустите этот скрипт из SciTE и кликните ПКМ по окну или по иконке в трее. При появлении меню вывод в консоль SciTE будет остановлен. Даже AdlibRegister не работает.

Как тогда не останавливать скрипт при трей меню?
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
что делает эта автопауза которая управляется через Opt("TrayAutoPause", X) ?
Указывает останавливать ли работу скрипта самим нажатием на иконку в трее.
AutoIt так устроен что не может работать в несколько потоков одновременно, но есть обходные пути, хоть и не без побочных эффектов.

Как тогда не останавливать скрипт при трей меню?
Использовать таймеры для обновления информации (не рекомендуется сильно нагружать функцию таймера)...
Код:
#include <Timers.au3>

HotKeySet('{ESC}', '_Quit')

Opt('TrayAutoPause', 0)
Opt('TrayMenuMode', 3)

$iProgress = 0
$iLoading_TrayItem = TrayCreateItem('Loading: 0')
$iExit_TrayItem = TrayCreateItem('Exit')

TraySetClick(16)
TraySetState(1)

_Timer_SetTimer(0, 100, '_Update')

While 1
    Switch TrayGetMsg()
        Case $iExit_TrayItem
            _Quit()
    EndSwitch
WEnd

Func _Quit()
    Exit
EndFunc

Func _Update($hWnd, $iMsg, $iIDTimer, $iTime)
    $iProgress += 0.1
  
    If $iProgress > 100 Then
        $iProgress = 0
    EndIf
  
    TrayItemSetText($iLoading_TrayItem, 'Loading: ' & Round($iProgress, 2) & '%')
EndFunc
 
Автор
V

VadimKHL

Новичок
Сообщения
155
Репутация
0
Код:
#include <Timers.au3>

HotKeySet('{ESC}', '_Quit')

Opt('TrayAutoPause', 0)
Opt('TrayMenuMode', 3)

GUICreate("Test", 300, 300, -1, -1)
GUISetState(@SW_SHOW)
Global $Label = GUICtrlCreateLabel("", 50, 50, 100, 15)
Global $Label2 = GUICtrlCreateLabel("", 50, 65, 100, 15)

$iProgress = 0
$iProgress2 = 0
$iLoading_TrayItem = TrayCreateItem('Loading: 0')
$iExit_TrayItem = TrayCreateItem('Exit')

TraySetClick(16)
TraySetState(1)

_Timer_SetTimer(0, 100, '_Update')

While 1
    Switch TrayGetMsg()
        Case $iExit_TrayItem
            _Quit()
    EndSwitch

    $iProgress2 += 0.1

    If $iProgress2 > 100 Then
        $iProgress2 = 0
    EndIf

    GUICtrlSetData($Label, 'Loading: ' & Round($iProgress2, 2) & '%')
    sleep(100)
WEnd

Func _Quit()
    Exit
EndFunc

Func _Update($hWnd, $iMsg, $iIDTimer, $iTime)
    $iProgress += 0.1

    If $iProgress > 100 Then
        $iProgress = 0
    EndIf

    TrayItemSetText($iLoading_TrayItem, 'Loading: ' & Round($iProgress, 2) & '%')
    GUICtrlSetData($Label2, 'Loading: ' & Round($iProgress, 2) & '%')

EndFunc


Да, действительно таймеры срабатывают!
И только они срабатывают, больше никаких средств?
Сообщение автоматически объединено:

Использовать таймеры для обновления информации (не рекомендуется сильно нагружать функцию таймера)...

А что значит сильно не нагружать?
Сообщение автоматически объединено:

Есть еще один вариант, режим MODELESS.
Гляньте пример, скрипт не останавливается:
Код:
#include <Timers.au3>
#include <WinAPI.au3>

HotKeySet('{ESC}', '_Quit')

Opt('TrayAutoPause', 0)
Opt('TrayMenuMode', 3)

GUICreate("Test", 300, 300, -1, -1)
GUISetState(@SW_SHOW)
Global $Label = GUICtrlCreateLabel("", 50, 50, 100, 15)

$iProgress = 0
$iLoading_TrayItem = TrayCreateItem('Loading: 0')
$iExit_TrayItem = TrayCreateItem('Exit')

TraySetClick(16)
TraySetState(1)

; Настройки Tray меню при помощи WinAPI.
; https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setmenuinfo
Global Const $MIM_APPLYTOSUBMENUS = 0x80000000
Global Const $MIM_STYLE = 0x00000010
Global Const $MNS_AUTODISMISS = 0x10000000
Global Const $MNS_MODELESS = 0x40000000
; Общие установки для всего меню.
Local $hMenu = TrayItemGetHandle(0)
Local $tMenuInfo = DllStructCreate($tagMENUINFO)
DllStructSetData($tMenuInfo, 1, DllStructGetSize($tMenuInfo))
; Записать параметры dwStyle.
DllStructSetData($tMenuInfo, 2, BitOR($MIM_APPLYTOSUBMENUS, $MIM_STYLE))
; Автоматическое закрытие меню через ~10 сек. Режим MODELESS.
DllStructSetData($tMenuInfo, 3, BitOR($MNS_AUTODISMISS, $MNS_MODELESS))
DllCall("user32.dll", "int", "SetMenuInfo", "hwnd", $hMenu, "struct*", $tMenuInfo)

While 1
    Switch TrayGetMsg()
        Case $iExit_TrayItem
            _Quit()
    EndSwitch

    $iProgress += 0.1

    If $iProgress > 100 Then
        $iProgress = 0
    EndIf

    TrayItemSetText($iLoading_TrayItem, 'Loading: ' & Round($iProgress, 2) & '%')
    GUICtrlSetData($Label, 'Loading: ' & Round($iProgress, 2) & '%')

    sleep(100)
WEnd

Func _Quit()
    Exit
EndFunc

Сообщение автоматически объединено:

Но в этом режиме есть один косяк, позже сниму видео в чем проблема...
 
Последнее редактирование:

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
что значит сильно не нагружать?
Любая callback-функция должна возвращать как можно быстрее, иначе могут быть непредвиденные последствия.
Например не желательно использовать MsgBox внутри этой функции.
 
Автор
V

VadimKHL

Новичок
Сообщения
155
Репутация
0
Есть еще один вариант, режим MODELESS.
Гляньте пример, скрипт не останавливается:
Вот в общем в чем проблема режима MODELESS:

Саб меню трея работают через раз. Основные меню работают исправно.
Вариант рабочий, что бы не останавливать скрипт, но только для меню без саб меню.
Нужно тогда делать на таймерах.
Сообщение автоматически объединено:

Например не желательно использовать MsgBox внутри этой функции.

А как быть, в таком случае:
Код:
#include <Timers.au3>

HotKeySet('{ESC}', '_Quit')

Opt('TrayAutoPause', 0)
Opt('TrayMenuMode', 3)

$iProgress = 0
$iLoading_TrayItem = TrayCreateItem('Loading: 0')
$iExit_TrayItem = TrayCreateItem('Exit')

TraySetClick(16)
TraySetState(1)

_Timer_SetTimer(0, 100, '_Update')

While 1
    Switch TrayGetMsg()
        Case $iExit_TrayItem
            _Quit()
    EndSwitch
WEnd

Func _Quit()
    Exit
EndFunc

Func _Update($hWnd, $iMsg, $iIDTimer, $iTime)
    $iProgress += 0.1

    If $iProgress > 100 Then
        $iProgress = 0
    EndIf

    TrayItemSetText($iLoading_TrayItem, 'Loading: ' & Round($iProgress, 2) & '%')

    ; Эта функция имеет неизвестное время выполнения, каждый раз разное.
    ; К примеру, это выполняется дольше, чем частота вызова по таймеру.
    Sleep(150)
    ; Это приводит к зависанию.
EndFunc


Как сделать, что бы не было зависаний от использования таймеров?
В справке указано что нельзя убивать таймеры в самой функции таймера:
Inside the callback function, the _Timer_KillAllTimers() or _Timer_KillTimer() referencing the current $iIDTimer must not be used.

Как быть тогда в такой ситуации?
 
Последнее редактирование:

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Как сделать, что бы не было зависаний от использования таймеров?
Не использовать паузу в функции таймера, я же выше писал об этом.
Это полезно для обновления информации, и всё, во всех остальных случаях нужно обрабатывать события помещая их в очередь (массив к примеру).
 
Автор
V

VadimKHL

Новичок
Сообщения
155
Репутация
0
Не использовать паузу в функции таймера, я же выше писал об этом.
А это не пауза. Это неизвестное время выполнения кода, чтения данных по COM порту.

Это полезно для обновления информации, и всё, во всех остальных случаях нужно обрабатывать события помещая их в очередь (массив к примеру).
Мне незачем обновлять информацию, пока не выполню пункт выше. Как помещать события в очередь?
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Это неизвестное время выполнения кода, чтения данных по COM порту
В этом случае лучше тогда вынести часть чтения данных в отдельный скрипт.
Можно ещё попробовать так:
Код:
#include <Timers.au3>

HotKeySet('{ESC}', '_Quit')

Opt('TrayAutoPause', 0)
Opt('TrayMenuMode', 3)

$bUpdate = True
$iProgress = 0
$iLoading_TrayItem = TrayCreateItem('Loading: 0')
$iExit_TrayItem = TrayCreateItem('Exit')

TraySetClick(16)
TraySetState(1)

$iTimer = _Timer_SetTimer(0, 100, '_Update')

While 1
    Switch TrayGetMsg()
        Case $iExit_TrayItem
            _Quit()
    EndSwitch
WEnd

Func _Quit()
    Exit
EndFunc

Func _Update($hWnd, $iMsg, $iIDTimer, $iTime)
    If $bUpdate Then
        AdlibRegister('_GetData', 10)
    EndIf
EndFunc

Func _GetData()
    $bUpdate = False
    AdlibUnRegister('_GetData')
    
    ; Тут выполняем то что нужно
    ;-------------------------
    $iProgress += 0.1
    
    If $iProgress > 100 Then
        $iProgress = 0
    EndIf
    
    TrayItemSetText($iLoading_TrayItem, 'Loading: ' & Round($iProgress, 2) & '%')
    ;-------------------------
    
    $bUpdate = True
EndFunc
 
Верх