18using System.Collections.Generic;
19using System.Collections.ObjectModel;
20using System.Diagnostics;
23using System.Runtime.InteropServices;
24using System.Text.RegularExpressions;
25using System.Threading;
27using System.Windows.Automation;
28using System.Windows.Forms;
30using OpenQA.Selenium.Interactions;
31using OpenQA.Selenium.Support.UI;
34using Condition = System.Windows.Automation.Condition;
39 internal class ElementHelper
41 delegate ReadOnlyCollection<GPALAutomationElement> FindElementsByDelegate(Application application, SelectorPathEntry selectorPath,
bool searchForSelector =
true, AutomationElement element =
null);
44 static byte ScanCode {
get; } = 0;
47 static List<string> listOfMessages =
new List<string>();
48 static bool supressedMessage =
false;
49 static Selector lastSelector =
null;
63 public static ReadOnlyCollection<GPALAutomationElement> FindElements(Application application, UnitOfWork currentUOW, Selector selector, out
bool matchedAll, out List<GPALAutomationElement> matchedElements, AutomationElement automationElement =
null,
bool callIfHandler =
true)
67 string elementStringToMatch =
null;
68 ReadOnlyCollection<GPALAutomationElement> retElems =
null;
69 List<GPALAutomationElement> matchedElems =
new List<GPALAutomationElement>();
70 MatchCollection mc =
null;
71 ReadOnlyCollection<GPALAutomationElement> allFoundElems =
null;
72 List<GPALAutomationElement> totalAllFoundElems =
new List<GPALAutomationElement>();
73 List<GPALAutomationElement> iterateOverTheseElements =
null;
74 bool tryNextSelector =
false;
76 string message =
string.Empty;
81 matchedElements =
new List<GPALAutomationElement>();
83 currentUOW.CurrentSelector = selector;
85 if (
false == lastSelector?.Name.Equals(selector.Name))
87 listOfMessages.Clear();
88 supressedMessage =
false;
89 lastSelector = selector;
91 else if (
null == lastSelector)
92 lastSelector = selector;
96 List<FindElementsByDelegate> functionList =
new List<FindElementsByDelegate> {
null , FindElementsByCSS, FindElementsByImage, FindElementsByText, FindElementsByValue, FindElementsByXPath, FindElementsByName, FindElementsByAutomationID, FindElementsByClassName };
98 foreach (SelectorSettings.SelectorPathEntry selectorPathEntry in selector.SelectorPaths)
101 int textLength = selectorPathEntry.SelectorPath.Length - 1;
102 string abbreviatedText = selectorPathEntry.SelectorPath.Substring(0, Math.Min(7, textLength)) +
"..." + selectorPathEntry.SelectorPath.Substring(Math.Max(0, textLength - 7));
103 if (18 > selectorPathEntry.SelectorPath.Length)
104 abbreviatedText = selectorPathEntry.SelectorPath;
106 int idx = GetIndexOfEnum<SelectorPathType>((
int)selectorPathEntry.SelectorPathType);
107 tryNextSelector =
false;
108 string errorMessage = $
"Error finding elements for selector [{selector.Name}][{abbreviatedText}]";
112 message = $
"Searching for elements for selector [{selector.Name}] using [{selectorPathEntry.SelectorPathType}] [{abbreviatedText}]";
114 if (
false == listOfMessages.Contains(message))
116 listOfMessages.Add(message);
117 GPAL.PublishSimpleEvent(GPALEventType.INFO, message, application, GPALObjectType.Application);
120 allFoundElems = functionList[idx](application, selectorPathEntry, selector.SearchForSelector, automationElement);
123 if (
null == allFoundElems || 0 == (allFoundElems?.Count ?? 0))
125 GPAL.PublishSimpleEvent(GPALEventType.INFO, $
"{errorMessage}. Null set returned. retrying.", application, GPALObjectType.Application);
129 totalAllFoundElems.AddRange(allFoundElems.ToList());
131 #region <Element Matching>
132 if (0 < selector.MatchCriteria.Count)
134 foreach (SelectorSettings.MatchCriteriaEntry matchCriteriaEntry in selector.MatchCriteria)
136 if (MatchType.Custom == matchCriteriaEntry.MatchType)
139 CallIfStatus handled = matchCriteriaEntry.AppMatchingFunction(allFoundElems.ToList(), out matchedElems, out matchedAll, selector, matchCriteriaEntry.ExactMatch);
141 if (CallIfStatus.Terminate == handled)
143 string msg = $
"Custom match handler [{matchCriteriaEntry.AppMatchingFunction.GetInvocationList()[0].Method.Name}] requested program termination for selector {selector.Name} path [{selectorPathEntry.SelectorPath}].";
144 GPAL.PublishSimpleEvent(GPALEventType.WARNING, msg, application, GPALObjectType.Application);
145 throw new GPALException(msg);
149 matchedElements.AddRange(matchedElems);
150 matchedElements = matchedElements.Distinct().ToList();
152 if (CallIfStatus.Handled == handled)
154 else if (CallIfStatus.TryNext == handled)
156 tryNextSelector =
true;
162 if (
true == tryNextSelector)
167 if (0 == matchedElements.Count)
168 iterateOverTheseElements =
new List<GPALAutomationElement>(allFoundElems);
170 iterateOverTheseElements =
new List<GPALAutomationElement>(matchedElements);
173 for (idx = 0; idx < iterateOverTheseElements.Count; idx++)
175 GPALAutomationElement automationElement2 = iterateOverTheseElements[idx];
178 for (
int matchIdx = 0; matchIdx < selector.MatchCriteria.Count; matchIdx++)
180 SelectorSettings.MatchCriteriaEntry matchCriteriaEntry = selector.MatchCriteria[matchIdx];
182 if (MatchType.None != matchCriteriaEntry.MatchType)
187 switch ((MatchType)((
int)matchCriteriaEntry.MatchType & 0XFE))
190 elementStringToMatch = automationElement2.Ae.GetText();
193 elementStringToMatch = automationElement2.Ae.GetText();
196 elementStringToMatch = automationElement2.Ae.GetText();
198 case MatchType.Value:
199 elementStringToMatch = automationElement2.Ae.GetText();
203 if (1 == ((
int)MatchType.Regex & (
int)matchCriteriaEntry.MatchType))
206 mc = Regex.Matches(elementStringToMatch, matchCriteriaEntry.StringToMatch);
208 matchedElems.Add(automationElement2);
212 if (
false == matchCriteriaEntry.ExactMatch && elementStringToMatch.Contains(matchCriteriaEntry.StringToMatch))
213 matchedElems.Add(automationElement2);
214 else if (
true == matchCriteriaEntry.ExactMatch && elementStringToMatch.Equals(matchCriteriaEntry.StringToMatch))
215 matchedElems.Add(automationElement2);
219 if (criteriaCnt == matchedElems.Count)
220 matchedElements.AddRange(matchedElems.Distinct());
222 matchedElements = matchedElements.Distinct().ToList();
223 matchedAll = (allFoundElems.Count == foundCount);
228 matchedElems = allFoundElems?.ToList() ??
new List<GPALAutomationElement>();
229 matchedElements = matchedElems;
231 #endregion <Element Matching>
236 GPAL.PublishSimpleEvent(GPALEventType.EXCEPTION, $
"Exception thrown trying to find elements for selector [{selector.Name}]. Continuing.", currentUOW, GPALObjectType.UnitOfWork, ex);
242 if (
int.MaxValue != currentUOW.WithAllThatMatch && 0 < matchedElements?.Count)
245 List<GPALAutomationElement> tmpList =
new List<GPALAutomationElement>();
248 while (elemIdx < Math.Min((
int)currentUOW.WithAllThatMatch, (
int)matchedElements?.Count))
249 tmpList.Add(matchedElements[elemIdx++]);
251 matchedElements = tmpList;
254 selectorPathEntry.AppSelectorFoundResults = allFoundElems?.ToList() ??
new List<GPALAutomationElement>();
255 selectorPathEntry.AppSelectorMatchedResults = matchedElems;
257 retElems =
new ReadOnlyCollection<GPALAutomationElement>(totalAllFoundElems.Distinct().ToList());
259 foreach (GPALAutomationElement element
in retElems)
261 element.Application = application;
262 element.Selector = selector;
265 foreach (GPALAutomationElement element
in matchedElements)
267 element.Application = application;
268 element.Selector = selector;
271 if (
true == retry && 0 < retries--)
277 selector.ElementsFoundAndMatchedCount = matchedElements.Count();
279 message = $
"[{retElems?.Count ?? 0}] elements found for selector [{selector.Name}]";
281 if (
false == listOfMessages.Contains(message))
283 listOfMessages.Add(message);
284 GPAL.PublishSimpleEvent(GPALEventType.INFO, message, application, GPALObjectType.Application);
286 if (0 < retElems?.Count && (
true == selector.AnyMatchCriteria() || Int32.MaxValue != currentUOW.WithAllThatMatch))
288 var matchCount = selector.MatchCriteria.Count > 0 ? selector.MatchCriteria.Count.ToString() : $
"WithAllThatMatch({currentUOW.WithAllThatMatch})";
290 if ((
true == matchCount.Contains(
"WithAllThatMatch") && 1 < currentUOW.WithAllThatMatch) || 0 < selector.MatchCriteria.Count)
291 GPAL.PublishSimpleEvent(GPALEventType.INFO, $
"[{matchedElements.Count}] elements matched for selector [{selector.Name}] with [{matchCount}] match criteria", application, GPALObjectType.Application);
294 else if (
false == supressedMessage)
296 GPAL.PublishSimpleEvent(GPALEventType.INFO,
"Supressing repeat messages", application, GPALObjectType.Application);
297 supressedMessage =
true;
303 if (
true == matchedAll || retElems.Count > 0)
309 if (
true == callIfHandler)
310 CallIfHandlers(application, currentUOW, allFoundElems, matchedElements, selector, matchedAll);
312 selector.ElementsFoundAndMatchedCount =
true == selector.AnyMatchCriteria() ? matchedElements.Count() : retElems.Count();
330 private static void CallIfHandlers(Application application, UnitOfWork currentUOW, ReadOnlyCollection<GPALAutomationElement> foundElements, List<GPALAutomationElement> matchedElements, Selector selector,
bool matchedAll)
333 string currentMethodName =
null;
342 if (0 < (foundElements?.Count ?? 0))
344 if (0 < selector.AppCallIfFound?.Count)
346 foreach (Application.CallIfDelegate func in selector.AppCallIfFound)
348 bool safeActionCalled = application.CurrentUOW.ActionCalled;
349 safeUOW = application.CurrentUOW;
350 application.CurrentUOW.ActionCalled =
true;
352 currentMethodName = func.Method.Name;
353 str = $
"Application Selector CallIfFound handler [{currentMethodName}] requested program termination on selector [{selector.Name}] [{selector.SelectorPaths[0].SelectorPath}]";
355 GPAL.PublishSimpleEvent(GPALEventType.INFO, $
"Invoking Selector CallIfFound [{func.Method.Name}]", application, GPALObjectType.Application);
357 selector.AppCallIfFoundHandled = func(application, foundElements?.Cast<IGPALAutomationElement>().ToList(), matchedElements?.Cast<IGPALAutomationElement>().ToList(), selector, matchedAll);
359 application.CurrentUOW = safeUOW;
360 application.CurrentUOW.ActionCalled = safeActionCalled;
362 if (CallIfStatus.NotHandled == selector.AppCallIfFoundHandled)
368 if (CallIfStatus.Terminate == selector.AppCallIfFoundHandled)
370 GPAL.PublishSimpleEvent(GPALEventType.INFO, str, application, GPALObjectType.Application);
371 throw new GPALException(str);
376 if (0 == selector.AppCallIfFoundHandled && 0 < currentUOW.AppCallIfFound.Count)
378 foreach (Application.CallIfDelegate func in currentUOW.AppCallIfFound)
380 safeUOW = application.CurrentUOW;
382 currentMethodName = func.Method.Name;
383 str = $
"Application UOW Selector CallIfFound handler [{currentMethodName}] requested program termination on selector [{selector.Name}] [{selector.SelectorPaths[0].SelectorPath}]";
385 GPAL.PublishSimpleEvent(GPALEventType.INFO, $
"Invoking UOW CallIfFound [{func.Method.Name}]", application, GPALObjectType.Application);
387 currentUOW.CallIfNotFoundHandled = func(application, foundElements?.Cast<IGPALAutomationElement>().ToList(), matchedElements?.Cast<IGPALAutomationElement>().ToList(), selector, matchedAll);
389 application.CurrentUOW = safeUOW;
391 if (CallIfStatus.NotHandled == currentUOW.CallIfNotFoundHandled)
397 if (CallIfStatus.Terminate == currentUOW.AppCallIfFoundHandled)
399 GPAL.PublishSimpleEvent(GPALEventType.INFO, str, application, GPALObjectType.Application);
400 throw new GPALException(str);
405 if (0 == currentUOW.AppCallIfFoundHandled && 0 < GPAL.GPALSettings.AppCallIfFoundList.Count)
407 foreach (Application.CallIfDelegate func in GPAL.GPALSettings.AppCallIfFoundList)
409 safeUOW = application.CurrentUOW;
411 currentMethodName = func.Method.Name;
412 str = $
"Gloabl CallIfFound handler [{currentMethodName}] requested program termination on selector [{selector.Name}] [{selector.SelectorPaths[0].SelectorPath}]";
414 GPAL.PublishSimpleEvent(GPALEventType.INFO, $
"Invoking Global CallIfFound [{func.Method.Name}]", application, GPALObjectType.Application);
416 GPAL.GPALSettings.AppCallIfFoundHandled = func(application, foundElements?.Cast<IGPALAutomationElement>().ToList(), matchedElements?.Cast<IGPALAutomationElement>().ToList(), selector, matchedAll);
418 application.CurrentUOW = safeUOW;
420 if (CallIfStatus.NotHandled == GPAL.GPALSettings.AppCallIfFoundHandled)
426 if (CallIfStatus.Terminate == GPAL.GPALSettings.AppCallIfFoundHandled)
428 GPAL.PublishSimpleEvent(GPALEventType.INFO, str, application, GPALObjectType.Browser);
429 throw new GPALException(str);
435 if (0 < selector.AppCallIfNotFound.Count)
437 foreach (Application.CallIfDelegate func in currentUOW.AppCallIfNotFound)
439 safeUOW = application.CurrentUOW;
441 currentMethodName = func.Method.Name;
442 str = $
"Application Selector CallIfNotFound handler [{currentMethodName}] requested program termination on selector [{selector.Name}] [{selector.SelectorPaths[0].SelectorPath}]";
444 GPAL.PublishSimpleEvent(GPALEventType.INFO, $
"Invoking Selector CallIfNotFound [{func.Method.Name}]", application, GPALObjectType.Application);
446 selector.AppCallIfNotFoundHandled = func(application, foundElements?.Cast<IGPALAutomationElement>().ToList(), matchedElements?.Cast<IGPALAutomationElement>().ToList(), selector, matchedAll);
448 application.CurrentUOW = safeUOW;
450 if (CallIfStatus.NotHandled == selector.AppCallIfNotFoundHandled)
456 if (CallIfStatus.Terminate == currentUOW.AppCallIfNotFoundHandled)
458 GPAL.PublishSimpleEvent(GPALEventType.INFO, str, application, GPALObjectType.Application);
459 throw new GPALException(str);
463 if (0 == selector.AppCallIfNotFoundHandled && 0 < currentUOW.AppCallIfNotFound.Count)
465 foreach (Application.CallIfDelegate func in currentUOW.AppCallIfNotFound)
467 safeUOW = application.CurrentUOW;
469 currentMethodName = func.Method.Name;
470 str = $
"Application UOW Selector CallIfNotFound handler [{currentMethodName}] requested program termination on selector ]{selector.Name}] [{selector.SelectorPaths[0].SelectorPath}]";
472 GPAL.PublishSimpleEvent(GPALEventType.INFO, $
"Invoking UOW CallIfNotFound [{func.Method.Name}]", application, GPALObjectType.Application);
474 currentUOW.AppCallIfNotFoundHandled = func(application, foundElements?.Cast<IGPALAutomationElement>().ToList(), matchedElements?.Cast<IGPALAutomationElement>().ToList(), selector, matchedAll);
476 application.CurrentUOW = safeUOW;
478 if (CallIfStatus.NotHandled == currentUOW.AppCallIfNotFoundHandled)
484 if (CallIfStatus.Terminate == currentUOW.AppCallIfNotFoundHandled)
486 GPAL.PublishSimpleEvent(GPALEventType.INFO, str, application, GPALObjectType.Application);
487 throw new GPALException(str);
492 if (0 == currentUOW.AppCallIfNotFoundHandled && 0 < GPAL.GPALSettings.AppCallIfNotFoundList.Count)
494 foreach (Application.CallIfDelegate func in GPAL.GPALSettings.AppCallIfNotFoundList)
496 safeUOW = application.CurrentUOW;
498 currentMethodName = func.Method.Name;
499 str = $
"Gloabl CallIfNotFound handler [{currentMethodName}] requested program termination on selector [{selector.Name}] [{selector.SelectorPaths[0].SelectorPath}]";
501 GPAL.PublishSimpleEvent(GPALEventType.INFO, $
"Invoking Global CallIfNotFound [{func.Method.Name}]", application, GPALObjectType.Application);
503 GPAL.GPALSettings.AppCallIfNotFoundHandled = func(application, foundElements?.Cast<IGPALAutomationElement>().ToList(), matchedElements?.Cast<IGPALAutomationElement>().ToList(), selector, matchedAll);
505 application.CurrentUOW = safeUOW;
507 if (CallIfStatus.NotHandled == GPAL.GPALSettings.AppCallIfNotFoundHandled)
513 if (CallIfStatus.Terminate == GPAL.GPALSettings.AppCallIfNotFoundHandled)
515 GPAL.PublishSimpleEvent(GPALEventType.INFO, str, application, GPALObjectType.Browser);
516 throw new GPALException(str);
520 if (
true == selector.StopOnNotFound ||
true == GPAL.StopOnNotFound)
522 str =
$@"{(true == selector.StopOnNotFound ? "selector.
" : "GPAL.
")}StopOnNotFound set, terminating on Not Found element for [{selector.Name}] [{selector.SelectorPaths[0].SelectorPath}]";
523 GPAL.PublishSimpleEvent(GPALEventType.INFO, str, application, GPALObjectType.Application);
524 throw new GPALException(str);
537 private static ReadOnlyCollection<GPALAutomationElement> FindElementsByImage(Application application, SelectorPathEntry selectorPath,
bool searchForSelector =
true, AutomationElement element =
null)
539 ReadOnlyCollection<GPALAutomationElement> elems =
null;
541 Rectangle foundImageBounds =
new Rectangle();
542 List<GPALAutomationElement> retElement =
new List<GPALAutomationElement>(); ;
544 if (
null == selectorPath.Image)
548 selectorPath.Image = Image.FromFile(selectorPath.SelectorPath);
552 GPAL.PublishSimpleEvent(GPALEventType.EXCEPTION, $
"Unable to load image for [{selectorPath.SelectorPath}]", application, GPALObjectType.Application, ex);
557 Image
template = selectorPath.Image;
558 foundImageBounds = ((ImageHelper)GPAL.ImageHelper).FindImage(selectorPath.SelectorPath, application);
576 if (
false == foundImageBounds.IsEmpty)
579 retElement.Add(
new GPALAutomationElement(
null,
new GPALElement(foundImageBounds.Location, foundImageBounds.Size, selectorPath.SelectorPathType.ToString(),
null,
"GPALElement")));
580 elems =
new ReadOnlyCollection<GPALAutomationElement>(retElement);
583 GPAL.PublishSimpleEvent(GPALEventType.ERROR, $
"Unable to find the image you are attempting to match.", application, GPALObjectType.Application);
595 private static ReadOnlyCollection<GPALAutomationElement> FindElementsByCSS(Application application, SelectorPathEntry selectorPath,
bool searchForElement =
true, AutomationElement element =
null)
597 GPAL.PublishSimpleEvent(GPALEventType.WARNING, $
"Find elements by CSS is not supported for applications.", application, GPALObjectType.Application);
610 private static ReadOnlyCollection<GPALAutomationElement> FindElementsByXPath(
611 Application application,
612 SelectorPathEntry selectorPath,
613 bool searchForElement =
true,
614 AutomationElement element =
null)
616 if (
string.IsNullOrWhiteSpace(selectorPath?.SelectorPath))
617 return new ReadOnlyCollection<GPALAutomationElement>(Array.Empty<GPALAutomationElement>());
619 AutomationElement current = element ?? application.RootAutomationElement;
621 return new ReadOnlyCollection<GPALAutomationElement>(Array.Empty<GPALAutomationElement>());
624 string[] tokens = selectorPath.SelectorPath.Split(
'/');
629 bool firstToken =
true;
631 foreach (
string token
in tokens)
633 if (
string.IsNullOrWhiteSpace(token))
continue;
635 string controlTypeStr = token;
636 var conditions =
new List<Condition>();
638 int attrStart = token.IndexOf(
'[');
641 controlTypeStr = token.Substring(0, attrStart);
644 string remaining = token.Substring(attrStart);
645 while (remaining.Contains(
"[@"))
647 int start = remaining.IndexOf(
"[@");
648 int end = remaining.IndexOf(
']', start);
649 if (end == -1)
break;
651 string attrSegment = remaining.Substring(start + 2, end - start - 2);
653 var parts = attrSegment.Split(
new char[] {
'=' }, 2);
655 if (parts.Length == 2)
657 string attrName = parts[0].Trim();
658 string value = parts[1].Trim().Trim(
'\'',
'"');
660 Condition cond = attrName.ToLowerInvariant()
switch
662 "name" =>
new PropertyCondition(AutomationElement.NameProperty, value),
663 "automationid" =>
new PropertyCondition(AutomationElement.AutomationIdProperty, value),
664 "classname" =>
new PropertyCondition(AutomationElement.ClassNameProperty, value),
669 conditions.Add(cond);
672 remaining = remaining.Substring(end + 1);
677 ControlType controlType = GetControlType(controlTypeStr);
678 if (controlType !=
null)
680 conditions.Add(
new PropertyCondition(AutomationElement.ControlTypeProperty, controlType));
683 if (conditions.Count == 0)
686 Condition finalCondition = conditions.Count == 1
688 :
new AndCondition(conditions.ToArray());
690 AutomationElement match =
null;
695 match = current.FindFirst(TreeScope.Element, finalCondition);
700 var found = current.FindAll(TreeScope.Children, finalCondition);
707 GPAL.PublishSimpleEvent(GPALEventType.ERROR,
708 $
"Unable to locate element for Selector {selectorPath.SelectorPath}, token '{token}'.",
709 application, GPALObjectType.Application);
710 return new ReadOnlyCollection<GPALAutomationElement>(Array.Empty<GPALAutomationElement>());
718 if (current.Current.ControlType == ControlType.MenuItem)
720 ExpandMenuItem(application, current);
724 return current !=
null
725 ?
new ReadOnlyCollection<GPALAutomationElement>(
new List<GPALAutomationElement> {
new GPALAutomationElement(current) })
726 : new ReadOnlyCollection<GPALAutomationElement>(Array.Empty<GPALAutomationElement>());
735 private static ControlType GetControlType(
string programmaticName)
737 if (
string.IsNullOrWhiteSpace(programmaticName))
741 _ = ControlType.Button.ToString();
744 if (Enum.TryParse<System.Windows.Automation.Peers.AutomationControlType>(programmaticName,
true, out var enumValue))
746 int id = (int)enumValue + 50000;
747 return ControlType.LookupById(
id);
751 return programmaticName.ToLowerInvariant()
switch
753 "window" => ControlType.Window,
754 "pane" => ControlType.Pane,
755 "button" => ControlType.Button,
756 "edit" => ControlType.Edit,
757 "textbox" => ControlType.Edit,
758 "combobox" => ControlType.ComboBox,
759 "list" => ControlType.List,
760 "listitem" => ControlType.ListItem,
761 "menuitem" => ControlType.MenuItem,
762 "tab" => ControlType.Tab,
763 "tabitem" => ControlType.TabItem,
764 "tree" => ControlType.Tree,
765 "treeitem" => ControlType.TreeItem,
766 "document" => ControlType.Document,
767 "group" => ControlType.Group,
768 "checkbox" => ControlType.CheckBox,
769 "radiobutton" => ControlType.RadioButton,
770 "hyperlink" => ControlType.Hyperlink,
771 "image" => ControlType.Image,
772 "spinner" => ControlType.Spinner,
773 "slider" => ControlType.Slider,
774 "statusbar" => ControlType.StatusBar,
775 "toolbar" => ControlType.ToolBar,
776 "datagrid" => ControlType.DataGrid,
777 "dataitem" => ControlType.DataItem,
862 private static ReadOnlyCollection<GPALAutomationElement> FindElementsByAutomationID(Application application, SelectorPathEntry selectorPath,
bool searchForElement =
true, AutomationElement element =
null)
864 return FindElementsBy(application, selectorPath, ConditionPropertyType.AutomationID, searchForElement, element);
874 private static ReadOnlyCollection<GPALAutomationElement> FindElementsByText(Application application, SelectorPathEntry selectorPath,
bool searchForElement =
true, AutomationElement element =
null)
876 return FindElementsBy(application, selectorPath, ConditionPropertyType.Value, searchForElement, element);
886 private static ReadOnlyCollection<GPALAutomationElement> FindElementsByValue(Application application, SelectorPathEntry selectorPath,
bool searchForElement =
true, AutomationElement element =
null)
888 return FindElementsBy(application, selectorPath, ConditionPropertyType.Value, searchForElement, element);
898 private static ReadOnlyCollection<GPALAutomationElement> FindElementsByName(Application application, SelectorPathEntry selectorPath,
bool searchForElement =
true, AutomationElement element =
null)
900 return FindElementsBy(application, selectorPath, ConditionPropertyType.Name, searchForElement, element);
910 private static ReadOnlyCollection<GPALAutomationElement> FindElementsByClassName(Application application, SelectorPathEntry selectorPath,
bool searchForElement =
true, AutomationElement element =
null)
912 return FindElementsBy(application, selectorPath, ConditionPropertyType.ClassName, searchForElement, element);
924 private static ReadOnlyCollection<GPALAutomationElement> FindElementsBy(Application application, SelectorPathEntry selectorPath, ConditionPropertyType conditionPropertyType,
bool searchForElement =
true, AutomationElement element =
null)
926 ReadOnlyCollection<GPALAutomationElement> elem;
929 elem = element.FindElements(selectorPath.SelectorPath, conditionPropertyType);
931 elem = application.RootAutomationElement.FindElements(selectorPath.SelectorPath, conditionPropertyType);
944 internal static void PublishToEventHandler(Application application, Selector selector, List<GPALAutomationElement> elements)
947 if (
true == selector.DeleteMe)
948 msg = $
"Ignoring selector {selector.Name} marked for deletion. Continuing.";
949 else if (
null == elements || 0 == elements.Count)
950 msg = $
"No elements found for selector {selector.Name}. Continuing.";
952 GPAL.PublishSimpleEvent(GPALEventType.INFO, msg, application, GPALObjectType.Application);
962 public static List<GPALAutomationElement> WaitFor(Application application,
int timeoutInTicks, out
bool matchedAll)
964 bool matchedAll2 =
true;
965 List<GPALAutomationElement> foundElements =
null;
966 List<GPALAutomationElement> tmpFoundElements =
null;
967 List<GPALAutomationElement> matchedElements;
969 foundElements =
new List<GPALAutomationElement>();
971 foreach (Selector selector
in application.CurrentUOW.WithSelectorList)
973 if (SelectorType.Selector != selector.SelectorType)
976 tmpFoundElements = WaitFor(application, selector, timeoutInTicks, out matchedAll2, out matchedElements);
978 tmpFoundElements = matchedElements;
981 if (
true == selector.DeleteMe ||
null == tmpFoundElements)
983 PublishToEventHandler(application, selector, tmpFoundElements);
989 foreach (GPALAutomationElement element
in tmpFoundElements)
991 foundElements.Add(element);
992 if (++rowCount >= application.CurrentUOW.WithAllThatMatch)
997 matchedAll = matchedAll2;
998 return foundElements;
1011 private static List<GPALAutomationElement> WaitFor(Application application, Selector selector,
int timeoutInTicks, out
bool matchedAll, out List<GPALAutomationElement> matchedElements, AutomationElement element =
null)
1013 bool matchedAll2 =
true, matchedAll3 =
true;
1014 List<GPALAutomationElement> matchedElements2;
1015 ReadOnlyCollection<GPALAutomationElement> elements = FindElements(application, application.CurrentUOW, selector, out matchedAll2, out matchedElements2, element);
1017 if (WaitTime.Forever == timeoutInTicks)
1018 timeoutInTicks = Int32.MaxValue;
1022 for (; 0 < timeoutInTicks && 0 == (elements?.Count ?? 0); timeoutInTicks -= 1000)
1024 elements = FindElements(application, application.CurrentUOW, selector, out matchedAll3, out matchedElements2, element);
1025 if (0 == elements.Count)
1026 Thread.Sleep(Math.Min(1000, timeoutInTicks));
1031 matchedAll = (matchedAll2 | matchedAll3);
1032 matchedElements = matchedElements2;
1034 return elements?.ToList<GPALAutomationElement>();
1044 public static void FillInFrom(Application application,
string useText, WriteMode writeMode)
1046 List<GPALAutomationElement> matchedElements;
1048 foreach (Selector selector
in application.CurrentUOW.WithSelectorList)
1050 if (SelectorType.Selector != selector.SelectorType)
1053 ReadOnlyCollection<GPALAutomationElement> elems = ElementHelper.FindElements(application, application.CurrentUOW, selector, out
bool matchedAll, out matchedElements);
1056 if (
true == selector.DeleteMe ||
null == elems)
1058 PublishToEventHandler(application, selector, elems?.ToList());
1062 if (
null != matchedElements)
1063 elems =
new ReadOnlyCollection<GPALAutomationElement>(matchedElements);
1067 foreach (GPALAutomationElement elem
in elems)
1069 if (
null != elem.Ae)
1071 bool isPassword = elem.Ae.Current.IsPassword;
1073 string abbreviatedText = useText[0] +
"..." + useText[useText.Length - 1];
1075 if (
false == isPassword)
1077 if (GPALEventType.DEBUG == (GPALEventType.DEBUG & GPAL.GPALSettings.DebugEvents) || GPALEventType.DEBUG == (GPALEventType.DEBUG & GPAL.GPALSettings.ConsoleEvents))
1078 GPAL.PublishSimpleEvent(GPALEventType.DEBUG, $
"[{writeMode}] text [{useText}] in element [{elem.Ae.Current.LocalizedControlType}][{selector.Name}]", application, GPALObjectType.Application);
1080 GPAL.PublishSimpleEvent(GPALEventType.INFO, $
"[{writeMode}] text [{abbreviatedText}] in element [{elem.Ae.Current.LocalizedControlType}][{selector.Name}]", application, GPALObjectType.Application);
1083 GPAL.PublishSimpleEvent(GPALEventType.INFO, $
"[{writeMode}] XXXpasswordXXX in element [{elem.Ae.Current.LocalizedControlType}][{selector.Name}]", application, GPALObjectType.Application);
1085 FillInFrom(application, elem.Ae,
new UnitOfWork.ElementNode() { OffsetX = selector.OffsetX, OffsetY = selector.OffsetY }, useText, writeMode);
1086 if (++rowCount >= application.CurrentUOW.WithAllThatMatch)
1091 UnitOfWork safeUOW = application.CurrentUOW;
1092 CallIfStatus handled = 0;
1095 IGPALGrid<string> tokens = GPAL.Grid.ToGPALObject();
1096 tokens.AddRow(
new List<string> { useText });
1097 if (
null != application.CurrentUOW.AppCallAfterFillIn)
1098 handled = application.CurrentUOW.AppCallAfterFillIn(application, tokens, 1);
1102 application.CurrentUOW = safeUOW;
1104 if (CallIfStatus.Terminate == handled)
1106 GPAL.PublishSimpleEvent(GPALEventType.INFO, $
"CallAfterFillIn handler [{application.CurrentUOW.AppCallAfterFillIn.GetInvocationList()[0].Method.Name}] requested program termination.", application, GPALObjectType.Application);
1107 throw new GPALException($
"CallAfterFillIn handler [{application.CurrentUOW.AppCallAfterFillIn.GetInvocationList()[0].Method.Name}] requested program termination.");
1118 internal static void Scroll(Application application,
object amount, ScrollTypes incrementsPercent, ScrollTypes horzVert)
1120 List<GPALAutomationElement> matchedElements;
1122 foreach (Selector selector
in application.CurrentUOW.WithSelectorList)
1124 if (SelectorType.Selector != selector.SelectorType)
1127 ReadOnlyCollection<GPALAutomationElement> elems = ElementHelper.FindElements(application, application.CurrentUOW, selector, out
bool matchedAll, out matchedElements);
1130 if (
true == selector.DeleteMe ||
null == elems)
1132 PublishToEventHandler(application, selector, elems?.ToList());
1136 if (
null != matchedElements)
1137 elems =
new ReadOnlyCollection<GPALAutomationElement>(matchedElements);
1141 foreach (GPALAutomationElement elem
in elems)
1143 if (
null != elem.Ae)
1145 Scroll(application, elem.Ae, selector.InteractionType, amount, incrementsPercent, horzVert);
1146 if (++rowCount >= application.CurrentUOW.WithAllThatMatch)
1162 internal static void Scroll(Application application, AutomationElement ae, InteractionType interactionType,
object amount, ScrollTypes incrementsPercent, ScrollTypes horzVert)
1165 if (Enums.InteractionType.Hardware == interactionType ||
true == application.applicationSettings.UseHardware)
1166 GPAL.PublishSimpleEvent(GPALEventType.INFO,
"Hardware scrolling is not supported at this time. Find the scroll controls and click them instead.", application, GPALObjectType.Application);
1170 if (
true == ae.TryGetCurrentPattern(RangeValuePattern.Pattern, out
object rangeValuePattern))
1172 ((RangeValuePattern)rangeValuePattern).SetValue((
double)amount);
1174 else if (
true == ae.TryGetCurrentPattern(ScrollPattern.Pattern, out
object scrollPattern))
1176 if (ScrollTypes.Percent == incrementsPercent)
1178 double hPercent = ScrollTypes.Horizontal == horzVert ? (double)amount : ScrollPatternIdentifiers.NoScroll;
1179 double vPercent = ScrollTypes.Vertical == horzVert ? (double)amount : ScrollPatternIdentifiers.NoScroll;
1182 ((ScrollPattern)scrollPattern).SetScrollPercent(hPercent, vPercent);
1184 catch (Exception ex)
1186 GPAL.PublishSimpleEvent(GPALEventType.EXCEPTION, $
"Unable to set SetScrollPercent on control [{ae.Current.ControlType.LocalizedControlType}].", application, GPALObjectType.Application, ex);
1191 ScrollAmount hAmount = ScrollTypes.Horizontal == horzVert ? (ScrollAmount)amount : ScrollAmount.NoAmount;
1192 ScrollAmount vAmount = ScrollTypes.Vertical == horzVert ? (ScrollAmount)amount : ScrollAmount.NoAmount;
1196 ((ScrollPattern)scrollPattern).Scroll(hAmount, vAmount);
1198 catch (Exception ex)
1200 GPAL.PublishSimpleEvent(GPALEventType.EXCEPTION, $
"Unable to Scroll on control [{ae.Current.ControlType.LocalizedControlType}].", application, GPALObjectType.Application, ex); ;
1216 internal static void FillInFrom(Application application, AutomationElement ae, UnitOfWork.ElementNode elementNode,
string useText, WriteMode writeMode)
1218 if (Enums.InteractionType.Hardware == elementNode.InteractionType ||
true == application.applicationSettings.UseHardware)
1219 HardwareFillInFrom(application,
new GPALAutomationElement(ae), elementNode.OffsetX, elementNode.OffsetY, useText, writeMode);
1264 if (
true == ae.TryGetCurrentPattern(ValuePattern.Pattern, out
object valuePattern))
1271 catch (Exception ex)
1273 GPAL.PublishSimpleEvent(GPALEventType.EXCEPTION, $
"Unable to set focus on control [{ae.Current.ControlType.LocalizedControlType}].", application, GPALObjectType.Application, ex);
1276 if (WriteMode.Overwrite == writeMode)
1277 ((ValuePattern)valuePattern).SetValue(useText);
1278 else if (WriteMode.Append == writeMode)
1280 string content = ((ValuePattern)valuePattern).Current.Value;
1282 ((ValuePattern)valuePattern).SetValue(content);
1284 else if (WriteMode.Insert == writeMode)
1286 string content = ((ValuePattern)valuePattern).Current.Value;
1288 ((ValuePattern)valuePattern).SetValue(content);
1293 if (
false == GPAL.NoFallbackRecoveryActions)
1295 GPAL.PublishSimpleEvent(GPALEventType.EXCEPTION, $
"Control [{ae.Current.ControlType.LocalizedControlType}] for ElementNode does not support ValuePattern. Using hardware input fallback.", application, GPALObjectType.Application);
1296 HardwareFillInFrom(application,
new GPALAutomationElement(ae), elementNode.OffsetX, elementNode.OffsetY, useText, writeMode);
1299 GPAL.PublishSimpleEvent(GPALEventType.EXCEPTION, $
"Control [{ae.Current.ControlType.LocalizedControlType}] for ElementNode does not support ValuePattern. Continuing.", application, GPALObjectType.Application);
1314 public static void HardwareFillInFrom(Application application, GPALAutomationElement element,
int offsetX,
int offsetY,
string text, WriteMode writeMode)
1316 ApplicationHelper.TopProcess(application.Process);
1318 HardwareFocus(application, element, offsetX, offsetY);
1320 if (WriteMode.Overwrite == writeMode)
1323 HardwareHelper.SendChar(
'a', ModifierKeys.Control,
true);
1327 else if (WriteMode.Append == writeMode)
1329 HardwareHelper.SendKey(GPAL.VK_END, ModifierKeys.Control);
1332 else if (WriteMode.Insert == writeMode)
1334 HardwareHelper.SendKey(GPAL.VK_HOME, ModifierKeys.Control);
1338 HardwareHelper.SendString(text, GPAL.TypingDelay);
1346 public static void Focus(Application application)
1348 List<GPALAutomationElement> matchedElements;
1350 foreach (Selector selector
in application.CurrentUOW.WithSelectorList)
1352 if (SelectorType.Selector != selector.SelectorType)
1355 ReadOnlyCollection<GPALAutomationElement> elems = ElementHelper.FindElements(application, application.CurrentUOW, selector, out
bool matchedAll, out matchedElements);
1358 if (
true == selector.DeleteMe ||
null == elems)
1360 PublishToEventHandler(application, selector, elems?.ToList());
1364 if (
null != matchedElements)
1365 elems =
new ReadOnlyCollection<GPALAutomationElement>(matchedElements);
1369 foreach (GPALAutomationElement elem
in elems)
1371 if (
null != elem.Ae)
1373 if (Enums.InteractionType.Hardware == selector.InteractionType ||
true == application.applicationSettings.UseHardware)
1375 int offsetX, offsetY;
1376 offsetX = selector.SelectorSettings.OffsetX;
1377 offsetY = selector.SelectorSettings.OffsetY;
1379 HardwareFocus(application, elem, offsetX, offsetY);
1386 if (
null != elem.Ae)
1389 HardwareFocus(application, elem, 0, 0);
1391 catch (Exception ex)
1393 GPAL.PublishSimpleEvent(GPALEventType.EXCEPTION, $
"Focus threw an excaption on selector [{selector.Name}].", application, GPALObjectType.Application, ex);
1397 if (++rowCount >= application.CurrentUOW.WithAllThatMatch)
1410 public static void Hover(Application application, UnitOfWork currentUOW)
1412 List<GPALAutomationElement> matchedElements;
1414 foreach (Selector selector
in currentUOW.WithSelectorList)
1416 if (SelectorType.Selector != selector.SelectorType)
1419 ReadOnlyCollection<GPALAutomationElement> elems = ElementHelper.FindElements(application, currentUOW, selector, out
bool matchedAll, out matchedElements);
1422 if (
true == selector.DeleteMe ||
null == elems)
1424 PublishToEventHandler(application, selector, elems?.ToList());
1428 if (
null != matchedElements)
1429 elems =
new ReadOnlyCollection<GPALAutomationElement>(matchedElements);
1433 foreach (GPALAutomationElement elem
in elems)
1435 if (
null != elem.Ae)
1437 if (0 == elem.Ae.Current.BoundingRectangle.Width && 0 == elem.Ae.Current.BoundingRectangle.Height)
1439 GPAL.PublishSimpleEvent(GPALEventType.WARNING, $
"Element has Zero Width and Height, skipping", application, GPALObjectType.Application);
1443 if (Enums.InteractionType.Hardware == selector.InteractionType ||
true == application.applicationSettings.UseHardware)
1446 HardwareMoveTo(application, elem, selector.OffsetX, selector.OffsetY);
1448 else if (0 != elem.Ae.Current.BoundingRectangle.Width && 0 != elem.Ae.Current.BoundingRectangle.Height)
1453 HardwareMoveTo(application, elem, selector.OffsetX, selector.OffsetY);
1455 catch (Exception ex)
1457 GPAL.PublishSimpleEvent(GPALEventType.EXCEPTION, $
"MoveToElement threw an excaption on selector [{selector.Name}], continuing.", application, GPALObjectType.Application, ex);
1458 HardwareMoveTo(application, elem, selector.OffsetX, selector.OffsetY);
1462 if (++rowCount >= application.CurrentUOW.WithAllThatMatch)
1473 public static void MoveTo(Application application)
1475 List<GPALAutomationElement> matchedElements;
1477 foreach (Selector selector
in application.CurrentUOW.WithSelectorList)
1479 if (SelectorType.Selector != selector.SelectorType)
1482 ReadOnlyCollection<GPALAutomationElement> elems = ElementHelper.FindElements(application, application.CurrentUOW, selector, out
bool matchedAll, out matchedElements);
1485 if (
true == selector.DeleteMe ||
null == elems)
1487 PublishToEventHandler(application, selector, elems?.ToList());
1491 if (
null != matchedElements)
1492 elems =
new ReadOnlyCollection<GPALAutomationElement>(matchedElements);
1496 foreach (GPALAutomationElement elem
in elems)
1498 if (InteractionType.Hardware == selector.InteractionType ||
null != elem.Gae)
1499 HardwareMoveTo(application, elem, selector.OffsetX, selector.OffsetY);
1500 else if (
null != elem.Ae)
1501 MoveTo(elem.Ae, selector.OffsetX, selector.OffsetY, application.Name);
1503 if (++rowCount >= application.CurrentUOW.WithAllThatMatch)
1517 private static void MoveTo(AutomationElement element,
int offsetX,
int offsetY,
string appName)
1523 catch (Exception ex)
1525 if (
false == GPAL.NoFallbackRecoveryActions)
1527 GPAL.PublishSimpleEvent(GPALEventType.EXCEPTION, $
"(ElementHelper): SetFocus threw an excaption in Application [{appName}], falling back to hardware mouse move.", element, GPALObjectType.Other, ex);
1528 HardwareMoveTo(
null,
new GPALAutomationElement(element), offsetX, offsetY);
1531 GPAL.PublishSimpleEvent(GPALEventType.EXCEPTION, $
"(ElementHelper): SetFocus threw an excaption in Application [{appName}], continuing.", element, GPALObjectType.Other, ex);
1542 private static void HardwareFocus(Application application, GPALAutomationElement element,
int OffsetX,
int OffsetY)
1544 if (
null != element.Ae && ControlType.Text == element.Ae.Current.ControlType)
1545 HardwareClick(application, element, ClickType.LeftClick, ModifierKeys.NONE, OffsetX, OffsetY);
1547 HardwareMoveTo(application, element, OffsetX, OffsetY);
1556 private static void HardwareMoveTo(Application application, GPALAutomationElement element,
int OffsetX,
int OffsetY)
1558 Rectangle rect2 =
new Rectangle(), iframeRect =
new Rectangle(0, 0, 0, 0);
1560 if (
null != element.Gae)
1561 rect2.Location = element.Gae.Location;
1564 rect2.Location =
new System.Drawing.Point((
int) element.Ae.Current.BoundingRectangle.Location.X, (
int) element.Ae.Current.BoundingRectangle.Location.Y);
1584 if (
true == GPAL.SimulateMouse ||
true == application.CurrentUOW.CurrentSelector?.SimulateMouse)
1585 HardwareHelper.MoveMouse(rect2.X + OffsetX, rect2.Y + OffsetY, 10, 10);
1587 HardwareHelper.MoveMouse(rect2.X + OffsetX, rect2.Y + OffsetY);
1594 public static void LeftClick(Application application, ModifierKeys modifierKeys = ModifierKeys.NONE)
1596 List<GPALAutomationElement> matchedElements;
1598 foreach (Selector selector
in application.CurrentUOW.WithSelectorList)
1600 if (SelectorType.Selector != selector.SelectorType)
1603 ReadOnlyCollection<GPALAutomationElement> elems = ElementHelper.FindElements(application, application.CurrentUOW, selector, out
bool matchedAll, out matchedElements);
1606 if (
true == selector.DeleteMe ||
null == elems)
1608 PublishToEventHandler(application, selector, elems?.ToList());
1612 if (
null != matchedElements)
1613 elems =
new ReadOnlyCollection<GPALAutomationElement>(matchedElements);
1617 foreach (GPALAutomationElement elem
in elems)
1619 Click(application, selector, elem, ClickType.LeftClick, modifierKeys);
1621 if (++rowCount >= application.CurrentUOW.WithAllThatMatch)
1632 public static bool GenericClick(Application application, ClickType clickType)
1634 List<GPALAutomationElement> matchedElements;
1635 bool matchedAll =
false;
1636 bool clickPerformed =
false;
1638 foreach (Selector sel
in application.CurrentUOW.WithSelectorList)
1640 if (SelectorType.Selector != sel.SelectorType)
1643 ElementHelper.FindElements(application, application.CurrentUOW, sel, out matchedAll, out matchedElements);
1645 if (
null != matchedElements)
1649 foreach (GPALAutomationElement elem
in matchedElements)
1651 Click(application, sel, elem, clickType, ModifierKeys.NONE);
1652 clickPerformed =
true;
1654 if (++rowCount >= application.CurrentUOW.WithAllThatMatch)
1659 return clickPerformed;
1670 public static void Click(Application application, Selector selector, GPALAutomationElement element, ClickType clickType, ModifierKeys modifierKeys)
1672 int offsetX, offsetY;
1673 offsetX = selector.SelectorSettings.OffsetX;
1674 offsetY = selector.SelectorSettings.OffsetY;
1676 if (Enums.InteractionType.Hardware == selector.InteractionType ||
null != element.Gae ||
true == application.applicationSettings.UseHardware)
1677 HardwareClick(application, element, clickType, modifierKeys, offsetX, offsetY);
1678 else if (
null != element.Ae)
1680 UIAutomationClick(application, selector, element, clickType, modifierKeys);
1693 public static void UIAutomationClick(Application application, Selector selector, GPALAutomationElement element, ClickType clickType, ModifierKeys modifierKeys)
1698 if (
true == element.Ae.TryGetCurrentPattern(InvokePattern.Pattern, out objPattern))
1700 ((InvokePattern)objPattern).Invoke();
1703 catch (Exception ex)
1705 GPAL.PublishSimpleEvent(GPALEventType.EXCEPTION, $
"Invoke Pattern failed, trying hardware click.", application, GPALObjectType.Application, ex);
1706 HardwareClick(application, element, clickType, modifierKeys, selector?.OffsetX ?? 5, selector?.OffsetY ?? 5);
1720 public static void HardwareClick(Application application, GPALAutomationElement element, ClickType clickType, ModifierKeys modifierKeys,
int OffsetX = 0,
int OffsetY = 0)
1722 int offsetX = 0, offsetY = 0;
1723 Rectangle rect, iframeRect =
new Rectangle(0,0,0,0);
1724 Random random =
new Random(10007);
1729 if (ModifierKeys.NONE != modifierKeys)
1730 HardwareHelper.PressModifierKey(modifierKeys);
1732 HardwareMoveTo(application, element, OffsetX, OffsetY);
1735 if (
null != element.Gae)
1736 rect =
new Rectangle(element.Gae.Location, element.Gae.Size);
1738 rect =
new Rectangle(
new System.Drawing.Point((
int)element.Ae.Current.BoundingRectangle.Location.X, (
int)element.Ae.Current.BoundingRectangle.Location.Y),
new System.Drawing.Size((
int)element.Ae.Current.BoundingRectangle.Size.Width, (
int)element.Ae.Current.BoundingRectangle.Size.Height));
1741 if (0 < rect.Width && 0 < rect.Height)
1742 if (0 == OffsetX && 0 == OffsetY)
1744 offsetX = random.Next(1, 0 != rect.Width ? rect.Width - 2 : 10);
1745 offsetY = random.Next(1, 0 != rect.Height ? rect.Height - 2 : 10);
1754 if (
null != element.Ae &&
true == element.Ae.TryGetClickablePoint(out System.Windows.Point clickablePoint))
1755 HardwareHelper.LeftClick((
int)clickablePoint.X, (
int)clickablePoint.Y);
1757 HardwareHelper.HardwareClick(rect.X + offsetX + iframeRect.X, rect.Y + offsetY + iframeRect.Y, clickType);
1765 if (ModifierKeys.NONE != modifierKeys)
1766 HardwareHelper.ReleaseModifierKeys(modifierKeys);
1775 public static void DragAndDrop(Application application, ModifierKeys modifierKeys = ModifierKeys.NONE)
1777 List<GPALAutomationElement> matchedElements;
1779 foreach (Selector selector
in application.CurrentUOW.WithSelectorList)
1781 if (SelectorType.Selector != selector.SelectorType)
1784 ReadOnlyCollection<GPALAutomationElement> elems = ElementHelper.FindElements(application, application.CurrentUOW, selector, out
bool matchedAll, out matchedElements);
1786 if (
true == selector.DeleteMe ||
null == elems)
1788 PublishToEventHandler(application, selector, elems?.ToList());
1792 if (
null != matchedElements)
1793 elems =
new ReadOnlyCollection<GPALAutomationElement>(matchedElements);
1797 foreach (GPALAutomationElement elem
in elems)
1801 if (
null != elem.Gae)
1802 rect =
new Rectangle(elem.Gae.Location, elem.Gae.Size);
1804 rect =
new Rectangle(
1805 new System.Drawing.Point((
int)elem.Ae.Current.BoundingRectangle.X, (
int)elem.Ae.Current.BoundingRectangle.Y),
1806 new System.Drawing.Size((
int)elem.Ae.Current.BoundingRectangle.Width, (
int)elem.Ae.Current.BoundingRectangle.Height));
1808 if (ModifierKeys.NONE != modifierKeys)
1809 HardwareHelper.PressModifierKey(modifierKeys);
1812 HardwareHelper.MouseDown(rect.X + selector.OffsetX, rect.Y + selector.OffsetY, ClickType.LeftClick);
1813 HardwareHelper.MouseUp(rect.X + selector.OffsetX + selector.DeltaX, rect.Y + selector.OffsetY + selector.DeltaY, ClickType.LeftClick);
1815 if (ModifierKeys.NONE != modifierKeys)
1816 HardwareHelper.ReleaseModifierKeys(modifierKeys);
1818 if (++rowCount >= application.CurrentUOW.WithAllThatMatch)
1831 public static void ExpandMenuItem(Application application, AutomationElement automationElement)
1833 if (
true == GPAL.SimulateMouse ||
true == application.CurrentUOW.CurrentSelector?.SimulateMouse)
1835 HardwareHelper.MoveMouse((
int)automationElement.Current.BoundingRectangle.X, (
int)automationElement.Current.BoundingRectangle.Y, 10, 10);
1836 HardwareHelper.LeftClick((
int)automationElement.Current.BoundingRectangle.X, (
int)automationElement.Current.BoundingRectangle.Y);
1843 ExpandCollapsePattern pattern = automationElement.GetCurrentPattern(ExpandCollapsePattern.Pattern) as ExpandCollapsePattern;
1846 catch (Exception ex)
1848 GPAL.PublishSimpleEvent(GPALEventType.EXCEPTION, $
"Unable to expand menuitem for Control [{automationElement.Current.LocalizedControlType}], trying InvokePattern.", application, GPALObjectType.Application, ex);
1851 InvokePattern pattern = automationElement.GetCurrentPattern(ExpandCollapsePattern.Pattern) as InvokePattern;
1854 catch (Exception ex2)
1856 GPAL.PublishSimpleEvent(GPALEventType.EXCEPTION, $
"Unable to expand menuitem for Control [{automationElement.Current.LocalizedControlType}], using hardware fallback.", application, GPALObjectType.Application, ex2);
1858 Random random =
new Random(10007);
1860 int offsetX = random.Next(1, (
int)automationElement.Current.BoundingRectangle.Width - 2);
1861 int offsetY = random.Next(1, (
int)automationElement.Current.BoundingRectangle.Height - 2);
1862 ElementHelper.HardwareClick(
null,
new GPALAutomationElement(automationElement), Enums.ClickType.LeftClick, Enums.ModifierKeys.NONE, offsetX, offsetY);
1871 public static void SwitchToTab(Application application)
1873 List<GPALAutomationElement> matchedElements;
1874 bool matchedAll =
false;
1876 foreach (Selector sel
in application.CurrentUOW.WithSelectorList)
1878 if (SelectorType.Selector != sel.SelectorType)
1881 ElementHelper.FindElements(application, application.CurrentUOW, sel, out matchedAll, out matchedElements);
1883 if (
null != matchedElements)
1887 foreach (GPALAutomationElement elem
in matchedElements)
1889 if (
null != elem.Ae &&
"TabControl" == elem.Ae.Current.LocalizedControlType)
1891 if (
true == elem.Ae.TryGetCurrentPattern(SelectionItemPattern.Pattern, out
object selectionPattern))
1895 ((SelectionItemPattern)selectionPattern).Select();
1897 catch (Exception ex)
1899 GPAL.PublishSimpleEvent(GPALEventType.WARNING, $
"Unable to use SelectionPattern to select the tab [{elem.Ae.Current.Name}], falling back on hardware click.", application, GPALObjectType.Application, ex);
1900 HardwareClick(application, elem, ClickType.LeftClick, ModifierKeys.NONE, sel.OffsetX, sel.OffsetY);
1904 HardwareClick(application, elem, ClickType.LeftClick, ModifierKeys.NONE, sel.OffsetX, sel.OffsetY);
1906 if (++rowCount >= application.CurrentUOW.WithAllThatMatch)
1919 public static void SetRange(Application application,
double rangeValue)
1921 List<GPALAutomationElement> matchedElements;
1922 bool matchedAll =
false;
1924 foreach (Selector sel
in application.CurrentUOW.WithSelectorList)
1926 if (SelectorType.Selector != sel.SelectorType)
1929 ElementHelper.FindElements(application, application.CurrentUOW, sel, out matchedAll, out matchedElements);
1931 if (
null != matchedElements)
1933 foreach (GPALAutomationElement elem
in matchedElements)
1935 if (
null == elem.Ae)
continue;
1937 if (
true == elem.Ae.TryGetCurrentPattern(RangeValuePattern.Pattern, out
object rangeValuePattern))
1941 ((RangeValuePattern)rangeValuePattern).SetValue(rangeValue);
1943 catch (Exception ex)
1945 GPAL.PublishSimpleEvent(GPALEventType.WARNING, $
"Unable to use RangeValuePattern to set value [{rangeValue}] on [{elem.Ae.Current.LocalizedControlType}].", application, GPALObjectType.Application, ex);
1948 else if (
true == elem.Ae.TryGetCurrentPattern(ValuePattern.Pattern, out
object valuePattern))
1952 ((ValuePattern)valuePattern).SetValue(rangeValue.ToString());
1954 catch (Exception ex)
1956 GPAL.PublishSimpleEvent(GPALEventType.WARNING, $
"Unable to use ValuePattern to set value [{rangeValue}] on [{elem.Ae.Current.LocalizedControlType}].", application, GPALObjectType.Application, ex);
1961 GPAL.PublishSimpleEvent(GPALEventType.WARNING, $
"Control [{elem.Ae.Current.LocalizedControlType}] does not support RangeValuePattern or ValuePattern - unable to set range value.", application, GPALObjectType.Application);
Settings for the current selector. Use this only for debugging.