rdaler
Интересующийся
Offline
|
|
« : 15-12-2009 06:12 » |
|
Народ, помогите ПРАВИЛЬНО вызвать диалог выбора элемента справочника (Метод "Выбрать()/Choose()"). Подключаюсь к 1С методом динамического связывания. Окно авторизации показывается активным (поверх окна вызывающего приложения), а диалоговое окно неактивно (под окном вызывающего), что не есть ГУД. Если подключаться к 1С без вызова диалога авторизации (прописать нужные параметры), то в первый раз диалог отображается правильно, а все остальные вызовы проходят как и в первом случае (в неактивном окне).
|
|
|
Записан
|
|
|
|
Kivals
|
|
« Ответ #1 : 15-12-2009 09:21 » |
|
ИМХО - глюк платформы. Средствами 1С вроде бы никак не побороть - или писать addin для 1С, или программу, которая мониторит окна и делает его активным (по названию класса окна, по заголовку или еще как-то) - но это в системное программирование
|
|
|
Записан
|
|
|
|
rdaler
Интересующийся
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
|
|
« Ответ #3 : 15-12-2009 18:14 » |
|
Да нет - к сожалению в 7 вроде не особо развиты методы работы с интерфейсом. Попробуй чем-то вроде WinSpy отследить класс окна и перебирай дочерние окна процесса чем-то типа FindWindow / EnumWindows. Подробностей не помню - давно уже с WinAPI не работал.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #4 : 15-12-2009 18:32 » |
|
А если к найденному диалогу присобачить стиль WS_EX_TOPMOST, то диалог будет всегда поверх всех окон
|
|
« Последнее редактирование: 15-12-2009 18:34 от Алексей1153++ »
|
Записан
|
|
|
|
rdaler
Интересующийся
Offline
|
|
« Ответ #5 : 16-12-2009 06:10 » |
|
Попытался аналогичную ситуацию сделать в Delphi10 (авось это Framework выпендривается) - нифига, аналогичную ситуацию и получил: первый вызов Top, а все последующие Back. С перебором окон идея, конечно, скорее всего правильная, вот только для этого перебора придется отдельный поток создавать, т.к. це ж вызов модального окна. А кроме того у меня может быть подключено несколько ИБ, а их процессы как близнецы - отличаются только PID-ом. Короче, довольно геморно! Хотя, скорее всего это и будет окончательным вариантом решения. Может есть ещё какие варианты динамического связывания, о которых, так сказать, скромно умалчивают?
|
|
|
Записан
|
|
|
|
Kivals
|
|
« Ответ #6 : 16-12-2009 09:12 » |
|
Дык - вроде по PID ты можешь перебирать дочерние окна конкретного процесса... А что касается отдельного потока - так в твоем случае он никак взаимодействовать с основным не должен, так что задача тривиальная. Единственный момент - наверное второй поток нужно с приоритетом ниже нормального делать.
|
|
|
Записан
|
|
|
|
rdaler
Интересующийся
Offline
|
|
« Ответ #7 : 24-12-2009 06:39 » |
|
Короче уговорили! Решил запустить поток непосредственно перед вызовом метода, который ищет необходимое мне окно и делает его TOPMOST. Но вот проблема!!! Окно действительно становится поверх всех окон, КРОМЕ окна вызывающего приложения. Причем, если запускаю в режиме пошаговой отладки (активное окно VS), то все нормально - 1С-овское окно всплывает поверх него; если делаю отдельное консольное приложение, выполняющее нужный поиск и перемещение, - тоже все зашибись. Т.е. пока фокус ввода находится в окне приложения никак не получается переключиться на 1С-овский диалог.
|
|
|
Записан
|
|
|
|
Kivals
|
|
« Ответ #8 : 24-12-2009 11:44 » |
|
Активируй еще и приложение
|
|
|
Записан
|
|
|
|
rdaler
Интересующийся
Offline
|
|
« Ответ #9 : 24-12-2009 12:00 » |
|
Какое приложение ты имеешь ввиду? Если вызывающее, то оно и так в фокусе.
|
|
|
Записан
|
|
|
|
Kivals
|
|
« Ответ #10 : 24-12-2009 19:04 » |
|
Окно действительно становится поверх всех окон, КРОМЕ окна вызывающего приложения.
Вот для этого по-моему и нужно активировать главное окно приложения, PID которого у тебя есть
|
|
|
Записан
|
|
|
|
rdaler
Интересующийся
Offline
|
|
« Ответ #11 : 25-12-2009 05:01 » |
|
Оно и так активно (я же из него и вызываю метод по кнопке). Да и зачем мне к нему по PID-у обращаться. Или я тебя совсем не понимаю. Постарайся изложить свою мысль более полно.
|
|
|
Записан
|
|
|
|
rdaler
Интересующийся
Offline
|
|
« Ответ #12 : 25-12-2009 08:10 » |
|
Проблема решена. Никакие стили тут не помогают. Нужно тупо вызвать SetForegroundWindow(HWND x); Странно, но SetActiveWindow, SetWindowPos не катят
|
|
« Последнее редактирование: 25-12-2009 08:12 от rdaler »
|
Записан
|
|
|
|
rdaler
Интересующийся
Offline
|
|
« Ответ #13 : 25-12-2009 08:16 » |
|
Единственное, что меня во всём этом убивает, так жто тот факт, что идентифицировать окно приходится по Caption-у. Т.е. получается, если у меня отдельно запущена 1С и в ней совершенно случайно тоже открыт диалог выбора, то он и это окно тоже выведет на передний план. Поэтому считаю, что нужно оставить тему открытой, т.к. возможно существует другой способ активизировать окно диалога, не перебирая при этом процессы.
|
|
|
Записан
|
|
|
|
Kivals
|
|
« Ответ #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 главного окна
|
|
|
Записан
|
|
|
|
|