I need to automate common activities for a few programs, such as Microsoft Word. The testings are not for commercial use, but for regression testing.
Until now I would just move my mouse, and send a left mouse click above the button. However, our program verifies that the button is in "Pressed" state. When the automation presses the button with a mouse click, the button is not pressed (The button does not "sink")
Why is that? How do I cause the automated mouse click to cause the button to be "Pressed" just like a normal mouse click?
In this case, BTW, I am referring to the "Save" button in the quick tool bar.
The code I am using is pretty simple - First I find the object I want to click on, and then this code is used;
public void MouseClick(params string[] args)
{
AutomationElement automationElement = elementUtils.FindObjectFullPath(args[1], args[4], args[5]);
string action = args[args.Length - 1];
if (automationElement == null)
return;
FocusApplicationExp(automationElement);
try
{
int x = (int)automationElement.GetClickablePoint().X;
int y = (int)automationElement.GetClickablePoint().Y;
MouseMoveExp(x, y);
MouseAction(action, automationElement);
}
catch (Exception)
{
Console.WriteLine("Failed to get clickable point for " + automationElement.Current.Name + " - Trying to get coordinates of bounding rectangle");
tl.AddLine("Failed to get clickable point for " + automationElement.Current.Name + " - Trying to get coordinates of bounding rectangle");
res.AddLine("Failed to get clickable point for " + automationElement.Current.Name + " - Trying to get coordinates of bounding rectangle");
int x = (int)(automationElement.Current.BoundingRectangle.Right - automationElement.Current.BoundingRectangle.Width / 2);
int y = (int)(automationElement.Current.BoundingRectangle.Bottom - automationElement.Current.BoundingRectangle.Height / 2);
MouseMoveExp(x, y);
MouseAction(action, automationElement);
return;
}
}
private void MouseAction(string action, AutomationElement automationElement)
{
switch (action)
{
case "Left":
Console.WriteLine("Left clicking on: " + automationElement.Current.Name);
tl.AddLine("Left clicking on: " + automationElement.Current.Name);
AutomationUtility.DoMouseClick();
res.AddLine("Left clicked on: " + automationElement.Current.Name);
break;
case "Right":
Console.WriteLine("Right clicking on: " + automationElement.Current.Name);
tl.AddLine("Right clicking on: " + automationElement.Current.Name);
AutomationUtility.DoMouseRightClick();
res.AddLine("Right clicked on: " + automationElement.Current.Name);
break;
case "Double":
Console.WriteLine("Double clicking on: " + automationElement.Current.Name);
tl.AddLine("Double clicking on: " + automationElement.Current.Name);
AutomationUtility.DoMouseDoubleClick();
res.AddLine("Double clicked on: " + automationElement.Current.Name);
break;
default:
break;
}
}
public static void DoMouseClick()
{
Mouse.Click(MouseButton.Left);
}
And I did try a few variations, such as giving some delay between button down and up, in case the event happened but too quick. But the button never enters "Pressed" state even if I keep the button down (in the automation, of course)
Just to be more clear - The automation DOES work, it DOES click the button, and it DOES cause word to save. The issue here is to cause the button to be pressed visually (and program-wise, change it's state).
I am not sure if it means anything, but the system that identifies the button states and events is "UX", and the Win32-based identifier DOES find the "pressed" state somehow.
EDIT: I have been reading up on it for the past few days and things are becoming clearer. The automation I use is based on UIAutomation, but the button state "Pressed" is a MSAA state that did not move onto the UIAutomation generation of UI objects, so UIAutomation-based automation does not invoke this state. In other words, I need to find a way to use UIAutomation code to send MSAA signals to UIAutomation elements (That contain the IAccessible interface). Problem is, it is only supported the other way around (Send UIAutomation signals masked as MSAA signals to MSAA elements, which does not support MSAA-Only signals, such as "Enter state Pressed")