| 
			| 
					
						| 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 главного окна |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	|  |