If I programmatically activate a window in another application, can I detect when it loses focus?

前端 未结 1 1413
孤独总比滥情好
孤独总比滥情好 2021-01-15 04:44

Bear with me, I\'m a web developer attempting a WinForms application.

When responding please do not comment on whether the purpose of my application is a \"best prac

相关标签:
1条回答
  • 2021-01-15 05:32

    I have the start of some working code. I think I have enough that this may be useful to someone else.

    I found a way to use the UIAutomation library instead of the Microsoft.VisualBasic library. There was a lot of trial and error, but this is much "slicker" than my first few attempts using the VisualBasic library.

    I used the StructureChanged event to detect the Help window popping up in a previous iteration of this proof of concept app. I was able to successfully detect that the Help window popped up, but I was running into snags trying to handle the appearance of the Help window. I still have the event handler in my application, but for some reason the Help window does not pop up now, I tried forcing invalid data into one of the fields to test the handling of the Help window, and the Help window did not appear. This is not an issue for me, since the Help window was causing trouble for me, but I felt that it needed to be mentioned since this post was asking how I could detect the Help window's appearance.

    Some resources I used:

    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.");
    }
    

    Here's the event handler for the StructureChangedEvent:

     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);
        }
      }
    }
    
    0 讨论(0)
提交回复
热议问题