Click here to Skip to main content
15,884,628 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I cannot perform very simple task using Microsoft UI automation API -> write something in notepad..

C#
Process process = Process.GetProcessesByName("notepad").Length == 0
                                  ? Process.Start("notepad")
                                  : Process.GetProcessesByName("notepad")[0];
Condition processIdCondition = new PropertyCondition(AutomationElement.ProcessIdProperty, process.Id);
var window = AutomationElement.RootElement.FindFirst(TreeScope.Children, processIdCondition);
window.SetFocus();
var edit = window.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.AutomationIdProperty, "15"));
// control type is ControlType.Document
string controlType = ((ControlType)edit.GetCurrentPropertyValue(AutomationElement.ControlTypeProperty)).ProgrammaticName;
// only 2 patterns are supported TextPattern and ScrollPattern
var patterns = edit.GetSupportedPatterns().Select(p => p.ProgrammaticName).ToArray();
// using TextPattern I can get a text
var textPattern = edit.GetCurrentPattern(TextPattern.Pattern) as TextPattern;
string text = textPattern.DocumentRange.GetText(-1);
// but what about setting the value?
// Microsoft says that ValuePattern is not supported
// 
// Does it mean that we have no way to set content of Document type?


http://msdn.microsoft.com/en-us/library/ms752058.aspx#Required_UI_Automation_Control_Patterns

Any ideas?
Posted
Comments
Sergey Alexandrovich Kryukov 18-Nov-12 12:25pm    
What is "notepad text"? :-)

1 solution

I ended up using SendKeys as the Document object in notepad does not support the "SetValue" ValuePattern.

private void NotepadInsertButton_Click(object sender, EventArgs e)
{
    string windowTitle = "Untitled - Notepad";
    AutomationElement result = getRootElement(windowTitle);

    if (result == null)
    {
        throw new ArgumentException();
    }
    Condition conditions = new AndCondition(
      new PropertyCondition(AutomationElement.IsEnabledProperty, true),
      new PropertyCondition(AutomationElement.ControlTypeProperty,
      ControlType.Document)
      );

    // Find all children that match the specified conditions.
    AutomationElementCollection elementCollection =
       result.FindAll(TreeScope.Children, conditions);
    //return elementCollection;

    foreach (AutomationElement x in elementCollection)
    {
        InsertTextUsingUIAutomation(x, "Hello World!");
    }
}


private AutomationElement getRootElement(string windowTitle)
{
    AutomationElement root = AutomationElement.RootElement;
    AutomationElement result = null;
    foreach (AutomationElement window in root.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window)))
    {
        try
        {
            if (window.Current.Name.Contains(windowTitle) && window.Current.IsKeyboardFocusable)
            {
                result = window;
                break;
            }
        }
        catch (Exception e)
        {
            //this will throw if a window has been closed since the start of the program.. no need to stop
        }
    }

    return result;
}


Condition conditions = new AndCondition(
  new PropertyCondition(AutomationElement.IsEnabledProperty, true),
  new PropertyCondition(AutomationElement.ControlTypeProperty,
      ControlType.Document)
  );

// Find all children that match the specified conditions.
AutomationElementCollection elementCollection =
    result.FindAll(TreeScope.Children, conditions);
//return elementCollection;

foreach (AutomationElement x in elementCollection)
{
    InsertTextUsingUIAutomation(x, "Hello World!");
}


C#
///--------------------------------------------------------------------
        /// <summary>
        /// Inserts a string into each text control of interest.
        /// </summary>
        /// <param name="element">A text control.</param>
        /// <param name="value">The string to be inserted.</param>
        ///--------------------------------------------------------------------
        private void InsertTextUsingUIAutomation(AutomationElement element, string value)
        {
            try
            {
                // Validate arguments / initial setup
                if (value == null)
                    throw new ArgumentNullException(
                        "String parameter must not be null.");

                if (element == null)
                    throw new ArgumentNullException(
                        "AutomationElement parameter must not be null");

                // A series of basic checks prior to attempting an insertion.
                //
                // Check #1: Is control enabled?
                // An alternative to testing for static or read-only controls
                // is to filter using
                // PropertyCondition(AutomationElement.IsEnabledProperty, true)
                // and exclude all read-only text controls from the collection.
                if (!element.Current.IsEnabled)
                {
                    throw new InvalidOperationException(
                        "The control with an AutomationID of "
                        + element.Current.AutomationId.ToString()
                        + " is not enabled.\n\n");
                }

                // Check #2: Are there styles that prohibit us
                //           from sending text to this control?
                if (!element.Current.IsKeyboardFocusable)
                {
                    throw new InvalidOperationException(
                        "The control with an AutomationID of "
                        + element.Current.AutomationId.ToString()
                        + "is read-only.\n\n");
                }


                // Once you have an instance of an AutomationElement,
                // check if it supports the ValuePattern pattern.
                object valuePattern = null;

                // Control does not support the ValuePattern pattern
                // so use keyboard input to insert content.
                //
                // NOTE: Elements that support TextPattern
                //       do not support ValuePattern and TextPattern
                //       does not support setting the text of
                //       multi-line edit or document controls.
                //       For this reason, text input must be simulated
                //       using one of the following methods.
                //
                if (!element.TryGetCurrentPattern(
                    ValuePattern.Pattern, out valuePattern))
                {
                    richTextBox1.AppendText("The control with an AutomationID of ");
                    richTextBox1.AppendText(element.Current.AutomationId.ToString());
                    richTextBox1.AppendText(" does not support ValuePattern.");
                    richTextBox1.AppendText(" Using keyboard input.\n");

                    // Set focus for input functionality and begin.
                    element.SetFocus();

                    // Pause before sending keyboard input.
                    Thread.Sleep(100);

                    // Delete existing content in the control and insert new content.
                    SendKeys.SendWait("^{HOME}");   // Move to start of control
                    SendKeys.SendWait("^+{END}");   // Select everything
                    SendKeys.SendWait("{DEL}");     // Delete selection
                    SendKeys.SendWait(value);
                }
                // Control supports the ValuePattern pattern so we can
                // use the SetValue method to insert content.
                else
                {
                    //string currVal = ((ValuePattern)valuePattern).Current.Value.ToString();
                    richTextBox1.AppendText("The control with an AutomationID of ");
                    richTextBox1.AppendText(element.Current.AutomationId.ToString());
                    richTextBox1.AppendText((" supports ValuePattern."));
                    richTextBox1.AppendText(" Using ValuePattern.SetValue().\n");

                    // Set focus for input functionality and begin.
                    element.SetFocus();

                    ((ValuePattern)valuePattern).SetValue(value);

                }
            }
            catch (ArgumentNullException exc)
            {
                richTextBox1.AppendText(exc.Message);
            }
            catch (InvalidOperationException exc)
            {
                richTextBox1.AppendText(exc.Message);
            }
            finally
            {
                richTextBox1.AppendText("");
            }
        }
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900