Частое неожиданное изменение режима окна модуля при выполнении команды скрипта

tormozit Закрыто

Последние дни стал часто замечать, что при вызове различных команд скрипта "ИР Адаптер" окно текущего модуля стало менять режим отображения с "Обычное" на "Свободное".

Код самой простой команды, на которой это наблюдалось неоднократно

Процедура НайтиСсылкиНаМетод()
	ПодключениеИР = ПодключениеИР();
	Если ПодключениеИР = Неопределено Тогда
		Возврат;
	КонецЕсли;
	ПолеТекстаПрограммы = ПолеТекстаПрограммыИР(ПодключениеИР, ТекстМодуля, ПозицияВТексте, ВыделенныйТекст, Ложь, Ложь);
	Если ПолеТекстаПрограммы = Неопределено Тогда
		Возврат;
	КонецЕсли;
	ВосстановитьОкноПриложения(ПодключениеИР);
	ПолеТекстаПрограммы.ОткрытьПоискВызововМетода(,, Ложь);
	ТурбоКонф.КонтролКлавиша(Клавиши.Enter); // Так пользователь сможет прерывать
КонецПроцедуры

Ссылка скрыта

Исходный вид окна модуля :

После выполнения команды:

Комментарии

bolsun
#1, 07 декабря 2023 17:32

Что за ВосстановитьОкноПриложения(ПодключениеИР), для чего это?


tormozit
#2, 07 декабря 2023 17:37

(1) bolsun, так я делаю видимым и окно COM приложения


bolsun
#3, 07 декабря 2023 17:38

(2) tormozit, давно это появилось в коде?


tormozit
#4, 07 декабря 2023 17:39

(3) bolsun, ну месяца 2 точно уже


bolsun
#5, 07 декабря 2023 17:46

Что там за вызовы Alt+Minus для открытия меню окна? Я вроде такого не отправляю.


tormozit
#6, 07 декабря 2023 18:43

По Alt+Minus у меня нет версий, кто это отправляет. В коде скрипта есть только одно место где отправляется CTRL+OemMinus и оно в этой ситуации вроде бы не исполнялось, т.к. вызывается только в модуле формы.


bolsun
#7, ред. 09 декабря 2023 18:00

В скрипте окно делается свободным во время выполнения скрипта, в этом месте

ВосстановитьОкноПриложения(ПодключениеИР);
ПолеТекстаПрограммы.ОткрытьПоискВызововМетода(,, Ложь);

путем вызова меню Alt+OemMinus
Затем несколько раз Up
Enter
Затем происходит Ctrl+Enter
Так же, в процессе несколько раз нажиается NumLock

Может что-то подобное есть в ПолеТекстаПрограммы.ОткрытьПоискВызововМетода(,, Ложь);

Но все это выполняется в конфигураторе, а не в клиенте, т.к. было вызвано ЗавершитьВызовВнешнегоОкна.

bolsun изменил статус на На выяснении


bolsun
#8, ред. 09 декабря 2023 18:09

Это видно абсолютно точно.

[07.12.23 17:14:00:614] -------------------------------------------UIAutomation Focus Changed = Соединяемое
[07.12.23 17:14:00:614] -------------------------------------------UIAutomation Focus Changed = Следующее окно
[07.12.23 17:14:00:615] -------------------------------------------UIAutomation Focus Changed = Восстановить положение окна
[07.12.23 17:14:00:617] -------------------------------------------UIAutomation Focus Changed = Прикрепленное
[07.12.23 17:14:00:620] -------------------------------------------UIAutomation Focus Changed = Свободное
[07.12.23 17:14:00:621] Received Return DOWN
[07.12.23 17:14:00:622] OnKeyUp Return


tormozit
#9, ред. 09 декабря 2023 18:35

Внутри метода ИР ПолеТекстаПрограммы.ОткрытьПоискВызововМетода() и в ряде других мест в коде ИР есть отправка нажатий клавиш для установки прикрепления окна управляемой формы. Эти нажатия попадают в очередь ввода. Затем конфигуратор забирает фокус и они прилетают в его окно.

				Если Истина
					И ТипЗнч(ЭтаФорма) = Тип("Форма") 
					И ирКэш.НомерВерсииПлатформыЛкс() < 803021 
				Тогда
					КомандаАктивацииПунктаОкна = "{UP 2}";
				Иначе
					КомандаАктивацииПунктаОкна = "{UP 4}";
				КонецЕсли; 
				ОтправитьНажатияКлавишЛкс("%-", ОжидатьЗавершения); // Такой вызов меню окна не работает в 8.3.15-16
				ОтправитьНажатияКлавишЛкс(КомандаАктивацииПунктаОкна, ОжидатьЗавершения);
				ОтправитьНажатияКлавишЛкс("{ENTER}", ОжидатьЗавершения);
				// Снизу может находиться пункт меню "Сообщения", если было выведено хотя бы одно сообщение
				//Если ПоложениеПрикрепленногоОкна = ВариантПрикрепленияОкна.Верх Тогда
				//	ОтправитьНажатияКлавишЛкс("{UP 3}", ОжидатьЗавершения);
				//ИначеЕсли ПоложениеПрикрепленногоОкна = ВариантПрикрепленияОкна.Низ Тогда
				//	ОтправитьНажатияКлавишЛкс("{UP 2}", ОжидатьЗавершения);
				//ИначеЕсли ПоложениеПрикрепленногоОкна = ВариантПрикрепленияОкна.Лево Тогда
				//	ОтправитьНажатияКлавишЛкс("{UP 5}", ОжидатьЗавершения);
				//ИначеЕсли ПоложениеПрикрепленногоОкна = ВариантПрикрепленияОкна.Право Тогда
				//	ОтправитьНажатияКлавишЛкс("{UP 4}", ОжидатьЗавершения);
				//КонецЕсли; 
				Если ПоложениеПрикрепленногоОкна = ВариантПрикрепленияОкна.Верх Тогда
					ОтправитьНажатияКлавишЛкс("{Down 4}", ОжидатьЗавершения);
				ИначеЕсли ПоложениеПрикрепленногоОкна = ВариантПрикрепленияОкна.Низ Тогда
					ОтправитьНажатияКлавишЛкс("{Down 5}", ОжидатьЗавершения);
				ИначеЕсли ПоложениеПрикрепленногоОкна = ВариантПрикрепленияОкна.Лево Тогда
					ОтправитьНажатияКлавишЛкс("{Down 2}", ОжидатьЗавершения);
				ИначеЕсли ПоложениеПрикрепленногоОкна = ВариантПрикрепленияОкна.Право Тогда
					ОтправитьНажатияКлавишЛкс("{Down 3}", ОжидатьЗавершения);
				КонецЕсли; 
				ОтправитьНажатияКлавишЛкс("{ENTER}", ОжидатьЗавершения);


tormozit
#10, ред. 09 декабря 2023 18:43

Почему конфигуратор забирает фокус - мне непонятно. Что нужно сделать чтобы он его не забирал?
В этой команде мне нужно

  1. Активировать окно приложения ИР.
  2. Открыть в нем окно и оставить там фокус.


bolsun
#11, ред. 09 декабря 2023 18:42

(10) tormozit, я же написал почему

Но все это выполняется в конфигураторе, а не в клиенте, т.к. было вызвано ЗавершитьВызовВнешнегоОкна.

Этот метод, помимо всего прочего возвращает фокус в конфигуратор.


tormozit
#12, ред. 09 декабря 2023 18:52

Метод ЗавершитьВызовВнешнегоОкна() выполняется до вызова ПолеТекстаПрограммы.ОткрытьПоискВызововМетода(). Получается мне не нужно вызывать метод ЗавершитьВызовВнешнегоОкнаАсинх() в этом случае совсем? Но тогда Турбоконф останется отключенным насколько я понимаю.


bolsun
#13, 09 декабря 2023 18:53

ЗавершитьВызовВнешнегоОкнаАсинх - нужно делать если начался вызов внешнего окна, через НачатьВызовВнешнегоОкнаАсинх.

Самый простой вариант вернуть после этого фокус в клиент, через АктивироватьОкно(Указатель)


bolsun
#14, 09 декабря 2023 18:54

Второй вариант добавить параметр в ЗавершитьВызовВнешнегоОкна(ВернутьФокус)


tormozit
#15, 09 декабря 2023 18:58

(14) bolsun, это было бы идеально


tormozit
#16, ред. 09 декабря 2023 19:09

Напомню почему я активирую окно приложения ИР таким странным образом. Если просто делать
ПодключениеИР.Visible = Истина;
то главное окно ИР не восстанавливается, если до этого было открыто модальное окно, и отображается в виде маленькой полоски:


bolsun
#17, 09 декабря 2023 19:10

(16) tormozit, да я понял. Мы не восстанавливаем его, чтобы не было моргания.


bolsun
#18, ред. 09 декабря 2023 19:19

(15) tormozit, посмотрел еще раз методы НачатьВызовВнешнегоОкнаАсинх и ЗавершитьВызовВнешнегоОкнаАсинх.

Проблема похоже несколько в другом

ЗавершитьВызовВнешнегоОкнаАсинх - не возвращает фокус в конфигуратор, если не задан параметр для этого

StopExternalWindowCallAsync(long fg = 0, bool continueProcess = true)

Поэтому, проблема скорее всего в том, что главное окно клиента не успело получить фокус, нужно добавить задержку после НачатьВызовВнешнегоОкнаАсинх


bolsun
#19, 09 декабря 2023 19:29

ЗавершитьВызовВнешнегоОкнаАсинх почему он вообще Асинх называется, он вообще не асинхронный.


tormozit
#20, 09 декабря 2023 19:38

Про задержку - будет еще один ненадежный элемент в логике. Все равно будет "протекать" иногда как я понимаю. Даже если 1 из 20 раз будет протекать, неудобства доставить может ощутимые. Можно как то надежнее понять в какое окно направляются события ввода в текущий момент?


bolsun
#21, 09 декабря 2023 19:43

ПолучитьАктивноеОкно()


tormozit
#22, 09 декабря 2023 19:57

Может тогда внутри НачатьВызовВнешнегоОкнаАсинх сделать ожидание, что заданное окно стало активным? У меня нет сценариев, когда нужно просто показать окно и что то дальше делать, не дожидаясь когда оно станет активным (получит фокус ввода). Думаю и другим такое маловероятно будет нужно. Иными словами это нужно всем и всегда при вызове метода НачатьВызовВнешнегоОкнаАсинх().


tormozit
#23, ред. 09 декабря 2023 20:23

Если не станешь делать цикл ожидания активации у себя, то хотя бы верни мне указатель на найденное окно из метода ЗавершитьВызовВнешнегоОкнаАсинх(), чтобы я в своем коде сделал тот же цикл ожидания активации.


bolsun
#24, 09 декабря 2023 20:33

(23) tormozit, я не смогу ничего из него вернуть, т.к. метод асинхронно работает, в другом потоке.
Просто получи активное окно до начала вызова окна COM и потом жди что оно изменится.


tormozit
#25, 09 декабря 2023 22:19

Сделал цикл ожидания. Немного потестировал. Пока проблема не появлялась.


bolsun
#26, 10 декабря 2023 15:01

Добавлен метод ЖдатьСменуАктивногоОкна, который можно использовать после НачатьВызовВнешнегоОкнаАсинх, в случае если необходимо дождаться фокуса, для интерактивного взаимодействия с клиентским окном.
bolsun изменил статус на Закрыто


Для вставки изображения или файла, перетащите его в поле редактора или вставьте файл из буфера