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,336 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module Win32
4
+ # @private
5
+ module Functions
6
+ extend FFI::Library
7
+
8
+ ffi_lib 'user32', 'kernel32', 'ole32', File.dirname(__FILE__) + '/../../../../ext/IAccessibleDLL/Release/iaccessibleDll.dll'
9
+ ffi_convention :stdcall
10
+
11
+ callback :enum_callback, [:long, :pointer], :bool
12
+
13
+ # user32
14
+ attach_function :_get_window_rect, :GetWindowRect,
15
+ [:long, :pointer], :bool
16
+ attach_function :_move_window, :MoveWindow,
17
+ [:long, :int, :int, :int, :int, :bool], :bool
18
+ attach_function :enum_windows, :EnumWindows,
19
+ [:enum_callback, :pointer], :long
20
+ attach_function :enum_child_windows, :EnumChildWindows,
21
+ [:long, :enum_callback, :pointer], :long
22
+ attach_function :_close_window, :CloseWindow,
23
+ [:long], :bool
24
+ attach_function :minimized, :IsIconic,
25
+ [:long], :bool
26
+ attach_function :_window_title, :GetWindowTextA,
27
+ [:long, :pointer, :int], :int
28
+ attach_function :window_title_length, :GetWindowTextLengthA,
29
+ [:long], :int
30
+ attach_function :window_exists, :IsWindow,
31
+ [:long], :bool
32
+ attach_function :_window_class, :GetClassNameA,
33
+ [:long, :pointer, :int], :int
34
+ attach_function :window_visible, :IsWindowVisible,
35
+ [:long], :bool
36
+ attach_function :show_window, :ShowWindow,
37
+ [:long, :int], :bool
38
+ attach_function :send_message, :SendMessageA,
39
+ [:long, :uint, :uint, :pointer], :long
40
+ attach_function :send_message_timeout, :SendMessageTimeoutA,
41
+ [:long, :uint, :uint, :pointer, :uint, :uint, :pointer], :bool
42
+ attach_function :post_message, :PostMessageA,
43
+ [:long, :uint, :uint, :pointer], :bool
44
+ attach_function :window_thread_process_id, :GetWindowThreadProcessId,
45
+ [:long, :pointer], :long
46
+ attach_function :attach_thread_input, :AttachThreadInput,
47
+ [:long, :long, :bool], :bool
48
+ attach_function :set_foreground_window, :SetForegroundWindow,
49
+ [:long], :bool
50
+ attach_function :bring_window_to_top, :BringWindowToTop,
51
+ [:long], :bool
52
+ attach_function :set_active_window, :SetActiveWindow,
53
+ [:long], :long
54
+ attach_function :foreground_window, :GetForegroundWindow,
55
+ [], :long
56
+ attach_function :send_key, :keybd_event,
57
+ [:uchar, :uchar, :int, :pointer], :void
58
+ attach_function :control_id, :GetDlgCtrlID,
59
+ [:long], :int
60
+ attach_function :_set_control_focus, :SetFocus,
61
+ [:long], :long
62
+ attach_function :get_window, :GetWindow,
63
+ [:long, :uint], :long
64
+ attach_function :get_last_error, :GetLastError,
65
+ [], :long
66
+ attach_function :send_input, :SendInput,
67
+ [:uint, :pointer, :int], :int
68
+ attach_function :_get_cursor_pos, :GetCursorPos,
69
+ [:pointer], :bool
70
+ attach_function :set_cursor_pos, :SetCursorPos,
71
+ [:int, :int], :int
72
+
73
+ # kernel32
74
+ attach_function :current_thread_id, :GetCurrentThreadId,
75
+ [], :long
76
+ attach_function :open_process, :OpenProcess,
77
+ [:int, :bool, :int], :long
78
+ attach_function :terminate_process, :TerminateProcess,
79
+ [:long, :uint], :bool
80
+ attach_function :close_handle, :CloseHandle,
81
+ [:long], :bool
82
+ attach_function :_load_library_x86, :LoadLibraryA,
83
+ [:string], :long
84
+ attach_function :_load_library_x64, :LoadLibraryA,
85
+ [:string], :uint64
86
+
87
+ # ole32
88
+ attach_function :co_initialize, :CoInitialize,
89
+ [:pointer], :uint16
90
+
91
+ # iaccessible
92
+ attach_function :get_button_state, :get_button_state,
93
+ [:long], :long
94
+ attach_function :get_table_row_strings, :get_table_row_strings,
95
+ [:long, :long, :pointer, :long, :pointer], :void
96
+ attach_function :_select_table_row_x86, :select_table_row,
97
+ [:long, :long, :long], :void
98
+ attach_function :_select_table_row_x64, :select_table_row,
99
+ [:uint64, :long, :long], :void
100
+ attach_function :_get_table_row_state_x86, :get_table_row_state,
101
+ [:long, :long, :long], :long
102
+ attach_function :_get_table_row_state_x64, :get_table_row_state,
103
+ [:uint64, :long, :long], :long
104
+
105
+ class << self
106
+
107
+ def window_title(hwnd)
108
+ title_length = window_title_length(hwnd) + 1
109
+ title = FFI::MemoryPointer.new :char, title_length
110
+ _window_title(hwnd, title, title_length)
111
+ title.read_string
112
+ end
113
+
114
+ alias_method :control_title, :window_title
115
+
116
+ def move_window(hwnd, x, y, width, height)
117
+ _move_window(hwnd, x, y, width, height, true)
118
+ end
119
+
120
+ def get_cursor_pos
121
+ ptr = FFI::MemoryPointer.new(:long, 2)
122
+ _get_cursor_pos(ptr)
123
+ x, y = ptr.read_array_of_long(2)
124
+ return {:x => x, :y => y}
125
+ end
126
+
127
+ def window_rect(hwnd)
128
+ x = FFI::MemoryPointer.new(:long, 4)
129
+ _get_window_rect(hwnd, x)
130
+ x.read_array_of_long(4)
131
+ end
132
+
133
+ def window_text(hwnd)
134
+ found_text = []
135
+ window_callback = FFI::Function.new(:bool, [:long, :pointer], {:convention => :stdcall}) do |child_hwnd, _|
136
+ found_text << text_for(child_hwnd)
137
+ true
138
+ end
139
+ enum_child_windows(hwnd, window_callback, nil)
140
+ found_text.join(" ")
141
+ end
142
+
143
+ alias_method :control_text, :window_text
144
+
145
+ def window_hwnd(locators)
146
+ find_hwnd(locators) do |hwnd|
147
+ window_visible(hwnd) && locators_match?(locators, window_properties(hwnd, locators))
148
+ end
149
+ end
150
+
151
+ def child_window_locators(parent_hwnd, locators)
152
+ child_hwnd = locators[:hwnd] || child_hwnd(parent_hwnd, locators)
153
+ if child_hwnd
154
+ locators.merge!(:hwnd => child_hwnd)
155
+ else
156
+ popup_hwnd = get_window(parent_hwnd, Constants::GW_ENABLEDPOPUP)
157
+ if popup_hwnd != parent_hwnd
158
+ popup_properties = window_properties(popup_hwnd, locators)
159
+ locators.merge!(:hwnd => popup_hwnd) if locators_match?(locators, popup_properties)
160
+ end
161
+ end
162
+ locators
163
+ end
164
+
165
+ def window_pid(hwnd)
166
+ pid = FFI::MemoryPointer.new :int
167
+ window_thread_process_id(hwnd, pid)
168
+ pid.read_int
169
+ end
170
+
171
+ def window_class(hwnd)
172
+ class_name = FFI::MemoryPointer.new :char, 512
173
+ _window_class(hwnd, class_name, 512)
174
+ class_name.read_string
175
+ end
176
+
177
+ alias_method :control_class, :window_class
178
+
179
+ def close_window(hwnd)
180
+ _close_window(hwnd)
181
+ closed = send_message_timeout(hwnd, Constants::WM_CLOSE,
182
+ 0, nil, Constants::SMTO_ABORTIFHUNG, 1000, nil)
183
+ # force it to close
184
+ unless closed
185
+ process_hwnd = open_process(Constants::PROCESS_ALL_ACCESS, false, window_pid(hwnd))
186
+ terminate_process(process_hwnd, 0)
187
+ close_handle(process_hwnd)
188
+ end
189
+ end
190
+
191
+ def activate_window(hwnd)
192
+ set_foreground_window(hwnd)
193
+ set_active_window(hwnd)
194
+ bring_window_to_top(hwnd)
195
+ within_foreground_thread(hwnd) do
196
+ set_foreground_window(hwnd)
197
+ set_active_window(hwnd)
198
+ bring_window_to_top(hwnd)
199
+ end
200
+ end
201
+
202
+ alias_method :activate_control, :activate_window
203
+
204
+ def control_hwnd(window_hwnd, locators)
205
+ find_hwnd(locators, window_hwnd) do |hwnd|
206
+ locators_match?(locators, control_properties(hwnd, locators))
207
+ end
208
+ end
209
+
210
+ alias_method :child_hwnd, :control_hwnd
211
+
212
+ def control_value(control_hwnd)
213
+ text_for(control_hwnd)
214
+ end
215
+
216
+ def control_click(control_hwnd)
217
+ post_message(control_hwnd, Constants::BM_CLICK, 0, nil)
218
+ end
219
+
220
+ def set_control_focus(control_hwnd)
221
+ within_foreground_thread control_hwnd do
222
+ _set_control_focus(control_hwnd)
223
+ end
224
+ end
225
+
226
+ def set_control_text(control_hwnd, text)
227
+ send_message(control_hwnd, Constants::WM_SETTEXT, 0, text)
228
+ end
229
+
230
+ def control_set?(control_hwnd)
231
+ get_button_state(control_hwnd) & Constants::STATE_SYSTEM_CHECKED != 0
232
+ end
233
+
234
+ def has_focus?(control_hwnd)
235
+ get_button_state(control_hwnd) & Constants::STATE_SYSTEM_FOCUSED != 0
236
+ end
237
+
238
+ def unavailable?(control_hwnd)
239
+ get_button_state(control_hwnd) & Constants::STATE_SYSTEM_UNAVAILABLE != 0
240
+ end
241
+
242
+ def retrieve_combobox_item_text(control_hwnd, item_no)
243
+ text_len = send_message(control_hwnd, Constants::CB_GETLBTEXTLEN, item_no, nil)
244
+
245
+ string_buffer = FFI::MemoryPointer.new :char, text_len
246
+ send_message(control_hwnd, Constants::CB_GETLBTEXT, item_no, string_buffer)
247
+ string_buffer.read_string
248
+ end
249
+
250
+ def load_library(dll)
251
+ send("_load_library_#{Platform.architecture}", dll)
252
+ end
253
+
254
+ def get_table_row_state(oleacc_module_handle, control_hwnd, row)
255
+ send("_get_table_row_state_#{Platform.architecture}", oleacc_module_handle, control_hwnd, row)
256
+ end
257
+
258
+ def select_table_row(oleacc_module_handle, control_hwnd, row)
259
+ send("_select_table_row_#{Platform.architecture}", oleacc_module_handle, control_hwnd, row)
260
+ end
261
+
262
+ private
263
+
264
+ def within_foreground_thread(hwnd)
265
+ foreground_thread = current_thread_id
266
+ other_thread = window_thread_process_id(hwnd, nil)
267
+ attach_thread_input(foreground_thread, other_thread, true) unless other_thread == foreground_thread
268
+ yield
269
+ ensure
270
+ attach_thread_input(foreground_thread, other_thread, false) unless other_thread == foreground_thread
271
+ end
272
+
273
+ def window_properties(hwnd, locators)
274
+ element_properties(:window, hwnd, locators)
275
+ end
276
+
277
+ def control_properties(hwnd, locators)
278
+ element_properties(:control, hwnd, locators)
279
+ end
280
+
281
+ def element_properties(type, hwnd, locators)
282
+ locators.inject({}) do |properties, locator|
283
+ if locator[0] == :hwnd
284
+ properties[locator[0]] = hwnd
285
+ elsif locator[0] != :index
286
+ properties[locator[0]] = self.send("#{type}_#{locator[0]}", hwnd)
287
+ end
288
+ properties
289
+ end
290
+ end
291
+
292
+ def locators_match?(locators, properties)
293
+ locators.all? do |locator, value|
294
+ locator == :index or
295
+ value.is_a?(Regexp) ? properties[locator] =~ value : properties[locator] == value
296
+ end
297
+ end
298
+
299
+ def find_hwnd(locators, window_hwnd = nil)
300
+ found_hwnd = nil
301
+ found_index = -1
302
+ window_callback = FFI::Function.new(:bool, [:long, :pointer], {:convention => :stdcall}) do |hwnd, _|
303
+ if yield(hwnd)
304
+ found_index += 1
305
+
306
+ if locators[:index]
307
+ found_hwnd = hwnd if locators[:index] == found_index
308
+ else
309
+ found_hwnd = hwnd
310
+ end
311
+ end
312
+ !found_hwnd
313
+ end
314
+
315
+ unless window_hwnd
316
+ enum_windows(window_callback, nil)
317
+ else
318
+ enum_child_windows(window_hwnd, window_callback, nil)
319
+ end
320
+
321
+ found_hwnd
322
+ end
323
+
324
+ def text_for(hwnd)
325
+ text_length = send_message(hwnd, Constants::WM_GETTEXTLENGTH, 0, nil) + 1
326
+ text = FFI::MemoryPointer.new :char, text_length
327
+ send_message(hwnd, Constants::WM_GETTEXT, text_length, text)
328
+ text.read_string
329
+ end
330
+
331
+ end
332
+ end
333
+ end
334
+ end
335
+ end
336
+
@@ -0,0 +1,146 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module Win32
4
+ class Keys
5
+ KEYS = {
6
+ # keycodes from http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).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
+ :left_bracket => 0xDB,
22
+ :right_bracket => 0xDD,
23
+ :single_quote => 0xDE,
24
+ :pause => 0x13,
25
+ :escape => 0x1B,
26
+ :space => 0x20,
27
+ :page_up => 0x21,
28
+ :page_down => 0x22,
29
+ :end => 0x23,
30
+ :home => 0x24,
31
+ :left => 0x25,
32
+ :arrow_left => 0x25,
33
+ :up => 0x26,
34
+ :arrow_up => 0x26,
35
+ :right => 0x27,
36
+ :arrow_right => 0x27,
37
+ :down => 0x28,
38
+ :arrow_down => 0x28,
39
+ :insert => 0x2D,
40
+ :delete => 0x2E,
41
+ :semicolon => 0xBA,
42
+ :equals => 0xBB,
43
+ :numpad0 => 0x60,
44
+ :numpad1 => 0x61,
45
+ :numpad2 => 0x62,
46
+ :numpad3 => 0x63,
47
+ :numpad4 => 0x64,
48
+ :numpad5 => 0x65,
49
+ :numpad6 => 0x66,
50
+ :numpad7 => 0x67,
51
+ :numpad8 => 0x68,
52
+ :numpad9 => 0x69,
53
+ :multiply => 0x6A,
54
+ :add => 0x6B,
55
+ :separator => 0x6C,
56
+ :subtract => 0x6D,
57
+ :decimal => 0x6E,
58
+ :divide => 0x6F,
59
+ :f1 => 0x70,
60
+ :f2 => 0x71,
61
+ :f3 => 0x72,
62
+ :f4 => 0x73,
63
+ :f5 => 0x74,
64
+ :f6 => 0x75,
65
+ :f7 => 0x76,
66
+ :f8 => 0x77,
67
+ :f9 => 0x78,
68
+ :f10 => 0x79,
69
+ :f11 => 0x7A,
70
+ :f12 => 0x7B,
71
+ :comma => 0xBC,
72
+ :dash => 0xBD,
73
+ :period => 0xBE,
74
+ :slash => 0xBF,
75
+ :grave => 0xC0,
76
+ :backslash => 0xDC
77
+ }
78
+
79
+ MAPPED_KEYS = {
80
+ "\\" => KEYS[:backslash],
81
+ "-" => KEYS[:dash],
82
+ "/" => KEYS[:slash],
83
+ "=" => KEYS[:equals],
84
+ ";" => KEYS[:semicolon],
85
+ "'" => KEYS[:single_quote],
86
+ "." => KEYS[:period],
87
+ "," => KEYS[:comma],
88
+ "[" => KEYS[:left_bracket],
89
+ "]" => KEYS[:right_bracket],
90
+ '`' => KEYS[:grave]
91
+ }
92
+
93
+ # Assumes US standard keyboard layout
94
+ SPECIAL_KEYS = {
95
+ "!" => 0x31,
96
+ "@" => 0x32,
97
+ "#" => 0x33,
98
+ "$" => 0x34,
99
+ "%" => 0x35,
100
+ "^" => 0x36,
101
+ "&" => 0x37,
102
+ "*" => 0x38,
103
+ "(" => 0x39,
104
+ ")" => 0x30,
105
+ "_" => KEYS[:dash],
106
+ "+" => KEYS[:equals],
107
+ "{" => KEYS[:left_bracket],
108
+ "}" => KEYS[:right_bracket],
109
+ ":" => KEYS[:semicolon],
110
+ "\"" => KEYS[:single_quote],
111
+ "|" => KEYS[:backslash],
112
+ "?" => KEYS[:slash],
113
+ ">" => KEYS[:period],
114
+ "<" => KEYS[:comma],
115
+ "~" => KEYS[:grave]
116
+ }
117
+
118
+ def self.[](key)
119
+ KEYS[key] or raise "unsupported key #{key.inspect}"
120
+ end
121
+
122
+ def self.encode(keys)
123
+ keys.reduce([]) do |converted, key|
124
+ if key.is_a?(Symbol)
125
+ converted << Keys[key]
126
+ elsif key.is_a?(Array)
127
+ converted << (key.map {|k| encode([k])} << Keys[:null]).flatten
128
+ else # key is a string
129
+ converted += encode_str(key)
130
+ end
131
+ converted
132
+ end
133
+ end
134
+
135
+ def self.encode_str(keys)
136
+ keys.to_s.split("").map do |key|
137
+ key =~ /[a-z]/ || MAPPED_KEYS[key] ? MAPPED_KEYS[key] || key.upcase.unpack("c")[0] :
138
+ key =~ /[A-Z]/ || SPECIAL_KEYS[key] ? [Keys[:shift], SPECIAL_KEYS[key] || key.unpack("c")[0], Keys[:null]] :
139
+ key.unpack("c")[0]
140
+ end
141
+ end
142
+
143
+ end
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,10 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module Win32
4
+ class Label < Control
5
+ include WaitHelper
6
+ include Locators
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,40 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module Win32
4
+ class ListBox < Control
5
+ include WaitHelper
6
+ include Locators
7
+
8
+ # Default locators used for searching buttons.
9
+ DEFAULT_LOCATORS = {:class => /listbox/i}
10
+
11
+ def count
12
+ Functions.send_message(hwnd, Constants::LB_GETCOUNT, 0, nil)
13
+ end
14
+
15
+ alias_method :size, :count
16
+
17
+ def items
18
+ count.times.reduce([]) do |memo, i|
19
+ text_length = Functions.send_message(hwnd, Constants::LB_GETTEXTLEN, 0, nil) + 1
20
+ text = FFI::MemoryPointer.new :char, text_length
21
+ Functions.send_message(hwnd, Constants::LB_GETTEXT, i, text)
22
+ memo << text.read_string
23
+ end
24
+ end
25
+
26
+ alias_method :strings, :items
27
+
28
+ def selected?(i)
29
+ Functions.send_message(hwnd, Constants::LB_GETSEL, i, nil) > 0
30
+ end
31
+
32
+ def select(i)
33
+ Functions.send_message(hwnd, Constants::LB_SETCURSEL, i, nil)
34
+ end
35
+
36
+ end
37
+ end
38
+ end
39
+ end
40
+
@@ -0,0 +1,22 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module Win32
4
+ # @private
5
+ module Locators
6
+
7
+ private
8
+
9
+ def extract(locators)
10
+ # windows locators
11
+ @hwnd = locators[:hwnd].to_i if locators[:hwnd]
12
+ locators[:pid] = locators[:pid].to_i if locators[:pid]
13
+ locators[:index] = locators[:index].to_i if locators[:index]
14
+
15
+ # control locator
16
+ locators = self.class::DEFAULT_LOCATORS.merge(locators) if self.class.const_defined?(:DEFAULT_LOCATORS)
17
+ @locators = {:index => 0}.merge locators
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,59 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module Win32
4
+ class Mouse
5
+ def initialize(window)
6
+ @window = window
7
+ end
8
+
9
+ def move(coords={})
10
+ @last_position = coords = (@last_position || position).merge(coords)
11
+
12
+ until position[:x] == coords[:x] && position[:y] == coords[:y]
13
+ @window.activate
14
+ Functions.set_cursor_pos coords[:x], coords[:y]
15
+ end
16
+ end
17
+
18
+ def position
19
+ Functions.get_cursor_pos
20
+ end
21
+
22
+ def click
23
+ send_input down_event, up_event
24
+ end
25
+
26
+ def press
27
+ send_input down_event, down_event
28
+ end
29
+
30
+ def release
31
+ send_input up_event, up_event
32
+ end
33
+
34
+ private
35
+
36
+ def send_input *inputs
37
+ @window.activate
38
+ Functions.send_input inputs.size, inputs.join, inputs[0].size
39
+ end
40
+
41
+ def down_event
42
+ input Constants::MOUSEEVENTF_LEFTDOWN
43
+ end
44
+
45
+ def up_event
46
+ input Constants::MOUSEEVENTF_LEFTUP
47
+ end
48
+
49
+ def input flag
50
+ mouse_input = Array.new(7, 0)
51
+ mouse_input[0] = Constants::INPUT_MOUSE
52
+ mouse_input[4] = flag
53
+ Platform.is_x86? ? mouse_input.pack('L*') : mouse_input.pack('QLLLLQQ')
54
+ end
55
+
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,15 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module Win32
4
+ class PasswordField < TextField
5
+
6
+ private
7
+
8
+ def set?(text)
9
+ # getting value from password field will not retrieve anything
10
+ true
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module Win32
4
+ class Radio < Control
5
+ include WaitHelper
6
+ include Locators
7
+ include ButtonHelper
8
+ end
9
+ end
10
+ end
11
+ end