2014-09-11 2 views
2

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

При ответе, пожалуйста, не комментируйте, является ли цель моего приложения «лучшей практикой» или нет, и т. Д. Это приложение, которое мне нужно написать, к лучшему или худшему, и я не могу тратить время на объяснение «почему». Я прошу вас просто ответить с советами (1). Я пытаюсь сделать это (2). Каков «лучший» способ выполнить то, что я пытаюсь сделать.

Итак, вот что я пытаюсь сделать: Мне нужно написать приложение WinForms, которое будет считывать данные из приложения-поставщика, отображать определенные записи конечному пользователю и разрешать им выбирать «перенос» записи к другому заявлению поставщика. Повреждение ... система назначения не предоставляет apis, без sprocs, не предоставляет «хороший» метод для вставки данных, кроме ввода его в свой графический интерфейс. (поверьте мне, команда из 3 человек изучила КАЖДУЮ возможность автоматизации этого)

Таким образом, это приложение WinForms будет использовать Microsoft.VisualBasic.Interaction.AppActivate (строка) и вставить данные непосредственно в поля во входном окне системы назначения. Система назначения имеет справку F1 в определенных полях, поэтому, если вы выделите поле и нажмите «F1», или, альтернативно, если вы введете неверные данные в одном из этих полей, появится дочернее окно с именем «Справка», чтобы предложить руководство ,

Итак, мое приложение подключается, используя SendKeys.SendWait (string) для записи данных в поля этого приложения, а затем обнаруживаются некоторые недопустимые данные и появляется окно справки, и мое приложение продолжает выписывать остальная часть данных, но теперь все это записывается в поле 1 в окне справки, потому что это окно теперь имеет фокус.

миллиона долларов вопрос ...

Есть ли способ обнаружения, с моей WinForms приложения, что окно справки активирован в системе назначения, так что я могу работать вокруг него?


Обновления

Первая попытка в этом приложении я использовал библиотеку UIAutomationClient. Мне не удалось успешно активировать целевое окно и записать в первое поле. После дня борьбы с ним мне пришлось начать искать альтернативы.

+0

SetWinEventHook(). У этого есть умение превращаться в готическую ошибку. По крайней мере, рассмотрите приличную библиотеку автоматизации пользовательского интерфейса, поэтому вам не придется ее взламывать, моделируя нажатия клавиш. –

+0

Ханс, я сначала попытался использовать UIAutomationClient, но не смог выполнить то, что мне нужно, из-за большего количества проблем с системой назначения. Здесь есть устаревшее приложение VB6/VBA, которое делает это, его нужно обновить по нескольким причинам ... Мой партнер и я решили попытаться улучшить решение и избежать использования VBA. После испытаний и сбоев мы снова используем Microsoft.VisualBasic.Interation.AppActivate(), в основном имитирующий код в устаревшем приложении, но мы по-прежнему намерены улучшить функциональность/производительность. Унаследованное приложение действительно что-то другое. – CDR12

ответ

2

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

Я нашел способ использовать библиотеку UIAutomation вместо библиотеки Microsoft.VisualBasic. Существовал много проб и ошибок, но это гораздо «slicker», чем мои первые несколько попыток с использованием библиотеки VisualBasic.

Я использовал событие StructureChanged, чтобы обнаружить окно справки, появившееся в предыдущей итерации этого доказательства концепции. Мне удалось успешно обнаружить, что появилось окно справки, но я столкнулся с ошибками, пытаясь обработать внешний вид окна справки. У меня все еще есть обработчик событий в моем приложении, но по какой-то причине окно справки не появляется сейчас, я попытался заставить недействительные данные в одно из полей проверить обработку окна справки, а окно справки не появилось. Для меня это не проблема, так как окно справки вызывало у меня проблемы, но я чувствовал, что это нужно упомянуть, поскольку этот пост спрашивал, как я могу обнаружить появление окна справки.

Некоторые ресурсы я использовал:

http://msdn.microsoft.com/en-us/library/ms747327%28v=vs.110%29.aspx

https://www.universalthread.com/ViewPageArticle.aspx?ID=199

http://msdn.microsoft.com/en-us/library/ms750582%28v=vs.110%29.aspx

http://msdn.microsoft.com/en-us/library/windows/desktop/dd318521%28v=vs.85%29.aspx

private void IncidentGridView_CellContentClick(object sender, DataGridViewCellEventArgs e) 
{ 
    if ((e.RowIndex < 0) || (e.ColumnIndex < 0)) 
    return; 

    // Grab the data object that populated the row 
    Incident incident = (Incident)IncidentGridView.Rows[e.RowIndex].DataBoundItem; 

    // Create a property condition with the element's type 
    PropertyCondition typeCondition = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window); 
    // Create a property condition with the element's name 
    PropertyCondition nameCondition = new PropertyCondition(AutomationElement.NameProperty, "Incident"); 
    // Create the conjunction condition 
    AndCondition andCondition = new AndCondition(typeCondition, nameCondition); 
    // Ask the Desktop to find the element within its children with the given condition 
    _mainWindow = AutomationElement.RootElement.FindFirst(TreeScope.Children, andCondition); 

    #region Register Automation Events 
    //AutomationEventHandler handler = new AutomationEventHandler(OnWindowOpened); 
    //Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent, _mainWindow, TreeScope.Element, handler); 
    Automation.AddStructureChangedEventHandler(_mainWindow, TreeScope.Children, new StructureChangedEventHandler(OnStructureChanged)); 
    #endregion 

    // Wait for the application 
    Thread.Sleep(2000); 

    // Write the incident to the Incident window 
    PropertyCondition idCondition = new PropertyCondition(AutomationElement.AutomationIdProperty, "3279"); 
    AutomationElement reportedDate = _mainWindow.FindFirst(TreeScope.Descendants, idCondition); 
    InsertTextUsingUIAutomation(reportedDate, incident.ReportedDate); 

    PropertyCondition idCondition2 = new PropertyCondition(AutomationElement.AutomationIdProperty, "4256"); 
    AutomationElement reportedTime = _mainWindow.FindFirst(TreeScope.Descendants, idCondition2); 
    InsertTextUsingUIAutomation(reportedTime, incident.ReportedTime); 

    PropertyCondition idCondition4 = new PropertyCondition(AutomationElement.AutomationIdProperty, "7256"); 
    AutomationElement status = _mainWindow.FindFirst(TreeScope.Descendants, idCondition4); 
    InsertTextUsingUIAutomation(status, "WAR"); 

    PropertyCondition idCondition5 = new PropertyCondition(AutomationElement.AutomationIdProperty, "5404"); 
    AutomationElement natureOfCall = _mainWindow.FindFirst(TreeScope.Descendants, idCondition5); 
    InsertTextUsingUIAutomation(natureOfCall, "TRAF WARN"); 

    PropertyCondition idCondition11 = new PropertyCondition(AutomationElement.AutomationIdProperty, "4935"); 
    AutomationElement location = _mainWindow.FindFirst(TreeScope.Descendants, idCondition11); 
    InsertTextUsingUIAutomation(location, incident.Location); 

    PropertyCondition idCondition12 = new PropertyCondition(AutomationElement.AutomationIdProperty, "2876"); 
    AutomationElement city = _mainWindow.FindFirst(TreeScope.Descendants, idCondition12); 
    InsertTextUsingUIAutomation(city, incident.City); 

    PropertyCondition idCondition15 = new PropertyCondition(AutomationElement.AutomationIdProperty, "5693"); 
    AutomationElement officer = _mainWindow.FindFirst(TreeScope.Descendants, idCondition15); 
    InsertTextUsingUIAutomation(officer, incident.Officer); 

    PropertyCondition idCondition19 = new PropertyCondition(AutomationElement.AutomationIdProperty, "4023"); 
    AutomationElement fromDate = _mainWindow.FindFirst(TreeScope.Descendants, idCondition19); 
    InsertTextUsingUIAutomation(fromDate, incident.FromDate); 

    PropertyCondition idCondition20 = new PropertyCondition(AutomationElement.AutomationIdProperty, "4042"); 
    AutomationElement fromTime = _mainWindow.FindFirst(TreeScope.Descendants, idCondition20); 
    InsertTextUsingUIAutomation(fromTime, incident.FromTime); 

    PropertyCondition idCondition21 = new PropertyCondition(AutomationElement.AutomationIdProperty, "7556"); 
    AutomationElement toDate = _mainWindow.FindFirst(TreeScope.Descendants, idCondition21); 
    InsertTextUsingUIAutomation(toDate, incident.ToDate); 

    PropertyCondition idCondition22 = new PropertyCondition(AutomationElement.AutomationIdProperty, "7576"); 
    AutomationElement toTime = _mainWindow.FindFirst(TreeScope.Descendants, idCondition22); 
    InsertTextUsingUIAutomation(toTime, incident.ToTime); 

    PropertyCondition idCondition30 = new PropertyCondition(AutomationElement.AutomationIdProperty, "2001"); 
    AutomationElement remarks = _mainWindow.FindFirst(TreeScope.Descendants, idCondition30); 
    InsertTextUsingUIAutomation(remarks, incident.Remarks); 


    MessageBox.Show("Incident was transferred."); 
} 

Вот обработчик события для STRUC tureChangedEvent:

private void OnStructureChanged(object sender, StructureChangedEventArgs e) 
{ 
    AutomationElement element = sender as AutomationElement; 

    if (e.StructureChangeType == StructureChangeType.ChildAdded) 
    { 
    Object windowPattern; 
    if (false == element.TryGetCurrentPattern(WindowPattern.Pattern, out windowPattern)) 
     return; 

    if (element.Current.Name == "Help") 
    { 
     // How do we want to handle this??? 
     MessageBox.Show("Waiting 30 seconds to allow user to resolve data issue."); 
     Thread.Sleep(30000); 
    } 
    } 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^