uia 0.7 → 1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: c966c5e58a5c2b30fad2f966be8e24a881d4f309
4
- data.tar.gz: 324ddfa069b36dd359f9f794cd639f8aab3dfef0
2
+ SHA256:
3
+ metadata.gz: f8c2b4d015985e4d591a9896fa2cee66e60b5eb29a6f774accc23094d4ec1429
4
+ data.tar.gz: '08f1ae75dcf5b10a3e59f077c8ead8bb9e81834f61b1eebf4838606569c006ad'
5
5
  SHA512:
6
- metadata.gz: 4eae7ba71eea61ab05e842e03c61537d6893d94052fa0e514987e51b977159535cfb3ea7096c3778163e4370317f4f1ea145b4f61c14d7dd254559c354b48a8d
7
- data.tar.gz: ab750c1795c1e1bf7c43444526f1d6198b703396e0563224ffddf2e4f95e5c75a135813a2dba1e1b4bdacf29f17c8a57dfbf03c94aeb5a062102be61d48e4b5c
6
+ metadata.gz: da1e59adbead52a98088604751feb2ae5aa2c0fe64ddb1dc02a9794427992a0e0cbb52fa6adddc59cb3a15a57047fe0c1f8b22dc8882b7ff8aa09f76e31bd057
7
+ data.tar.gz: ac970d4aeb30e37182311295d4a70ce7f9c161422eae8b7c7078a98b6ecefcc37df913d8be65307bf6e790854960ff9c44cf1310d358ef1fb3a27c4e32069f28
data/.gitmodules CHANGED
@@ -1,3 +1,3 @@
1
1
  [submodule "spec/app/src"]
2
- path = spec/app/src
3
- url = git://github.com/leviwilson/mohawk-testing-app
2
+ path = spec/app/src
3
+ url = https://github.com/leviwilson/mohawk-testing-app.git
data/ChangeLog CHANGED
@@ -1,35 +1,40 @@
1
- === Version 0.7 / 2019-01-22
2
- * Changes
3
- * Drag events now send an intermediate MouseMove event
4
-
5
- === Version 0.6 / 2014-11-14
6
- * Changes
7
- * Loosened the ffi dependency to ~> 1.9.4
8
-
9
- === Version 0.5 / 2014-05-26
10
- * Bug Fixes
11
- * fixed issue #5 where finding by runtime_id was not working on Windows 8
12
- machines
13
-
14
- === Version 0.4.4 / 2014-05-23
15
- * Enhancements
16
- * modified how it uses the runtime_id to locate an element to use the
17
- first found handle section, rather than the last
18
-
19
- === Version 0.4.3 / 2014-05-23
20
- * Enhancements
21
- * improved the speed at which you can locate an element by runtime_id
22
-
23
- === Version 0.4.2 / 2014-05-21
24
- * Enhancements
25
- * Exceptions on the .NET side of things now include stack trace
26
- information
27
- * Better errors when elements that are expected to exist are no longer
28
- there
29
-
30
- * Bug Fixes
31
- * Fixes a potential memory leak if an ElementNotAvailableException
32
- occurs when grabbing elements
1
+ === Version 0.8 / 2021-01-19
2
+ * Changes
3
+ * Bumped gem dependencies
4
+ * Removed albacore
5
+
6
+ === Version 0.7 / 2019-01-22
7
+ * Changes
8
+ * Drag events now send an intermediate MouseMove event
9
+
10
+ === Version 0.6 / 2014-11-14
11
+ * Changes
12
+ * Loosened the ffi dependency to ~> 1.9.4
13
+
14
+ === Version 0.5 / 2014-05-26
15
+ * Bug Fixes
16
+ * fixed issue #5 where finding by runtime_id was not working on Windows 8
17
+ machines
18
+
19
+ === Version 0.4.4 / 2014-05-23
20
+ * Enhancements
21
+ * modified how it uses the runtime_id to locate an element to use the
22
+ first found handle section, rather than the last
23
+
24
+ === Version 0.4.3 / 2014-05-23
25
+ * Enhancements
26
+ * improved the speed at which you can locate an element by runtime_id
27
+
28
+ === Version 0.4.2 / 2014-05-21
29
+ * Enhancements
30
+ * Exceptions on the .NET side of things now include stack trace
31
+ information
32
+ * Better errors when elements that are expected to exist are no longer
33
+ there
34
+
35
+ * Bug Fixes
36
+ * Fixes a potential memory leak if an ElementNotAvailableException
37
+ occurs when grabbing elements
33
38
 
34
39
  === Version 0.4.1 / 2014-05-14
35
40
  * Enhancements
@@ -83,84 +88,84 @@
83
88
  * changed #click to be clickable point only
84
89
  * added #click_center to try to click in the bounding_rectangle
85
90
 
86
- === Version 0.0.9 / 2014-02-06
87
- * Enhancements
88
- * Element#focused? and Element#focus
89
- * Element#bounding_rectangle
90
- * Selection#selected_items for multi-select
91
- * #focus will try multiple times to focus an element before it gives up
92
- * #click will attempt to use the bounding_rectangle if there is no
93
- "clickable point"
91
+ === Version 0.0.9 / 2014-02-06
92
+ * Enhancements
93
+ * Element#focused? and Element#focus
94
+ * Element#bounding_rectangle
95
+ * Selection#selected_items for multi-select
96
+ * #focus will try multiple times to focus an element before it gives up
97
+ * #click will attempt to use the bounding_rectangle if there is no
98
+ "clickable point"
94
99
 
95
100
  === Version 0.0.8 / 2013-12-02
96
- * Enhancements
97
- * Uia#find_element and Element#find can locate by :title
98
- * Element#send_keys
99
- * Window#close
100
- * TextPattern support to get / set the text
101
+ * Enhancements
102
+ * Uia#find_element and Element#find can locate by :title
103
+ * Element#send_keys
104
+ * Window#close
105
+ * TextPattern support to get / set the text
101
106
 
102
- * Bug Fixes
103
- * Fix issue with selecting cells in a table
107
+ * Bug Fixes
108
+ * Fix issue with selecting cells in a table
104
109
 
105
110
  === Version 0.0.7.3 / 2013-11-02
106
- * Enhancements
107
- * Element#visible?
108
- * added support for RangeValuePattern
111
+ * Enhancements
112
+ * Element#visible?
113
+ * added support for RangeValuePattern
109
114
 
110
115
  === Version 0.0.7.2 / 2013-11-02
111
- * Enhancements
112
- * Element#find can specify the scope of the search
116
+ * Enhancements
117
+ * Element#find can specify the scope of the search
113
118
 
114
119
  === Version 0.0.7.1 / 2013-11-01
115
- * Bug Fixes
116
- * Fixes issue with ComboBox controls for Selection#selection_items
120
+ * Bug Fixes
121
+ * Fixes issue with ComboBox controls for Selection#selection_items
117
122
 
118
123
  === Version 0.0.7 / 2013-11-01
119
- * Enhancements
120
- * added a base implementation for the Window pattern
121
- * added support for WindowPattern, TablePattern and TableItemPattern
122
- * Element#as raises UnsupportedPattern if the element does not implement it
123
- * added an Element#select method to filter descendants by:
124
- - pattern
125
- - name
126
- - id
127
-
128
- * Bug Fixes
129
- * modified ffi calls that return Element arrays to be individually GC'd.
130
- This prevents FFI::ManagedStruct from being taken out from underneath you
124
+ * Enhancements
125
+ * added a base implementation for the Window pattern
126
+ * added support for WindowPattern, TablePattern and TableItemPattern
127
+ * Element#as raises UnsupportedPattern if the element does not implement it
128
+ * added an Element#select method to filter descendants by:
129
+ - pattern
130
+ - name
131
+ - id
132
+
133
+ * Bug Fixes
134
+ * modified ffi calls that return Element arrays to be individually GC'd.
135
+ This prevents FFI::ManagedStruct from being taken out from underneath you
131
136
 
132
137
  === Version 0.0.6.1 / 2013-10-30
133
138
  * Bug Fixes
134
- * Fixed issue when finding root children by RegEx initially
135
- * all Find methods consistently return Element classes
139
+ * Fixed issue when finding root children by RegEx initially
140
+ * all Find methods consistently return Element classes
136
141
 
137
142
  === Version 0.0.6 / 2013-10-22
138
- * Enhancements
139
- * Have implemented the following patterns:
140
- * ExpandCollapse
141
- * Invoke
142
- * Selection
143
- * SelectionItem
144
- * Toggle
145
- * Value
146
- * Element can find their descendants by :id or :name
147
- * Can search for top-level elements with Regex
148
- * Elements can be refreshed
149
- * Moved Uia methods to be class-level (i.e. Uia.find_element rather than
150
- including Uia)
151
-
152
- === Version 0.0.5.1 / 2013-10-16
153
- * Enhancements
154
- * reduced the size of the gem package by excluding gmock and gtest
155
-
156
- === Version 0.0.5 / 2013-10-16
157
-
158
- * Enhancements
159
- * Pushed #find_element into the Uia module
160
- * Can locate elements by :id, :handle, :runtime_pid and :pid
161
- * Element now knows about :id,:control_type, :patterns, :handle and :runtime_id
162
- * Elements know about their :children and :descendants
163
-
164
- === Version 0.0.4 / 2013-10-11
143
+ * Enhancements
144
+ * Have implemented the following patterns:
145
+ * ExpandCollapse
146
+ * Invoke
147
+ * Selection
148
+ * SelectionItem
149
+ * Toggle
150
+ * Value
151
+ * Element can find their descendants by :id or :name
152
+ * Can search for top-level elements with Regex
153
+ * Elements can be refreshed
154
+ * Moved Uia methods to be class-level (i.e. Uia.find_element rather than
155
+ including Uia)
156
+
157
+ === Version 0.0.5.1 / 2013-10-16
158
+ * Enhancements
159
+ * reduced the size of the gem package by excluding gmock and gtest
160
+
161
+ === Version 0.0.5 / 2013-10-16
162
+
163
+ * Enhancements
164
+ * Pushed #find_element into the Uia module
165
+ * Can locate elements by :id, :handle, :runtime_pid and :pid
166
+ * Element now knows about :id,:control_type, :patterns, :handle and :runtime_id
167
+ * Elements know about their :children and :descendants
168
+
169
+ === Version 0.0.4 / 2013-10-11
165
170
  Initial release with very limited support for finding an element and
166
171
  displaying various properties.
data/Rakefile CHANGED
@@ -2,18 +2,17 @@ require 'bundler/setup'
2
2
  require 'bundler/gem_tasks'
3
3
  require 'rspec/core/rake_task'
4
4
 
5
- require 'albacore'
6
- require 'albacore/tasks/versionizer'
7
-
8
5
  RSpec::Core::RakeTask.new(:spec)
9
6
 
10
7
  task :default => :spec
11
-
12
8
  task :spec => :build_release
13
9
  task :build => :spec
14
10
 
15
11
  desc 'Build the release version of UiaDll'
16
- build :build_release do |b|
17
- b.sln = 'ext/UiaDll/UiaDll.sln'
18
- b.prop :Configuration, :Release
12
+ task :build_release do
13
+ Dir.chdir('ext/UiaDll') do
14
+ if !system('msbuild UiaDll.sln -target:Rebuild -property:Configuration=Release')
15
+ fail "Failed to build UiaDll: #{$?.exitstatus}"
16
+ end
17
+ end
19
18
  end
Binary file
Binary file
@@ -179,6 +179,11 @@ namespace UIA.Helper
179
179
  return FindFirst(TreeScope.Subtree, new AndCondition(name.NameCondition(), ControlType.MenuItem.Condition()));
180
180
  }
181
181
 
182
+ public Element FirstMenuItem()
183
+ {
184
+ return FindFirst(TreeScope.Subtree, new AndCondition(Condition.TrueCondition, ControlType.MenuItem.Condition()));
185
+ }
186
+
182
187
  public static Element ByRuntimeId(int[] runtimeId)
183
188
  {
184
189
  var condition = new PropertyCondition(AutomationElement.RuntimeIdProperty, runtimeId);
@@ -1,5 +1,5 @@
1
1
  <?xml version="1.0" encoding="utf-8"?>
2
- <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
2
+ <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3
3
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
4
4
  <PropertyGroup>
5
5
  <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -9,7 +9,7 @@
9
9
  <AppDesignerFolder>Properties</AppDesignerFolder>
10
10
  <RootNamespace>UIA.Helper</RootNamespace>
11
11
  <AssemblyName>UIA.Helper</AssemblyName>
12
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
12
+ <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
13
13
  <FileAlignment>512</FileAlignment>
14
14
  <TargetFrameworkProfile />
15
15
  </PropertyGroup>
@@ -21,6 +21,7 @@
21
21
  <DefineConstants>DEBUG;TRACE</DefineConstants>
22
22
  <ErrorReport>prompt</ErrorReport>
23
23
  <WarningLevel>4</WarningLevel>
24
+ <Prefer32Bit>false</Prefer32Bit>
24
25
  </PropertyGroup>
25
26
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
26
27
  <DebugType>pdbonly</DebugType>
@@ -29,6 +30,7 @@
29
30
  <DefineConstants>TRACE</DefineConstants>
30
31
  <ErrorReport>prompt</ErrorReport>
31
32
  <WarningLevel>4</WarningLevel>
33
+ <Prefer32Bit>false</Prefer32Bit>
32
34
  </PropertyGroup>
33
35
  <ItemGroup>
34
36
  <Reference Include="System" />
@@ -60,4 +62,4 @@
60
62
  <Target Name="AfterBuild">
61
63
  </Target>
62
64
  -->
63
- </Project>
65
+ </Project>
@@ -0,0 +1,89 @@
1
+ #include "Stdafx.h"
2
+
3
+ extern "C"
4
+ {
5
+ __declspec(dllexport) int ComboBox_GetItems(ElementInformationPtr element, ElementInformation** items, char* errorInfo, const int errorInfoLength)
6
+ {
7
+ try {
8
+ int count = 0;
9
+
10
+ ElementFrom(element)->As<ExpandCollapsePattern^>(ExpandCollapsePattern::Pattern)->Expand();
11
+
12
+ if ("ComboLBox" == Element::Windows[0]->ClassName)
13
+ {
14
+ auto childElements = Element::Windows[0]->Children;
15
+ *items = ElementInformation::From(childElements);
16
+ count = childElements->Length;
17
+ }
18
+ else
19
+ {
20
+ StringHelper::CopyToUnmanagedString("Unable to find list control associated with combo box", errorInfo, errorInfoLength);
21
+ }
22
+
23
+ ElementFrom(element)->As<ExpandCollapsePattern^>(ExpandCollapsePattern::Pattern)->Collapse();
24
+
25
+ return count;
26
+ }
27
+ catch (Exception^ e) {
28
+ StringHelper::CopyToUnmanagedString(e, errorInfo, errorInfoLength);
29
+ return 0;
30
+ }
31
+ }
32
+
33
+ __declspec(dllexport) void ComboBox_SetItemByIndex(ElementInformationPtr element, const int itemIndex, char* errorInfo, const int errorInfoLength)
34
+ {
35
+ try {
36
+ ElementFrom(element)->As<ExpandCollapsePattern^>(ExpandCollapsePattern::Pattern)->Expand();
37
+
38
+ if ("ComboLBox" == Element::Windows[0]->ClassName)
39
+ {
40
+ auto childElements = Element::Windows[0]->Children;
41
+ if (childElements->Length > itemIndex && itemIndex > -1)
42
+ {
43
+ childElements[itemIndex]->As<SelectionItemPattern^>(SelectionItemPattern::Pattern)->Select();
44
+ }
45
+ else
46
+ {
47
+ StringHelper::CopyToUnmanagedString("Specified index was not found in combo box list", errorInfo, errorInfoLength);
48
+ }
49
+ }
50
+ else
51
+ {
52
+ StringHelper::CopyToUnmanagedString("Unable to find list control associated with combo box", errorInfo, errorInfoLength);
53
+ }
54
+
55
+ ElementFrom(element)->As<ExpandCollapsePattern^>(ExpandCollapsePattern::Pattern)->Collapse();
56
+ }
57
+ catch (Exception^ e) {
58
+ StringHelper::CopyToUnmanagedString(e, errorInfo, errorInfoLength);
59
+ }
60
+ }
61
+
62
+ __declspec(dllexport) void ComboBox_SetItemByValue(ElementInformationPtr element, const char* itemValue, char* errorInfo, const int errorInfoLength)
63
+ {
64
+ try {
65
+ ElementFrom(element)->As<ExpandCollapsePattern^>(ExpandCollapsePattern::Pattern)->Expand();
66
+
67
+ if ("ComboLBox" == Element::Windows[0]->ClassName)
68
+ {
69
+ auto childElements = Element::Windows[0]->Children;
70
+ for each (auto item in childElements)
71
+ {
72
+ if (strcmp(StringHelper::ToUnmanaged(item->Name), itemValue) == 0)
73
+ {
74
+ item->As<SelectionItemPattern^>(SelectionItemPattern::Pattern)->Select();
75
+ }
76
+ }
77
+ }
78
+ else
79
+ {
80
+ StringHelper::CopyToUnmanagedString("Unable to find list control associated with combo box", errorInfo, errorInfoLength);
81
+ }
82
+
83
+ ElementFrom(element)->As<ExpandCollapsePattern^>(ExpandCollapsePattern::Pattern)->Collapse();
84
+ }
85
+ catch (Exception^ e) {
86
+ StringHelper::CopyToUnmanagedString(e, errorInfo, errorInfoLength);
87
+ }
88
+ }
89
+ }
@@ -39,17 +39,47 @@ extern "C" {
39
39
  }
40
40
  }
41
41
 
42
+ void OpenMenuToCreateChildControls(ElementInformationPtr element)
43
+ {
44
+ auto firstItem = ElementFrom(element)->FirstMenuItem();
45
+ if (nullptr != firstItem)
46
+ {
47
+ try
48
+ {
49
+ auto asExpand = firstItem->As<ExpandCollapsePattern^>(ExpandCollapsePattern::Pattern);
50
+ if (asExpand->Current.ExpandCollapseState == ExpandCollapseState::Collapsed)
51
+ {
52
+ asExpand->Expand();
53
+ }
54
+ }
55
+ catch (Exception^)
56
+ {}
57
+ }
58
+ }
59
+
42
60
  Element^ MenuItemPath(ElementInformationPtr element, list<const char*>& items) {
43
61
  auto current = ElementFrom(element);
62
+ bool foundAtleastOneItem = false;
44
63
 
45
64
  for(auto item = items.begin(); item != items.end(); ++item) {
46
65
  auto name = gcnew String(*item);
47
66
 
48
67
  current = current->MenuItem(name);
49
- if( nullptr == current) {
68
+
69
+ if (nullptr == current && !foundAtleastOneItem)
70
+ {
71
+ OpenMenuToCreateChildControls(element);
72
+
73
+ current = ElementFrom(element)->MenuItem(name);
74
+ }
75
+
76
+ if (nullptr == current)
77
+ {
50
78
  throw gcnew MenuItemNotFound(String::Format("the menu item \"{0}\" was not found", name));
51
79
  }
52
80
 
81
+ foundAtleastOneItem = true;
82
+
53
83
  if( *item != items.back() ) {
54
84
  current->As<InvokePattern^>(InvokePattern::Pattern)->Invoke();
55
85
  }
@@ -57,4 +87,4 @@ extern "C" {
57
87
 
58
88
  return current;
59
89
  }
60
- }
90
+ }
@@ -16,12 +16,45 @@ extern "C" {
16
16
 
17
17
  __declspec(dllexport) int Selection_Selections(ElementInformationPtr element, ElementInformation** selections, char* errorInfo, const int errorInfoLength) {
18
18
  try {
19
- auto selectedElements = Element::From(ElementFrom(element)->As<SelectionPattern^>(SelectionPattern::Pattern)->Current.GetSelection());
20
- *selections = ElementInformation::From(selectedElements);
21
- return selectedElements->Length;
19
+ int selectedItemCount = 0;
20
+
21
+ auto selectedElements = ElementFrom(element)->Find(TreeScope::Descendants, gcnew PropertyCondition(AutomationElement::ControlTypeProperty, ControlType::ListItem));
22
+ if (selectedElements->Length == 0)
23
+ {
24
+ selectedElements = ElementFrom(element)->Find(TreeScope::Descendants, gcnew PropertyCondition(AutomationElement::ControlTypeProperty, ControlType::TreeItem));
25
+ }
26
+
27
+ if (selectedElements->Length > 0)
28
+ {
29
+ for each (auto item in selectedElements)
30
+ {
31
+ if (item->As<SelectionItemPattern^>(SelectionItemPattern::Pattern)->Current.IsSelected)
32
+ {
33
+ selectedItemCount++;
34
+ }
35
+ }
36
+
37
+ auto selectedItems = new _ElementInformation[selectedItemCount];
38
+ int i = 0;
39
+ for each (auto item in selectedElements)
40
+ {
41
+ if (item->As<SelectionItemPattern^>(SelectionItemPattern::Pattern)->Current.IsSelected)
42
+ {
43
+ selectedItems[i].Refresh(item);
44
+ i++;
45
+ }
46
+ }
47
+ *selections = selectedItems;
48
+ }
49
+ else
50
+ {
51
+ *selections = nullptr;
52
+ }
53
+
54
+ return selectedItemCount;
22
55
  } catch(Exception^ e) {
23
56
  StringHelper::CopyToUnmanagedString(e, errorInfo, errorInfoLength);
24
57
  return 0;
25
58
  }
26
59
  }
27
- }
60
+ }
@@ -16,9 +16,15 @@ extern "C" {
16
16
 
17
17
  __declspec(dllexport) int Table_Headers(ElementInformationPtr element, ElementInformation** headers, char* errorInfo, const int errorInfoLength) {
18
18
  try {
19
- auto headerElements = ElementFrom(element)->As<TablePattern^>(TablePattern::Pattern)->Current.GetColumnHeaders();
20
- *headers = ElementInformation::From(Element::From(headerElements));
21
- return headerElements->Length;
19
+ auto headerParent = ElementFrom(element)->Find(TreeScope::Children, gcnew PropertyCondition(AutomationElement::ControlTypeProperty, ControlType::Header));
20
+ if (headerParent->Length > 0)
21
+ {
22
+ auto headerElements = headerParent[0]->Children;
23
+ *headers = ElementInformation::From(headerElements);
24
+ return headerElements->Length;
25
+ }
26
+ *headers = nullptr;
27
+ return 0;
22
28
  } catch(Exception^ e) {
23
29
  StringHelper::CopyToUnmanagedString(e, errorInfo, errorInfoLength);
24
30
  return 0;
@@ -34,4 +40,4 @@ extern "C" {
34
40
  return NULL;
35
41
  }
36
42
  }
37
- }
43
+ }
@@ -12,7 +12,7 @@
12
12
  </ItemGroup>
13
13
  <PropertyGroup Label="Globals">
14
14
  <ProjectGuid>{16531A20-39FB-4BDB-8F1C-E2D619BBCF58}</ProjectGuid>
15
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
15
+ <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
16
16
  <Keyword>ManagedCProj</Keyword>
17
17
  <RootNamespace>UiaDll</RootNamespace>
18
18
  </PropertyGroup>
@@ -90,6 +90,7 @@
90
90
  </ItemGroup>
91
91
  <ItemGroup>
92
92
  <ClCompile Include="AssemblyInfo.cpp" />
93
+ <ClCompile Include="ComboBoxMethods.cpp" />
93
94
  <ClCompile Include="ConditionMethods.cpp" />
94
95
  <ClCompile Include="DynamicAssemblyResolver.cpp" />
95
96
  <ClCompile Include="ElementMethods.cpp" />
@@ -104,5 +104,8 @@
104
104
  <ClCompile Include="MenuItemMethods.cpp">
105
105
  <Filter>Source Files\ControlTypes</Filter>
106
106
  </ClCompile>
107
+ <ClCompile Include="ComboBoxMethods.cpp">
108
+ <Filter>Source Files\ControlTypes</Filter>
109
+ </ClCompile>
107
110
  </ItemGroup>
108
111
  </Project>
@@ -12,7 +12,7 @@
12
12
  </ItemGroup>
13
13
  <PropertyGroup Label="Globals">
14
14
  <ProjectGuid>{E83CF3F7-74C6-4333-89E3-36C6297F0A06}</ProjectGuid>
15
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
15
+ <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
16
16
  <Keyword>ManagedCProj</Keyword>
17
17
  <RootNamespace>UiaDllTest</RootNamespace>
18
18
  </PropertyGroup>
@@ -0,0 +1,25 @@
1
+ module Uia
2
+ module ControlTypes
3
+ module ComboBox
4
+
5
+ def items
6
+ Library.combo_box_items @element
7
+ end
8
+
9
+ def set(value)
10
+ case value
11
+ when String
12
+ Library.combo_box_set_item_by_value @element, value
13
+ when Regexp
14
+ found_item = items.find { |e| e.name =~ value }
15
+ if found_item
16
+ Library.combo_box_set_item_by_value @element, found_item.name
17
+ end
18
+ when Fixnum
19
+ Library.combo_box_set_item_by_index @element, value
20
+ end
21
+ end
22
+
23
+ end
24
+ end
25
+ end
data/lib/uia/library.rb CHANGED
@@ -144,6 +144,11 @@ module Uia
144
144
  # TextPattern methods
145
145
  attach_function :Text_GetText, [:pointer, :pointer, :int, :pointer, :int], :int
146
146
 
147
+ # ComboBox methods
148
+ elements_from :combo_box_items, :ComboBox_GetItems, [:pointer]
149
+ attach_throwable_function :combo_box_set_item_by_value, :ComboBox_SetItemByValue, [:pointer, :pointer], :void
150
+ attach_throwable_function :combo_box_set_item_by_index, :ComboBox_SetItemByIndex, [:pointer, :int], :void
151
+
147
152
  def self.get_text(element)
148
153
  length = can_throw(:Text_GetText, element, nil, 0) + 1
149
154
  p = FFI::MemoryPointer.new :pointer, length
data/lib/uia/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Uia
2
- VERSION = '0.7'
2
+ VERSION = '1.0'
3
3
  end
Binary file
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <configuration>
3
+ <startup>
4
+ <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
5
+ </startup>
6
+ </configuration>
@@ -0,0 +1,21 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ describe Uia::ControlTypes::ComboBox do
4
+ let(:main) { Uia.find_element(id: 'MainFormWindow') }
5
+ Given(:combo_box) { main.find(id: 'FruitsComboBox').as(:value).with(:combo_box) }
6
+
7
+ context '#items' do
8
+ Then { combo_box.items.map(&:name) == ['Apple', 'Caimito', 'Coconut', 'Orange', 'Passion Fruit'] }
9
+ end
10
+
11
+ context '#set' do
12
+ context 'by index' do
13
+ When { combo_box.set 1 }
14
+ Then { combo_box.value == 'Caimito' }
15
+ end
16
+ context 'by value' do
17
+ When { combo_box.set 'Orange' }
18
+ Then { combo_box.value == 'Orange' }
19
+ end
20
+ end
21
+ end
@@ -76,7 +76,7 @@ describe Uia::Element do
76
76
 
77
77
  context '#as' do
78
78
  When(:cast) { element.as :toggle }
79
- Then { expect(cast).to have_failed UnsupportedPattern, "Pattern toggle not found in [:window, :transform]" }
79
+ Then { cast == Failure(UnsupportedPattern, "Pattern toggle not found in [:window, :transform]") }
80
80
  end
81
81
  end
82
82
 
@@ -133,7 +133,7 @@ describe Uia::Element do
133
133
 
134
134
  context 'combinations' do
135
135
  Then { element.find(control_type: :list, name: 'linkLabel1').id == 'FruitListBox' }
136
- Then { element.find(control_type: :button, name: 'Forward', scope: :children) == nil }
136
+ Then { element.find(control_type: :button, name: 'Forward', scope: :element) == nil }
137
137
  Then { element.find(pattern: :invoke, name: 'About').id == 'aboutButton' }
138
138
  Then { element.find(control_type: :custom, id: 'automatableMonthCalendar1').name == 'linkLabel1' }
139
139
  Then { element.find(value: 'linkLabel1', id: 'automatableMonthCalendar1').control_type == :custom }
@@ -141,7 +141,7 @@ describe Uia::Element do
141
141
 
142
142
  context 'invalid' do
143
143
  When(:bad_locator) { element.find(bad_locator: 123) }
144
- Then { expect(bad_locator).to have_failed BadLocator, "{:bad_locator=>123} is not a valid locator" }
144
+ Then { bad_locator == Failure(BadLocator, "{:bad_locator=>123} is not a valid locator") }
145
145
  end
146
146
 
147
147
  context 'limiting scope' do
@@ -164,7 +164,7 @@ describe Uia::Element do
164
164
  end
165
165
 
166
166
  context 'pattern' do
167
- Then { element.filter(pattern: :value).count == 4 }
167
+ Then { element.filter(pattern: :value).count == 6 }
168
168
  end
169
169
 
170
170
  context 'combinations' do
@@ -172,11 +172,11 @@ describe Uia::Element do
172
172
  end
173
173
 
174
174
  context 'multiple' do
175
- When(:radio_or_value) { element.filter(control_type: [:radio_button, :text]) }
176
- Then { expect(radio_or_value.count).to eq(8) }
175
+ When(:radio_or_text) { element.filter(control_type: [:radio_button, :text]) }
176
+ Then { expect(radio_or_text.count).to eq(10) }
177
177
 
178
- When(:value_or_invoke) { element.filter(pattern: [:value, :text]) }
179
- Then { expect(value_or_invoke.count).to eq(5) }
178
+ When(:value_or_text) { element.filter(pattern: [:value, :text]) }
179
+ Then { expect(value_or_text.count).to eq(7) }
180
180
  end
181
181
  end
182
182
 
@@ -192,7 +192,7 @@ describe Uia::Element do
192
192
  end
193
193
 
194
194
  context '#children' do
195
- Then { element.children.count == 27 }
195
+ Then { element.children.count == 30 }
196
196
  Then { element.children.all? { |c| c.instance_of? Uia::Element } }
197
197
  end
198
198
 
@@ -25,6 +25,6 @@ describe Uia::Keys do
25
25
 
26
26
  context 'invalid' do
27
27
  When(:bad_keys) { encode('something', :bad_key) }
28
- Then { expect(bad_keys).to have_failed InvalidKey, "#{:bad_key} is not a valid key" }
28
+ Then { bad_keys == Failure(InvalidKey, "#{:bad_key} is not a valid key") }
29
29
  end
30
30
  end
@@ -3,7 +3,6 @@ require 'spec_helper'
3
3
  describe Uia::Patterns::Selection do
4
4
  let(:main) { Uia.find_element id: 'MainFormWindow' }
5
5
  Given(:select_list) { main.find(id: 'FruitListBox').as :selection }
6
- Given(:combo_box) { main.find(id: 'FruitsComboBox').as :selection }
7
6
 
8
7
  context 'properties' do
9
8
  context '#multi_select?' do
@@ -17,7 +16,6 @@ describe Uia::Patterns::Selection do
17
16
  context '#selection_items' do
18
17
  let(:respond_to_selections) { lambda { |e| e.respond_to? :add_to_selection } }
19
18
 
20
- Then { combo_box.selection_items.map(&:name) == ['Apple', 'Caimito', 'Coconut', 'Orange', 'Passion Fruit'] }
21
19
  Then { select_list.selection_items.all?(&respond_to_selections) == true }
22
20
 
23
21
  context 'multiple levels of #selection_items' do
@@ -26,6 +24,16 @@ describe Uia::Patterns::Selection do
26
24
  When { tree_view.selection_items.first.as(:expand_collapse).expand }
27
25
  Then { tree_view.selection_items.map(&:name) == ['Parent One', 'Child 1', 'Child 2', 'Parent Two'] }
28
26
  end
27
+
28
+ context 'can select tree view items' do
29
+ Given(:tree_view) { main.find(id: 'treeView').as :selection }
30
+ When do
31
+ tree_view.selection_items[0].as(:expand_collapse).expand
32
+ tree_view.selection_items[2].as(:expand_collapse).expand
33
+ tree_view.selection_items[3].select
34
+ end
35
+ Then { tree_view.selected_items.map(&:name) == ['Grandchild 1']}
36
+ end
29
37
  end
30
38
 
31
39
  context '#selected_items' do
data/spec/uia_spec.rb CHANGED
@@ -30,8 +30,9 @@ describe Uia do
30
30
  Then { expect(Uia.find_element(runtime_id: main_window.runtime_id)).to be_instance_of(Element) }
31
31
 
32
32
  context 'can search descendants' do
33
- Given(:element_with_no_handle) { Uia.find_element(id: 'MainFormWindow').find(name: 'Parent Two') }
34
- Then { expect(element_with_no_handle.click).to be true }
33
+ Given(:element_with_no_handle) { Uia.find_element(id: 'MainFormWindow').find(name: 'Parent Two').as(:selection_item) }
34
+ When { element_with_no_handle.select }
35
+ Then { expect(element_with_no_handle.selected?).to be true }
35
36
  end
36
37
  end
37
38
 
@@ -48,7 +49,7 @@ describe Uia do
48
49
 
49
50
  context 'invalid locators' do
50
51
  When(:bad_input) { Uia.find_element(bad: 123) }
51
- Then { expect(bad_input).to have_failed(Uia::BadLocator, '{:bad=>123} is not a valid locator') }
52
+ Then { bad_input == Failure(Uia::BadLocator, '{:bad=>123} is not a valid locator') }
52
53
  end
53
54
  end
54
- end
55
+ end
data/uia.gemspec CHANGED
@@ -25,13 +25,12 @@ Gem::Specification.new do |spec|
25
25
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
26
26
  spec.require_paths = ['lib']
27
27
 
28
- spec.add_runtime_dependency 'ffi', '~> 1.11.2'
28
+ spec.add_runtime_dependency 'ffi', '~> 1.14'
29
29
  spec.add_runtime_dependency 'require_all', '~> 3.0'
30
30
 
31
31
  spec.add_development_dependency 'bundler', '>= 1.3'
32
- spec.add_development_dependency 'rake', '~> 10.5'
32
+ spec.add_development_dependency 'rake', '~> 13.0'
33
33
  spec.add_development_dependency 'rspec', '~> 3.9'
34
34
  spec.add_development_dependency 'rspec-given', '~> 3.8'
35
- spec.add_development_dependency 'childprocess', '~> 3.0'
36
- spec.add_development_dependency 'albacore', '~> 3.0.1'
35
+ spec.add_development_dependency 'childprocess', '~> 4.0'
37
36
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uia
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.7'
4
+ version: '1.0'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Levi Wilson
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-13 00:00:00.000000000 Z
11
+ date: 2023-01-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 1.11.2
19
+ version: '1.14'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 1.11.2
26
+ version: '1.14'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: require_all
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '10.5'
61
+ version: '13.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '10.5'
68
+ version: '13.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -100,28 +100,14 @@ dependencies:
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '3.0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: '3.0'
111
- - !ruby/object:Gem::Dependency
112
- name: albacore
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - "~>"
116
- - !ruby/object:Gem::Version
117
- version: 3.0.1
103
+ version: '4.0'
118
104
  type: :development
119
105
  prerelease: false
120
106
  version_requirements: !ruby/object:Gem::Requirement
121
107
  requirements:
122
108
  - - "~>"
123
109
  - !ruby/object:Gem::Version
124
- version: 3.0.1
110
+ version: '4.0'
125
111
  description: A low-level wrapper around Microsoft UI Automation for ruby
126
112
  email:
127
113
  - levi@leviwilson.com
@@ -166,6 +152,7 @@ files:
166
152
  - ext/UiaDll/UiaDll.sln
167
153
  - ext/UiaDll/UiaDll/ArrayHelper.h
168
154
  - ext/UiaDll/UiaDll/AssemblyInfo.cpp
155
+ - ext/UiaDll/UiaDll/ComboBoxMethods.cpp
169
156
  - ext/UiaDll/UiaDll/ConditionHelper.h
170
157
  - ext/UiaDll/UiaDll/ConditionMethods.cpp
171
158
  - ext/UiaDll/UiaDll/DynamicAssemblyResolver.cpp
@@ -201,6 +188,7 @@ files:
201
188
  - lib/core_ext/string.rb
202
189
  - lib/core_ext/symbol.rb
203
190
  - lib/uia.rb
191
+ - lib/uia/control_types/combo_box.rb
204
192
  - lib/uia/control_types/menu_item.rb
205
193
  - lib/uia/element.rb
206
194
  - lib/uia/finder.rb
@@ -228,8 +216,10 @@ files:
228
216
  - spec/app/FizzWare.NBuilder.dll
229
217
  - spec/app/UIA.Extensions.dll
230
218
  - spec/app/WindowsForms.exe
219
+ - spec/app/WindowsForms.exe.config
231
220
  - spec/core_ext/symbol_spec.rb
232
221
  - spec/spec_helper.rb
222
+ - spec/uia/control_types/combo_box_spec.rb
233
223
  - spec/uia/control_types/menu_item_spec.rb
234
224
  - spec/uia/element_spec.rb
235
225
  - spec/uia/keys_spec.rb
@@ -251,7 +241,7 @@ homepage: https://github.com/northwoodspd/uia
251
241
  licenses:
252
242
  - MIT
253
243
  metadata: {}
254
- post_install_message:
244
+ post_install_message:
255
245
  rdoc_options: []
256
246
  require_paths:
257
247
  - lib
@@ -266,17 +256,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
266
256
  - !ruby/object:Gem::Version
267
257
  version: '0'
268
258
  requirements: []
269
- rubyforge_project:
270
- rubygems_version: 2.5.2
271
- signing_key:
259
+ rubygems_version: 3.2.32
260
+ signing_key:
272
261
  specification_version: 4
273
262
  summary: A low-level wrapper around Microsoft UI Automation for ruby
274
263
  test_files:
275
264
  - spec/app/FizzWare.NBuilder.dll
276
265
  - spec/app/UIA.Extensions.dll
277
266
  - spec/app/WindowsForms.exe
267
+ - spec/app/WindowsForms.exe.config
278
268
  - spec/core_ext/symbol_spec.rb
279
269
  - spec/spec_helper.rb
270
+ - spec/uia/control_types/combo_box_spec.rb
280
271
  - spec/uia/control_types/menu_item_spec.rb
281
272
  - spec/uia/element_spec.rb
282
273
  - spec/uia/keys_spec.rb