rautomation 2.0.1-x86-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.gitignore +41 -0
  4. data/.rspec +2 -0
  5. data/.yardopts +8 -0
  6. data/CHANGES.md +276 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE +20 -0
  9. data/README.md +142 -0
  10. data/Rakefile +73 -0
  11. data/ext/AutoItX/AutoItX.chm +0 -0
  12. data/ext/AutoItX/AutoItX3.dll +0 -0
  13. data/ext/IAccessibleDLL/IAccessibleDLL/IAccessibleDLL.cpp +30 -0
  14. data/ext/IAccessibleDLL/IAccessibleDLL/IAccessibleDLL.vcxproj +179 -0
  15. data/ext/IAccessibleDLL/IAccessibleDLL/IAccessibleDLL.vcxproj.filters +42 -0
  16. data/ext/IAccessibleDLL/IAccessibleDLL/IAccessibleDLL.vcxproj.user +3 -0
  17. data/ext/IAccessibleDLL/IAccessibleDLL/ReadMe.txt +48 -0
  18. data/ext/IAccessibleDLL/IAccessibleDLL/dllmain.cpp +19 -0
  19. data/ext/IAccessibleDLL/IAccessibleDLL/stdafx.cpp +8 -0
  20. data/ext/IAccessibleDLL/IAccessibleDLL/stdafx.h +22 -0
  21. data/ext/IAccessibleDLL/IAccessibleDLL/table_support.cpp +282 -0
  22. data/ext/IAccessibleDLL/IAccessibleDLL/targetver.h +8 -0
  23. data/ext/IAccessibleDLL/IAccessibleDLL.sln +31 -0
  24. data/ext/IAccessibleDLL/IAccessibleDLL.suo +0 -0
  25. data/ext/IAccessibleDLL/Release/IAccessibleDLL.dll +0 -0
  26. data/ext/UiaDll/RAutomation.UIA/Controls/Clicker.cs +63 -0
  27. data/ext/UiaDll/RAutomation.UIA/Controls/SelectList.cs +116 -0
  28. data/ext/UiaDll/RAutomation.UIA/Controls/Spinner.cs +46 -0
  29. data/ext/UiaDll/RAutomation.UIA/Controls/TabControl.cs +54 -0
  30. data/ext/UiaDll/RAutomation.UIA/Controls/TableControl.cs +132 -0
  31. data/ext/UiaDll/RAutomation.UIA/Controls/TextControl.cs +50 -0
  32. data/ext/UiaDll/RAutomation.UIA/Expander.cs +59 -0
  33. data/ext/UiaDll/RAutomation.UIA/Extensions/Element.cs +166 -0
  34. data/ext/UiaDll/RAutomation.UIA/Extensions/Enumerable.cs +76 -0
  35. data/ext/UiaDll/RAutomation.UIA/Extensions/Property.cs +27 -0
  36. data/ext/UiaDll/RAutomation.UIA/Properties/AssemblyInfo.cs +36 -0
  37. data/ext/UiaDll/RAutomation.UIA/Properties/AutomationProperties.cs +18 -0
  38. data/ext/UiaDll/RAutomation.UIA/RAutomation.UIA.csproj +77 -0
  39. data/ext/UiaDll/Release/RAutomation.UIA.dll +0 -0
  40. data/ext/UiaDll/Release/UiaDll.dll +0 -0
  41. data/ext/UiaDll/UiaDll/ArrayHelper.cpp +14 -0
  42. data/ext/UiaDll/UiaDll/ArrayHelper.h +7 -0
  43. data/ext/UiaDll/UiaDll/AssemblyInfo.cpp +40 -0
  44. data/ext/UiaDll/UiaDll/ControlMethods.cpp +16 -0
  45. data/ext/UiaDll/UiaDll/DynamicAssemblyResolver.cpp +24 -0
  46. data/ext/UiaDll/UiaDll/DynamicAssemblyResolver.h +16 -0
  47. data/ext/UiaDll/UiaDll/Locator.cpp +93 -0
  48. data/ext/UiaDll/UiaDll/Locator.h +55 -0
  49. data/ext/UiaDll/UiaDll/MenuItemSelector.cpp +75 -0
  50. data/ext/UiaDll/UiaDll/MenuItemSelector.h +24 -0
  51. data/ext/UiaDll/UiaDll/MenuMethods.cpp +62 -0
  52. data/ext/UiaDll/UiaDll/ReadMe.txt +38 -0
  53. data/ext/UiaDll/UiaDll/SelectListMethods.cpp +84 -0
  54. data/ext/UiaDll/UiaDll/SpinnerMethods.cpp +61 -0
  55. data/ext/UiaDll/UiaDll/StringHelper.cpp +57 -0
  56. data/ext/UiaDll/UiaDll/StringHelper.h +15 -0
  57. data/ext/UiaDll/UiaDll/StringMethods.cpp +8 -0
  58. data/ext/UiaDll/UiaDll/TabControlMethods.cpp +40 -0
  59. data/ext/UiaDll/UiaDll/TableMethods.cpp +108 -0
  60. data/ext/UiaDll/UiaDll/TextMethods.cpp +25 -0
  61. data/ext/UiaDll/UiaDll/ToggleStateHelper.h +10 -0
  62. data/ext/UiaDll/UiaDll/UiaDll.cpp +216 -0
  63. data/ext/UiaDll/UiaDll/UiaDll.h +13 -0
  64. data/ext/UiaDll/UiaDll/UiaDll.vcxproj +167 -0
  65. data/ext/UiaDll/UiaDll/UiaDll.vcxproj.filters +110 -0
  66. data/ext/UiaDll/UiaDll/app.ico +0 -0
  67. data/ext/UiaDll/UiaDll/app.rc +0 -0
  68. data/ext/UiaDll/UiaDll/dllmain.cpp +1 -0
  69. data/ext/UiaDll/UiaDll/resource.h +3 -0
  70. data/ext/UiaDll/UiaDll/stdafx.cpp +5 -0
  71. data/ext/UiaDll/UiaDll/stdafx.h +41 -0
  72. data/ext/UiaDll/UiaDll/targetver.h +8 -0
  73. data/ext/UiaDll/UiaDll.sln +57 -0
  74. data/ext/WindowsForms/.nuget/NuGet.Config +6 -0
  75. data/ext/WindowsForms/.nuget/NuGet.exe +0 -0
  76. data/ext/WindowsForms/.nuget/NuGet.targets +136 -0
  77. data/ext/WindowsForms/Release/FizzWare.NBuilder.dll +0 -0
  78. data/ext/WindowsForms/Release/UIA.Extensions.dll +0 -0
  79. data/ext/WindowsForms/Release/WindowsForms.exe +0 -0
  80. data/ext/WindowsForms/WindowsForms/AboutBox.Designer.cs +168 -0
  81. data/ext/WindowsForms/WindowsForms/AboutBox.cs +103 -0
  82. data/ext/WindowsForms/WindowsForms/AboutBox.resx +123 -0
  83. data/ext/WindowsForms/WindowsForms/DataEntryForm.Designer.cs +218 -0
  84. data/ext/WindowsForms/WindowsForms/DataEntryForm.cs +52 -0
  85. data/ext/WindowsForms/WindowsForms/DataEntryForm.resx +120 -0
  86. data/ext/WindowsForms/WindowsForms/DataGridView.Designer.cs +77 -0
  87. data/ext/WindowsForms/WindowsForms/DataGridView.cs +43 -0
  88. data/ext/WindowsForms/WindowsForms/DataGridView.resx +120 -0
  89. data/ext/WindowsForms/WindowsForms/FizzWare.NBuilder.dll +0 -0
  90. data/ext/WindowsForms/WindowsForms/MainFormWindow.Designer.cs +527 -0
  91. data/ext/WindowsForms/WindowsForms/MainFormWindow.cs +109 -0
  92. data/ext/WindowsForms/WindowsForms/MainFormWindow.resx +126 -0
  93. data/ext/WindowsForms/WindowsForms/PersonForm.Designer.cs +119 -0
  94. data/ext/WindowsForms/WindowsForms/PersonForm.cs +34 -0
  95. data/ext/WindowsForms/WindowsForms/PersonForm.resx +120 -0
  96. data/ext/WindowsForms/WindowsForms/Program.cs +21 -0
  97. data/ext/WindowsForms/WindowsForms/Properties/AssemblyInfo.cs +36 -0
  98. data/ext/WindowsForms/WindowsForms/Properties/Resources.Designer.cs +71 -0
  99. data/ext/WindowsForms/WindowsForms/Properties/Resources.resx +117 -0
  100. data/ext/WindowsForms/WindowsForms/Properties/Settings.Designer.cs +30 -0
  101. data/ext/WindowsForms/WindowsForms/Properties/Settings.settings +7 -0
  102. data/ext/WindowsForms/WindowsForms/SimpleElementsForm.Designer.cs +93 -0
  103. data/ext/WindowsForms/WindowsForms/SimpleElementsForm.cs +19 -0
  104. data/ext/WindowsForms/WindowsForms/SimpleElementsForm.resx +120 -0
  105. data/ext/WindowsForms/WindowsForms/UIA.Extensions.dll +0 -0
  106. data/ext/WindowsForms/WindowsForms/ValueMonthCalendar.cs +28 -0
  107. data/ext/WindowsForms/WindowsForms/WindowsForms.csproj +166 -0
  108. data/ext/WindowsForms/WindowsForms/packages.config +4 -0
  109. data/ext/WindowsForms/WindowsForms.sln +46 -0
  110. data/lib/rautomation/adapter/autoit/button.rb +59 -0
  111. data/lib/rautomation/adapter/autoit/locators.rb +22 -0
  112. data/lib/rautomation/adapter/autoit/mouse.rb +38 -0
  113. data/lib/rautomation/adapter/autoit/text_field.rb +70 -0
  114. data/lib/rautomation/adapter/autoit/window.rb +197 -0
  115. data/lib/rautomation/adapter/autoit.rb +8 -0
  116. data/lib/rautomation/adapter/helper.rb +64 -0
  117. data/lib/rautomation/adapter/ms_uia/button.rb +21 -0
  118. data/lib/rautomation/adapter/ms_uia/button_helper.rb +19 -0
  119. data/lib/rautomation/adapter/ms_uia/checkbox.rb +23 -0
  120. data/lib/rautomation/adapter/ms_uia/constants.rb +111 -0
  121. data/lib/rautomation/adapter/ms_uia/control.rb +134 -0
  122. data/lib/rautomation/adapter/ms_uia/functions.rb +279 -0
  123. data/lib/rautomation/adapter/ms_uia/keys.rb +121 -0
  124. data/lib/rautomation/adapter/ms_uia/keystroke_converter.rb +122 -0
  125. data/lib/rautomation/adapter/ms_uia/label.rb +18 -0
  126. data/lib/rautomation/adapter/ms_uia/list_box.rb +46 -0
  127. data/lib/rautomation/adapter/ms_uia/list_item.rb +22 -0
  128. data/lib/rautomation/adapter/ms_uia/locators.rb +23 -0
  129. data/lib/rautomation/adapter/ms_uia/menu.rb +36 -0
  130. data/lib/rautomation/adapter/ms_uia/radio.rb +23 -0
  131. data/lib/rautomation/adapter/ms_uia/select_list.rb +85 -0
  132. data/lib/rautomation/adapter/ms_uia/spinner.rb +31 -0
  133. data/lib/rautomation/adapter/ms_uia/tab_control.rb +46 -0
  134. data/lib/rautomation/adapter/ms_uia/table.rb +140 -0
  135. data/lib/rautomation/adapter/ms_uia/text_field.rb +39 -0
  136. data/lib/rautomation/adapter/ms_uia/uia_dll.rb +428 -0
  137. data/lib/rautomation/adapter/ms_uia/value_control.rb +21 -0
  138. data/lib/rautomation/adapter/ms_uia/window.rb +289 -0
  139. data/lib/rautomation/adapter/ms_uia.rb +27 -0
  140. data/lib/rautomation/adapter/win_32/button.rb +14 -0
  141. data/lib/rautomation/adapter/win_32/button_helper.rb +24 -0
  142. data/lib/rautomation/adapter/win_32/checkbox.rb +14 -0
  143. data/lib/rautomation/adapter/win_32/constants.rb +73 -0
  144. data/lib/rautomation/adapter/win_32/control.rb +86 -0
  145. data/lib/rautomation/adapter/win_32/functions.rb +336 -0
  146. data/lib/rautomation/adapter/win_32/keys.rb +146 -0
  147. data/lib/rautomation/adapter/win_32/label.rb +10 -0
  148. data/lib/rautomation/adapter/win_32/list_box.rb +40 -0
  149. data/lib/rautomation/adapter/win_32/locators.rb +22 -0
  150. data/lib/rautomation/adapter/win_32/mouse.rb +59 -0
  151. data/lib/rautomation/adapter/win_32/password_field.rb +15 -0
  152. data/lib/rautomation/adapter/win_32/radio.rb +11 -0
  153. data/lib/rautomation/adapter/win_32/select_list.rb +97 -0
  154. data/lib/rautomation/adapter/win_32/table.rb +25 -0
  155. data/lib/rautomation/adapter/win_32/text_field.rb +52 -0
  156. data/lib/rautomation/adapter/win_32/window.rb +277 -0
  157. data/lib/rautomation/adapter/win_32.rb +23 -0
  158. data/lib/rautomation/button.rb +55 -0
  159. data/lib/rautomation/element_collections.rb +55 -0
  160. data/lib/rautomation/platform.rb +15 -0
  161. data/lib/rautomation/text_field.rb +60 -0
  162. data/lib/rautomation/version.rb +3 -0
  163. data/lib/rautomation/wait_helper.rb +23 -0
  164. data/lib/rautomation/window.rb +248 -0
  165. data/lib/rautomation.rb +8 -0
  166. data/rautomation.gemspec +52 -0
  167. data/spec/adapter/autoit/mouse_spec.rb +53 -0
  168. data/spec/adapter/autoit/window_spec.rb +17 -0
  169. data/spec/adapter/ms_uia/button_spec.rb +39 -0
  170. data/spec/adapter/ms_uia/checkbox_spec.rb +55 -0
  171. data/spec/adapter/ms_uia/control_spec.rb +88 -0
  172. data/spec/adapter/ms_uia/functions_spec.rb +39 -0
  173. data/spec/adapter/ms_uia/keystroke_converter_spec.rb +48 -0
  174. data/spec/adapter/ms_uia/label_spec.rb +18 -0
  175. data/spec/adapter/ms_uia/list_item_spec.rb +14 -0
  176. data/spec/adapter/ms_uia/listbox_spec.rb +73 -0
  177. data/spec/adapter/ms_uia/radio_spec.rb +39 -0
  178. data/spec/adapter/ms_uia/select_list_spec.rb +118 -0
  179. data/spec/adapter/ms_uia/spinner_spec.rb +44 -0
  180. data/spec/adapter/ms_uia/tab_control_spec.rb +53 -0
  181. data/spec/adapter/ms_uia/table_spec.rb +197 -0
  182. data/spec/adapter/ms_uia/text_field_spec.rb +43 -0
  183. data/spec/adapter/ms_uia/value_control_spec.rb +11 -0
  184. data/spec/adapter/ms_uia/window_spec.rb +81 -0
  185. data/spec/adapter/win_32/button_spec.rb +31 -0
  186. data/spec/adapter/win_32/checkbox_spec.rb +46 -0
  187. data/spec/adapter/win_32/label_spec.rb +13 -0
  188. data/spec/adapter/win_32/listbox_spec.rb +41 -0
  189. data/spec/adapter/win_32/mouse_spec.rb +49 -0
  190. data/spec/adapter/win_32/radio_spec.rb +33 -0
  191. data/spec/adapter/win_32/select_list_spec.rb +65 -0
  192. data/spec/adapter/win_32/table_spec.rb +27 -0
  193. data/spec/adapter/win_32/text_field_spec.rb +24 -0
  194. data/spec/adapter/win_32/window_spec.rb +61 -0
  195. data/spec/button_spec.rb +67 -0
  196. data/spec/buttons_spec.rb +21 -0
  197. data/spec/spec_helper.rb +128 -0
  198. data/spec/text_field_spec.rb +64 -0
  199. data/spec/text_fields_spec.rb +22 -0
  200. data/spec/window_spec.rb +150 -0
  201. data/spec/windows_spec.rb +76 -0
  202. metadata +369 -0
@@ -0,0 +1,279 @@
1
+ #todo - replace as much of this as possible with UIA versions
2
+
3
+
4
+ module RAutomation
5
+ module Adapter
6
+ module MsUia
7
+ # @private
8
+ module Functions
9
+ extend FFI::Library
10
+
11
+ ffi_lib 'user32', 'kernel32', 'ole32', File.dirname(__FILE__) + '/../../../../ext/IAccessibleDLL/Release/iaccessibleDll.dll'
12
+ ffi_convention :stdcall
13
+
14
+ callback :enum_callback, [:long, :pointer], :bool
15
+
16
+ # user32
17
+ attach_function :enum_windows, :EnumWindows,
18
+ [:enum_callback, :pointer], :long
19
+ attach_function :enum_child_windows, :EnumChildWindows,
20
+ [:long, :enum_callback, :pointer], :long
21
+ attach_function :_close_window, :CloseWindow,
22
+ [:long], :bool
23
+ attach_function :minimized, :IsIconic,
24
+ [:long], :bool
25
+ attach_function :_window_title, :GetWindowTextA,
26
+ [:long, :pointer, :int], :int
27
+ attach_function :window_title_length, :GetWindowTextLengthA,
28
+ [:long], :int
29
+ attach_function :window_exists, :IsWindow,
30
+ [:long], :bool
31
+ attach_function :_window_class, :GetClassNameA,
32
+ [:long, :pointer, :int], :int
33
+ attach_function :window_visible, :IsWindowVisible,
34
+ [:long], :bool
35
+ attach_function :show_window, :ShowWindow,
36
+ [:long, :int], :bool
37
+ attach_function :send_message, :SendMessageA,
38
+ [:long, :uint, :uint, :pointer], :long
39
+ attach_function :send_message_timeout, :SendMessageTimeoutA,
40
+ [:long, :uint, :uint, :pointer, :uint, :uint, :pointer], :bool
41
+ attach_function :post_message, :PostMessageA,
42
+ [:long, :uint, :uint, :pointer], :bool
43
+ attach_function :window_thread_process_id, :GetWindowThreadProcessId,
44
+ [:long, :pointer], :long
45
+ attach_function :attach_thread_input, :AttachThreadInput,
46
+ [:long, :long, :bool], :bool
47
+ attach_function :set_foreground_window, :SetForegroundWindow,
48
+ [:long], :bool
49
+ attach_function :bring_window_to_top, :BringWindowToTop,
50
+ [:long], :bool
51
+ attach_function :set_active_window, :SetActiveWindow,
52
+ [:long], :long
53
+ attach_function :foreground_window, :GetForegroundWindow,
54
+ [], :long
55
+ attach_function :send_key, :keybd_event,
56
+ [:uchar, :uchar, :int, :pointer], :void
57
+ attach_function :control_id, :GetDlgCtrlID,
58
+ [:long], :int
59
+ attach_function :_set_control_focus, :SetFocus,
60
+ [:long], :long
61
+ attach_function :get_window, :GetWindow,
62
+ [:long, :uint], :long
63
+ attach_function :get_last_error, :GetLastError,
64
+ [], :long
65
+
66
+ # kernel32
67
+ attach_function :open_process, :OpenProcess,
68
+ [:int, :bool, :int], :long
69
+ attach_function :terminate_process, :TerminateProcess,
70
+ [:long, :uint], :bool
71
+ attach_function :close_handle, :CloseHandle,
72
+ [:long], :bool
73
+ attach_function :load_library, :LoadLibraryA,
74
+ [:string], :long
75
+
76
+ # ole32
77
+ attach_function :co_initialize, :CoInitialize,
78
+ [:pointer], :uint16
79
+
80
+ # iaccessible
81
+ attach_function :get_button_state, :get_button_state,
82
+ [:long], :long
83
+ attach_function :get_table_row_strings, :get_table_row_strings,
84
+ [:long, :long, :pointer, :long, :pointer], :void
85
+ attach_function :select_table_row, :select_table_row,
86
+ [:long, :long, :long], :void
87
+
88
+ class << self
89
+
90
+ def window_title(hwnd)
91
+ title_length = window_title_length(hwnd) + 1
92
+ title = FFI::MemoryPointer.new :char, title_length
93
+ _window_title(hwnd, title, title_length)
94
+ title.read_string
95
+ end
96
+
97
+ alias_method :control_title, :window_title
98
+
99
+ def window_text(hwnd)
100
+ found_text = ""
101
+ window_callback = FFI::Function.new(:bool, [:long, :pointer], {:convention => :stdcall}) do |child_hwnd, _|
102
+ found_text << text_for(child_hwnd)
103
+ true
104
+ end
105
+ enum_child_windows(hwnd, window_callback, nil)
106
+ found_text
107
+ end
108
+
109
+ alias_method :control_text, :window_text
110
+
111
+ def window_hwnd(locators)
112
+ find_hwnd(locators) do |hwnd|
113
+ window_visible(hwnd) && locators_match?(locators, window_properties(hwnd, locators))
114
+ end
115
+ end
116
+
117
+ def child_window_locators(parent_hwnd, locators)
118
+ child_hwnd = locators[:hwnd] || child_hwnd(parent_hwnd, locators)
119
+ if child_hwnd
120
+ locators.merge!(:hwnd => child_hwnd)
121
+ else
122
+ popup_hwnd = get_window(parent_hwnd, Constants::GW_ENABLEDPOPUP)
123
+ if popup_hwnd != parent_hwnd
124
+ popup_properties = window_properties(popup_hwnd, locators)
125
+ locators.merge!(:hwnd => popup_hwnd) if locators_match?(locators, popup_properties)
126
+ end
127
+ end
128
+ locators.merge(:adapter => :ms_uia)
129
+ end
130
+
131
+ def window_pid(hwnd)
132
+ pid = FFI::MemoryPointer.new :int
133
+ window_thread_process_id(hwnd, pid)
134
+ pid.read_int
135
+ end
136
+
137
+ def window_class(hwnd)
138
+ class_name = FFI::MemoryPointer.new :char, 512
139
+ _window_class(hwnd, class_name, 512)
140
+ class_name.read_string
141
+ end
142
+
143
+ alias_method :control_class, :window_class
144
+
145
+ def close_window(hwnd)
146
+ _close_window(hwnd)
147
+ closed = send_message_timeout(hwnd, Constants::WM_CLOSE,
148
+ 0, nil, Constants::SMTO_ABORTIFHUNG, 1000, nil)
149
+ # force it to close
150
+ unless closed
151
+ process_hwnd = open_process(Constants::PROCESS_ALL_ACCESS, false, window_pid(hwnd))
152
+ terminate_process(process_hwnd, 0)
153
+ close_handle(process_hwnd)
154
+ end
155
+ end
156
+
157
+ def activate_window(hwnd)
158
+ set_foreground_window(hwnd)
159
+ set_active_window(hwnd)
160
+ bring_window_to_top(hwnd)
161
+ within_foreground_thread(hwnd) do
162
+ set_foreground_window(hwnd)
163
+ set_active_window(hwnd)
164
+ bring_window_to_top(hwnd)
165
+ end
166
+ end
167
+
168
+ def control_hwnd(window_hwnd, locators)
169
+ case
170
+ when locators[:id]
171
+ UiaDll.cached_hwnd(UiaDll::SearchCriteria.from_locator(window_hwnd, locators))
172
+ when locators[:point]
173
+ UiaDll::handle_from_point(*locators[:point])
174
+ else
175
+ find_hwnd(locators, window_hwnd) do |hwnd|
176
+ locators_match?(locators, control_properties(hwnd, locators))
177
+ end
178
+ end
179
+ end
180
+
181
+ alias_method :child_hwnd, :control_hwnd
182
+
183
+ def control_value(control_hwnd)
184
+ text_for(control_hwnd)
185
+ end
186
+
187
+ def set_control_focus(control_hwnd)
188
+ within_foreground_thread control_hwnd do
189
+ _set_control_focus(control_hwnd)
190
+ end
191
+ end
192
+
193
+ def retrieve_combobox_item_text(control_hwnd, item_no)
194
+ text_len = 1024
195
+ string_buffer = FFI::MemoryPointer.new :char, text_len
196
+ UiaDll::select_list_value_at control_hwnd, item_no, string_buffer, text_len
197
+ string_buffer.read_string
198
+ end
199
+
200
+ def control_name(control_hwnd)
201
+ UiaDll::name(UiaDll::SearchCriteria.from_locator(control_hwnd, :hwnd => control_hwnd))
202
+ end
203
+
204
+ private
205
+
206
+ def within_foreground_thread(hwnd)
207
+ foreground_thread = window_thread_process_id(foreground_window, nil)
208
+ other_thread = window_thread_process_id(hwnd, nil)
209
+ attach_thread_input(foreground_thread, other_thread, true) unless other_thread == foreground_thread
210
+ yield
211
+ ensure
212
+ attach_thread_input(foreground_thread, other_thread, false) unless other_thread == foreground_thread
213
+ end
214
+
215
+ def window_properties(hwnd, locators)
216
+ element_properties(:window, hwnd, locators)
217
+ end
218
+
219
+ def control_properties(hwnd, locators)
220
+ element_properties(:control, hwnd, locators)
221
+ end
222
+
223
+ def element_properties(type, hwnd, locators)
224
+ locators.inject({}) do |properties, locator|
225
+ properties[locator[0]] = self.send("#{type}_#{locator[0]}", hwnd) unless locator[0] == :index
226
+ properties
227
+ end
228
+ end
229
+
230
+ def locators_match?(locators, properties)
231
+ locators.all? do |locator, value|
232
+ if locator == :index
233
+ true
234
+ elsif value.is_a?(Regexp)
235
+ properties[locator] =~ value
236
+ else
237
+ properties[locator] == value
238
+ end
239
+ end
240
+ end
241
+
242
+ def find_hwnd(locators, window_hwnd = nil)
243
+ found_hwnd = nil
244
+ found_index = -1
245
+ window_callback = FFI::Function.new(:bool, [:long, :pointer], {:convention => :stdcall}) do |hwnd, _|
246
+ if yield(hwnd)
247
+ found_index += 1
248
+
249
+ if locators[:index]
250
+ found_hwnd = hwnd if locators[:index] == found_index
251
+ else
252
+ found_hwnd = hwnd
253
+ end
254
+ end
255
+ !found_hwnd
256
+ end
257
+
258
+ unless window_hwnd
259
+ enum_windows(window_callback, nil)
260
+ else
261
+ enum_child_windows(window_hwnd, window_callback, nil)
262
+ end
263
+
264
+ found_hwnd
265
+ end
266
+
267
+ def text_for(hwnd)
268
+ text_length = send_message(hwnd, Constants::WM_GETTEXTLENGTH, 0, nil) + 1
269
+ text = FFI::MemoryPointer.new :char, text_length
270
+ send_message(hwnd, Constants::WM_GETTEXT, text_length, text)
271
+ text.read_string
272
+ end
273
+
274
+ end
275
+ end
276
+ end
277
+ end
278
+ end
279
+
@@ -0,0 +1,121 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module MsUia
4
+ class Keys
5
+ KEYS = {
6
+ # keycodes from http://msdn.microsoft.com/en-us/library/ms927178.aspx
7
+ :null => 0x00,
8
+ :cancel => 0x03,
9
+ :help => 0x2F,
10
+ :backspace => 0x08,
11
+ :tab => 0x09,
12
+ :clear => 0x0C,
13
+ :return => 0x0D,
14
+ :enter => 0x0D,
15
+ :shift => 0x10,
16
+ :left_shift => 0xA0,
17
+ :control => 0x11,
18
+ :left_control => 0xA2,
19
+ :alt => 0x12,
20
+ :left_alt => 0xA4,
21
+ :pause => 0x13,
22
+ :escape => 0x1B,
23
+ :space => 0x20,
24
+ :page_up => 0x21,
25
+ :page_down => 0x22,
26
+ :end => 0x23,
27
+ :home => 0x24,
28
+ :left => 0x25,
29
+ :arrow_left => 0x25,
30
+ :up => 0x26,
31
+ :arrow_up => 0x26,
32
+ :right => 0x27,
33
+ :arrow_right => 0x27,
34
+ :down => 0x28,
35
+ :arrow_down => 0x28,
36
+ :insert => 0x2D,
37
+ :delete => 0x2E,
38
+ :semicolon => 0x3B,
39
+ :equals => 0x3D,
40
+ :numpad0 => 0x60,
41
+ :numpad1 => 0x61,
42
+ :numpad2 => 0x62,
43
+ :numpad3 => 0x63,
44
+ :numpad4 => 0x64,
45
+ :numpad5 => 0x65,
46
+ :numpad6 => 0x66,
47
+ :numpad7 => 0x67,
48
+ :numpad8 => 0x68,
49
+ :numpad9 => 0x69,
50
+ :multiply => 0x6A,
51
+ :add => 0x6B,
52
+ :separator => 0x6C,
53
+ :subtract => 0x6D,
54
+ :decimal => 0x6E,
55
+ :divide => 0x6F,
56
+ :f1 => 0x70,
57
+ :f2 => 0x71,
58
+ :f3 => 0x72,
59
+ :f4 => 0x73,
60
+ :f5 => 0x74,
61
+ :f6 => 0x75,
62
+ :f7 => 0x76,
63
+ :f8 => 0x77,
64
+ :f9 => 0x78,
65
+ :f10 => 0x79,
66
+ :f11 => 0x7A,
67
+ :f12 => 0x7B,
68
+ }
69
+
70
+ SPECIAL_KEYS = {
71
+ "!" => 0x31,
72
+ "@" => 0x32,
73
+ "#" => 0x33,
74
+ "$" => 0x34,
75
+ "%" => 0x35,
76
+ "^" => 0x36,
77
+ "&" => 0x37,
78
+ "*" => 0x38,
79
+ "(" => 0x39,
80
+ ")" => 0x30,
81
+ "_" => 0x2D,
82
+ "+" => 0x3D,
83
+ "{" => 0x5B,
84
+ "}" => 0x5D,
85
+ ":" => 0x3B,
86
+ "\"" => 0x27,
87
+ "|" => 0x5C,
88
+ "?" => 0x2F,
89
+ ">" => 0x2E,
90
+ "<" => 0x2C
91
+ }
92
+
93
+ def self.[](key)
94
+ KEYS[key] or raise "unsupported key #{key.inspect}"
95
+ end
96
+
97
+ def self.encode(keys)
98
+ keys.reduce([]) do |converted, key|
99
+ if key.is_a?(Symbol)
100
+ converted << Keys[key]
101
+ elsif key.is_a?(Array)
102
+ converted << (key.map {|k| encode([k])} << Keys[:null]).flatten
103
+ else # key is a string
104
+ converted += encode_str(key)
105
+ end
106
+ converted
107
+ end
108
+ end
109
+
110
+ def self.encode_str(keys)
111
+ keys.to_s.split("").map do |key|
112
+ key =~ /[a-z]/ ? key.upcase.unpack("c")[0] :
113
+ key =~ /[A-Z]/ || SPECIAL_KEYS[key] ? [Keys[:shift], SPECIAL_KEYS[key] || key.unpack("c")[0], Keys[:null]] :
114
+ key.unpack("c")[0]
115
+ end
116
+ end
117
+
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,122 @@
1
+ #todo - common file, extract it
2
+
3
+ module RAutomation
4
+ module Adapter
5
+ module MsUia
6
+ class KeystrokeConverter
7
+ class << self
8
+ def convert(str)
9
+ special_characters = ""
10
+
11
+ str.split(/([{}])/).inject([]) do |converted_keys, str|
12
+ if str == "}"
13
+ converted_keys << convert_special_characters(special_characters << str)
14
+ special_characters = ""
15
+ elsif str == "{" || !special_characters.empty?
16
+ special_characters << str
17
+ else
18
+ converted_keys += convert_characters(str)
19
+ end
20
+ converted_keys
21
+ end.flatten
22
+ end
23
+
24
+ private
25
+
26
+ def convert_special_characters chars
27
+ case chars.downcase
28
+ when "{tab}"
29
+ Constants::VK_TAB
30
+ when "{backspace}"
31
+ Constants::VK_BACK
32
+ when "{enter}"
33
+ Constants::VK_RETURN
34
+ when "{left}"
35
+ Constants::VK_LEFT
36
+ when "{right}"
37
+ Constants::VK_RIGHT
38
+ when "{down}"
39
+ Constants::VK_DOWN
40
+ when "{up}"
41
+ Constants::VK_UP
42
+ when "{home}"
43
+ Constants::VK_HOME
44
+ when "{end}"
45
+ Constants::VK_END
46
+ when "{delete}"
47
+ Constants::VK_DELETE
48
+ when "{pgdown}"
49
+ Constants::VK_NEXT
50
+ when "{pgup}"
51
+ Constants::VK_PRIOR
52
+ else
53
+ # unsupported special tag, ignore the tag itself, but convert the
54
+ # characters inside the tag
55
+ convert_characters(chars.gsub(/[{}]/, ""))
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def convert_characters(element)
62
+ element.split(//).inject([]) do |chars, char|
63
+ char_code = char.upcase.unpack("c")[0]
64
+ case char
65
+ when "!"
66
+ chars += in_upcase(49)
67
+ when "@"
68
+ chars += in_upcase(50)
69
+ when "\#"
70
+ chars += in_upcase(51)
71
+ when "$"
72
+ chars += in_upcase(52)
73
+ when "%"
74
+ chars += in_upcase(53)
75
+ when "^"
76
+ chars += in_upcase(54)
77
+ when "&"
78
+ chars += in_upcase(55)
79
+ when "*"
80
+ chars += in_upcase(56)
81
+ when "("
82
+ chars += in_upcase(57)
83
+ when ")"
84
+ chars += in_upcase(48)
85
+ when "\""
86
+ chars += in_upcase(0xDE)
87
+ when "'"
88
+ chars << 0xDE
89
+ when "/"
90
+ chars << 0xBF
91
+ when "-"
92
+ chars << 0xBD
93
+ when ","
94
+ chars << 0xBC
95
+ when "'"
96
+ chars << 0xDE
97
+ when "&"
98
+ chars += in_upcase(0x37)
99
+ when "_"
100
+ chars += in_upcase(0xBD)
101
+ when "<"
102
+ chars += in_upcase(0xBC)
103
+ when ">"
104
+ chars += in_upcase(0xBE)
105
+ else
106
+ if char =~ /[A-Z]/
107
+ chars += in_upcase(char_code)
108
+ else
109
+ chars << char_code
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ def in_upcase(char_code)
116
+ [Constants::VK_LSHIFT, char_code]
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,18 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module MsUia
4
+ class Label < Control
5
+ include WaitHelper
6
+ include Locators
7
+
8
+ def exist?
9
+ super && matches_type?(Constants::UIA_TEXT_CONTROL_TYPE)
10
+ end
11
+
12
+ alias_method :exists?, :exist?
13
+ alias_method :value, :control_name
14
+
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,46 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module MsUia
4
+
5
+ class ListBox < Control
6
+ include WaitHelper
7
+ include Locators
8
+
9
+ def count
10
+ UiaDll::select_list_count search_information
11
+ end
12
+
13
+ def items
14
+ UiaDll::table_values(search_information).map do |list_item|
15
+ @window.list_item(:value => list_item)
16
+ end
17
+ end
18
+
19
+ def strings
20
+ UiaDll::table_values(search_information)
21
+ end
22
+
23
+ def value
24
+ UiaDll::selection search_information
25
+ end
26
+
27
+ def exist?
28
+ super && matches_type?(Constants::UIA_LIST_CONTROL_TYPE)
29
+ end
30
+
31
+ alias_method :exists?, :exist?
32
+
33
+ def selected?(index)
34
+ item = items[index]
35
+ return item && item.selected?
36
+ end
37
+
38
+ def select(index)
39
+ UiaDll::select_list_select_index search_information, index
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+ end
46
+
@@ -0,0 +1,22 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module MsUia
4
+ class ListItem < Control
5
+ include WaitHelper
6
+ include Locators
7
+
8
+ def exist?
9
+ super && matches_type?(Constants::UIA_LIST_ITEM_CONTROL_TYPE)
10
+ end
11
+
12
+ def selected?
13
+ UiaDll::is_selected(search_information)
14
+ end
15
+
16
+ alias_method :exists?, :exist?
17
+ alias_method :value, :control_name
18
+
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,23 @@
1
+ #todo - some files are common between Win32 and MsUia adapter, consider pulling out to shared location
2
+
3
+ module RAutomation
4
+ module Adapter
5
+ module MsUia
6
+ module Locators
7
+
8
+ private
9
+
10
+ def extract(locators)
11
+ # windows locators
12
+ @hwnd = locators[:hwnd].to_i if locators[:hwnd]
13
+ locators[:pid] = locators[:pid].to_i if locators[:pid]
14
+ locators[:index] = locators[:index].to_i if locators[:index]
15
+
16
+ # control locator
17
+ locators = self.class::DEFAULT_LOCATORS.merge(locators) if self.class.const_defined?(:DEFAULT_LOCATORS)
18
+ @locators = {:index => 0}.merge locators
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,36 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module MsUia
4
+ class Menu
5
+ attr_reader :menu_items
6
+ attr_reader :window
7
+
8
+ def initialize(window, locator)
9
+ @menu_items = [] << locator[:text]
10
+ @window = window
11
+ end
12
+
13
+ def menu(locator)
14
+ @menu_items << locator[:text]
15
+ self
16
+ end
17
+
18
+ def exists?
19
+ UiaDll::menu_item_exists window.hwnd, *menu_items_arg
20
+ end
21
+
22
+ def open
23
+ error_info = FFI::MemoryPointer.new :char, 1024
24
+ UiaDll::select_menu_item window.hwnd, error_info, 1024, *menu_items_arg
25
+ error = error_info.get_string 0
26
+ raise error unless error.empty?
27
+ end
28
+
29
+ private
30
+ def menu_items_arg
31
+ menu_items.map {|s| [:string, s]}.flatten << :pointer << nil
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,23 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module MsUia
4
+ class Radio < Control
5
+ include WaitHelper
6
+ include Locators
7
+ include ButtonHelper
8
+
9
+
10
+ def exist?
11
+ super && matches_type?(Constants::UIA_RADIO_BUTTON_CONTROL_TYPE)
12
+ end
13
+
14
+ def set?
15
+ UiaDll::is_selected(search_information)
16
+ end
17
+
18
+ alias_method :exists?, :exist?
19
+
20
+ end
21
+ end
22
+ end
23
+ end