├── .idea ├── .name ├── codeStyles │ └── codeStyleConfig.xml ├── vcs.xml ├── sbt.xml ├── modules.xml ├── encodings.xml ├── hydra.xml ├── libraries │ ├── Maven__org_ow2_asm_asm_5_0_2.xml │ └── Maven__xml_apis_xml_apis_1_0_b2.xml ├── checkstyle-idea.xml ├── compiler.xml ├── misc.xml └── jarRepositories.xml ├── docs ├── events.md ├── _config.yml ├── editbox.md ├── swt.md ├── swing.md ├── images │ ├── word.png │ ├── powerpoint.png │ └── delphi_toolbar.png ├── treewalker.md ├── panel.md ├── hyperlink.md ├── radiobutton.md ├── splitbutton.md ├── tab.md ├── calendar.md ├── textbox.md ├── treeview.md ├── application.md ├── statusbar.md ├── button.md ├── document.md ├── slider.md ├── combobox.md ├── custom.md ├── progressbar.md ├── window.md ├── checkbox.md ├── excel.md ├── word.md ├── examples.md ├── maskedit.md ├── toolbar.md ├── chrome.md ├── powerpoint.md ├── notepad.md ├── ribbon.md ├── caching.md ├── explorer.md ├── grids.md ├── windows-support.md ├── scala.md └── menus.md ├── _config.yml ├── apps ├── Project1.exe ├── GridsDemo.exe ├── SampleWpfApplication.exe └── WpfApplicationWithAutomationIds.exe ├── src ├── test │ ├── resources │ │ ├── locals_de.properties │ │ └── locals.properties │ └── java │ │ └── mmarquee │ │ └── automation │ │ ├── ControlTypeTest.java │ │ └── controls │ │ ├── AppBarTest.java │ │ ├── AutomationCustomTest.java │ │ ├── AutomationToolbarTest.java │ │ ├── AutomationStatusBarTest.java │ │ ├── TextBoxTest.java │ │ ├── AutomationNUIPaneTest.java │ │ ├── AutomationRibbonBarTest.java │ │ ├── AutomationRibbonWorkPaneTest.java │ │ └── AutomationRibbonCommandBarTest.java └── main │ ├── java │ └── mmarquee │ │ ├── automation │ │ ├── package-info.java │ │ ├── utils │ │ │ └── package-info.java │ │ ├── controls │ │ │ ├── package-info.java │ │ │ ├── mouse │ │ │ │ └── package-info.java │ │ │ ├── Slider.java │ │ │ ├── DocumentPage.java │ │ │ ├── PasswordEditBox.java │ │ │ ├── ReBar.java │ │ │ ├── Automatable.java │ │ │ ├── ImplementsFocus.java │ │ │ ├── Spinner.java │ │ │ ├── SplitButton.java │ │ │ ├── StatusBar.java │ │ │ ├── PowerpointSlide.java │ │ │ ├── Custom.java │ │ │ ├── RadioButton.java │ │ │ ├── ProgressBar.java │ │ │ ├── Image.java │ │ │ ├── AppBar.java │ │ │ ├── Calendar.java │ │ │ ├── DataGridCell.java │ │ │ ├── ImplementsClick.java │ │ │ ├── CheckBox.java │ │ │ ├── NetUIHWND.java │ │ │ ├── MaskedEdit.java │ │ │ ├── ImplementsLegacyIAccessible.java │ │ │ ├── CanRequestBasePattern.java │ │ │ ├── EditBox.java │ │ │ ├── TabItem.java │ │ │ ├── Hyperlink.java │ │ │ ├── ListItem.java │ │ │ ├── TreeViewItem.java │ │ │ ├── RibbonBar.java │ │ │ ├── TitleBar.java │ │ │ ├── RibbonCommandBar.java │ │ │ ├── ImplementsText.java │ │ │ ├── ImplementsTable.java │ │ │ ├── ImplementsToggle.java │ │ │ └── ImplementsGridItem.java │ │ ├── pattern │ │ │ ├── package-info.java │ │ │ ├── Pattern.java │ │ │ ├── PatternNotFoundException.java │ │ │ ├── Dock.java │ │ │ ├── Scroll.java │ │ │ ├── TableItem.java │ │ │ ├── Transform.java │ │ │ ├── ScrollItem.java │ │ │ └── MultipleView.java │ │ ├── ConversionFailure.java │ │ ├── AutomationEventHandler.java │ │ ├── MetaDataID.java │ │ ├── ItemNotFoundException.java │ │ └── ElementNotFoundException.java │ │ ├── uiautomation │ │ ├── package-info.java │ │ ├── IUIAutomationScrollItemPattern.java │ │ ├── IUIAutomationCondition.java │ │ ├── IUIAutomationTextRange2.java │ │ ├── IUIAutomationInvokePattern.java │ │ ├── IUIAutomationSpreadsheetPattern.java │ │ ├── IUIAutomationElement2.java │ │ ├── IUIAutomation6.java │ │ ├── IUIAutomationTextRange.java │ │ ├── IUIAutomationElement5.java │ │ ├── IUIAutomationElement8.java │ │ ├── IUIAutomationElement9.java │ │ ├── IUIAutomation4.java │ │ ├── IUIAutomation5.java │ │ ├── IUIAutomationExpandCollapsePattern.java │ │ ├── IUIAutomationStylesPattern.java │ │ ├── IUIAutomationTextPattern.java │ │ ├── IUIAutomationTextRangeArray.java │ │ ├── IUIAutomationElementArray.java │ │ ├── IUIAutomation3.java │ │ ├── IUIAutomationGridItemPattern.java │ │ ├── IUIAutomationElement4.java │ │ ├── IUIAutomationTablePattern.java │ │ ├── IUIAutomationValuePattern.java │ │ ├── IUIAutomationGridPattern.java │ │ ├── IUIAutomationSelectionPattern.java │ │ ├── IUIAutomationSelectionItemPattern.java │ │ ├── IUIAutomationBoolCondition.java │ │ ├── IUIAutomationSelectionPattern2.java │ │ ├── IUIAutomationItemContainerPattern.java │ │ ├── ExpandCollapseState.java │ │ ├── IUIAutomationTreeWalker.java │ │ ├── IUIAutomationTogglePattern.java │ │ ├── IUIAutomationElement6.java │ │ ├── IUIAutomationRangeValuePattern.java │ │ ├── ToggleState.java │ │ ├── RowOrColumnMajor.java │ │ └── WindowVisualState.java │ │ └── demo │ │ ├── TestBase.java │ │ ├── Main.java │ │ ├── MainGrid.java │ │ ├── Explorer.java │ │ ├── MainWPF.java │ │ ├── MainWord.java │ │ ├── Notepad.java │ │ ├── DemoChrome.java │ │ ├── MainExcel.java │ │ ├── MainCaching.java │ │ ├── MainPowerpoint.java │ │ ├── MainWPFAutomationId.java │ │ ├── ChromeDemo.java │ │ ├── PointerOver.java │ │ ├── EventHandler.java │ │ ├── TreeWalker.java │ │ └── DemoPointOver.java │ ├── resources │ └── log4j.properties │ └── scala │ └── mmarquee │ └── demo │ ├── PacketLoggerTest.scala │ ├── AutomationTest.scala │ ├── PacketLoggerApplication.scala │ ├── NotepadApplication.scala │ └── BaseApplication.scala ├── .travis.yml ├── deploy └── settings.xml └── README.md /.idea/.name: -------------------------------------------------------------------------------- 1 | ui-automation -------------------------------------------------------------------------------- /docs/events.md: -------------------------------------------------------------------------------- 1 | Not yet implemented -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-hacker -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-midnight -------------------------------------------------------------------------------- /docs/editbox.md: -------------------------------------------------------------------------------- 1 | # Discovery 2 | * See [Element Discovery](element-discovery.md) 3 | -------------------------------------------------------------------------------- /docs/swt.md: -------------------------------------------------------------------------------- 1 | Unfortunately it looks like `swt` is largely opaque to the automation APIs. -------------------------------------------------------------------------------- /apps/Project1.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmarquee/ui-automation/HEAD/apps/Project1.exe -------------------------------------------------------------------------------- /docs/swing.md: -------------------------------------------------------------------------------- 1 | Unfortunately it looks like `Swing` is largely opaque to the automation APIs. -------------------------------------------------------------------------------- /apps/GridsDemo.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmarquee/ui-automation/HEAD/apps/GridsDemo.exe -------------------------------------------------------------------------------- /docs/images/word.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmarquee/ui-automation/HEAD/docs/images/word.png -------------------------------------------------------------------------------- /docs/treewalker.md: -------------------------------------------------------------------------------- 1 | This uses the ContentViewWalker to get elements marked as being content elements. -------------------------------------------------------------------------------- /docs/images/powerpoint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmarquee/ui-automation/HEAD/docs/images/powerpoint.png -------------------------------------------------------------------------------- /apps/SampleWpfApplication.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmarquee/ui-automation/HEAD/apps/SampleWpfApplication.exe -------------------------------------------------------------------------------- /docs/images/delphi_toolbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmarquee/ui-automation/HEAD/docs/images/delphi_toolbar.png -------------------------------------------------------------------------------- /apps/WpfApplicationWithAutomationIds.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmarquee/ui-automation/HEAD/apps/WpfApplicationWithAutomationIds.exe -------------------------------------------------------------------------------- /src/test/resources/locals_de.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmarquee/ui-automation/HEAD/src/test/resources/locals_de.properties -------------------------------------------------------------------------------- /docs/panel.md: -------------------------------------------------------------------------------- 1 | # Discovery 2 | * See [Element Discovery](element-discovery.md) 3 | 4 | Panels (or Panes) are generic containers for other controls. 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | sudo: false 3 | jdk: 4 | - oraclejdk11 5 | script: mvn test -B 6 | after_success: mvn deploy --settings ~/deploy/settings.xml 7 | -------------------------------------------------------------------------------- /docs/hyperlink.md: -------------------------------------------------------------------------------- 1 | # Discovery 2 | * See [Element Discovery](element-discovery.md) 3 | 4 | ``` 5 | Hyperlink link = window.getHyperlink(Search.getBuilder(0).build()); 6 | link.click(); 7 | ``` -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/radiobutton.md: -------------------------------------------------------------------------------- 1 | # Discovery 2 | * See [Element Discovery](element-discovery.md) 3 | 4 | ``` 5 | RadioButton radio = window.getRadioButton(Search.getBuilder(1).build()); 6 | radio.selectItem(); 7 | ``` -------------------------------------------------------------------------------- /.idea/sbt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /docs/splitbutton.md: -------------------------------------------------------------------------------- 1 | # Discovery 2 | * See [Element Discovery](element-discovery.md) 3 | 4 | ``` 5 | SplitButton split = panes.getSplitButton(Search.getBuilder("Navigation pane").build()); 6 | split.click(); 7 | ``` -------------------------------------------------------------------------------- /docs/tab.md: -------------------------------------------------------------------------------- 1 | # Discovery 2 | * See [Element Discovery](element-discovery.md) 3 | 4 | # Example 5 | 6 | ``` 7 | Tab tab = applicationWindow.getTab(Search.getBuilder(0).build()); 8 | tab.selectTabPage("Details"); 9 | ``` -------------------------------------------------------------------------------- /src/test/resources/locals.properties: -------------------------------------------------------------------------------- 1 | pane=pane 2 | notepad.title=Untitled - Notepad 3 | systemmenu.name=System 4 | appmenu.name=Application 5 | menu.file=File 6 | menu.exit=Exit 7 | menu.exit.acc=x 8 | explorer.title=File Explorer 9 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Domain classes used to encapsulate the ms ui automation libraries. 3 | * 4 | * @since 0.4 5 | * @author Mark Humphreys 6 | * @version 0.4 7 | */ 8 | package mmarquee.automation; -------------------------------------------------------------------------------- /docs/calendar.md: -------------------------------------------------------------------------------- 1 | The Calendar control supports the Grid, Scroll, Table, Value and Selection patterns. 2 | 3 | ``` 4 | Calendar calendar = applicationWindow.getCalendar(Search.getBuilder(0).build()); 5 | logger.info("Date is " + calendar.name()); 6 | ``` -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/utils/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Domain classes used to encapsulate the ms ui automation libraries. 3 | * 4 | * @since 0.4 5 | * @author Mark Humphreys 6 | * @version 0.4 7 | */ 8 | package mmarquee.automation.utils; -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Domain classes used to encapsulate the raw ms ui automation interfaces. 3 | * 4 | * @since 0.4 5 | * @author Mark Humphreys 6 | * @version 0.4 7 | */ 8 | package mmarquee.uiautomation; 9 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Domain classes used to encapsulate the ms ui automation controls. 3 | * 4 | * @since 0.4 5 | * @author Mark Humphreys 6 | * @version 0.4 7 | */ 8 | package mmarquee.automation.controls; -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/pattern/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Domain classes used to encapsulate the ms ui automation patterns. 3 | * 4 | * @since 0.4 5 | * @author Mark Humphreys 6 | * @version 0.4 7 | */ 8 | package mmarquee.automation.pattern; -------------------------------------------------------------------------------- /deploy/settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ossrh 5 | \${env.OSSRH_USER} 6 | \${env.OSSRH_PASS} 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/textbox.md: -------------------------------------------------------------------------------- 1 | # Discovery 2 | * See [Element Discovery](element-discovery.md) 3 | 4 | # Example 5 | 6 | ``` 7 | TextBox tb0 = applicationWindow.getTextBox(Search.getBuilder(9).build()); 8 | String tb0Text = tb0.getValue(); 9 | logger.info("Text for text box 1 is " + tb0Text); 10 | ``` -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/mouse/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Domain classes used to encapsulate interaction with the mouse the ms ui automation libraries. 3 | * 4 | * @since 0.4 5 | * @author Mark Humphreys 6 | * @version 0.4 7 | */ 8 | package mmarquee.automation.controls.mouse; -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /docs/treeview.md: -------------------------------------------------------------------------------- 1 | # Discovery 2 | * See [Element Discovery](element-discovery.md) 3 | 4 | # Example 5 | ``` 6 | TreeView tree = window.getTreeView(Search.getBuilder(0).build()); 7 | 8 | TreeViewItem treeItem = tree.getItem(Search.getBuilder("Sub-SubItem").build()); 9 | treeItem.select(); 10 | ``` -------------------------------------------------------------------------------- /docs/application.md: -------------------------------------------------------------------------------- 1 | # Discovery 2 | * See [Element Discovery](element-discovery.md) 3 | 4 | # Methods 5 | 6 | ## quit 7 | 8 | Quits the application 9 | 10 | ## waitForInputIdle 11 | 12 | Waits of the application to accept input 13 | 14 | ## getWindow 15 | 16 | Gets a window, using the search criteria 17 | 18 | -------------------------------------------------------------------------------- /docs/statusbar.md: -------------------------------------------------------------------------------- 1 | # Discovery 2 | * See [Element Discovery](element-discovery.md) 3 | 4 | # Example 5 | 6 | ``` 7 | StatusBar statusBar = window.getStatusBar(); 8 | TextBox tb1 = statusBar.getTextBox(Search.getBuilder(1).build()); 9 | 10 | String eb1Text = tb1.getValue(); 11 | logger.info("Status Bar text = " + eb1Text); 12 | ``` -------------------------------------------------------------------------------- /docs/button.md: -------------------------------------------------------------------------------- 1 | # Discovery 2 | * See [Element Discovery](element-discovery.md) 3 | 4 | # Methods 5 | 6 | ## Name 7 | 8 | Gets the name of the button control 9 | 10 | ## Value 11 | 12 | Gets the value of the button, i.e. the text associated with it 13 | 14 | ## Click 15 | 16 | Calls the click event. 17 | 18 | ## Focus 19 | 20 | Sets the focus to the button control. -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # Set root logger level to DEBUG and its only appender to A1. 2 | log4j.rootLogger=INFO, A1 3 | 4 | # A1 is set to be a ConsoleAppender. 5 | log4j.appender.A1=org.apache.log4j.ConsoleAppender 6 | 7 | # A1 uses PatternLayout. 8 | log4j.appender.A1.layout=org.apache.log4j.PatternLayout 9 | log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n 10 | -------------------------------------------------------------------------------- /docs/document.md: -------------------------------------------------------------------------------- 1 | # Discovery 2 | * See [Element Discovery](element-discovery.md) 3 | 4 | ``` 5 | Document document = applicationWindow.getDocument(Search.getBuilder(0).build()); 6 | 7 | logger.info("Document name is `" + document.name() + "`"); 8 | logger.info("Text is " + document.getText()); 9 | 10 | String result = document.getSelection(); 11 | 12 | logger.info("Selection is " + result); 13 | ``` -------------------------------------------------------------------------------- /docs/slider.md: -------------------------------------------------------------------------------- 1 | # Discovery 2 | * See [Element Discovery](element-discovery.md) 3 | 4 | # Example 5 | 6 | ``` 7 | Slider slider = applicationWindow.getSlider(Search.getBuilder(0).build()); 8 | logger.info("Slider value = " + slider.getRangeValue()); 9 | 10 | // Set the value 11 | slider.setRangeValue(20); 12 | 13 | // Get the new valueOn 14 | logger.info("Slider value is now = " + slider.getRangeValue()); 15 | ``` -------------------------------------------------------------------------------- /.idea/hydra.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | -------------------------------------------------------------------------------- /docs/combobox.md: -------------------------------------------------------------------------------- 1 | # Discovery 2 | * See [Element Discovery](element-discovery.md) 3 | 4 | ``` 5 | ComboBox cb1 = window.getCombobox(Search.getBuilder("AutomatedCombobox1").build()); 6 | String oldTxt = cb1.text(); 7 | cb1.setText("Replacements"); 8 | String txt = cb1.text(); 9 | ``` 10 | 11 | # Methods 12 | 13 | ## Name 14 | 15 | Gets the name of the button control 16 | 17 | ## Value 18 | 19 | Gets the value of the button, i.e. the text associated with it -------------------------------------------------------------------------------- /docs/custom.md: -------------------------------------------------------------------------------- 1 | # Discovery 2 | * See [Element Discovery](element-discovery.md) 3 | 4 | The Custom control type covers a multitude of non-standard controls. Mostly these have been wrapped up in a single 5 | type - Custom, but where specific implementations are known, then sub-classes of Custom have been created - for 6 | example [Word](word.md) has a AutomationDocumentPage, which is different enough 7 | from a standard Custom 8 | control to have a specific implementation. -------------------------------------------------------------------------------- /docs/progressbar.md: -------------------------------------------------------------------------------- 1 | # Discovery 2 | * See [Element Discovery](element-discovery.md) 3 | 4 | ``` 5 | ProgressBar progress = applicationWindow.getProgressBar(Search.getBuilder(0).build()); 6 | logger.info("Progress = " + progress.getRangeValue()); 7 | 8 | if (progress.getIsReadOnly()) { 9 | logger.info("Progress range is read-only"); 10 | } else { 11 | progress.setRangeValue(50.0); 12 | logger.info("Progress is now = " + progress.getRangeValue()); 13 | } 14 | ``` -------------------------------------------------------------------------------- /docs/window.md: -------------------------------------------------------------------------------- 1 | * See [Element Discovery](element-discovery.md) 2 | 3 | Window is the ultimate container for an application, it may have menus and other control buttons that other controls do not have. 4 | 5 | # Methods 6 | 7 | ## SetTransparency 8 | 9 | This sets the `alpha attribute` of the window, allowing the automation API to indicate which window is beig processed (for example). 10 | 11 | ``` 12 | Window window = automation.getDesktopWindow("Form1"); 13 | window.setTransparency(128); 14 | ``` -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_ow2_asm_asm_5_0_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__xml_apis_xml_apis_1_0_b2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/Slider.java: -------------------------------------------------------------------------------- 1 | package mmarquee.automation.controls; 2 | 3 | /** 4 | * Wrapper for the Slider element. 5 | * 6 | * @author Mark Humphreys 7 | * Date 15/02/2016. 8 | * 9 | * IRangeProvider, ISelectionProvider, IValueProvider 10 | */ 11 | public final class Slider extends AutomationBase 12 | implements ImplementsRangeValue { 13 | 14 | /** 15 | * Construct the Slider. 16 | * @param builder The builder 17 | */ 18 | public Slider(final ElementBuilder builder) { 19 | super(builder); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/DocumentPage.java: -------------------------------------------------------------------------------- 1 | package mmarquee.automation.controls; 2 | 3 | /** 4 | * Represents a page in a document - i.e. a Word document. 5 | * 6 | * @author Mark Humphreys 7 | * Date 28/01/2017. 8 | * 9 | * It seems to be a specific set of custom elements. 10 | */ 11 | public final class DocumentPage extends Custom { 12 | /** 13 | * Constructor for the DocumentPage. 14 | * 15 | * @param builder The builder 16 | */ 17 | public DocumentPage(final ElementBuilder builder) { 18 | super(builder); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /docs/checkbox.md: -------------------------------------------------------------------------------- 1 | # Discovery 2 | * See [Element Discovery](element-discovery.md) 3 | 4 | ``` 5 | CheckBox check = window.getCheckBox(Search.getBuilder(0).build()); 6 | check.toggle(); 7 | 8 | try { 9 | ToggleState state = check.getToggleState(); 10 | logger.info("State: " + state); 11 | } catch (Exception ex) { 12 | logger.info("Failed to get toggle state"); 13 | } 14 | ``` 15 | 16 | # Methods 17 | 18 | ## Name 19 | 20 | Gets the name of the button control 21 | 22 | ## Value 23 | 24 | Gets the value of the button, i.e. the text associated with it 25 | 26 | ## Toggle 27 | ## ToggleState 28 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/demo/TestBase.java: -------------------------------------------------------------------------------- 1 | package mmarquee.demo; 2 | 3 | import mmarquee.automation.controls.AutomationBase; 4 | import org.apache.logging.log4j.LogManager; 5 | import org.apache.logging.log4j.Logger; 6 | 7 | /** 8 | * @author Mark Humphreys 9 | * Date 19/05/2016. 10 | */ 11 | public class TestBase { 12 | 13 | protected Logger logger = 14 | LogManager.getLogger(AutomationBase.class.getName()); 15 | 16 | protected void rest() { 17 | try { 18 | Thread.sleep(1500); 19 | } catch (Exception ex) { 20 | logger.info("Interrupted"); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.idea/checkstyle-idea.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/PasswordEditBox.java: -------------------------------------------------------------------------------- 1 | package mmarquee.automation.controls; 2 | 3 | import mmarquee.automation.AutomationException; 4 | 5 | /** 6 | * Wrapper around the PasswordEditBox control. 7 | */ 8 | public final class PasswordEditBox extends EditBox { 9 | 10 | /** 11 | * The class name. 12 | */ 13 | public static final String CLASS_NAME = "PasswordBox"; 14 | 15 | /** 16 | * Construct the PasswordEditBox. 17 | * @param builder The builder 18 | * @throws AutomationException Error in automation library 19 | */ 20 | public PasswordEditBox(final ElementBuilder builder) 21 | throws AutomationException { 22 | super(builder); 23 | assertClassName(CLASS_NAME); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /docs/excel.md: -------------------------------------------------------------------------------- 1 | Assuming that the application has already been started, the following code shows how to get data out of cells. 2 | 3 | ``` 4 | Window window = application.getWindow("Book1 - Excel"); 5 | logger.info(window.name()); 6 | 7 | Panel panelX = window.getPanelByClassName(0, "XLDESK"); 8 | logger.info(panelX.name()); 9 | logger.info(panelX.getClassName()); 10 | 11 | Tab tab = panelX.getTab(Search.getBuilder(0).build()); 12 | logger.info(tab.name()); 13 | DataGrid grid = tab.getDataGrid(Search.getBuilder(0).build()); 14 | logger.info(grid.name()); 15 | 16 | // Get some data 17 | DataGridCell cell = grid.getItem(0,0); 18 | logger.info(cell.name()); 19 | logger.info(cell.value()); 20 | ``` 21 | 22 | NOTE: The call to getPanelByClassName is only available post release 0.3.10 -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/ReBar.java: -------------------------------------------------------------------------------- 1 | package mmarquee.automation.controls; 2 | 3 | import mmarquee.automation.AutomationException; 4 | 5 | /** 6 | * Specialised type of pane, with a specific control name. 7 | * 8 | * @author Mark Humphreys 9 | * Date 02/03/2016. 10 | * 11 | */ 12 | public final class ReBar extends Panel { 13 | 14 | /** 15 | * The class name. 16 | */ 17 | public final static String CLASS_NAME = "ReBarWindow32"; 18 | 19 | /** 20 | * Construct the ReBar. 21 | * 22 | * @param builder The builder 23 | * @throws AutomationException Automation library error 24 | */ 25 | public ReBar(final ElementBuilder builder) 26 | throws AutomationException { 27 | super(builder); 28 | assertClassName(CLASS_NAME); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/demo/Main.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.demo; 18 | 19 | public class Main { 20 | 21 | public static void main(String[] args) { 22 | TestMain main = new TestMain(); 23 | 24 | main.run(); 25 | } 26 | } -------------------------------------------------------------------------------- /src/main/java/mmarquee/demo/MainGrid.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.demo; 17 | 18 | public class MainGrid { 19 | 20 | public static void main(String[] args) { 21 | DemoGrid main = new DemoGrid(); 22 | 23 | main.run(); 24 | } 25 | } -------------------------------------------------------------------------------- /src/main/java/mmarquee/demo/Explorer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.demo; 18 | 19 | public class Explorer { 20 | 21 | public static void main(String[] args) { 22 | TestExplorer main = new TestExplorer(); 23 | 24 | main.run(); 25 | } 26 | } -------------------------------------------------------------------------------- /src/main/java/mmarquee/demo/MainWPF.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.demo; 18 | 19 | public class MainWPF { 20 | 21 | public static void main(String[] args) { 22 | TestMainWPF main = new TestMainWPF(); 23 | 24 | main.run(); 25 | } 26 | } -------------------------------------------------------------------------------- /src/main/java/mmarquee/demo/MainWord.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.demo; 17 | 18 | public class MainWord { 19 | 20 | public static void main(String[] args) { 21 | TestMainWord main = new TestMainWord(); 22 | 23 | main.run(); 24 | } 25 | } -------------------------------------------------------------------------------- /src/main/java/mmarquee/demo/Notepad.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.demo; 17 | 18 | public class Notepad { 19 | 20 | public static void main(String[] args) { 21 | TestNotepad notepad = new TestNotepad(); 22 | 23 | notepad.run(); 24 | } 25 | } -------------------------------------------------------------------------------- /docs/word.md: -------------------------------------------------------------------------------- 1 | `Word` has a nice control hierarchy, and uses 'Pages' which are Custom controls. 2 | 3 | ![UISpy for Word](images/word.png) 4 | 5 | ``` 6 | Window window = application.getWindow(Search.getBuilder("Document1 - Word").build()); 7 | logger.info(window.name()); 8 | 9 | Panel pane = window.getPanel(Search.getBuilder("Document1").build()); 10 | logger.info(pane.name()); 11 | logger.info(pane.getClassName()); 12 | Panel pane1 = pane.getPanel(Search.getBuilder(0).build()); 13 | logger.info(pane1.name()); 14 | 15 | Document doc = pane1.getDocument(Search.getBuilder(0).build()); 16 | logger.info(doc.name()); 17 | 18 | DocumentPage page0 = doc.getPage(Search.getBuilder(0).build()); 19 | logger.info(page0.name()); 20 | 21 | EditBox edit = page0.getEditBox(Search.getBuilder(0).build()); 22 | logger.info(edit.name()); 23 | 24 | String text = edit.getText(); 25 | logger.info("Text = " + text.substring(0,10)); 26 | ``` -------------------------------------------------------------------------------- /src/main/java/mmarquee/demo/DemoChrome.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.demo; 18 | 19 | public class DemoChrome { 20 | public static void main(String[] args) { 21 | ChromeDemo main = new ChromeDemo(); 22 | 23 | main.run(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/demo/MainExcel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.demo; 18 | 19 | public class MainExcel { 20 | 21 | public static void main(String[] args) { 22 | TestMainExcel main = new TestMainExcel(); 23 | 24 | main.run(); 25 | } 26 | } -------------------------------------------------------------------------------- /docs/examples.md: -------------------------------------------------------------------------------- 1 | ## Element focus 2 | 3 | This example will periodically (every 1.5 seconds) display the element that has focus. 4 | 5 | ``` 6 | UIAutomation automation = UIAutomation.getInstance(); 7 | 8 | do { 9 | this.rest(); 10 | 11 | try { 12 | Element elementFocus = automation.getFocusedElement(); 13 | logger.info("From focus = " + elementFocus.getName()); 14 | 15 | } catch (Exception ex) { 16 | logger.info(ex.getStackTrace()); 17 | } 18 | } while (true); 19 | ``` 20 | 21 | # Real World Examples 22 | 23 | These applications have example code to show then working, in the mmarquee.demo folder / namespace. 24 | 25 | * [Excel](excel.md) 26 | * [Word](word.md) 27 | * [Powerpoint](powerpoint.md) 28 | * [Notepad](notepad.md) 29 | * [Explorer](explorer.md) 30 | 31 | 32 | ### These do not yet have examples 33 | * [Chrome](chrome.md) 34 | * [Swing](swing.md) 35 | * [SWT](swt.md) 36 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/demo/MainCaching.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.demo; 18 | 19 | public class MainCaching { 20 | public static void main(String[] args) { 21 | DemoCaching main = new DemoCaching(); 22 | 23 | main.run(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/demo/MainPowerpoint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.demo; 18 | 19 | public class MainPowerpoint { 20 | 21 | public static void main(String[] args) { 22 | TestMainPowerpoint main = new TestMainPowerpoint(); 23 | 24 | main.run(); 25 | } 26 | } -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/Automatable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | /** 19 | * The basic definition of an Automation control. 20 | * 21 | * @author Mark Humphreys 22 | * Date 21/09/2016. 23 | */ 24 | public interface Automatable { 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/demo/MainWPFAutomationId.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.demo; 18 | 19 | public class MainWPFAutomationId { 20 | 21 | public static void main(String[] args) { 22 | TestMainWPFAutomationId main = new TestMainWPFAutomationId(); 23 | 24 | main.run(); 25 | } 26 | } -------------------------------------------------------------------------------- /src/main/java/mmarquee/demo/ChromeDemo.java: -------------------------------------------------------------------------------- 1 | package mmarquee.demo; 2 | 3 | import mmarquee.automation.UIAutomation; 4 | import mmarquee.automation.controls.Application; 5 | import mmarquee.automation.controls.ElementBuilder; 6 | 7 | class ChromeDemo extends TestBase { 8 | public void run() { 9 | UIAutomation automation = UIAutomation.getInstance(); 10 | 11 | Application chrome = 12 | new Application( 13 | new ElementBuilder() 14 | .automation(automation) 15 | .applicationPath("C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe") 16 | .applicationArguments("--force-renderer-accessibility")); 17 | 18 | 19 | try { 20 | chrome.launchOrAttach(); 21 | } catch (Throwable ex) { 22 | logger.warn("Failed to find application", ex); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/ImplementsFocus.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | /** 19 | * @author Mark Humphreys 20 | * Date 21/09/2016. 21 | */ 22 | public interface ImplementsFocus extends Automatable { 23 | /** 24 | * Focus on the element. 25 | */ 26 | void focus(); 27 | } 28 | -------------------------------------------------------------------------------- /docs/maskedit.md: -------------------------------------------------------------------------------- 1 | # Discovery 2 | * See [Element Discovery](element-discovery.md) 3 | 4 | The [DelphiUIAutomation](https://github.com/markhumphreysjhc/DelphiUIAutomation) project introduced some Delphi controls that implement IUIAutomation providers, allowing them to be accessed by automation. The Delphi implementation of a masked edit is another of these. 5 | 6 | There does not seem to be an equivalent WPF control. 7 | 8 | ``` 9 | try { 10 | MaskedEdit me0 = window.getMaskedEdit(Search.getBuilder("AutomatedMaskEdit1").build()); 11 | 12 | // Get the current value 13 | String value = me0.getValue(); 14 | 15 | // Set the value 16 | me0.setValue("12/12/99"); 17 | 18 | // Get the value again 19 | String value1 = me0.getValue(); 20 | 21 | } catch (ElementNotFoundException ex) { 22 | .. 23 | } 24 | ``` 25 | 26 | This specifically looks controls with a control name of "TAutomatedMaskEdit", which is the name of the Delphi control introduced in the above project. 27 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/demo/PointerOver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.demo; 18 | 19 | /** 20 | * @author Mark Humphreys 21 | * Date 12/02/2017. 22 | */ 23 | public class PointerOver { 24 | public static void main(String[] args) { 25 | DemoPointOver main = new DemoPointOver(); 26 | 27 | main.run(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/demo/EventHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.demo; 18 | 19 | /** 20 | * @author Mark Humphreys 21 | * Date 04/02/2017. 22 | */ 23 | public class EventHandler { 24 | public static void main(String[] args) { 25 | DemoEventHandler main = new DemoEventHandler(); 26 | 27 | main.run(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/pattern/Pattern.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.pattern; 17 | 18 | /** 19 | * @author Mark Humphreys 20 | * Date 28/02/2016. 21 | * 22 | * Interface describing the basic behaviour of a pattern. 23 | */ 24 | public interface Pattern { 25 | /** 26 | * Is the pattern available? 27 | * @return True if available 28 | */ 29 | boolean isAvailable(); 30 | } 31 | -------------------------------------------------------------------------------- /docs/toolbar.md: -------------------------------------------------------------------------------- 1 | # Discovery 2 | * See [Element Discovery](element-discovery.md) 3 | 4 | # Example 5 | 6 | ``` 7 | ToolBar toolbar = applicationWindow.getToolBar(Search.getBuilder(0).build()); 8 | logger.info("Toolbar name is " + toolbar.name()); // Blank in default WPF 9 | 10 | ToolBarButton btn0 = toolbar.getToolbarButton(Search.getBuilder(0).build()); 11 | 12 | if (btn0.isEnabled()) { 13 | logger.info("btn0 Enabled"); 14 | logger.info(btn1.name()); 15 | btn1.click(); 16 | } 17 | ``` 18 | 19 | ## Toolbar buttons 20 | 21 | The above example shows getting a button from the toolbar, and checking for status, etc. 22 | 23 | When a Delphi toolbar has no imagelist associated with it, then the buttons show in automation as menu items, and will correctly call the Invoke pattern's Invoke method, but when the toolbar as images associated with it, then they show as Buttons, but don't seem to implement the Invoke pattern correctly, and so don't fire the event in the underlying control. The same functionality works for WPF. 24 | This appears not to be a library issue as it also does not work from UISpy. 25 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/pattern/PatternNotFoundException.java: -------------------------------------------------------------------------------- 1 | package mmarquee.automation.pattern; 2 | 3 | import mmarquee.automation.AutomationException; 4 | 5 | /** 6 | * Exception to indicate that a pattern has not been found. 7 | * 8 | * @author Mark Humphreys 9 | * Date 26/02/2016. 10 | */ 11 | public class PatternNotFoundException extends AutomationException { 12 | 13 | /** 14 | * The serial version id. 15 | */ 16 | private static final long serialVersionUID = -6758087543897914809L; 17 | 18 | /** 19 | * Constructor for class. 20 | */ 21 | public PatternNotFoundException() 22 | { 23 | super("Pattern not found"); 24 | } 25 | 26 | /** 27 | * Constructor for class. 28 | * 29 | * @param message The message 30 | */ 31 | public PatternNotFoundException(String message) 32 | { 33 | super(message); 34 | } 35 | 36 | /** 37 | * Constructor for class. 38 | * 39 | * @param cause The throwable cause 40 | */ 41 | public PatternNotFoundException(Throwable cause) 42 | { 43 | super(cause); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/demo/TreeWalker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-18 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.demo; 18 | 19 | /** 20 | * Demo of TreeWalker. 21 | * 22 | * @author Mark Humphreys 23 | * Date 02/02/2017. 24 | */ 25 | class TreeWalker { 26 | /** 27 | * Demo the tree walker. 28 | * @param args Command line arguments. 29 | */ 30 | static void main(final String[] args) { 31 | DemoTreeWalker main = new DemoTreeWalker(); 32 | 33 | main.run(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/Spinner.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | /** 19 | * Wrapper for the Spinner element. 20 | * 21 | * @author Mark Humphreys 22 | * Date 26/02/2016. 23 | */ 24 | public final class Spinner extends AutomationBase { 25 | /** 26 | * Construct the Spinner. 27 | * @param builder The builder 28 | */ 29 | public Spinner(final ElementBuilder builder) { 30 | super(builder); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /docs/chrome.md: -------------------------------------------------------------------------------- 1 | By default Chrome is opaque to the UI Automation API, but there is a way of turn on the support, and thus being able to navigate through the control hierarchy. 2 | 3 | If you navigate to chrome://accessibility/, then you can turn accessibility on globally or in a given page. 4 | 5 | Starting the application with the `--force-renderer-accessibility` option will start the application in the correct mode. 6 | 7 | An example of starting chrome with the correct settings is shown below. Note that is Chrome is already running, then the argument will have no effect. 8 | 9 | ``` 10 | UIAutomation automation = UIAutomation.getInstance(); 11 | 12 | Application chrome = 13 | new Application( 14 | new ElementBuilder() 15 | .automation(automation) 16 | .applicationPath("C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe") 17 | .applicationArguments("--force-renderer-accessibility")); 18 | 19 | 20 | try { 21 | chrome.launchOrAttach(); 22 | } catch (Throwable ex) { 23 | logger.warn("Failed to find application", ex); 24 | } 25 | ``` 26 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/SplitButton.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | /** 19 | * Wrapper for the SplitButton element. 20 | 21 | * @author Mark Humphreys 22 | * Date 03/03/2016. 23 | */ 24 | public final class SplitButton extends Button { 25 | /** 26 | * Construct the SplitButton. 27 | * 28 | * @param builder The builder 29 | */ 30 | public SplitButton(final ElementBuilder builder) { 31 | super(builder); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationScrollItemPattern.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.COM.IUnknown; 19 | import com.sun.jna.platform.win32.Guid; 20 | 21 | public interface IUIAutomationScrollItemPattern extends IUnknown { 22 | /** 23 | * The interface IID for QueryInterface et al 24 | */ 25 | Guid.IID IID = new Guid.IID( 26 | "{B488300F-D015-4F19-9C29-BB595E3645EF}"); 27 | 28 | int scrollIntoView(); 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/StatusBar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.automation.controls; 18 | 19 | /** 20 | * Wrapper for the StatusBar element. 21 | * 22 | * @author Mark Humphreys 23 | * Date 01/02/2016. 24 | */ 25 | public final class StatusBar extends Container { 26 | 27 | /** 28 | * Constructor for StatusBar. 29 | * 30 | * @param builder The builder 31 | */ 32 | public StatusBar(final ElementBuilder builder) { 33 | super(builder); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationCondition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.COM.IUnknown; 19 | import com.sun.jna.platform.win32.Guid; 20 | 21 | /** 22 | * @author Mark Humphreys 23 | * Date 08/07/2016. 24 | */ 25 | public interface IUIAutomationCondition extends IUnknown { 26 | /** 27 | * The interface IID for QueryInterface et al. 28 | */ 29 | Guid.IID IID = new Guid.IID( 30 | "352FFBA8-0973-437C-A61F-F64CAFD81DF9"); 31 | } -------------------------------------------------------------------------------- /docs/powerpoint.md: -------------------------------------------------------------------------------- 1 | Powerpoint has a control hierarchy, and uses 'Slides' which are Custom controls. There is some weirdness associated with the contents of each page, as they appear to be Images, even though they are actually text on the screen. 2 | 3 | ![UISpy for Powerpoint](images/powerpoint.png) 4 | 5 | ``` 6 | Window window = application.getWindow("This is text.pptx - PowerPoint"); 7 |   logger.info(window.name()); 8 | 9 |   Panel panelX = window.getPanel(Search.getBuilder().className("MDIClient").build()); 10 |   logger.info(panelX.name()); 11 |   logger.info(panelX.getClassName()); 12 | 13 |   Panel panel1 = panelX.getPanel(Search.getBuilder("PowerPoint Edit View - [This is text.pptx]").build()); 14 |   logger.info(panelX.name()); 15 |   Panel panel2 = panel1.getPanel(Search.getBuilder("Slide").build(); 16 |   logger.info(panel2.name()); 17 |   PowerpointSlide slide = panel2.getPowerpointSlide(Search.getBuilder("Slide 1 - This is text").build()); 18 |   logger.info(slide.name()); 19 | 20 |   // Oddly enough this is an image control, and has text in it's selection 21 |   Image image = slide.getImage((Search.getBuilder("Title TextBox").build()); 22 | ``` 23 | 24 | -------------------------------------------------------------------------------- /docs/notepad.md: -------------------------------------------------------------------------------- 1 | Notepad is quite a simple application, and the following code is adapted from the demo program. 2 | 3 | ``` 4 | Application application = automation.launchOrAttach("notepad.exe"); 5 | 6 | // Wait for the process to start 7 | application.waitForInputIdle(5000); 8 | 9 | Window window = automation.getDesktopWindow("Untitled - Notepad"); 10 | String name = window.name(); 11 | logger.info(name); 12 | 13 | Object framework = window.getFramework(); 14 | logger.info("Framework is " + framework.toString()); 15 | 16 | logger.info("Modal = " + window.isModal()); 17 | 18 | EditBox edit = window.getEditBox(Search.getBuilder(0).build()); 19 | 20 | edit.setValue("This is a test of automation"); 21 | 22 | window.focus(); 23 | window.maximize(); 24 | 25 | this.rest(); 26 | 27 | // Interact with menus 28 | MainMenu menu = window.getMainMenu(); 29 | 30 | MenuItem exit = menu.getMenuItem("File", "Exit"); 31 | exit.click(); 32 | 33 | Window popup = window.getWindow("Notepad"); 34 | Button btn = popup.getButton("Don't Save"); 35 | 36 | btn.click(); 37 | 38 | logger.info("All closed down now"); 39 | 40 | ``` -------------------------------------------------------------------------------- /src/main/scala/mmarquee/demo/PacketLoggerTest.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.demo 18 | 19 | object PacketLoggerTest { 20 | 21 | var logger: PacketLoggerApplication = _ 22 | 23 | def start(): Unit = { 24 | logger = new PacketLoggerApplication() 25 | 26 | logger.launch() 27 | 28 | // Wait for it (enough time to collect something) ... 29 | Thread.sleep(2000) 30 | 31 | // Now kill it 32 | logger.exit 33 | 34 | logger.dump() 35 | } 36 | 37 | def main(args: Array[String]) { 38 | start() 39 | } 40 | } -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/ConversionFailure.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation; 17 | 18 | /** 19 | * Thrown when a conversion to an interface fails. 20 | * 21 | * @author Mark Humphreys 22 | * Date 24/12/2017. 23 | */ 24 | public class ConversionFailure extends AutomationException { 25 | 26 | /** 27 | * Constructor for ConversionFailure exception. 28 | * @param message The value to pass as a message 29 | */ 30 | public ConversionFailure(final String message) { 31 | super(message); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/PowerpointSlide.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | /** 19 | * Specialised custom control representing a powerpoint slide. 20 | * 21 | * @author Mark Humphreys 22 | * Date 01/02/2017. 23 | */ 24 | public final class PowerpointSlide extends Custom { 25 | /** 26 | * Constructor for the PowerpointSlide. 27 | * 28 | * @param builder The builder 29 | */ 30 | PowerpointSlide(final ElementBuilder builder) { 31 | super(builder); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/Custom.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | /** 19 | * Wrapper for the Custom ControlId, which is usually a container. 20 | * @author Mark Humphreys 21 | * Date 08/03/2016. 22 | */ 23 | public class Custom extends Container implements ImplementsValue { 24 | 25 | /** 26 | * Constructor for the Custom element. 27 | * 28 | * @param builder The builder 29 | */ 30 | public Custom(final ElementBuilder builder) { 31 | super(builder); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/RadioButton.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.automation.controls; 18 | 19 | /** 20 | * Wrapper for the RadioButton element. 21 | * 22 | * @author Mark Humphreys 23 | * Date 31/01/2016. 24 | */ 25 | public final class RadioButton extends AutomationBase implements ImplementsSelect { 26 | 27 | /** 28 | * Construct the RadioButton. 29 | * 30 | * @param builder The builder. 31 | */ 32 | public RadioButton(final ElementBuilder builder) { 33 | super(builder); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationTextRange2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.Guid; 19 | 20 | /** 21 | * @author Mark Humphreys 22 | * Date 04/12/2017. 23 | * 24 | * Windows 8.1 [desktop apps only] 25 | */ 26 | public interface IUIAutomationTextRange2 extends IUIAutomationTextRange { 27 | /** 28 | * The interface IID for QueryInterface et al 29 | */ 30 | Guid.IID IID = new Guid.IID("{BB9B40E0-5E04-46BD-9BE0-4B601B9AFAD4}"); 31 | 32 | int showContextMenu(); 33 | } 34 | -------------------------------------------------------------------------------- /docs/ribbon.md: -------------------------------------------------------------------------------- 1 | # Discovery 2 | * See [Element Discovery](element-discovery.md) 3 | 4 | The ribbon control is a complex structure, but the tree of controls is navigable, as the snippet below shows (automating the Windows Explorer), finding the button associated with the Preview Pane and clicking on it to turn it on/off. 5 | 6 | ``` 7 | RibbonBar ribbon = window.getRibbonBar(); 8 | RibbonCommandBar commandBar = ribbon.getRibbonCommandBar(); 9 | RibbonWorkPane pane = commandBar.getRibbonWorkPane(); 10 | logger.info("First work pane is " + pane.name()); 11 | 12 | NUIPane uiPane = pane.getNUIPane(Search.getBuilder(0).build()); 13 | logger.info("First NUIPane is " + uiPane.name()); 14 | 15 | NetUIHWND uiHWND = uiPane.getNetUIHWND(Search.getBuilder(0).build()); 16 | AutomationButton btn = uiHWND.getButton(Search.getBuilder("Minimise the Ribbon").build()); 17 | 18 | Tab tab = uiHWND.getTab(Search.getBuilder(0).build()); 19 | tab.selectTabPage("View"); 20 | 21 | Panel panel = uiHWND.getPanel(Search.getBuilder("Lower Ribbon").build()); 22 | 23 | ToolBar panes = panel.getToolBar(Search.getBuilder("Panes").build()); 24 | 25 | panes.getButton(Search.getBuilder("Preview pane").build()).click(); 26 | ``` -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/ProgressBar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.automation.controls; 18 | 19 | /** 20 | * Wrapper for the ProgressBar control. 21 | * 22 | * @author Mark Humphreys 23 | * Date 25/04/2016. 24 | */ 25 | public final class ProgressBar extends AutomationBase 26 | implements ImplementsRangeValue { 27 | 28 | /** 29 | * Construct the Panel. 30 | * 31 | * @param builder The builder 32 | */ 33 | ProgressBar(final ElementBuilder builder) { 34 | super(builder); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /docs/caching.md: -------------------------------------------------------------------------------- 1 | There is limited support for caching, enough to demonstrate the functionality that is available. 2 | 3 | #### Getting properties and patterns into the cache 4 | 5 | The following code example shows a function that retrieves items from a window and caches the Selection pattern and Name property for each item. 6 | By default, the list items are returned with a full reference, so that all current properties are still available. 7 | ``` 8 | Window window = automation.getDesktopWindow("Form1"); 9 | 10 | PointerByReference condition = automation.createTrueCondition(); 11 | 12 | CacheRequest cacheRequest = new CacheRequest(automation); 13 | 14 | cacheRequest.addPattern(PatternID.Selection.getValue()); 15 | cacheRequest.addProperty(PropertyID.Name.getValue()); 16 | 17 | List all = 18 | window.getElement().findAll(new TreeScope(TreeScope.Children), condition, cacheRequest); 19 | 20 | logger.info(all.size()); 21 | 22 | for(AutomationElement item: all) { 23 | logger.info(" *" +item.getCachedName()); 24 | } 25 | ``` 26 | 27 | ## See also 28 | * [How to Use Caching](https://msdn.microsoft.com/en-us/library/windows/desktop/ff625921(v=vs.85).aspx) 29 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationInvokePattern.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.COM.IUnknown; 19 | import com.sun.jna.platform.win32.Guid; 20 | 21 | /** 22 | * @author Mark Humphreys 23 | * Date 13/07/2016. 24 | */ 25 | public interface IUIAutomationInvokePattern extends IUnknown { 26 | /** 27 | * The interface IID for QueryInterface et al. 28 | */ 29 | Guid.IID IID = new Guid.IID( 30 | "{FB377FBE-8EA6-46D5-9C73-6499642D3059}"); 31 | 32 | int invoke(); 33 | } 34 | 35 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationSpreadsheetPattern.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.COM.IUnknown; 19 | import com.sun.jna.platform.win32.Guid; 20 | import com.sun.jna.ptr.PointerByReference; 21 | 22 | public interface IUIAutomationSpreadsheetPattern extends IUnknown { 23 | /** 24 | * The interface IID for QueryInterface et al 25 | */ 26 | Guid.IID IID = new Guid.IID("{7517A7C8-FAAE-4DE9-9F08-29B91E8595C1}"); 27 | 28 | int getItemByNameA(PointerByReference name, PointerByReference retVal); 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/Image.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | /** 19 | * Wrapper for the Image control element. 20 | * 21 | * @author Mark Humphreys 22 | * Date 26/02/2016. 23 | */ 24 | public final class Image extends AutomationBase implements ImplementsSelect { 25 | /** 26 | * Construct the Image. 27 | * @param builder The builder 28 | */ 29 | public Image(final ElementBuilder builder) { 30 | super(builder); 31 | } 32 | 33 | // Powerpoint weirdness, probably needs it's own class in the end 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationElement2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.Guid; 19 | 20 | /** 21 | * Wrapper around the IUIAutomation2 interface. 22 | * 23 | * This interface is supported fro Windows 8.1 desktop onwards 24 | * 25 | * @author Mark Humphreys 26 | * Date 24/07/2016. 27 | */ 28 | public interface IUIAutomationElement2 extends IUIAutomationElement { 29 | /** 30 | * The interface IID for QueryInterface et al. 31 | */ 32 | Guid.IID IID = new Guid.IID("{6749C683-F70D-4487-A698-5F79D55290D}"); 33 | } -------------------------------------------------------------------------------- /docs/explorer.md: -------------------------------------------------------------------------------- 1 | The Windows Explorer application has a complex user interface, and the examples below only show some of the possible interactions that are available. 2 | 3 | ``` 4 | Window window = automation.getDesktopWindow("File Explorer"); 5 | window.focus(); 6 | 7 | // Get the ribbon, work our way down and click the "Preview Button" 8 | RibbonBar ribbon = window.getRibbonBar(); 9 | RibbonCommandBar commandBar = ribbon.getRibbonCommandBar(); 10 | RibbonWorkPane pane = commandBar.getRibbonWorkPane(); 11 | logger.info("First work pane is " + pane.name()); 12 | 13 | NUIPane uiPane = pane.getNUIPane(Search.getBuilder(0).build()); 14 | logger.info("First NUIPane is " + uiPane.name()); 15 | 16 | NetUIHWND uiHWND = uiPane.getNetUIHWND(Search.getBuilder(0).build()); 17 | 18 | Button btn = uiHWND.getButton("Minimise the Ribbon"); 19 | 20 | Tab tab = uiHWND.getTab(Search.getBuilder(0).build()); 21 | tab.selectTabPage("View"); 22 | 23 | Panel panel = uiHWND.getPanel(Search.getBuilder("Lower Ribbon").build()); 24 | ToolBar panes = panel.getToolBar("Panes"); 25 | 26 | panes.getButton("Preview pane").click(); 27 | SplitButton split = panes.getSplitButton(Search.getBuilder(""Navigation pane").build()); 28 | split.click(); 29 | ``` -------------------------------------------------------------------------------- /docs/grids.md: -------------------------------------------------------------------------------- 1 | # Discovery 2 | * See [Element Discovery](element-discovery.md) 3 | 4 | ## WFP 5 | ``` 6 | DataGrid grid = window.getDataGrid(Search.getBuilder(0).build()); 7 | DataGridCell cell = grid.getItem(0,0); 8 | String itemName = item.name(); 9 | ``` 10 | 11 | ## Delphi 12 | 13 | The [DelphiUIAutomation](https://github.com/markhumphreysjhc/DelphiUIAutomation) project 14 | introduced some Delphi controls that implement `IUIAutomation` providers, allowing 15 | them to be accessed by automation. The `TAutomatedStringGrid` is one of these, as the 16 | base Delphi (as of `10.2 Rio` at least) control does not implement the `Grid` or 17 | `Table` interfaces and so is opaque to automation. In order to get the element associated 18 | with the specific `TAutomationStringGrid`, then this is done in the following manner. 19 | 20 | ``` 21 | DataGrid grid = window.getDataGrid(Search.getBuilder(0).className("TAutomationStringGrid").build()); 22 | DataGridCell item = grid.getItem(0,0); 23 | String itemName = item.name(); 24 | ``` 25 | 26 | This specifically looks controls with a control name of `TAutomationStringGrid`, 27 | which is the name of the Delphi control introduced in the above project. 28 | 29 | ## Further Examples 30 | * [Excel](excel.d) 31 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/AppBar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.automation.controls; 18 | 19 | /** 20 | * Wrapper for the AppBar element. 21 | * 22 | * @author Mark Humphreys 23 | * Date 02/03/2016. 24 | */ 25 | public class AppBar extends AutomationBase { 26 | /** 27 | *

28 | * Constructor for the AppBar. 29 | *

30 | *

31 | * This element seems to be undocumented by Microsoft 32 | *

33 | * @param builder The builder 34 | */ 35 | public AppBar(final ElementBuilder builder) { 36 | super(builder); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/Calendar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | /** 19 | * Wrapper for the Calendar element. 20 | * 21 | * @author Mark Humphreys 22 | * Date 16/02/2016. 23 | * 24 | * Implements IGridProvider, IScrollProvider, ITableProvider, IValueProvider 25 | */ 26 | public class Calendar extends AutomationBase 27 | implements ImplementsValue { 28 | 29 | /** 30 | * Constructor for the Calendar. 31 | * 32 | * @param builder The element builder 33 | */ 34 | public Calendar(final ElementBuilder builder) { 35 | super(builder); 36 | } 37 | } -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomation6.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.Guid; 19 | 20 | /** 21 | * Wrapper for the IUIAutomation6 COM interface. 22 | * 23 | * Extends the IUIAutomation5 interface to expose additional methods for 24 | * controlling UI Automation functionality. 25 | * 26 | * @author Mark Humphreys 27 | * Date 04/10/2018 28 | */ 29 | public interface IUIAutomation6 extends IUIAutomation5 { 30 | /** 31 | * The interface IID for QueryInterface et al. 32 | */ 33 | Guid.IID IID = new Guid.IID("{AAE072DA-29E3-413D-87A7-192DBF81ED10}"); 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/DataGridCell.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | /** 19 | * Wrapper around the 'virtual' cell element in the automated Delphi string grid. 20 | * 21 | * @author Mark Humphreys 22 | * Date 04/02/2016. 23 | */ 24 | public final class DataGridCell 25 | extends AutomationBase 26 | implements ImplementsValue, ImplementsSelect, ImplementsGridItem { 27 | 28 | /** 29 | * Construct the DataGridCell. 30 | * @param builder The builder 31 | */ 32 | public DataGridCell(final ElementBuilder builder) { 33 | super(builder); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationTextRange.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.COM.IUnknown; 19 | import com.sun.jna.platform.win32.Guid; 20 | import com.sun.jna.ptr.PointerByReference; 21 | 22 | /** 23 | * @author Mark Humphreys 24 | * Date 13/07/2016. 25 | */ 26 | public interface IUIAutomationTextRange extends IUnknown { 27 | /** 28 | * The interface IID for QueryInterface et al 29 | */ 30 | Guid.IID IID = new Guid.IID("{A543CC6A-F4AE-494B-8239-C814481187A8}"); 31 | 32 | int select(); 33 | int getText(Integer maxLength, PointerByReference sr); 34 | } -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationElement5.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.Guid; 19 | 20 | /** 21 | * Wrapper around the IUIAutomation5 interface, only implementing the extra methods. 22 | * 23 | * This interface is supported in Windows 10 [desktop apps only] upwards 24 | * 25 | * @author Mark Humphreys 26 | * Date 24/07/2016. 27 | */ 28 | public interface IUIAutomationElement5 extends IUIAutomationElement4 { 29 | /** 30 | * The interface IID for QueryInterface et al. 31 | */ 32 | Guid.IID IID = new Guid.IID("{98141C1D-0D0E-4175-BBE2-6BFF455842A7}"); 33 | 34 | } -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationElement8.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.Guid; 19 | 20 | /** 21 | * Wrapper around the IUIAutomation8 interface, only implementing the extra 22 | * methods. 23 | * 24 | * This interface is supported in Windows 10 [desktop apps only] upwards 25 | * 26 | * @author Mark Humphreys 27 | * Date 04/10/2018 28 | */ 29 | public interface IUIAutomationElement8 extends IUIAutomationElement7 { 30 | /** 31 | * The interface IID for QueryInterface et al. 32 | */ 33 | Guid.IID IID = new Guid.IID("{8C60217D-5411-4CDE-BCC0-1CEDA223830C}"); 34 | 35 | } -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationElement9.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.Guid; 19 | 20 | /** 21 | * Wrapper around the IUIAutomation9 interface, only implementing the extra 22 | * methods. 23 | * 24 | * This interface is supported in Windows 10 [desktop apps only] upwards 25 | * 26 | * @author Mark Humphreys 27 | * Date 04/10/2018 28 | */ 29 | public interface IUIAutomationElement9 extends IUIAutomationElement8 { 30 | /** 31 | * The interface IID for QueryInterface et al. 32 | */ 33 | Guid.IID IID = new Guid.IID("{39325FAC-039D-440E-A3A3-5EB81A5CECC3}"); 34 | 35 | } -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomation4.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.Guid; 19 | 20 | /** 21 | * Wrapper for the IUIAutomation4 COM interface. 22 | * 23 | * Extends the IUIAutomation3 interface to expose additional methods for controlling UI Automation functionality. 24 | * 25 | * Windows 10, version 1607 [desktop apps only] 26 | * Windows Server 2016 [desktop apps only] 27 | */ 28 | public interface IUIAutomation4 extends IUIAutomation3 { 29 | /** 30 | * The interface IID for QueryInterface et al. 31 | */ 32 | Guid.IID IID = new Guid.IID("{1189C02A-05F8-4319-8E21-E817E3DB2860}"); 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomation5.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.Guid; 19 | 20 | /** 21 | * Wrapper for the IUIAutomation5 COM interface. 22 | * 23 | * Extends the IUIAutomation4 interface to expose additional methods for 24 | * controlling UI Automation functionality. 25 | * 26 | * Windows 10, version 1607 [desktop apps only] 27 | * Windows Server, version 1709 [desktop apps only] 28 | */ 29 | public interface IUIAutomation5 extends IUIAutomation4 { 30 | /** 31 | * The interface IID for QueryInterface et al. 32 | */ 33 | Guid.IID IID = new Guid.IID("{25F700C8-D816-4057-A9DC-3CBDEE77E256}"); 34 | } 35 | -------------------------------------------------------------------------------- /src/main/scala/mmarquee/demo/AutomationTest.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-18 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.demo 18 | 19 | object AutomationTest { 20 | 21 | var notepad: NotepadApplication = _ 22 | 23 | def start(): Unit = { 24 | notepad = new NotepadApplication() 25 | 26 | notepad.launch() 27 | notepad.addText("Hello there") 28 | notepad.clickExit() 29 | val confirm = notepad.getConfirm 30 | 31 | if (confirm != null) { 32 | System.out.println(s"Found the confirmation popup") 33 | } else { 34 | System.out.println(s"Didn't find confirmation window") 35 | } 36 | 37 | notepad.confirmExit() 38 | } 39 | 40 | def main(args: Array[String]) { 41 | start() 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/ImplementsClick.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | import mmarquee.automation.AutomationException; 19 | import mmarquee.automation.pattern.PatternNotFoundException; 20 | 21 | /** 22 | * Implement this interface to respond to the clickable action. 23 | * 24 | * @author Mark Humphreys 25 | * Date 21/09/2016. 26 | */ 27 | public interface ImplementsClick extends Automatable { 28 | /** 29 | * Clicks the element. 30 | * @throws AutomationException Automation library error 31 | * @throws PatternNotFoundException Failed to find pattern 32 | */ 33 | void click() throws AutomationException, PatternNotFoundException; 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationExpandCollapsePattern.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.COM.IUnknown; 19 | import com.sun.jna.platform.win32.Guid; 20 | import com.sun.jna.ptr.IntByReference; 21 | 22 | /** 23 | * @author Mark Humphreys 24 | * Date 13/07/2016. 25 | */ 26 | public interface IUIAutomationExpandCollapsePattern extends IUnknown { 27 | /** 28 | * The interface IID for QueryInterface et al 29 | */ 30 | Guid.IID IID = new Guid.IID( 31 | "{619BE086-1F4E-4EE4-BAFA-210128738730}"); 32 | 33 | int expand(); 34 | int collapse(); 35 | int getCurrentExpandCollapseState(IntByReference retVal); 36 | } 37 | 38 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/AutomationEventHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation; 17 | 18 | import mmarquee.uiautomation.IUIAutomationEventHandler; 19 | 20 | /** 21 | * @author Mark Humphreys 22 | * Date 05/02/2017. 23 | * 24 | * Wrapper for event handling. 25 | */ 26 | public class AutomationEventHandler { 27 | /** 28 | * Underlying raw event handler. 29 | */ 30 | private IUIAutomationEventHandler handler; 31 | 32 | /** 33 | * Constructor for the AutomationEventHandler. 34 | * @param inHandler The raw event handler. 35 | */ 36 | public AutomationEventHandler(final IUIAutomationEventHandler inHandler) { 37 | this.handler = inHandler; 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationStylesPattern.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.COM.IUnknown; 19 | import com.sun.jna.platform.win32.Guid; 20 | import com.sun.jna.ptr.IntByReference; 21 | import com.sun.jna.ptr.PointerByReference; 22 | 23 | /** 24 | * @author Mark Humphreys 25 | * Date 13/07/2016. 26 | */ 27 | public interface IUIAutomationStylesPattern extends IUnknown { 28 | /** 29 | * The interface IID for QueryInterface et al 30 | */ 31 | Guid.IID IID = new Guid.IID("{85B5F0A2-BD79-484A-AD2B-388C9838D5FB}"); 32 | 33 | int getCurrentStyleId(IntByReference retVal); 34 | int getCurrentStyleName(PointerByReference retVal); 35 | } 36 | 37 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationTextPattern.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.COM.IUnknown; 19 | import com.sun.jna.platform.win32.Guid; 20 | import com.sun.jna.ptr.PointerByReference; 21 | 22 | /** 23 | * @author Mark Humphreys 24 | * Date 13/07/2016. 25 | */ 26 | public interface IUIAutomationTextPattern extends IUnknown { 27 | /** 28 | * The interface IID for QueryInterface et al 29 | */ 30 | Guid.IID IID = new Guid.IID("{32EBA289-3583-42C9-9C59-3B6D9A1E9B6A}"); 31 | 32 | int getSelection(PointerByReference result); 33 | int getVisibleRanges(PointerByReference ranges); 34 | int getDocumentRange(PointerByReference range); 35 | } 36 | 37 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationTextRangeArray.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.COM.IUnknown; 19 | import com.sun.jna.platform.win32.Guid; 20 | import com.sun.jna.ptr.IntByReference; 21 | import com.sun.jna.ptr.PointerByReference; 22 | 23 | /** 24 | * @author Mark Humphreys 25 | * Date 13/07/2016. 26 | */ 27 | public interface IUIAutomationTextRangeArray extends IUnknown { 28 | 29 | /** 30 | * The interface IID for QueryInterface et al 31 | */ 32 | Guid.IID IID = new Guid.IID("{CE4AE76A-E717-4C98-81EA-47371D028EB6}"); 33 | 34 | int getLength(IntByReference ibr); 35 | int getElement(Integer index, PointerByReference element); 36 | } 37 | 38 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationElementArray.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.COM.IUnknown; 19 | import com.sun.jna.platform.win32.Guid; 20 | import com.sun.jna.ptr.IntByReference; 21 | import com.sun.jna.ptr.PointerByReference; 22 | 23 | /** 24 | * @author Mark Humphreys 25 | * Date 12/07/2016. 26 | */ 27 | public interface IUIAutomationElementArray extends IUnknown { 28 | 29 | /** 30 | * The interface IID for QueryInterface et al. 31 | */ 32 | Guid.IID IID = new Guid.IID( 33 | "{14314595-B4BC-4055-95F2-58F2E42C9855}"); 34 | 35 | int getLength(IntByReference length); // 3 36 | int getElement(int index, PointerByReference element); // 4 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomation3.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.Guid; 19 | 20 | /** 21 | * Wrapper for the IUIAutomation3 COM interface. 22 | * 23 | * @author Mark Humphreys 24 | * Date 12/09/2016. 25 | * 26 | * Use this like: 27 | * PointerByReference pbr=new PointerByReference(); 28 | * HRESULT result=SomeCOMObject.QueryInterface(IID, pbr); 29 | * if(COMUtils.SUCCEEDED(result)) IUIAutomation3 iua=IUIAutomation3.Converter.pointerToInterface(pbr); 30 | * 31 | */ 32 | public interface IUIAutomation3 extends IUIAutomation2 { 33 | /** 34 | * The interface IID for QueryInterface et al. 35 | */ 36 | Guid.IID IID = new Guid.IID("{73D768DA-9B51-4B89-936E-C209290973E7}"); 37 | } 38 | 39 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationGridItemPattern.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.COM.IUnknown; 19 | import com.sun.jna.platform.win32.Guid; 20 | import com.sun.jna.ptr.IntByReference; 21 | 22 | /** 23 | * @author Mark Humphreys 24 | * Date 27/01/2017. 25 | */ 26 | public interface IUIAutomationGridItemPattern extends IUnknown { 27 | /** 28 | * The interface IID for QueryInterface et al 29 | */ 30 | Guid.IID IID = new Guid.IID( 31 | "{78F8EF57-66C3-4E09-BD7C-E79B2004894D}"); 32 | 33 | int getCurrentRow(IntByReference retVal); 34 | int getCurrentColumn(IntByReference retVal); 35 | int getRowSpan(IntByReference retVal); 36 | int getColumnSpan(IntByReference retVal); 37 | } 38 | 39 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/MetaDataID.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-18 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation; 17 | 18 | /** 19 | * Meta Data Identifiers. 20 | * 21 | * @author Mark Humphreys 22 | * Date 24/12/2017. 23 | */ 24 | public enum MetaDataID { 25 | /** 26 | * Say as interpret as. 27 | */ 28 | SayAsInterpretAs(100000); 29 | 30 | /** 31 | * The actual value. 32 | */ 33 | private final int value; 34 | 35 | /** 36 | * Gets the value. 37 | * @return The actual value 38 | */ 39 | public int getValue() { 40 | return this.value; 41 | } 42 | 43 | /** 44 | * Constructor for MetaDataID. 45 | * 46 | * @param theValue Initial value. 47 | */ 48 | MetaDataID(int theValue) { 49 | this.value = theValue; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/CheckBox.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.automation.controls; 18 | 19 | /** 20 | * Wrapper for the CheckBox element. 21 | * 22 | * @author Mark Humphreys 23 | * Date 31/01/2016. 24 | */ 25 | public final class CheckBox 26 | extends AutomationBase 27 | implements ImplementsToggle, 28 | ImplementsFocus { 29 | 30 | /** 31 | * Constructor for the CheckBox. 32 | * 33 | * @param builder The builder 34 | */ 35 | public CheckBox(final ElementBuilder builder) { 36 | super(builder); 37 | } 38 | 39 | /** 40 | *

41 | * Sets the focus to this control. 42 | *

43 | */ 44 | public void focus() { 45 | this.getElement().setFocus(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationElement4.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.Guid; 19 | 20 | /** 21 | * Wrapper around the IUIAutomation4 interface. 22 | * 23 | * This interface is supported in Windows 10 [desktop apps only] upwards 24 | * 25 | * @author Mark Humphreys 26 | * Date 24/07/2016. 27 | */ 28 | public interface IUIAutomationElement4 extends IUIAutomationElement3 { 29 | /** 30 | * The interface IID for QueryInterface et al. 31 | */ 32 | Guid.IID IID = new Guid.IID("{3B6E233C-52FB-4063-A4C9-77C075C2A06B}"); 33 | 34 | /* 35 | CachedLevel 36 | CachedPositionInSet 37 | CachedSizeOfSet 38 | CurrentLevel 39 | CurrentPositionInSet 40 | CurrentSizeOfSet 41 | */ 42 | 43 | } -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationTablePattern.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.COM.IUnknown; 19 | import com.sun.jna.platform.win32.Guid; 20 | import com.sun.jna.ptr.IntByReference; 21 | import com.sun.jna.ptr.PointerByReference; 22 | 23 | /** 24 | * @author Mark Humphreys 25 | * Date 13/07/2016. 26 | */ 27 | public interface IUIAutomationTablePattern extends IUnknown { 28 | /** 29 | * The interface IID for QueryInterface et al 30 | */ 31 | Guid.IID IID = new Guid.IID("{620E691C-EA96-4710-A850-754B24CE2417}"); 32 | 33 | int getCurrentRowHeaders(PointerByReference retVal); 34 | int getCurrentColumnHeaders(PointerByReference retVal); 35 | int getCurrentRowOrColumnMajor(IntByReference retVal); 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationValuePattern.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.COM.IUnknown; 19 | import com.sun.jna.platform.win32.Guid; 20 | import com.sun.jna.platform.win32.WTypes; 21 | import com.sun.jna.ptr.IntByReference; 22 | import com.sun.jna.ptr.PointerByReference; 23 | 24 | /** 25 | * @author Mark Humphreys 26 | * Date 13/07/2016. 27 | */ 28 | public interface IUIAutomationValuePattern extends IUnknown { 29 | /** 30 | * The interface IID for QueryInterface et al 31 | */ 32 | Guid.IID IID = new Guid.IID( 33 | "{A94CD8B1-0844-4CD6-9D2D-640537AB39E9}"); 34 | 35 | int setValue(WTypes.BSTR sr); 36 | int getValue(PointerByReference sr); 37 | int getCurrentIsReadOnly(IntByReference ibr); 38 | } -------------------------------------------------------------------------------- /docs/windows-support.md: -------------------------------------------------------------------------------- 1 | # Support for legacy Windows versions 2 | 3 | The underlying windows COM library is versioned, and uses different versions of the interfaces for different Windows releases. 4 | 5 | These versions are: 6 | 7 | ## Windows 7 8 | 9 | The library seems to be present in Windows 7, but doesn't seem to work as it does in later version, so it is not possible to use much of _this_ library for Windows 7 automation. 10 | 11 | * `IUIAutomation` 12 | * `IUIAutomationElement` 13 | ## Windows 8 14 | * `IUIAutomation2` 15 | * `IUIAutomationElement2` 16 | ## Windows 8.1 17 | * `IUIAutomation3` 18 | * `IUIAutomationElement3` 19 | 20 | The functionality supported by this library is the addition of the 21 | `showContextMenu()` method that is available in 22 | `IUIAutomationElement3`. 23 | 24 | ## Windows 10 25 | * `IUIAutomationElement4` 26 | 27 | ## Windows 10 (Build 1607) 28 | * `IUIAutomation4` 29 | * `IUIAutomation5` 30 | 31 | ## Windows 10 (Build 1703) 32 | * `IUIAutomationElement5` 33 | * `IUIAutomationElement6` 34 | 35 | The functionality supported by this library is the addition of the `getFullDescription()` method that is available in 36 | `IUIAutomationElement6`. 37 | 38 | * `IUIAutomationElement7` 39 | 40 | ## Windows 10 (Build 1709) 41 | * `IUIAutomationSelectionPattern2` 42 | * `IUIAutomation6` 43 | 44 | ## Windows 10 (Build 1803) 45 | * `IUIAutomationElement8` 46 | 47 | ## Windows 10 (Build 1809) 48 | * `IUIAutomationElement9` 49 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationGridPattern.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.COM.IUnknown; 19 | import com.sun.jna.platform.win32.Guid; 20 | import com.sun.jna.ptr.IntByReference; 21 | import com.sun.jna.ptr.PointerByReference; 22 | 23 | /** 24 | * @author Mark Humphreys 25 | * Date 13/07/2016. 26 | */ 27 | public interface IUIAutomationGridPattern extends IUnknown { 28 | /** 29 | * The interface IID for QueryInterface et al 30 | */ 31 | Guid.IID IID = new Guid.IID( 32 | "{414C3CDC-856B-4F5B-8538-3131C6302550}"); 33 | 34 | int getItem(int row, int column, PointerByReference item); 35 | int getCurrentRowCount(IntByReference retVal); 36 | int getCurrentColumnCount(IntByReference retVal); 37 | } 38 | 39 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationSelectionPattern.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.COM.IUnknown; 19 | import com.sun.jna.platform.win32.Guid; 20 | import com.sun.jna.ptr.IntByReference; 21 | import com.sun.jna.ptr.PointerByReference; 22 | 23 | /** 24 | * @author Mark Humphreys 25 | * Date 13/07/2016. 26 | */ 27 | public interface IUIAutomationSelectionPattern extends IUnknown { 28 | /** 29 | * The interface IID for QueryInterface et al 30 | */ 31 | Guid.IID IID = 32 | new Guid.IID("{5ED5202E-B2AC-47A6-B638-4B0BF140D78E}"); 33 | 34 | int getCurrentSelection(PointerByReference retVal); 35 | int getCurrentCanSelectMultiple(IntByReference retval); 36 | int getCurrentIsSelectionRequired(IntByReference retval); 37 | } 38 | 39 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/NetUIHWND.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | import mmarquee.automation.AutomationException; 19 | 20 | /** 21 | * Specialist pane that represents the NetUIHWND (part of the MS ribbon controls). 22 | * 23 | * @author Mark Humphreys 24 | * Date 02/03/2016. 25 | */ 26 | public final class NetUIHWND extends Panel { 27 | 28 | /** 29 | * The class name. 30 | */ 31 | public final static String CLASS_NAME = "NetUIHWND"; 32 | 33 | /** 34 | * Construct the NetUIHWND. 35 | * @param builder The builder 36 | * @throws AutomationException Automation library error 37 | */ 38 | public NetUIHWND(final ElementBuilder builder) throws AutomationException { 39 | super(builder); 40 | assertClassName(CLASS_NAME); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationSelectionItemPattern.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.COM.IUnknown; 19 | import com.sun.jna.platform.win32.Guid; 20 | import com.sun.jna.ptr.IntByReference; 21 | import com.sun.jna.ptr.PointerByReference; 22 | 23 | /** 24 | * @author Mark Humphreys 25 | * Date 13/07/2016. 26 | */ 27 | public interface IUIAutomationSelectionItemPattern extends IUnknown { 28 | /** 29 | * The interface IID for QueryInterface et al 30 | */ 31 | Guid.IID IID = 32 | new Guid.IID("{A8EFA66A-0FDA-421A-9194-38021F3578EA}"); 33 | 34 | int select(); 35 | int getCurrentIsSelected(IntByReference ibr); 36 | int addToSelection(); 37 | int removeFromSelection(); 38 | int getCurrentSelectionContainer(PointerByReference pbr); 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationBoolCondition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.Guid; 19 | 20 | /** 21 | * Represents a condition that can be either TRUE (selects all elements) or FALSE (selects no elements). 22 | */ 23 | public interface IUIAutomationBoolCondition extends IUIAutomationCondition { 24 | /** 25 | * The interface IID for QueryInterface et al. 26 | */ 27 | Guid.IID IID = new 28 | Guid.IID("1B4E1F2E-75EB-4D0B-8952-5A69988E2307"); 29 | 30 | /** 31 | * Retrieves the value of the condition: either TRUE or FALSE. 32 | * @param boolVal The condition 33 | * @return If this method succeeds, it returns S_OK. Otherwise, it returns 34 | * an HRESULT error code. 35 | */ 36 | int getBooleanValue(Integer boolVal); 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/MaskedEdit.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | import mmarquee.automation.AutomationException; 19 | 20 | /** 21 | * Wrapper around the MaskedEdit control - specifically the automated version. 22 | * 23 | * @author Mark Humphreys 24 | * Date 15/02/2016. 25 | */ 26 | public final class MaskedEdit extends EditBox { 27 | 28 | /** 29 | * The class name. 30 | */ 31 | public static final String CLASS_NAME = "TAutomatedMaskEdit"; 32 | 33 | /** 34 | * Construct the MaskedEdit. 35 | * @param builder The builder 36 | * @throws AutomationException Error in automation library 37 | */ 38 | public MaskedEdit(final ElementBuilder builder) 39 | throws AutomationException { 40 | super(builder); 41 | assertClassName(CLASS_NAME); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationSelectionPattern2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.Guid; 19 | import com.sun.jna.ptr.IntByReference; 20 | import com.sun.jna.ptr.PointerByReference; 21 | 22 | /** 23 | * @author Mark Humphreys 24 | * Date 10/12/2017 25 | */ 26 | public interface IUIAutomationSelectionPattern2 27 | extends IUIAutomationSelectionPattern { 28 | /** 29 | * The interface IID for QueryInterface et al 30 | */ 31 | Guid.IID IID = 32 | new Guid.IID("{0532bfae-c011-4e32-a343-6d642d798555}"); 33 | 34 | int getCurrentFirstSelectedItem(PointerByReference retval); 35 | int getCurrentLastSelectedItem(PointerByReference retval); 36 | int getCurrentCurrentSelectedItem(PointerByReference retVal); 37 | int getCurrentItemCount(IntByReference retval); 38 | } 39 | -------------------------------------------------------------------------------- /docs/scala.md: -------------------------------------------------------------------------------- 1 | ## sbt 2 | To add the library as a prerequisite, use the following entry to the library dependencies in the `build.sbt` file 3 | 4 | ### Stable release 5 | ```scala 6 | libraryDependencies += "com.github.mmarquee" % "ui-automation" % "0.7.0" 7 | ``` 8 | 9 | ### Snapshot release 10 | ```scala 11 | resolvers += 12 | "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots" 13 | 14 | libraryDependencies += "com.github.mmarquee" % "ui-automation" % "0.8.0-SNAPSHOT" 15 | ``` 16 | 17 | ## Examples 18 | 19 | The sample code encapsulates some simple automation of the Notepad program, starting the application, adding text, exiting the application and confirming exit 20 | 21 | To simplify the code, the standard behaviour of the application has been encapsulated in the `NotepadApplication` class - ee the `main\Scala` folder for the full code 22 | 23 | ```scala 24 | object AutomationTest { 25 | 26 | var notepad: NotepadApplication = _ 27 | 28 | def start(): Unit = { 29 | notepad = new NotepadApplication() 30 | 31 | notepad.launch 32 | notepad.addText("Hello there") 33 | notepad.clickExit() 34 | val confirm = notepad.getConfirm 35 | 36 | if (confirm != null) { 37 | System.out.println(s"Found the confirmation popup") 38 | } else { 39 | System.out.println(s"Didn't find confirmation window") 40 | } 41 | 42 | notepad.confirmExit() 43 | } 44 | 45 | def main(args: Array[String]) { 46 | start() 47 | } 48 | } 49 | ``` 50 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/pattern/Dock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.pattern; 17 | 18 | import mmarquee.automation.AutomationException; 19 | import mmarquee.automation.Element; 20 | import mmarquee.automation.PatternID; 21 | import mmarquee.automation.PropertyID; 22 | 23 | /** 24 | * Wrapper around the dock pattern. 25 | * 26 | * This looks to be unused anywhere 27 | */ 28 | public class Dock extends BasePattern { 29 | 30 | /** 31 | * Constructor for the dock pattern. 32 | * 33 | * @param element The automation element for which the pattern is valid 34 | * @throws AutomationException If something goes wrong 35 | */ 36 | public Dock(final Element element) throws AutomationException { 37 | super(element); 38 | this.patternID = PatternID.Dock; 39 | this.availabilityPropertyID = PropertyID.IsDockPatternAvailable; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationItemContainerPattern.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.Pointer; 19 | import com.sun.jna.platform.win32.COM.IUnknown; 20 | import com.sun.jna.platform.win32.Guid; 21 | import com.sun.jna.platform.win32.Variant; 22 | import com.sun.jna.ptr.PointerByReference; 23 | 24 | /** 25 | * Wrapper for the IUIAutomationItemContainerPattern COM interface. 26 | * 27 | * @author Mark Humphreys 28 | * Date 13/07/2016. 29 | */ 30 | public interface IUIAutomationItemContainerPattern extends IUnknown { 31 | 32 | /** 33 | * The interface IID for QueryInterface et al 34 | */ 35 | Guid.IID IID = new Guid.IID( 36 | "{C690FDB2-27A8-423C-812D-429773C9084E}"); 37 | 38 | int AddRef(); 39 | 40 | int findItemByProperty(Pointer startAfter, int propertyId, Variant.VARIANT.ByValue value, PointerByReference found); 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/ItemNotFoundException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation; 17 | 18 | /** 19 | * Thrown when an item is not found. 20 | * 21 | * @author Mark Humphreys 22 | * Date 26/02/2016. 23 | */ 24 | public class ItemNotFoundException extends AutomationException { 25 | 26 | /** 27 | * Serial version uid. 28 | */ 29 | private static final long serialVersionUID = -7175159800746711939L; 30 | 31 | /** 32 | * Constructor, with a name of the not found item. 33 | * @param name The element name 34 | */ 35 | public ItemNotFoundException(String name) { 36 | super("Item " + name + " not found"); 37 | } 38 | 39 | /** 40 | * Constructor, with the index of the not found item. 41 | * @param index The index 42 | */ 43 | public ItemNotFoundException(int index) { 44 | super("Item " + index + " not found"); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/pattern/Scroll.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.pattern; 17 | 18 | import mmarquee.automation.AutomationException; 19 | import mmarquee.automation.Element; 20 | import mmarquee.automation.PatternID; 21 | import mmarquee.automation.PropertyID; 22 | 23 | /** 24 | * Wrapper around the Scroll pattern. 25 | * 26 | * This looks to be unused anywhere 27 | */ 28 | public class Scroll extends BasePattern { 29 | 30 | /** 31 | * Constructor for the Scroll pattern. 32 | * 33 | * @param element The automation element for which the pattern is valid 34 | * @throws AutomationException If something goes wrong 35 | */ 36 | public Scroll(final Element element) throws AutomationException { 37 | super(element); 38 | this.patternID = PatternID.Scroll; 39 | this.availabilityPropertyID = PropertyID.IsScrollPatternAvailable; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/pattern/TableItem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.pattern; 17 | 18 | import mmarquee.automation.AutomationException; 19 | import mmarquee.automation.Element; 20 | import mmarquee.automation.PatternID; 21 | import mmarquee.automation.PropertyID; 22 | 23 | /** 24 | * Wrapper around the TableItem pattern. 25 | * 26 | * This looks to be unused anywhere 27 | */ 28 | public class TableItem extends BasePattern { 29 | 30 | /** 31 | * Constructor for the TableItem pattern. 32 | * 33 | * @param element The automation element for which the pattern is valid 34 | * @throws AutomationException If something goes wrong 35 | */ 36 | public TableItem(final Element element) throws AutomationException { 37 | super(element); 38 | this.patternID = PatternID.TableItem; 39 | this.availabilityPropertyID = PropertyID.IsTableItemPatternAvailable; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/pattern/Transform.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.pattern; 17 | 18 | import mmarquee.automation.AutomationException; 19 | import mmarquee.automation.Element; 20 | import mmarquee.automation.PatternID; 21 | import mmarquee.automation.PropertyID; 22 | 23 | /** 24 | * Wrapper around the Transform pattern. 25 | * 26 | * This looks to be unused anywhere 27 | */ 28 | public class Transform extends BasePattern { 29 | 30 | /** 31 | * Constructor for the Transform pattern. 32 | * 33 | * @param element The automation element for which the pattern is valid 34 | * @throws AutomationException If something goes wrong 35 | */ 36 | public Transform(final Element element) throws AutomationException { 37 | super(element); 38 | this.patternID = PatternID.Transform; 39 | this.availabilityPropertyID = PropertyID.IsTransformPatternAvailable; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/ImplementsLegacyIAccessible.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-18 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.automation.controls; 18 | 19 | import mmarquee.automation.AutomationException; 20 | 21 | /** 22 | * Make interface for implementations of the ImplementsLegacyIAccessible pattern. 23 | * 24 | * @author Mark Humphreys 25 | * Date 24/12/2017. 26 | */ 27 | public interface ImplementsLegacyIAccessible extends Automatable { 28 | /** 29 | * Gets value from the IAccessible interface. 30 | * @return The string value 31 | * @throws AutomationException Automation library error 32 | */ 33 | String getValueFromIAccessible() throws AutomationException; 34 | 35 | /** 36 | * Sets value via the IAccessible interface. 37 | * @param value The string value 38 | * @throws AutomationException Automation library error 39 | */ 40 | void setValueFromIAccessible(final String value) throws AutomationException; 41 | } -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/pattern/ScrollItem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.automation.pattern; 18 | 19 | import mmarquee.automation.AutomationException; 20 | import mmarquee.automation.Element; 21 | import mmarquee.automation.PatternID; 22 | import mmarquee.automation.PropertyID; 23 | 24 | /** 25 | * Wrapper around the ScrollItem pattern. 26 | * 27 | * This looks to be unused anywhere 28 | */ 29 | public class ScrollItem extends BasePattern { 30 | 31 | /** 32 | * Constructor for the ScrollItem pattern. 33 | * 34 | * @param element The automation element for which the pattern is valid 35 | * @throws AutomationException If something goes wrong 36 | */ 37 | public ScrollItem(final Element element) throws AutomationException { 38 | super(element); 39 | this.patternID = PatternID.ScrollItem; 40 | this.availabilityPropertyID = PropertyID.IsScrollItemPatternAvailable; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/CanRequestBasePattern.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-18 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | import mmarquee.automation.AutomationException; 19 | import mmarquee.automation.pattern.BasePattern; 20 | import mmarquee.automation.pattern.PatternNotFoundException; 21 | 22 | /** 23 | * Interface that flags whether a control can get a base pattern. 24 | */ 25 | public interface CanRequestBasePattern { 26 | /** 27 | * Request an Automation pattern. 28 | * 29 | * @param automationPatternClass The pattern to request 30 | * @param The type 31 | * @return The base pattern 32 | * @throws AutomationException Automation library error 33 | * @throws PatternNotFoundException Failed to find pattern 34 | */ 35 | T requestAutomationPattern(Class automationPatternClass) throws PatternNotFoundException, AutomationException; 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/pattern/MultipleView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.pattern; 17 | 18 | import mmarquee.automation.AutomationException; 19 | import mmarquee.automation.Element; 20 | import mmarquee.automation.PatternID; 21 | import mmarquee.automation.PropertyID; 22 | 23 | /** 24 | * Wrapper around the multiple view pattern. 25 | * 26 | * This looks to be unused anywhere 27 | */ 28 | public class MultipleView extends BasePattern { 29 | 30 | /** 31 | * Constructor for the MultipleView pattern. 32 | * 33 | * @param element The automation element for which the pattern is valid 34 | * @throws AutomationException If something goes wrong 35 | */ 36 | public MultipleView(final Element element) throws AutomationException { 37 | super(element); 38 | this.patternID = PatternID.MultipleView; 39 | this.availabilityPropertyID = PropertyID.IsMultipleViewPatternAvailable; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/EditBox.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.automation.controls; 18 | 19 | import mmarquee.automation.AutomationException; 20 | 21 | /** 22 | * Wrapper around the edit box element. 23 | * @author Mark Humphreys 24 | * Date 26/01/2016. 25 | */ 26 | public class EditBox 27 | extends AutomationBase 28 | implements ImplementsValue, 29 | ImplementsText { 30 | 31 | /** 32 | * Whether the element is a password. 33 | * @return True if it's a password, otherwise false. 34 | * @throws AutomationException Automation error. 35 | */ 36 | public boolean isPassword() throws AutomationException { 37 | return this.getElement().isPassword(); 38 | } 39 | 40 | /** 41 | * Constructor for the EditBox. 42 | * @param builder The builder. 43 | */ 44 | public EditBox(final ElementBuilder builder) { 45 | super(builder); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/TabItem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | import mmarquee.automation.AutomationException; 19 | import mmarquee.automation.pattern.PatternNotFoundException; 20 | 21 | /** 22 | * Wrapper for the TabItem element. 23 | * 24 | * @author Mark Humphreys 25 | * Date 28/01/2016. 26 | */ 27 | public final class TabItem extends Container implements ImplementsSelect { 28 | 29 | /** 30 | * Construct the TabItem. 31 | * 32 | * @param builder The builder. 33 | */ 34 | public TabItem(final ElementBuilder builder) { 35 | super(builder); 36 | } 37 | 38 | /** 39 | * Selects this item. 40 | * @throws AutomationException Something has gone wrong 41 | * @throws PatternNotFoundException Pattern not found 42 | */ 43 | public void selectItem() 44 | throws AutomationException, PatternNotFoundException { 45 | select(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/Hyperlink.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | import mmarquee.automation.AutomationException; 19 | import mmarquee.automation.pattern.PatternNotFoundException; 20 | 21 | /** 22 | * Wrapper for the Hyperlink element. 23 | * 24 | * @author Mark Humphreys 25 | * Date 03/02/2016. 26 | */ 27 | public final class Hyperlink extends AutomationBase 28 | implements ImplementsClick { 29 | 30 | /** 31 | * Constructor for the Hyperlink. 32 | * 33 | * @param builder The builder 34 | */ 35 | public Hyperlink(final ElementBuilder builder) { 36 | super(builder); 37 | } 38 | 39 | /** 40 | * Fires the click event associated with this element. 41 | * @throws AutomationException Something has gone wrong 42 | * @throws PatternNotFoundException Did not find the pattern 43 | **/ 44 | public void click() throws AutomationException, PatternNotFoundException { 45 | super.invoke(); 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/ListItem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.automation.controls; 18 | 19 | import mmarquee.automation.AutomationException; 20 | import mmarquee.automation.pattern.PatternNotFoundException; 21 | 22 | /** 23 | * Wrapper for the ListItem element. 24 | * 25 | * @author Mark Humphreys 26 | * Date 09/02/2016. 27 | */ 28 | public final class ListItem extends Container 29 | implements ImplementsSelect, ImplementsClick { 30 | /** 31 | * Constructor for the ListItem. 32 | * @param builder The builder 33 | */ 34 | public ListItem(final ElementBuilder builder) { 35 | super(builder); 36 | } 37 | 38 | /** 39 | * Clicks the item. 40 | * 41 | * @throws AutomationException Error in the automation library. 42 | * @throws PatternNotFoundException Could not find the invoke pattern. 43 | */ 44 | public void click() 45 | throws AutomationException, PatternNotFoundException { 46 | super.invoke(); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/ExpandCollapseState.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | /** 19 | * The ExpandCollapseState. 20 | * 21 | * @author Mark Humphreys 22 | * Date 12/09/2016. 23 | */ 24 | public enum ExpandCollapseState { 25 | /** 26 | * Collapsed. 27 | */ 28 | Collapsed(0), 29 | 30 | /** 31 | * Expanded. 32 | */ 33 | Expanded(1), 34 | 35 | /** 36 | * Partially expanded. 37 | */ 38 | PartiallyExpanded(2), 39 | 40 | /** 41 | * A leaf. 42 | */ 43 | LeafNode(3); 44 | 45 | /** 46 | * The value. 47 | */ 48 | private int value; 49 | 50 | /** 51 | * Gets the value. 52 | * @return The value. 53 | */ 54 | public int getValue() { 55 | return this.value; 56 | } 57 | 58 | /** 59 | * Constructor for ExpandCollapseState. 60 | * 61 | * @param inValue The value. 62 | */ 63 | ExpandCollapseState(final int inValue) { 64 | this.value = inValue; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/TreeViewItem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | import mmarquee.automation.AutomationException; 19 | import mmarquee.automation.pattern.PatternNotFoundException; 20 | 21 | /** 22 | * Wrapper for the TreeViewItem element. 23 | * 24 | * @author Mark Humphreys 25 | * Date 20/02/2016 26 | */ 27 | public final class TreeViewItem 28 | extends AutomationBase 29 | implements ImplementsSelect, ImplementsClick, ImplementsExpand { 30 | 31 | /** 32 | * Construct the TreeViewItem. 33 | * @param builder The element. 34 | */ 35 | public TreeViewItem(final ElementBuilder builder) { 36 | super(builder); 37 | } 38 | 39 | /** 40 | * Click the item. 41 | * @throws AutomationException Automation library issue. 42 | * @throws PatternNotFoundException Pattern not found. 43 | */ 44 | public void click() 45 | throws AutomationException, PatternNotFoundException { 46 | super.invoke(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/ElementNotFoundException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation; 17 | 18 | /** 19 | * Thrown when an element is not found. 20 | * 21 | * @author Mark Humphreys 22 | * Date 06/03/2016. 23 | */ 24 | public class ElementNotFoundException extends AutomationException { 25 | 26 | /** 27 | * Serial version uid. 28 | */ 29 | private static final long serialVersionUID = 5575725853478222085L; 30 | 31 | /** 32 | * Default constructor. 33 | */ 34 | public ElementNotFoundException() { 35 | super("Element not found"); 36 | } 37 | 38 | /** 39 | * Constructor, with a name of the not found element. 40 | * @param name The element name 41 | */ 42 | public ElementNotFoundException(final String name) { 43 | super("Element " + name + " not found"); 44 | } 45 | 46 | /** 47 | * Constructor, with a cause. 48 | * @param cause The cause 49 | */ 50 | public ElementNotFoundException(final Throwable cause) { 51 | super(cause); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationTreeWalker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.Pointer; 19 | import com.sun.jna.platform.win32.COM.IUnknown; 20 | import com.sun.jna.platform.win32.Guid; 21 | import com.sun.jna.ptr.PointerByReference; 22 | 23 | /** 24 | * @author Mark Humphreys 25 | * Date 02/02/2017. 26 | */ 27 | public interface IUIAutomationTreeWalker extends IUnknown { 28 | /** 29 | * The interface IID for QueryInterface et al 30 | */ 31 | Guid.IID IID = new Guid.IID( 32 | "{4042C624-389C-4AFC-A630-9DF854A541FC}"); 33 | 34 | int getParentElement(Pointer element, PointerByReference parent); 35 | int getFirstChildElement(Pointer element, PointerByReference first); 36 | int getLastChildElement(Pointer element, PointerByReference last); 37 | int getNextSiblingElement(Pointer element, PointerByReference next); 38 | int getPreviousSiblingElement(Pointer element, PointerByReference previous); 39 | /* 8-14 cache equivalents */ 40 | int getCondition(PointerByReference condition); 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationTogglePattern.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.COM.IUnknown; 19 | import com.sun.jna.platform.win32.Guid; 20 | import com.sun.jna.ptr.IntByReference; 21 | 22 | /** 23 | * @author Mark Humphreys 24 | * Date 13/07/2016. 25 | */ 26 | public interface IUIAutomationTogglePattern extends IUnknown { 27 | /** 28 | * The interface IID for QueryInterface et al 29 | */ 30 | Guid.IID IID = new Guid.IID("{94CF8058-9B8D-4AB9-8BFD-4CD0A33C8C70}"); 31 | 32 | /** 33 | * Toggles the element via the pattern. 34 | * @return If this method succeeds, it returns S_OK. Otherwise, it returns 35 | * an HRESULT error code. 36 | */ 37 | int toggle(); 38 | 39 | /** 40 | * Gets the toggle state of the element, via the pattern. 41 | * @param ibr Toggle state 42 | * @return If this method succeeds, it returns S_OK. Otherwise, it returns 43 | * an HRESULT error code. 44 | */ 45 | int getCurrentToggleState(IntByReference ibr); 46 | } 47 | 48 | -------------------------------------------------------------------------------- /src/main/scala/mmarquee/demo/PacketLoggerApplication.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.demo 18 | 19 | class PacketLoggerApplication extends BaseApplication { 20 | applicationTitle = "C:\\Users\\inpwt\\Downloads\\windump.exe" 21 | 22 | def launch(): Unit = { 23 | application = automation.launchWithDirectory(applicationTitle, 24 | "-p", 25 | "-nn", 26 | "-N", 27 | "-wcapture.dump", 28 | "-X", 29 | "-s 0", 30 | "-i 1", 31 | "host 192.168.1.254") 32 | 33 | // A short wait for the call to gather some information 34 | Thread.sleep(10000) 35 | } 36 | 37 | def dump(): Unit = { 38 | Thread.sleep(1000); // So it can write the file properly 39 | automation.launchWithRedirect(applicationTitle, 40 | "-rC:\\Users\\inpwt\\Downloads\\capture.dump", 41 | "-nnvvvSeXX") 42 | } 43 | 44 | override def exit(): Unit = { 45 | application.end() 46 | } 47 | } -------------------------------------------------------------------------------- /src/test/java/mmarquee/automation/ControlTypeTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation; 17 | 18 | import static org.junit.Assert.*; 19 | 20 | import org.junit.Test; 21 | 22 | /** 23 | 24 | * Tests for the ControlType enum behaviour. 25 | */ 26 | public class ControlTypeTest { 27 | 28 | @Test 29 | public void getValue() throws Exception { 30 | int value = ControlType.HeaderItem.getValue(); 31 | assertEquals(50035,value); 32 | } 33 | 34 | @Test 35 | public void getValue_Min() throws Exception { 36 | int value = ControlType.None.getValue(); 37 | assertEquals(0,value); 38 | } 39 | 40 | @Test 41 | public void fromValue() throws Exception { 42 | ControlType type = ControlType.fromValue(50035); 43 | assertEquals(ControlType.HeaderItem, type); 44 | } 45 | 46 | @Test 47 | public void fromValue_Null() throws Exception { 48 | ControlType type = ControlType.fromValue(0); 49 | assertEquals(ControlType.None, type); 50 | } 51 | 52 | @Test 53 | public void fromValue_Invalid() throws Exception { 54 | ControlType type = ControlType.fromValue(-123); 55 | assertEquals(ControlType.None, type); 56 | } 57 | } -------------------------------------------------------------------------------- /src/test/java/mmarquee/automation/controls/AppBarTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | import com.sun.jna.ptr.PointerByReference; 19 | import mmarquee.automation.Element; 20 | import mmarquee.automation.UIAutomation; 21 | import mmarquee.uiautomation.IUIAutomation; 22 | import org.junit.Test; 23 | import org.mockito.Mockito; 24 | 25 | import static org.junit.Assert.assertTrue; 26 | import static org.mockito.ArgumentMatchers.isA; 27 | import static org.mockito.Mockito.when; 28 | 29 | /** 30 | * Tests for the appbar. 31 | * 32 | * @author Mark Humphreys 33 | * Date 28/12/2016. 34 | */ 35 | public class AppBarTest { 36 | @Test 37 | public void testGetName_Gets_Name_From_Element() throws Exception { 38 | Element element = Mockito.mock(Element.class); 39 | IUIAutomation mocked_automation = Mockito.mock(IUIAutomation.class); 40 | 41 | when(mocked_automation.createTrueCondition(isA(PointerByReference.class))).thenReturn(0); 42 | 43 | UIAutomation instance = new UIAutomation(mocked_automation); 44 | 45 | when(element.getName()).thenReturn("NAME"); 46 | 47 | AppBar ctrl = new AppBar( 48 | new ElementBuilder(element).automation(instance)); 49 | 50 | String name = ctrl.getName(); 51 | 52 | assertTrue(name.equals("NAME")); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationElement6.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.Guid; 19 | import com.sun.jna.ptr.PointerByReference; 20 | 21 | /** 22 | * Wrapper around the IUIAutomation6 interface. 23 | * 24 | * This interface is supported in Windows 10, version 1703 [desktop apps only] upwards 25 | * 26 | * @author Mark Humphreys 27 | * Date 24/07/2016. 28 | */ 29 | public interface IUIAutomationElement6 extends IUIAutomationElement5 { 30 | /** 31 | * The interface IID for QueryInterface et al. 32 | */ 33 | Guid.IID IID = new Guid.IID("{4780D450-8BCA-4977-AFA5-A4A517F555E3}"); 34 | 35 | /** 36 | * Gets the current full description of the automation element. 37 | * @param sr The pointer to the full description 38 | * @return If this method succeeds, it returns S_OK. Otherwise, it returns 39 | * an HRESULT error code. 40 | */ 41 | int getCurrentFullDescription(PointerByReference sr); 42 | 43 | /** 44 | * Gets the cached full description of the automation element. 45 | * @param sr The pointer to the full description 46 | * @return If this method succeeds, it returns S_OK. Otherwise, it returns 47 | * an HRESULT error code. 48 | */ 49 | int getCachedFullDescription(PointerByReference sr); 50 | } -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/RibbonBar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | import mmarquee.automation.AutomationException; 19 | import mmarquee.automation.ControlType; 20 | 21 | /** 22 | * Specialist pane that represents the RibbonBar. 23 | * 24 | * @author Mark Humphreys 25 | * Date 02/03/2016. 26 | */ 27 | public final class RibbonBar extends Panel { 28 | 29 | /** 30 | * Control name of the panel type. 31 | */ 32 | public final static String CLASS_NAME = "UIRibbonCommandBarDock"; 33 | 34 | /** 35 | * Construct the RibbonBar. 36 | * @param builder The builder 37 | * @throws AutomationException Something is wrong in automation. 38 | */ 39 | public RibbonBar(final ElementBuilder builder) 40 | throws AutomationException { 41 | super(builder); 42 | assertClassName(CLASS_NAME); 43 | } 44 | 45 | /** 46 | * Get the RibbonCommandBar associated with this container. 47 | * @return The RibbonBar. 48 | * @throws AutomationException Automation issue. 49 | */ 50 | public RibbonCommandBar getRibbonCommandBar() 51 | throws AutomationException { 52 | return new RibbonCommandBar(new ElementBuilder(this.getElementByControlType(0, 53 | ControlType.Pane, RibbonCommandBar.CLASS_NAME))); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/IUIAutomationRangeValuePattern.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import com.sun.jna.platform.win32.COM.IUnknown; 19 | import com.sun.jna.platform.win32.Guid; 20 | import com.sun.jna.ptr.DoubleByReference; 21 | import com.sun.jna.ptr.IntByReference; 22 | 23 | /** 24 | * Provides access to a control that presents a range of values. 25 | * 26 | * @author Mark Humphreys 27 | * Date 13/07/2016. 28 | */ 29 | public interface IUIAutomationRangeValuePattern extends IUnknown { 30 | /** 31 | * The interface IID for QueryInterface et al 32 | */ 33 | Guid.IID IID = new Guid.IID( 34 | "{59213F4F-7346-49E5-B120-80555987A148}"); 35 | 36 | /** 37 | * Sets the value of the control. 38 | * 39 | * @param val the value to set 40 | * @return Success or failure 41 | */ 42 | int setValue(Double val); 43 | 44 | /** 45 | * Retrieves the value of the control. 46 | * 47 | * @param retVal The value to set 48 | * @return Success or failure 49 | */ 50 | int getValue(DoubleByReference retVal); 51 | 52 | /** 53 | * Indicates whether the value of the element can be changed. 54 | * 55 | * @param retVal The return value 56 | * @return Success or failure 57 | */ 58 | int getIsReadOnly(IntByReference retVal); 59 | } -------------------------------------------------------------------------------- /src/main/scala/mmarquee/demo/NotepadApplication.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-18 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.demo 18 | 19 | import mmarquee.automation.controls.MenuItem 20 | import mmarquee.automation.controls.{Search, Window} 21 | 22 | class NotepadApplication extends BaseApplication { 23 | private var window: Window = _ 24 | 25 | def launch(): Unit = { 26 | application = automation.launch("notepad.exe") 27 | 28 | // A short wait for the expand to work, just in case 29 | Thread.sleep(500) 30 | 31 | // Find the window 32 | window = automation.getDesktopWindow("Untitled - Notepad") 33 | } 34 | 35 | def addText(tag: String): Unit = { 36 | val edit = window.getEditBox(Search.getBuilder(0).build()) 37 | 38 | edit.setValue(tag) 39 | } 40 | 41 | def clickExit(): Unit = { 42 | val menu = window.getMainMenu(1) 43 | val exit: MenuItem = menu.getMenuItem("File", "Exit") 44 | exit.click() 45 | } 46 | 47 | def confirmExit(): Unit = { 48 | val confirm = window.getWindow(Search.getBuilder("Notepad").build()) 49 | val button = confirm.getButton(Search.getBuilder("Don't Save").build()) 50 | button.click() 51 | } 52 | 53 | def getConfirm: Window = { 54 | window.getWindow(Search.getBuilder("Notepad").build()) 55 | } 56 | 57 | def findProcess: Boolean = { 58 | automation.findProcess("notepad.exe") != null 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/test/java/mmarquee/automation/controls/AutomationCustomTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | import mmarquee.automation.Element; 19 | import mmarquee.automation.UIAutomation; 20 | import mmarquee.automation.pattern.ItemContainer; 21 | import mmarquee.automation.pattern.Value; 22 | import mmarquee.uiautomation.IUIAutomation; 23 | import org.junit.Test; 24 | import org.mockito.Mockito; 25 | 26 | import static org.junit.Assert.assertTrue; 27 | import static org.mockito.Mockito.when; 28 | 29 | /** 30 | * @author Mark Humphreys 31 | * Date 28/12/2016. 32 | */ 33 | public class AutomationCustomTest { 34 | @Test 35 | public void testGetName_Gets_Name_From_Element() throws Exception { 36 | Element element = Mockito.mock(Element.class); 37 | ItemContainer container = Mockito.mock(ItemContainer.class); 38 | Value value = Mockito.mock(Value.class); 39 | when(element.getName()).thenReturn("NAME"); 40 | 41 | IUIAutomation mocked_automation = Mockito.mock(IUIAutomation.class); 42 | UIAutomation instance = new UIAutomation(mocked_automation); 43 | 44 | Custom ctrl = new Custom( 45 | new ElementBuilder(element).addPattern(container).addPattern(value).automation(instance)); 46 | 47 | String name = ctrl.getName(); 48 | 49 | assertTrue(name.equals("NAME")); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/TitleBar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | import com.sun.jna.ptr.PointerByReference; 19 | import mmarquee.automation.AutomationException; 20 | import mmarquee.automation.ControlType; 21 | import mmarquee.automation.Element; 22 | import mmarquee.uiautomation.TreeScope; 23 | 24 | /** 25 | * Wrapper for the TitleBar element. 26 | * 27 | * @author Mark Humphreys 28 | * Date 04/03/2016. 29 | * 30 | */ 31 | public final class TitleBar extends Container { 32 | /** 33 | * Constructor for the TitleBar. 34 | * @param builder The builder 35 | */ 36 | public TitleBar(final ElementBuilder builder){ 37 | super(builder); 38 | } 39 | 40 | /** 41 | * Gets the menu bar for this title-bar. 42 | * @return The Main menu 43 | * @throws AutomationException Automation library error 44 | */ 45 | public MainMenu getMenuBar() throws AutomationException { 46 | PointerByReference condition = this.getAutomation() 47 | .createControlTypeCondition(ControlType.MenuBar); 48 | 49 | Element element = 50 | this.getElement().findFirst( 51 | new TreeScope(TreeScope.DESCENDANTS), 52 | condition); 53 | 54 | return new MainMenu(new ElementBuilder(element).parent(this.getElement())); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/test/java/mmarquee/automation/controls/AutomationToolbarTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | import static org.junit.Assert.assertTrue; 19 | import static org.mockito.Mockito.when; 20 | 21 | import mmarquee.automation.Element; 22 | import org.junit.Test; 23 | import org.mockito.Mockito; 24 | 25 | import mmarquee.automation.UIAutomation; 26 | import mmarquee.automation.pattern.ItemContainer; 27 | import mmarquee.uiautomation.IUIAutomation; 28 | 29 | /** 30 | * @author Mark Humphreys 31 | * Date 01/12/2016. 32 | */ 33 | public class AutomationToolbarTest { 34 | 35 | static { 36 | ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); 37 | } 38 | 39 | @Test 40 | public void testGetName_Returns_Name_From_Element() throws Exception { 41 | Element element = Mockito.mock(Element.class); 42 | ItemContainer container = Mockito.mock(ItemContainer.class); 43 | when(element.getName()).thenReturn("NAME"); 44 | 45 | IUIAutomation mocked_automation = Mockito.mock(IUIAutomation.class); 46 | 47 | UIAutomation instance = new UIAutomation(mocked_automation); 48 | 49 | ToolBar ctrl = new ToolBar( 50 | new ElementBuilder(element).automation(instance).addPattern(container)); 51 | 52 | String name = ctrl.getName(); 53 | 54 | assertTrue(name.equals("NAME")); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/RibbonCommandBar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | import mmarquee.automation.AutomationException; 19 | import mmarquee.automation.ControlType; 20 | 21 | /** 22 | * Specialist pane that represents the RibbonCommandBar. 23 | * 24 | * @author Mark Humphreys 25 | * Date 02/03/2016. 26 | */ 27 | public final class RibbonCommandBar extends Container { 28 | 29 | /** 30 | * The class name for this panel. 31 | */ 32 | public final static String CLASS_NAME = "UIRibbonCommandBar"; 33 | 34 | /** 35 | * Construct the RibbonCommandBar. 36 | * 37 | * @param builder The builder. 38 | * @throws AutomationException Something is wrong in automation 39 | */ 40 | public RibbonCommandBar(final ElementBuilder builder) 41 | throws AutomationException { 42 | super(builder); 43 | assertClassName(CLASS_NAME); 44 | } 45 | 46 | /** 47 | * Get the RibbonWorkPane associated with the container. 48 | * @return The RibbonWorkPane. 49 | * @throws AutomationException Something is wrong in automation 50 | */ 51 | public RibbonWorkPane getRibbonWorkPane() 52 | throws AutomationException { 53 | return new RibbonWorkPane(new ElementBuilder(this.getElementByControlType(0, 54 | ControlType.Pane, RibbonWorkPane.CLASS_NAME))); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /docs/menus.md: -------------------------------------------------------------------------------- 1 | There appear to be 2 different types of menus, depending on the framework that is being used, MenuBar and Menu based, VCL/Delphi and 'classic' windows applications menus start with a MenuBar. where as .NET applications start with Menus. Examples are shown below and in the examples provided. 2 | 3 | ### Delphi / VCL Menus 4 | 5 | VCL menus are rather tricky, as they need to be expanded and collapsed before the menuitems can be seen via automation, also these menu items do not belong to the parent item, but the overall menu. 6 | 7 | The example below shows the current (as of 25/04/2016) support for 2 level menus. If either of these text items are not found the ElementNotFoundException exception will be thrown. 8 | 9 | ``` 10 | try { 11 | MenuItem exit = menu.getMenuItem("File", "Exit"); 12 | exit.click(); 13 | } catch (ElementNotFoundException ex) { 14 | .. 15 | } 16 | ``` 17 | 18 | ### WPF Menus 19 | 20 | ``` 21 | MainMenu mainMenu = window.getMenu(0); 22 | 23 | // Get the first menu item (i.e. "File") 24 | MenuItem file = mainMenu.getItems().get(0); 25 | file.expand(); 26 | 27 | // A short wait for the expand to work 28 | try { 29 | Thread.sleep(500); 30 | } catch (Exception ex) { 31 | logger.info("Interrupted"); 32 | } 33 | 34 | // Look for a specific menu item (in this case 'exit' is the 4th entry) 35 | MenuItem exit = file.getItems().get(3); 36 | 37 | exit.click(); 38 | ``` 39 | 40 | ## Popup Menus 41 | A popup menu is just another menu, and can be accessed in the same manner. In the WPF example, there is a button that has an associated context menu, the code below illustrates how to get at this menu and associated menu items 42 | 43 | ``` 44 | AutomationMouse mouse = new AutomationMouse(); 45 | mouse.setLocation(1119, 896); 46 | mouse.rightClick(); 47 | 48 | // Wait to make sure menu is displayed 49 | try { 50 | Thread.sleep(500); 51 | } catch (Exception ex) { 52 | logger.info("Interrupted"); 53 | } 54 | 55 | // Should be able to get the popup menu here 56 | Menu popup = window.getMenu(0) 57 | 58 | ``` -------------------------------------------------------------------------------- /src/main/java/mmarquee/demo/DemoPointOver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.demo; 18 | 19 | import com.sun.jna.platform.win32.WinDef; 20 | import mmarquee.automation.Element; 21 | import mmarquee.automation.UIAutomation; 22 | 23 | import java.awt.*; 24 | 25 | /** 26 | * Example for the PointOver functionality. 27 | * 28 | * @author Mark Humphreys 29 | * Date 12/02/2017. 30 | */ 31 | public class DemoPointOver extends TestBase { 32 | /** 33 | * Run the thing. 34 | */ 35 | public final void run() { 36 | UIAutomation automation = UIAutomation.getInstance(); 37 | 38 | do { 39 | this.rest(); 40 | 41 | Point p = MouseInfo.getPointerInfo().getLocation(); 42 | 43 | logger.info(p.getX() + " - " + p.getY()); 44 | 45 | WinDef.POINT point = new WinDef.POINT(); 46 | point.x = (int) p.getX(); 47 | point.y = (int) p.getY(); 48 | 49 | try { 50 | Element elementUnder = 51 | automation.getElementFromPoint(point); 52 | 53 | logger.info("From point = " + elementUnder.getName()); 54 | 55 | Element elementFocus = automation.getFocusedElement(); 56 | logger.info("From focus = " + elementFocus.getName()); 57 | 58 | } catch (Exception ex) { 59 | logger.info(ex.getStackTrace()); 60 | } 61 | } while (true); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/test/java/mmarquee/automation/controls/AutomationStatusBarTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | import mmarquee.automation.Element; 19 | import mmarquee.automation.UIAutomation; 20 | import mmarquee.automation.pattern.ItemContainer; 21 | import mmarquee.uiautomation.IUIAutomation; 22 | import org.apache.logging.log4j.LogManager; 23 | import org.apache.logging.log4j.Logger; 24 | import org.junit.Test; 25 | import org.mockito.Mockito; 26 | 27 | import static org.junit.Assert.assertTrue; 28 | import static org.mockito.Mockito.when; 29 | 30 | /** 31 | * @author Mark Humphreys 32 | * Date 02/12/2016. 33 | */ 34 | public class AutomationStatusBarTest { 35 | protected Logger logger = 36 | LogManager.getLogger(RadioButtonTest.class.getName()); 37 | 38 | @Test 39 | public void testName_Gets_Name_From_Element() throws Exception { 40 | Element element = Mockito.mock(Element.class); 41 | ItemContainer pattern = Mockito.mock(ItemContainer.class); 42 | 43 | when(element.getName()).thenReturn("NAME"); 44 | 45 | IUIAutomation mocked_automation = Mockito.mock(IUIAutomation.class); 46 | UIAutomation instance = new UIAutomation(mocked_automation); 47 | 48 | StatusBar statusBar = new StatusBar( 49 | new ElementBuilder(element).addPattern(pattern).automation(instance)); 50 | 51 | String name = statusBar.getName(); 52 | 53 | assertTrue(name.equals("NAME")); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ui-automation 2 | 3 | ui-automation is a framework for automating (via the [MS UIAutomation library](https://msdn.microsoft.com/en-us/library/vstudio/ms753388(v=vs.100).aspx)) rich client applications based on Win32 (including Delphi), WPF and other Windows applications ((including Java SWT)). It is written in Java, using the JNA library to make calls to the COM-based WIndows automation library. 4 | 5 | Tests and automation programs using ui-automation can be written with Java (or other JVM based languages, like Scala) and used in any testing framework available to the JVM. 6 | 7 | It provides a consistent, object-oriented API, hiding the complexity of Microsoft's UIAutomation library and windows messages from the user. 8 | 9 | # Blog 10 | * [Blog](https://github.com/mmarquee/ui-automation/wiki/Blog-Home) 11 | 12 | # Developer documentation 13 | * [Start here](docs/developer.md) 14 | 15 | # Continuous Builds 16 | The build is built (for PRs and master) via [travis-ci](https://travis-ci.org/mmarquee/ui-automation). Failed builds cannot be merged. 17 | 18 | ![build status](https://travis-ci.org/mmarquee/ui-automation.svg?branch=master) 19 | 20 | # Contributors 21 | Thanks to everyone that has used the library and contributed ideas and suggestions and issues, in order to improve the library. 22 | 23 | ## Code Contributors 24 | * [Mark Humphreys](https://github.com/mmarquee) 25 | * [Pascal Bihler](https://github.com/pbi-qfs) 26 | * [Filipe Dias Lewandowski](https://github.com/diasf) 27 | 28 | # License 29 | Apache Version 2.0 Copyright (C) 2016 30 | 31 | See LICENCE.txt for details. 32 | 33 | # See also 34 | * [DelphiUIAutomation](https://github.com/markhumphreysjhc/DelphiUIAutomation) 35 | * [Microsoft Accessibility](https://msdn.microsoft.com/en-us/library/vstudio/ms753388(v=vs.100).aspx) 36 | * [UIAutomation for Powershell](http://uiautomation.codeplex.com/documentation) 37 | * [TestStack.White](https://github.com/TestStack/White) 38 | * [UI Automation - A wrapper around Microsoft's UI Automation libraries.](https://github.com/vijayakumarsuraj/UIAutomation) 39 | * [Functional GUI Testing Automation Patterns](https://www.infoq.com/articles/gui-automation-patterns) 40 | 41 | -------------------------------------------------------------------------------- /src/test/java/mmarquee/automation/controls/TextBoxTest.java: -------------------------------------------------------------------------------- 1 | package mmarquee.automation.controls; 2 | 3 | import mmarquee.automation.Element; 4 | import mmarquee.automation.UIAutomation; 5 | import mmarquee.automation.pattern.Value; 6 | import mmarquee.uiautomation.IUIAutomation; 7 | import org.junit.Test; 8 | import org.mockito.Mockito; 9 | 10 | import static org.junit.Assert.assertTrue; 11 | import static org.mockito.Mockito.when; 12 | 13 | /** 14 | * Tests for TextBox. 15 | * 16 | * @author Mark Humphreys 17 | * Date 11/12/2016. 18 | */ 19 | public class TextBoxTest { 20 | static { 21 | ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); 22 | } 23 | 24 | @Test 25 | public void testName_Gets_Value_From_Element() throws Exception { 26 | Element element = Mockito.mock(Element.class); 27 | 28 | when(element.getName()).thenReturn("NAME"); 29 | 30 | Value value = Mockito.mock(Value.class); 31 | when(value.isAvailable()).thenReturn(true); 32 | when(value.value()).thenReturn("VALUE"); 33 | 34 | IUIAutomation mocked_automation = Mockito.mock(IUIAutomation.class); 35 | UIAutomation instance = new UIAutomation(mocked_automation); 36 | 37 | TextBox ctrl = new TextBox( 38 | new ElementBuilder(element).automation(instance).addPattern(value)); 39 | 40 | String name = ctrl.getName(); 41 | 42 | assertTrue(name.equals("NAME")); 43 | } 44 | 45 | @Test 46 | public void testGetValue_Gets_Value_From_Element_Value() throws Exception { 47 | Element element = Mockito.mock(Element.class); 48 | 49 | Value value = Mockito.mock(Value.class); 50 | when(value.isAvailable()).thenReturn(true); 51 | when(value.value()).thenReturn("NAME"); 52 | 53 | IUIAutomation mocked_automation = Mockito.mock(IUIAutomation.class); 54 | UIAutomation instance = new UIAutomation(mocked_automation); 55 | 56 | TextBox ctrl = new TextBox( 57 | new ElementBuilder(element).automation(instance).addPattern(value)); 58 | 59 | String name = ctrl.getValue(); 60 | 61 | assertTrue(name.equals("NAME")); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/ImplementsText.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | import mmarquee.automation.AutomationException; 19 | import mmarquee.automation.pattern.PatternNotFoundException; 20 | import mmarquee.automation.pattern.Text; 21 | 22 | /** 23 | * The Control supports the methods of the Text Pattern. 24 | */ 25 | public interface ImplementsText extends Automatable, CanRequestBasePattern { 26 | 27 | /** 28 | * Gets the text for the document. 29 | * @return The document's text 30 | * @throws AutomationException Something has gone wrong 31 | * @throws PatternNotFoundException Failed to find pattern 32 | */ 33 | default public String getText() throws AutomationException, PatternNotFoundException { 34 | final Text textPattern = requestAutomationPattern(Text.class); 35 | if (textPattern.isAvailable()) { 36 | return textPattern.getText(); 37 | } 38 | throw new PatternNotFoundException("Cannot get text"); 39 | } 40 | /** 41 | * Gets the selection. 42 | * 43 | * @return String of text that is selected 44 | * @throws AutomationException Something has gone wrong 45 | * @throws PatternNotFoundException Failed to find pattern 46 | */ 47 | default public String getSelection() throws AutomationException, PatternNotFoundException { 48 | final Text textPattern = requestAutomationPattern(Text.class); 49 | if (textPattern.isAvailable()) { 50 | return textPattern.getSelection(); 51 | } 52 | throw new PatternNotFoundException("Cannot get text"); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/ImplementsTable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | import mmarquee.automation.AutomationException; 19 | import mmarquee.automation.pattern.PatternNotFoundException; 20 | import mmarquee.uiautomation.RowOrColumnMajor; 21 | 22 | import java.util.List; 23 | 24 | /** 25 | * The Control supports the methods of the Table pattern. 26 | * 27 | * @author Mark Humphreys 28 | * Date 21/09/2016. 29 | */ 30 | public interface ImplementsTable extends Automatable { 31 | 32 | /** 33 | * Gets the list of the column headers. 34 | * 35 | * @return List of GridItems 36 | * @throws AutomationException Automation library error 37 | * @throws PatternNotFoundException Expected pattern not found 38 | */ 39 | List getCurrentColumnHeaders () 40 | throws PatternNotFoundException, AutomationException; 41 | 42 | /** 43 | * Gets the row headers for the grid. 44 | * @return The list of column header 45 | * @throws AutomationException Something has gone wrong 46 | */ 47 | List getCurrentRowHeaders() throws AutomationException; 48 | 49 | /** 50 | * Returns whether the grid has column or row headers. 51 | * 52 | * @return RowOrColumnMajor Row or column 53 | * @throws AutomationException Error thrown from automation library 54 | * @throws PatternNotFoundException Failed to find pattern 55 | */ 56 | RowOrColumnMajor getRowOrColumnMajor() 57 | throws AutomationException, PatternNotFoundException; 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/ImplementsToggle.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | import mmarquee.automation.AutomationException; 19 | import mmarquee.automation.pattern.PatternNotFoundException; 20 | import mmarquee.automation.pattern.Toggle; 21 | import mmarquee.uiautomation.ToggleState; 22 | 23 | /** 24 | * @author Mark Humphreys 25 | * Date 19/05/2017. 26 | */ 27 | public interface ImplementsToggle extends Automatable, CanRequestBasePattern { 28 | /** 29 | * Toggles the element. 30 | * @throws AutomationException Automation library error 31 | * @throws PatternNotFoundException Failed to find pattern 32 | */ 33 | default void toggle() throws AutomationException, PatternNotFoundException { 34 | final Toggle togglePattern = requestAutomationPattern(Toggle.class); 35 | if (togglePattern.isAvailable()) { 36 | togglePattern.toggle(); 37 | return; 38 | } 39 | throw new PatternNotFoundException("Cannot toggle"); 40 | } 41 | 42 | /** 43 | * Gets the state of the toggle. 44 | * @return Toggled state 45 | * @throws AutomationException Automation library error 46 | * @throws PatternNotFoundException Failed to find pattern 47 | */ 48 | default ToggleState getToggleState() throws AutomationException, PatternNotFoundException { 49 | final Toggle togglePattern = requestAutomationPattern(Toggle.class); 50 | if (togglePattern.isAvailable()) { 51 | return togglePattern.currentToggleState(); 52 | } 53 | throw new PatternNotFoundException("Cannot query toggle state"); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/automation/controls/ImplementsGridItem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | import mmarquee.automation.AutomationException; 19 | import mmarquee.automation.pattern.GridItem; 20 | import mmarquee.automation.pattern.PatternNotFoundException; 21 | 22 | /** 23 | * Methods to interact with the grid item pattern. 24 | */ 25 | public interface ImplementsGridItem extends Automatable, CanRequestBasePattern { 26 | 27 | 28 | /** 29 | * Gets the current row for this element. 30 | * @return The row. 31 | * @throws AutomationException Something has gone wrong. 32 | * @throws PatternNotFoundException Pattern not found. 33 | */ 34 | default int getRow() throws AutomationException, PatternNotFoundException { 35 | final GridItem gridItemPattern = requestAutomationPattern(GridItem.class); 36 | if (gridItemPattern.isAvailable()) { 37 | return gridItemPattern.getRow(); 38 | } 39 | throw new PatternNotFoundException("Cannot get row"); 40 | } 41 | 42 | /** 43 | * Gets the current column for this element. 44 | * @return The column. 45 | * @throws AutomationException Something has gone wrong. 46 | * @throws PatternNotFoundException Pattern not found. 47 | */ 48 | default int getColumn() throws AutomationException, PatternNotFoundException { 49 | 50 | final GridItem gridItemPattern = requestAutomationPattern(GridItem.class); 51 | if (gridItemPattern.isAvailable()) { 52 | return gridItemPattern.getColumn(); 53 | } 54 | throw new PatternNotFoundException("Cannot get column"); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/scala/mmarquee/demo/BaseApplication.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package mmarquee.demo 18 | 19 | import com.sun.jna.platform.win32.{User32, WinDef} 20 | import mmarquee.automation.UIAutomation 21 | import mmarquee.automation.controls.{Application, Window} 22 | 23 | import scala.util.{Failure, Success, Try} 24 | 25 | trait BaseApplication { 26 | val automation = UIAutomation.getInstance 27 | var application: Application = _ 28 | 29 | var applicationName = "" 30 | var applicationArguments = "" 31 | var applicationTitle = "" 32 | 33 | def start(): Unit = { 34 | application = automation.launchOrAttach(this.applicationName, this.applicationArguments) 35 | application.waitForInputIdle(500000) 36 | } 37 | 38 | def exit(): Unit = { 39 | if (this.application != null) { 40 | println(s"quiting ${this.applicationTitle}") 41 | 42 | val hwnd: WinDef.HWND = User32.INSTANCE.FindWindow(null, this.applicationTitle) 43 | println("hwnd=" + hwnd) 44 | 45 | this.application.close(this.applicationTitle) 46 | Thread.sleep(500) 47 | this.application.quit(this.applicationTitle) 48 | } 49 | } 50 | 51 | def getDesktopWindow: Try[Window] = { 52 | System.out.println(s"Looking for $applicationTitle") 53 | Try(automation.getDesktopWindow(applicationTitle, 3)) 54 | } 55 | 56 | def isRunning: Boolean = { 57 | // Need to wait for a couple or more of seconds to make sure it's started 58 | Thread.sleep(4000) 59 | 60 | getDesktopWindow match { 61 | case Success(window) => true 62 | case Failure(window) => false 63 | } 64 | } 65 | 66 | def end: Unit = { 67 | this.application.end(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/test/java/mmarquee/automation/controls/AutomationNUIPaneTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | import mmarquee.automation.Element; 19 | 20 | import static org.junit.Assert.*; 21 | import static org.mockito.Mockito.when; 22 | 23 | import mmarquee.automation.UIAutomation; 24 | import mmarquee.automation.pattern.ItemContainer; 25 | import mmarquee.uiautomation.IUIAutomation; 26 | import org.junit.Before; 27 | import org.junit.Test; 28 | import org.mockito.Mockito; 29 | import org.mockito.MockitoAnnotations; 30 | 31 | /** 32 | * @author Mark Humphreys 33 | * Date 28/11/2016. 34 | * 35 | * Tests for the NUIPane control. 36 | */ 37 | public class AutomationNUIPaneTest { 38 | 39 | @Before 40 | public void setup() { 41 | MockitoAnnotations.initMocks(this); 42 | } 43 | 44 | static { 45 | ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); 46 | } 47 | 48 | @Test 49 | public void testName_Is_Blank() throws Exception { 50 | Element element = Mockito.mock(Element.class); 51 | 52 | when(element.getClassName()).thenReturn(NUIPane.CLASS_NAME); 53 | when(element.getName()).thenReturn(""); 54 | 55 | IUIAutomation mocked_automation = Mockito.mock(IUIAutomation.class); 56 | UIAutomation instance = new UIAutomation(mocked_automation); 57 | 58 | ItemContainer container = Mockito.mock(ItemContainer.class); 59 | 60 | NUIPane pane = new NUIPane( 61 | new ElementBuilder(element).addPattern(container).automation(instance)); 62 | 63 | String name = pane.getName(); 64 | 65 | assertTrue(name.isEmpty()); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/test/java/mmarquee/automation/controls/AutomationRibbonBarTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | import mmarquee.automation.Element; 19 | import mmarquee.automation.UIAutomation; 20 | import mmarquee.automation.pattern.ItemContainer; 21 | import mmarquee.uiautomation.IUIAutomation; 22 | import org.junit.Before; 23 | import org.junit.Test; 24 | import org.mockito.Mockito; 25 | import org.mockito.MockitoAnnotations; 26 | 27 | import static org.junit.Assert.assertEquals; 28 | import static org.mockito.Mockito.when; 29 | 30 | /** 31 | * @author Mark Humphreys 32 | * Date 28/11/2016. 33 | * 34 | * Tests for RibbonBar. 35 | */ 36 | public class AutomationRibbonBarTest { 37 | 38 | @Before 39 | public void setup() { 40 | MockitoAnnotations.initMocks(this); 41 | } 42 | 43 | static { 44 | ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); 45 | } 46 | 47 | @Test 48 | public void testGetRibbonBar() throws Exception { 49 | Element element = Mockito.mock(Element.class); 50 | 51 | when(element.getClassName()).thenReturn(RibbonBar.CLASS_NAME); 52 | when(element.getName()).thenReturn("RIBBON-01"); 53 | 54 | IUIAutomation mocked_automation = Mockito.mock(IUIAutomation.class); 55 | UIAutomation instance = new UIAutomation(mocked_automation); 56 | 57 | ItemContainer container = Mockito.mock(ItemContainer.class); 58 | 59 | RibbonBar bar = new RibbonBar( 60 | new ElementBuilder(element).addPattern(container).automation(instance)); 61 | 62 | String name = bar.getName(); 63 | 64 | assertEquals(name, "RIBBON-01"); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/test/java/mmarquee/automation/controls/AutomationRibbonWorkPaneTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | import mmarquee.automation.Element; 19 | 20 | import static org.junit.Assert.*; 21 | import static org.mockito.Mockito.when; 22 | 23 | import mmarquee.automation.UIAutomation; 24 | import mmarquee.automation.pattern.ItemContainer; 25 | import mmarquee.uiautomation.IUIAutomation; 26 | import org.junit.Before; 27 | import org.junit.Test; 28 | import org.mockito.Mockito; 29 | import org.mockito.MockitoAnnotations; 30 | 31 | /** 32 | * @author Mark Humphreys 33 | * Date 01/12/2016. 34 | * 35 | * Tests for RibbonWorkPane controls 36 | */ 37 | public class AutomationRibbonWorkPaneTest { 38 | 39 | @Before 40 | public void setup() { 41 | MockitoAnnotations.initMocks(this); 42 | } 43 | 44 | static { 45 | ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); 46 | } 47 | 48 | @Test 49 | public void testName() throws Exception { 50 | Element element = Mockito.mock(Element.class); 51 | when(element.getClassName()).thenReturn(RibbonWorkPane.CLASS_NAME); 52 | when(element.getName()).thenReturn("NAME"); 53 | 54 | IUIAutomation mocked_automation = Mockito.mock(IUIAutomation.class); 55 | UIAutomation instance = new UIAutomation(mocked_automation); 56 | 57 | ItemContainer container = Mockito.mock(ItemContainer.class); 58 | 59 | RibbonWorkPane pane = new RibbonWorkPane( 60 | new ElementBuilder(element).automation(instance).addPattern(container)); 61 | 62 | String name = pane.getName(); 63 | 64 | assertTrue(name.equals("NAME")); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/ToggleState.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import java.util.HashMap; 19 | import java.util.Map; 20 | 21 | /** 22 | * @author Mark Humphreys 23 | * Date 13/07/2016. 24 | */ 25 | public enum ToggleState { 26 | /** 27 | * Toggled off. 28 | */ 29 | OFF(0), 30 | 31 | /** 32 | * Toggled on. 33 | */ 34 | ON(1), 35 | 36 | /** 37 | * INDETERMINATE toggle. 38 | */ 39 | INDETERMINATE(2); 40 | 41 | /** 42 | * The underlying value. 43 | */ 44 | private int value; 45 | 46 | /** 47 | * Gets the value associated with this enumeration. 48 | * @return The associated value. 49 | */ 50 | public int getValue() { 51 | return this.value; 52 | } 53 | 54 | /** 55 | * Constructor for ToggleState. 56 | * @param inValue The value of the object. 57 | */ 58 | ToggleState(final int inValue) { 59 | this.value = inValue; 60 | } 61 | 62 | /** 63 | * Map of integer to value. 64 | */ 65 | private static final Map INT_TO_TYPE_MAP = 66 | new HashMap<>(); 67 | 68 | static { 69 | for (ToggleState type : ToggleState.values()) { 70 | INT_TO_TYPE_MAP.put(type.value, type); 71 | } 72 | } 73 | 74 | /** 75 | * Gets the enumeration from the given integer. 76 | * @param i The given integer. 77 | * @return The value (as an ToggleState). 78 | */ 79 | public static ToggleState fromInt(final int i) { 80 | ToggleState type = INT_TO_TYPE_MAP.get(i); 81 | if (type == null) { 82 | return ToggleState.OFF; 83 | } 84 | 85 | return type; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/test/java/mmarquee/automation/controls/AutomationRibbonCommandBarTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.automation.controls; 17 | 18 | import mmarquee.automation.Element; 19 | 20 | import static org.junit.Assert.*; 21 | import static org.mockito.Mockito.when; 22 | 23 | import mmarquee.automation.UIAutomation; 24 | import mmarquee.automation.pattern.ItemContainer; 25 | import mmarquee.uiautomation.IUIAutomation; 26 | import org.junit.Before; 27 | import org.junit.Test; 28 | import org.mockito.Mockito; 29 | import org.mockito.MockitoAnnotations; 30 | 31 | /** 32 | * @author Mark Humphreys 33 | * Date 29/11/2016. 34 | * 35 | * Tests for RibbonCommandBar 36 | */ 37 | public class AutomationRibbonCommandBarTest { 38 | 39 | @Before 40 | public void setup() { 41 | MockitoAnnotations.initMocks(this); 42 | } 43 | 44 | static { 45 | ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true); 46 | } 47 | 48 | @Test 49 | public void testGetRibbonCommandBar_Gets_Correct_Name() throws Exception { 50 | Element element = Mockito.mock(Element.class); 51 | 52 | when(element.getClassName()).thenReturn(RibbonCommandBar.CLASS_NAME); 53 | when(element.getName()).thenReturn("NAME"); 54 | 55 | IUIAutomation mocked_automation = Mockito.mock(IUIAutomation.class); 56 | UIAutomation instance = new UIAutomation(mocked_automation); 57 | 58 | ItemContainer container = Mockito.mock(ItemContainer.class); 59 | 60 | RibbonCommandBar commandBar = new RibbonCommandBar( 61 | new ElementBuilder(element).addPattern(container).automation(instance)); 62 | 63 | String name = commandBar.getName(); 64 | 65 | assertTrue(name.equals("NAME")); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/RowOrColumnMajor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-18 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import java.util.HashMap; 19 | import java.util.Map; 20 | 21 | /** 22 | * @author Mark Humphreys 23 | * Date 12/09/2016. 24 | */ 25 | public enum RowOrColumnMajor { 26 | /** 27 | * Row is major. 28 | */ 29 | RowMajor(0), 30 | 31 | /** 32 | * Column is major. 33 | */ 34 | ColumnMajor(1), 35 | 36 | /** 37 | * INDETERMINATE major. 38 | */ 39 | Indeterminate(2); 40 | 41 | /** 42 | * The value. 43 | */ 44 | private int value; 45 | 46 | /** 47 | * Gets the value. 48 | * @return The value. 49 | */ 50 | public int getValue() { 51 | return this.value; 52 | } 53 | 54 | /** 55 | * Constructor for RowOrColumnMajor. 56 | * @param inValue The value. 57 | */ 58 | RowOrColumnMajor(final int inValue) { 59 | this.value = inValue; 60 | } 61 | 62 | /** 63 | * Map of values to integer. 64 | */ 65 | private static final Map INT_TO_TYPE_MAP = 66 | new HashMap<>(); 67 | 68 | static { 69 | for (RowOrColumnMajor type : RowOrColumnMajor.values()) { 70 | INT_TO_TYPE_MAP.put(type.value, type); 71 | } 72 | } 73 | 74 | /** 75 | * Gets the enumeration from the given integer. 76 | * 77 | * @param i The given integer 78 | * @return The value (as an RowOrColumnMajor) 79 | */ 80 | public static RowOrColumnMajor fromInt(final int i) { 81 | RowOrColumnMajor type = INT_TO_TYPE_MAP.get(i); 82 | if (type == null) { 83 | return RowOrColumnMajor.Indeterminate; 84 | } 85 | return type; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/mmarquee/uiautomation/WindowVisualState.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-17 inpwtepydjuf@gmail.com 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package mmarquee.uiautomation; 17 | 18 | import java.util.HashMap; 19 | import java.util.Map; 20 | 21 | /** 22 | * Mapping for the Windows Visual state. 23 | */ 24 | public enum WindowVisualState { 25 | /** 26 | * Normal state. 27 | */ 28 | Normal(0), 29 | 30 | /** 31 | * Maximized state. 32 | */ 33 | Maximized(1), 34 | 35 | /** 36 | * Minimized state. 37 | */ 38 | Minimized(2); 39 | 40 | /** 41 | * Underlying value. 42 | */ 43 | private int value; 44 | 45 | /** 46 | * Gets the state. 47 | * @return The visual state. 48 | */ 49 | public int getValue() { 50 | return this.value; 51 | } 52 | 53 | /** 54 | * Constructor for WindowVisualState. 55 | * @param inValue The value of the state. 56 | */ 57 | WindowVisualState(final int inValue) { 58 | this.value = inValue; 59 | } 60 | 61 | /** 62 | * Map of states to integers. 63 | */ 64 | private static final Map INT_TO_TYPE_MAP = 65 | new HashMap<>(); 66 | 67 | static { 68 | for (WindowVisualState type : WindowVisualState.values()) { 69 | INT_TO_TYPE_MAP.put(type.value, type); 70 | } 71 | } 72 | 73 | /** 74 | * Gets the enumeration from the given integer. 75 | * @param i The given integer 76 | * @return The inValue (as an WindowVisualState) 77 | */ 78 | public static WindowVisualState fromInt(final int i) { 79 | WindowVisualState type = INT_TO_TYPE_MAP.get(i); 80 | if (type == null) { 81 | return WindowVisualState.Normal; 82 | } 83 | return type; 84 | } 85 | } 86 | --------------------------------------------------------------------------------