1 (изменено: wisgest, 2020-03-12 01:37:21)

Тема: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

Рассмотрим пример по включению настройки «Отображать содержимое окна при перетаскивании» подделкой действий пользователя с апплетом Панели управления.
(Это нужно лишь для примера, саму задачу можно решить с помощью

DllCall("SystemParametersInfo"

без всяких мелькающих окон):

Run % "rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,2",,, PID
WinWait Свойства: Экран ahk_pid %PID%
WinGet HWND, ID
ControlClick &Эффекты..., ahk_id %HWND%

WinWait Эффекты
Control Check,, &Отображать содержимое окна при перетаскивании
ControlSend ,, {Enter}

WinWait ahk_id %HWND%
ControlClick ThemePreview1
ControlSend ,, {Enter}

Но ведь вместо rundll32.exe можно вызвать функцию из DLL собственными средствами AHK: раз уж наш сценарий начал выполняться, значит они доступны, а присутствует или нет rundll32.exe в точности не известно. Тем более, что мы выбрали функцию, вызываемую с помощью rundll32.exe лишь для примера. Если при этом вызвать функцию из DLL в отдельном процессе (например AHK-сценарий перезапускает себя с каким-либо ключом), то всё работает так же. Но опять же, если рассматривать общий случай, файл сценария может быть удалён во время его работы, поэтому хотелось бы обойтись одним процессом.

Если заменить первые две строки:

;Run % "rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,2",,, PID
;WinWait Свойства: Экран ahk_pid %PID%
DllCall("shell32.dll\Control_RunDLL" . (A_IsUnicode? "W": "A")
	, "UInt", A_ScriptHwnd ; HWND hwnd // 0 не работает...
	, "Ptr", 0 ; HINSTANCE hInstance
	, "Str", "desk.cpl,,2" ; LPTSTR lpszCmd
	, "UInt", 1) ; nCmdShow
Process Exist
WinWait Свойства: Экран ahk_pid %ErrorLevel%
WinGet HWND, ID
ControlClick &Эффекты..., ahk_id %HWND%

WinWait Эффекты
Control Check,, &Отображать содержимое окна при перетаскивании
ControlSend ,, {Enter}

WinWait ahk_id %HWND%
ControlClick ThemePreview1
ControlSend ,, {Enter}

то переход к следующему действию после DllCall произойдёт только, когда созданное им окно будет закрыто сторонними средствами (например, вручную).

В cправке сказано:

Timers are useful because they run asynchronously, meaning that they will run at the specified frequency (interval) even when the script is waiting for a window, displaying a dialog, or busy with another task

Попробуем действия после DllCall, запустить в отдельном потоке с помощью таймера:

;Run % "rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,2",,, PID
;WinWait Свойства: Экран ahk_pid %PID%
SetTimer Step2, -1
DllCall("shell32.dll\Control_RunDLL" . (A_IsUnicode? "W": "A")
	, "UInt", A_ScriptHwnd ; HWND hwnd // 0 не работает...
	, "Ptr", 0 ; HINSTANCE hInstance
	, "Str", "desk.cpl,,2" ; LPTSTR lpszCmd
	, "UInt", 1) ; nCmdShow
Exit
Step2:
Process Exist
WinWait Свойства: Экран ahk_pid %ErrorLevel%
WinGet HWND, ID
ControlClick &Эффекты..., ahk_id %HWND%

WinWait Эффекты
Control Check,, &Отображать содержимое окна при перетаскивании
ControlSend ,, {Enter}

WinWait ahk_id %HWND%
ControlClick ThemePreview1
ControlSend ,, {Enter}

— в этом случае кнопка «Эффекты» нажимается, поддиалог «Эффекты» открывается и на этом всё. Если его закрыть вручную, то основной диалог уже вручную не закрывается — надо завершать сам сценарий. Ещё можно заметить, что если после  ControlClick вставить MsgBox, то до него дело дойдёт только после закрытия «Эффекты».

Что делать?

+ 2020-03-12

Первончальное название вопроса «Взаимодействие с диалогами, созданными DllCall» не совсем удачно, т.к. подобные случаи возможны и без использования DllCall. Например открываем диалог свойств ярлыка и пытаемся взаимодействовать с ним дальше, открываем поддиалог выбора значка и т.д. — Изменил.

2 (изменено: stealzy, 2017-08-10 19:57:55)

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

Все таки ahk однопоточен, и "асинхронность" работает только? внутри языка.
Ваш пример несправедлив - таймер вызывается раньше DllCall, лучше наоборот засуньте DllCall в таймер.
Ах, да, на Win7 вызывается окно персонализации, контрола Элементы там нет.

файл сценария может быть удалён

Можно на ходу запустить бесфайловый в pipe.

3

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

wisgest пишет:

то переход к следующему действию после DllCall произойдёт только, когда созданное им окно будет закрыто сторонними средствами (например, вручную)

У меня ни на семёрке, ни на десятке такого не происходит, и там, и там открывается окно «Персонализация» и код выполняется дальше. Вы на XP? Пример не очень удачный.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

4 (изменено: wisgest, 2017-08-10 20:56:33)

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

stealzy пишет:

Ах, да, на Win7 вызывается окно персонализации, контрола Элементы там нет.

См. присоединённый архив.

stealzy пишет:

Можно на ходу запустить бесфайловый в pipe.

Не пойдёт, если сценарий скомпилирован в EXE. В этом случае он, конечно, не может быть удалён во время работы, но придётся учитывать большее число случаев — громоздко.

stealzy пишет:

Ваш пример несправедлив - таймер вызывается раньше DllCall, лучше наоборот засуньте DllCall в таймер.

Не совсем понял, но не уверен в этом. Всё таки какое-то взаимодействие с первым диалогом происходит. DllCall в таймер уже пробовал засунуть (может быть, неправильно) — в этом случае сценарий висит, в списке выполненных команд DllCall присутствует, но диалог даже не появляется.

teadrinker пишет:

Вы на XP? Пример не очень удачный.

Да. Почему?

teadrinker пишет:

и код выполняется дальше.

Т.е. MsgBox срабатывает до закрытия диалога?!

DllCall("shell32.dll\Control_RunDLL" . (A_IsUnicode? "W": "A")
	, "UInt", A_ScriptHwnd ; HWND hwnd // 0 не работает...
	, "Ptr", 0 ; HINSTANCE hInstance
	, "Str", "desk.cpl,,2" ; LPTSTR lpszCmd
	, "UInt", 1) ; nCmdShow
MsgBox
Post's attachments

dlgs.zip 13.64 kb, 2 downloads since 2017-08-10 

You don't have the permssions to download the attachments of this post.

5

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

wisgest пишет:

Не пойдёт, если сценарий скомпилирован в EXE.

Понятно, что вам не подойдет, но в ahk_H это возможно.

6

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

wisgest пишет:

Почему?

На семёрке и десятке таких окон нет, а те, что открываются, не являются диалогами. Поэтому протестировать пример нет возможности.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

7

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

wisgest пишет:

Т.е. MsgBox срабатывает до закрытия диалога?!

Да, но как я написал выше, открывающееся окно не является диалогом.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

8 (изменено: wisgest, 2020-03-12 01:45:23)

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

teadrinker, а MmSys.cpl?

+ 2020-03-12

Немного изменённое замечание о неудовлетворительном первоначальном названии темы перенесено в первое сообщение.

9

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

Да, открывается диалоговое окно «Звук».

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

10

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

wisgest пишет:

Например открываем диалог свойств ярлыка и пытаемся взаимодействовать с ним дальше, открываем поддиалог выбора значка и т.д.

Не совсем понятен смысл задачи. Диалоговые окна нужны для взаимодействия с пользователем, а не для эмуляции его действий.
Можно поэкспериментировать с таким таймером (он более живучий), но вряд ли это хороший путь.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

11

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

teadrinker пишет:

Да, открывается диалоговое окно «Звук».

Ну хотя бы так:

;Run % "rundll32.exe MmSys.cpl,ShowFullControlPanel",,, PID
; /*
SetTimer Step2, -1
DllCall("MmSys.cpl\ShowFullControlPanel"
;	, UInt, A_ScriptHwnd ; HWND hwnd
	, UInt, 0 ; HWND hwnd
	, Ptr, 0 ; HINSTANCE hInstance
	, Ptr, 0 ; LPTSTR lpszCmd
	, UInt, 1) ; nCmdShow
Exit
Step2:
Process Exist
PID = %ErrorLevel%
; */
WinWait Свойства: Звуки и аудиоустройства ahk_pid %PID%
WinGet HWND, ID
ControlClick Гром&кость динамиков..., ahk_id %HWND%

WinWait Динамики ahk_pid %PID%
Control Check,, П&ередвигать все регуляторы одновременно

— флажок уже не устанавливается.

teadrinker пишет:

Диалоговые окна нужны для взаимодействия с пользователем, а не для эмуляции его действий.

А AutoHotkey нужен для автоматизации, в том числе путём эмуляции действий пользователя.

12 (изменено: teadrinker, 2017-08-10 22:12:50)

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

wisgest пишет:
DllCall("MmSys.cpl\ShowFullControlPanel"
;   , UInt, A_ScriptHwnd ; HWND hwnd
   , UInt, 0 ; HWND hwnd
   , Ptr, 0 ; HINSTANCE hInstance
   , Ptr, 0 ; LPTSTR lpszCmd
   , UInt, 1) ; nCmdShow

Так вообще ничего не происходит. На семёрке нет параметра ShowFullControlPanel.

wisgest пишет:

А AutoHotkey нужен для автоматизации, в том числе путём эмуляции действий пользователя.

Так это самый примитивный способ автоматизации, обычно его стараются избегать и действовать как-то напрямую.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

13

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

teadrinker пишет:

Так вообще ничего не происходит.

А так?

DllCall("shell32.dll\Control_RunDLL" . (A_IsUnicode? "W": "A")
	, UInt, A_ScriptHwnd ; HWND hwnd
;	, UInt, 0 ; HWND hwnd
	, Ptr, 0 ; HINSTANCE hInstance
	, Str, "MmSys.cpl" ; LPTSTR lpszCmd
	, UInt, 1) ; nCmdShow
teadrinker пишет:

Так это самый примитивный способ автоматизации, обычно его стараются избегать

Кто бы спорил, но часто лучше как-нибудь, чем никак.

14

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

Так открывается такое окно:

http://i.imgur.com/a2TIQXh.png

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

15

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

Это на семёрке, а на десятке ничего.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

16

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

На семёрке пока не закроешь окно код далее не выполняется, наверное вопрос в этом...
То есть то что надо "по нажимать" не получается.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

17

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

serzh82saratov, в десятку!

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

18 (изменено: serzh82saratov, 2017-08-11 00:40:57)

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

Ок, если так?


DllCall("SetTimer", Ptr, A_ScriptHwnd, Ptr, 1, UInt, 300, Ptr, RegisterCallback("MyTimer", "Fast"))
DllCall("shell32.dll\Control_RunDLL" . (A_IsUnicode? "W": "A")
	, UInt, A_ScriptHwnd ; HWND hwnd
;	, UInt, 0 ; HWND hwnd
	, Ptr, 0 ; HINSTANCE hInstance
	, Str, "MmSys.cpl" ; LPTSTR lpszCmd
	, UInt, 1) ; nCmdShow

MyTimer()  {
	DllCall("KillTimer", Ptr, A_ScriptHwnd, Ptr, 1)
	WinWait Звук ahk_class #32770
	Loop	
		MsgBox, , , % A_Index, 0.2
}

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

19

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

serzh82saratov, непосредственно следующий за командой создающей диалог код не выполняется, естественно. Но если «понажимать» запустить в другом (псевдо)потоке, то, может быть что-то и получится. Оно и получается, но только до места, где создаётся следующий диалог. Я подозреваю, хотя и не проверял, что если перед этим местом  установить следующий таймер, то чего-то и можно добиться, но как-то это некрасиво выглядит. Может быть поиграться с приоритетами или какими-то директивами, но я в этом не разбираюсь.

20

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

wisgest пишет:

основной диалог уже вручную не закрывается

Эту проблему я пропустил, тоже не закрывается.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

21 (изменено: wisgest, 2017-08-11 00:52:25)

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

serzh82saratov пишет:

Ок, если так?

Так работает, если в моём случае изменить «Звук» на «Свойства: Звуки и аудиоустройства», но оно работает и через

SetTimer MyTimer, -1

Отличий не заметил.

22

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

Вот так у меня срабатывает на семёрке вызов диалога «Язык и региональные стандарты» и по кнопке поддиалога «Настройка формата»:

#Persistent
DllCall("SetTimer", Ptr, A_ScriptHwnd, Ptr, id := 1, UInt, 300, Ptr, RegisterCallback("MyTimer", "F"))
Return

MyTimer()  {
   static step := 0
   if (++step = 1)  {
      DllCall("shell32.dll\Control_RunDLL" . (A_IsUnicode ? "W" : "A")
         , "UInt", A_ScriptHwnd, "Ptr", 0, "Str", "intl.cpl", "UInt", nCmdShow := 1)
   }
   else if (step = 2)  {
      WinWait, Язык и региональные стандарты
      ControlClick, &Дополнительные параметры...
   }
   else if (step = 3)  {
      WinWait, Настройка формата
      ControlClick, Button3  ; Button OK, по OK не срабатывает
   }
   else if (step = 4)  {
      DllCall("KillTimer", Ptr, A_ScriptHwnd, Ptr, id := 1)
      WinWait, Язык и региональные стандарты
      ControlClick, Button4  ; Button OK
   }
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

23

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

"UInt", A_ScriptHwnd?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

24

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

А, это я же с коллеги wisgest скопировал. Конечно Ptr.

teadrinker пишет:

Вот так у меня срабатывает на семёрке вызов диалога «Язык и региональные стандарты»

Хотя как раз в этом случае весь сыр-бор ни к чему, поскольку можно просто

Run intl.cpl

без привязки к окну диалога.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

25

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

teadrinker пишет:

Хотя как раз в этом случае весь сыр-бор ни к чему, поскольку можно просто

Run intl.cpl

— это открытие *.cpl сопоставленным приложением, т.е. rundll32.exe…

Думаю, это решение можно воспроизвести и встроенной командой SetTimer:

wisgest пишет:

Я подозреваю, хотя и не проверял, что если перед этим местом  установить следующий таймер, то чего-то и можно добиться, но как-то это некрасиво выглядит.

Т.е. почему требуется разрыв между (step = 1) и (step = 2) понятно, а между (step = 2) и (step = 3) и почему они не могут быть в одном «потоке» — уже не очень…

26

Re: AHK: Взаимодействие с диалогами, принадлежащими собственному процессу

wisgest пишет:

между (step = 2) и (step = 3) и почему они не могут быть в одном «потоке» — уже не очень

По всей видимости, по той же причине, что и между 1 и 2 — открывается новое диалоговое окно и поток ждёт его закрытия.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder