Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Вызов диалогового окна 1С через OLEAutomation  (Прочитано 17511 раз)
0 Пользователей и 1 Гость смотрят эту тему.
rdaler
Интересующийся

ru
Offline Offline

« : 15-12-2009 06:12 » 

Народ, помогите ПРАВИЛЬНО вызвать диалог выбора элемента справочника (Метод "Выбрать()/Choose()").
Подключаюсь к 1С методом динамического  связывания.
Окно авторизации показывается активным (поверх окна вызывающего приложения), а диалоговое окно неактивно (под окном вызывающего), что не есть ГУД.
Если подключаться к 1С без вызова диалога авторизации (прописать нужные параметры), то в первый раз диалог отображается правильно, а все остальные вызовы проходят как и в первом случае (в неактивном окне).
Записан
Kivals
Модератор

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 15-12-2009 09:21 » 

ИМХО - глюк платформы. Средствами 1С вроде бы никак не побороть - или писать addin для 1С, или программу, которая мониторит окна и делает его активным (по названию класса окна, по заголовку или еще как-то) - но это в системное программирование Жаль
Записан
rdaler
Интересующийся

ru
Offline Offline

« Ответ #2 : 15-12-2009 09:59 » 

Мониторить окна не получится, т.к. в один момент у меня может быть запущено несколько подключений, а после второго подключения процесс первого перестает быть виден и доступа к нему соответственно даже по PID нету.
Может всё же не глюк платформы, а я что-либо не так делаю?

object Trade;
...
//Метод подключения
Type t=Type.GetTypeFromProgID("V77.Application");
Trade=System.Activator.CreateInstance(t);
Object[] args=new Object[3];
args[0]=Trade.GetType().InvokeMember(@"RMTrade", BindingFlags.Public|BindingFlags.InvokeMethod, null, Trade, null);
StringBuilder Str=new StringBuilder(@"/D"+'"'+MDPath+'"');
if(username!="") { Str.Append(" /N"+username); }
if(password!="") { Str.Append(" /P"+password); }
args[1]=Str.ToString();
args[2]=@"NO_SPLASH_SHOW";
Trade.GetType().InvokeMember(@"Initialize", BindingFlags.Public|BindingFlags.InvokeMethod, null, Trade, args);
...
//Метод вызова
object Ref=Trade.GetType().InvokeMember("CreateObject", BindingFlags.GetProperty, null, Trade, new object[1] {"Reference.XXX"});
Ref.GetType().InvokeMember("Choose", BindingFlags.InvokeMethod, null, TradeObject, new object[2] { "", "" });
Записан
Kivals
Модератор

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 15-12-2009 18:14 » 

Да нет - к сожалению в 7 вроде не особо развиты методы работы с интерфейсом.
Попробуй чем-то вроде WinSpy отследить класс окна и перебирай дочерние окна процесса чем-то типа FindWindow / EnumWindows. Подробностей не помню - давно уже с WinAPI не работал.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #4 : 15-12-2009 18:32 » 

А если к найденному диалогу присобачить стиль WS_EX_TOPMOST, то диалог будет всегда поверх всех окон Улыбаюсь
« Последнее редактирование: 15-12-2009 18:34 от Алексей1153++ » Записан

rdaler
Интересующийся

ru
Offline Offline

« Ответ #5 : 16-12-2009 06:10 » 

Попытался аналогичную ситуацию сделать в Delphi10 (авось это Framework выпендривается) - нифига, аналогичную ситуацию и получил: первый вызов Top, а все последующие Back.
С перебором окон идея, конечно, скорее всего правильная, вот только для этого перебора придется отдельный поток создавать, т.к. це ж вызов модального окна. А кроме того у меня может быть подключено несколько ИБ, а их процессы как близнецы - отличаются только PID-ом. Короче, довольно геморно! Хотя, скорее всего это и будет окончательным вариантом решения.
Может есть ещё какие варианты динамического связывания, о которых, так сказать, скромно умалчивают?
Записан
Kivals
Модератор

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #6 : 16-12-2009 09:12 » 

Дык - вроде по PID ты можешь перебирать дочерние окна конкретного процесса... А что касается отдельного потока - так в твоем случае он никак взаимодействовать с основным не должен, так что задача тривиальная. Единственный момент - наверное второй поток нужно с приоритетом ниже нормального делать.
Записан
rdaler
Интересующийся

ru
Offline Offline

« Ответ #7 : 24-12-2009 06:39 » 

Короче уговорили! Решил запустить поток непосредственно перед вызовом метода, который ищет необходимое мне окно и делает его TOPMOST. Но вот проблема!!! Окно действительно становится поверх всех окон, КРОМЕ окна вызывающего приложения. Причем, если запускаю в режиме пошаговой отладки (активное окно VS), то все нормально - 1С-овское окно всплывает поверх него; если делаю отдельное консольное приложение, выполняющее нужный поиск и перемещение, - тоже все зашибись. Т.е. пока фокус ввода находится в окне приложения никак не получается переключиться на 1С-овский диалог.
Записан
Kivals
Модератор

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #8 : 24-12-2009 11:44 » 

Активируй еще и приложение
Записан
rdaler
Интересующийся

ru
Offline Offline

« Ответ #9 : 24-12-2009 12:00 » 

Какое приложение ты имеешь ввиду?
Если вызывающее, то оно и так в фокусе.
Записан
Kivals
Модератор

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #10 : 24-12-2009 19:04 » 

Окно действительно становится поверх всех окон, КРОМЕ окна вызывающего приложения.
Вот для этого по-моему и нужно активировать главное окно приложения, PID которого у тебя есть
Записан
rdaler
Интересующийся

ru
Offline Offline

« Ответ #11 : 25-12-2009 05:01 » 

Оно и так активно (я же из него и вызываю метод по кнопке). Да и зачем мне к нему по PID-у обращаться.
Или я тебя совсем не понимаю. Постарайся изложить свою мысль более полно.
Записан
rdaler
Интересующийся

ru
Offline Offline

« Ответ #12 : 25-12-2009 08:10 » 

Проблема решена.
Никакие стили тут не помогают. Нужно тупо вызвать SetForegroundWindow(HWND x);
Странно, но SetActiveWindow, SetWindowPos не катят
« Последнее редактирование: 25-12-2009 08:12 от rdaler » Записан
rdaler
Интересующийся

ru
Offline Offline

« Ответ #13 : 25-12-2009 08:16 » 

Единственное, что меня во всём этом убивает, так жто тот факт, что идентифицировать окно приходится по Caption-у.
Т.е. получается, если у меня отдельно запущена 1С и в ней совершенно случайно тоже открыт диалог выбора, то он и это окно тоже выведет на передний план.
Поэтому считаю, что нужно оставить тему открытой, т.к. возможно существует другой способ активизировать окно диалога, не перебирая при этом процессы.
Записан
Kivals
Модератор

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #14 : 25-12-2009 20:07 » 

...Нужно тупо вызвать SetForegroundWindow...
Ну писал же - не помню я уже WinAPI Улыбаюсь Именно на эту мысль и пытался натолкнуть, но забыл метод...

А получив новый OLE объект
Код:
args[0]=Trade.GetType().InvokeMember(@"RMTrade", BindingFlags.Public|BindingFlags.InvokeMethod, null, Trade, null);
ты никак из него PID процесса получить не можешь? а по PID процесса уже можно получить HWND главного окна
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines