rautomation 0.6.3 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. data/.gitignore +34 -0
  2. data/Gemfile +3 -0
  3. data/Gemfile.lock +24 -0
  4. data/History.rdoc +21 -0
  5. data/LICENSE +1 -1
  6. data/README.rdoc +8 -7
  7. data/Rakefile +22 -32
  8. data/VERSION +1 -1
  9. data/ext/UiaDll/Release/UiaDll.dll +0 -0
  10. data/ext/UiaDll/UiaDll.suo +0 -0
  11. data/ext/UiaDll/UiaDll/UiaDll.cpp +236 -10
  12. data/lib/rautomation/adapter/autoit/locators.rb +1 -1
  13. data/lib/rautomation/adapter/autoit/text_field.rb +10 -1
  14. data/lib/rautomation/adapter/autoit/window.rb +50 -23
  15. data/lib/rautomation/adapter/helper.rb +6 -6
  16. data/lib/rautomation/adapter/ms_uia.rb +22 -0
  17. data/lib/rautomation/adapter/{win_ffi → ms_uia}/button.rb +3 -2
  18. data/lib/rautomation/adapter/ms_uia/button_helper.rb +25 -0
  19. data/lib/rautomation/adapter/ms_uia/checkbox.rb +27 -0
  20. data/lib/rautomation/adapter/{win_ffi → ms_uia}/constants.rb +20 -5
  21. data/lib/rautomation/adapter/ms_uia/control.rb +180 -0
  22. data/lib/rautomation/adapter/{win_ffi → ms_uia}/functions.rb +24 -26
  23. data/lib/rautomation/adapter/ms_uia/keystroke_converter.rb +122 -0
  24. data/lib/rautomation/adapter/{win_ffi → ms_uia}/label.rb +3 -2
  25. data/lib/rautomation/adapter/ms_uia/list_box.rb +91 -0
  26. data/lib/rautomation/adapter/ms_uia/list_item.rb +49 -0
  27. data/lib/rautomation/adapter/ms_uia/locators.rb +23 -0
  28. data/lib/rautomation/adapter/{win_ffi → ms_uia}/radio.rb +2 -2
  29. data/lib/rautomation/adapter/{win_ffi → ms_uia}/select_list.rb +41 -7
  30. data/lib/rautomation/adapter/ms_uia/table.rb +86 -0
  31. data/lib/rautomation/adapter/{win_ffi → ms_uia}/text_field.rb +5 -4
  32. data/lib/rautomation/adapter/ms_uia/uia_dll.rb +62 -0
  33. data/lib/rautomation/adapter/ms_uia/window.rb +364 -0
  34. data/lib/rautomation/adapter/win_32.rb +21 -0
  35. data/lib/rautomation/adapter/win_32/button.rb +14 -0
  36. data/lib/rautomation/adapter/{win_ffi → win_32}/button_helper.rb +1 -1
  37. data/lib/rautomation/adapter/win_32/checkbox.rb +14 -0
  38. data/lib/rautomation/adapter/win_32/constants.rb +68 -0
  39. data/lib/rautomation/adapter/{win_ffi → win_32}/control.rb +30 -23
  40. data/lib/rautomation/adapter/win_32/functions.rb +313 -0
  41. data/lib/rautomation/adapter/win_32/keys.rb +121 -0
  42. data/lib/rautomation/adapter/win_32/label.rb +10 -0
  43. data/lib/rautomation/adapter/win_32/list_box.rb +40 -0
  44. data/lib/rautomation/adapter/{win_ffi → win_32}/locators.rb +2 -2
  45. data/lib/rautomation/adapter/win_32/radio.rb +11 -0
  46. data/lib/rautomation/adapter/win_32/select_list.rb +97 -0
  47. data/lib/rautomation/adapter/win_32/table.rb +22 -0
  48. data/lib/rautomation/adapter/win_32/text_field.rb +42 -0
  49. data/lib/rautomation/adapter/{win_ffi → win_32}/window.rb +79 -62
  50. data/lib/rautomation/element_collections.rb +9 -1
  51. data/lib/rautomation/window.rb +17 -9
  52. data/rautomation.gemspec +24 -0
  53. data/spec/adapter/autoit/window_spec.rb +71 -0
  54. data/spec/adapter/{win_ffi → ms_uia}/button_spec.rb +1 -1
  55. data/spec/adapter/{win_ffi → ms_uia}/checkbox_spec.rb +9 -3
  56. data/spec/adapter/ms_uia/control_spec.rb +28 -0
  57. data/spec/adapter/ms_uia/keystroke_converter_spec.rb +50 -0
  58. data/spec/adapter/{win_ffi → ms_uia}/label_spec.rb +2 -2
  59. data/spec/adapter/ms_uia/list_item_spec.rb +14 -0
  60. data/spec/adapter/{win_ffi → ms_uia}/listbox_spec.rb +18 -5
  61. data/spec/adapter/{win_ffi → ms_uia}/radio_spec.rb +3 -1
  62. data/spec/adapter/ms_uia/select_list_spec.rb +109 -0
  63. data/spec/adapter/{win_ffi → ms_uia}/table_spec.rb +12 -1
  64. data/spec/adapter/{win_ffi → ms_uia}/text_field_spec.rb +2 -1
  65. data/spec/adapter/ms_uia/window_spec.rb +89 -0
  66. data/spec/adapter/win_32/button_spec.rb +30 -0
  67. data/spec/adapter/win_32/checkbox_spec.rb +48 -0
  68. data/spec/adapter/win_32/label_spec.rb +15 -0
  69. data/spec/adapter/win_32/listbox_spec.rb +42 -0
  70. data/spec/adapter/win_32/radio_spec.rb +32 -0
  71. data/spec/adapter/{win_ffi → win_32}/select_list_spec.rb +16 -16
  72. data/spec/adapter/win_32/table_spec.rb +28 -0
  73. data/spec/adapter/win_32/text_field_spec.rb +24 -0
  74. data/spec/adapter/{win_ffi → win_32}/window_spec.rb +19 -14
  75. data/spec/button_spec.rb +1 -0
  76. data/spec/buttons_spec.rb +4 -4
  77. data/spec/spec_helper.rb +30 -4
  78. data/spec/text_field_spec.rb +6 -7
  79. data/spec/window_spec.rb +12 -0
  80. data/spec/windows_spec.rb +19 -0
  81. metadata +116 -97
  82. data/lib/rautomation/adapter/win_ffi.rb +0 -21
  83. data/lib/rautomation/adapter/win_ffi/checkbox.rb +0 -19
  84. data/lib/rautomation/adapter/win_ffi/keystroke_converter.rb +0 -67
  85. data/lib/rautomation/adapter/win_ffi/list_box.rb +0 -60
  86. data/lib/rautomation/adapter/win_ffi/ms_uia/uia_dll.rb +0 -36
  87. data/lib/rautomation/adapter/win_ffi/table.rb +0 -57
  88. data/spec/adapter/win_ffi/keystroke_converter_spec.rb +0 -47
@@ -0,0 +1,86 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module MsUia
4
+ class Table < Control
5
+ include WaitHelper
6
+ include Locators
7
+
8
+ def strings
9
+ rows = []
10
+ header_columns = []
11
+
12
+ raise "Not a list control" unless UiaDll::current_control_type(uia_element) == Constants::UIA_LIST_CONTROL_TYPE
13
+
14
+
15
+ children_count = count_children(uia_element)
16
+
17
+ children = FFI::MemoryPointer.new :pointer, children_count
18
+ UiaDll::find_children(uia_element, children)
19
+
20
+
21
+ children.read_array_of_pointer(children_count).each do |child|
22
+ grandchildren_count = count_children(child)
23
+
24
+ if grandchildren_count > 0
25
+
26
+ grandchildren = FFI::MemoryPointer.new :pointer, grandchildren_count
27
+ UiaDll::find_children(child, grandchildren)
28
+
29
+ grandchildren.read_array_of_pointer(grandchildren_count).each do |grandchild|
30
+ grandchild_name = FFI::MemoryPointer.new :char, UiaDll::get_name(grandchild, nil) + 1
31
+ UiaDll::get_name(grandchild, grandchild_name)
32
+ header_columns.push grandchild_name.read_string
33
+ end
34
+ else
35
+ grandchild_name = FFI::MemoryPointer.new :char, UiaDll::get_name(child, nil) + 1
36
+ UiaDll::get_name(child, grandchild_name)
37
+ header_columns = grandchild_name.read_string
38
+ end
39
+
40
+ rows.push header_columns
41
+ header_columns = []
42
+ end
43
+
44
+ rows
45
+ end
46
+
47
+ # def select(row)
48
+ # Functions.select_table_row(Window.oleacc_module_handle, Functions.control_hwnd(@window.hwnd, @locators), row)
49
+ # end
50
+
51
+ def select(index)
52
+ children = FFI::MemoryPointer.new :pointer, row_count
53
+
54
+ length = UiaDll::find_children(uia_element, children)
55
+
56
+ target_element = children.read_array_of_pointer(length)[index]
57
+
58
+ UiaDll::select(target_element)
59
+ end
60
+
61
+ #todo - replace with UIA version
62
+ def selected?(row)
63
+ state = Functions.get_table_row_state(Window.oleacc_module_handle, Functions.control_hwnd(@window.hwnd, @locators), row)
64
+ state & Constants::STATE_SYSTEM_SELECTED != 0
65
+ end
66
+
67
+ def row_count
68
+ UiaDll::find_children(uia_element, nil)
69
+ end
70
+
71
+ def exist?
72
+ super && matches_type?(Constants::UIA_LIST_CONTROL_TYPE)
73
+ end
74
+
75
+ alias_method :exists?, :exist?
76
+
77
+ private
78
+
79
+ def count_children(element)
80
+ UiaDll::find_children(element, nil)
81
+ end
82
+
83
+ end
84
+ end
85
+ end
86
+ end
@@ -1,6 +1,6 @@
1
1
  module RAutomation
2
2
  module Adapter
3
- module WinFfi
3
+ module MsUia
4
4
  class TextField < Control
5
5
  include WaitHelper
6
6
  include Locators
@@ -8,6 +8,7 @@ module RAutomation
8
8
  # Default locators used for searching text fields.
9
9
  DEFAULT_LOCATORS = {:class => /edit/i}
10
10
 
11
+ #todo - replace with UIA version
11
12
  # @see RAutomation::TextField#set
12
13
  def set(text)
13
14
  raise "Cannot set value on a disabled text field" if disabled?
@@ -28,24 +29,24 @@ module RAutomation
28
29
  set ""
29
30
  end
30
31
 
32
+ #todo - replace with UIA version
31
33
  # @see RAutomation::TextField#value
32
34
  def value
33
35
  Functions.control_value(hwnd)
34
36
  end
35
37
 
38
+ #todo - replace with UIA version
36
39
  # @see RAutomation::TextField#hwnd
37
40
  def hwnd
38
41
  Functions.control_hwnd(@window.hwnd, @locators)
39
42
  end
40
43
 
41
44
  def exist?
42
- @locators[:id].nil? ? super : super && matches_type(Constants::UIA_EDIT_CONTROL_TYPE)
45
+ super && matches_type?(Constants::UIA_EDIT_CONTROL_TYPE)
43
46
  end
44
47
 
45
48
  alias_method :exists?, :exist?
46
49
 
47
-
48
-
49
50
  end
50
51
  end
51
52
  end
@@ -0,0 +1,62 @@
1
+ #todo - move this file up to the same level as the others
2
+ #todo - organize the methods better
3
+
4
+ module RAutomation
5
+ module Adapter
6
+ module MsUia
7
+ module UiaDll
8
+ extend FFI::Library
9
+
10
+ ffi_lib File.dirname(__FILE__) + '/../../../../ext/UiaDll/Release/UiaDll.dll'
11
+ ffi_convention :stdcall
12
+
13
+ attach_function :find_window, :RA_FindWindow,
14
+ [:string], :pointer
15
+ attach_function :is_offscreen, :RA_IsOffscreen,
16
+ [:pointer], :bool
17
+ attach_function :element_from_handle, :RA_ElementFromHandle,
18
+ [:long], :pointer
19
+ attach_function :element_from_point, :RA_ElementFromPoint,
20
+ [:int, :int], :pointer
21
+ attach_function :get_focused_element, :RA_GetFocusedElement,
22
+ [], :pointer
23
+ attach_function :find_child_by_id, :RA_FindChildById,
24
+ [:pointer, :string], :pointer
25
+ attach_function :find_child_by_name, :RA_FindChildByName,
26
+ [:pointer, :string], :pointer
27
+ attach_function :current_native_window_handle, :RA_CurrentNativeWindowHandle,
28
+ [:pointer], :long
29
+ attach_function :set_focus, :RA_SetFocus,
30
+ [:pointer], :bool
31
+ attach_function :current_control_type, :RA_GetCurrentControlType,
32
+ [:pointer], :int
33
+ attach_function :desktop_handle, :RA_GetDesktopHandle,
34
+ [], :long
35
+ attach_function :move_mouse, :RA_MoveMouse,
36
+ [:int,:int], :long
37
+ attach_function :click_mouse, :RA_ClickMouse,
38
+ [], :long
39
+ attach_function :bounding_rectangle, :RA_CurrentBoundingRectangle,
40
+ [:pointer, :pointer], :int
41
+ attach_function :is_offscreen, :RA_CurrentIsOffscreen,
42
+ [:pointer, :pointer], :int
43
+ attach_function :find_children, :RA_FindChildren,
44
+ [:pointer, :pointer], :int
45
+ attach_function :get_name, :RA_GetName,
46
+ [:pointer, :pointer], :int
47
+ attach_function :get_class_name, :RA_GetClassName,
48
+ [:pointer, :pointer], :int
49
+ attach_function :get_is_selected, :RA_GetIsSelected,
50
+ [:pointer], :bool
51
+ attach_function :select, :RA_Select,
52
+ [:pointer], :int
53
+ attach_function :set_value, :RA_Set_Value,
54
+ [:pointer, :pointer], :int
55
+ attach_function :find_window_by_pid, :RA_FindWindowByPID,
56
+ [:int], :pointer
57
+ attach_function :current_process_id, :RA_GetCurrentProcessId,
58
+ [:pointer], :int
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,364 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module MsUia
4
+ autoload :UiaDll, File.dirname(__FILE__) + "/uia_dll"
5
+
6
+ class Window
7
+ include WaitHelper
8
+ include Locators
9
+ extend ElementCollections
10
+
11
+ has_many :controls
12
+
13
+ #todo - figure out what this is for and see if MsUia still needs it
14
+ class << self
15
+ def oleacc_module_handle
16
+ @oleacc_module_handle ||= begin
17
+ oleacc = Functions.load_library "oleacc.dll"
18
+ Functions.co_initialize nil
19
+ oleacc
20
+ end
21
+ end
22
+ end
23
+
24
+ # Locators of the window.
25
+ attr_reader :locators
26
+
27
+ # Possible locators are :title, :text, :hwnd, :pid, :class and :index.
28
+ #todo - update list of valid locators for UIA
29
+ # Creates the window object.
30
+ # @note this method is not meant to be accessed directly, but only through {RAutomation::Window#initialize}!
31
+ # @param [Hash] locators for searching the window.
32
+ # @option locators [String, Regexp] :title Title of the window
33
+ # @option locators [String, Regexp] :text Visible text of the window
34
+ # @option locators [String, Regexp] :class Internal class name of the window
35
+ # @option locators [String, Fixnum] :hwnd Window handle in decimal format
36
+ # @option locators [String, Fixnum] :pid Window process ID (PID)
37
+ # @option locators [String, Fixnum] :index 0-based index to specify n-th window if all other criteria match
38
+ # all other criteria match
39
+ # @see RAutomation::Window#initialize
40
+ def initialize(container, locators)
41
+ @container = container
42
+ extract(locators)
43
+ end
44
+
45
+ #todo - replace with UIA version
46
+ # Retrieves handle of the window.
47
+ # @note Searches only for visible windows.
48
+ # @see RAutomation::Window#hwnd
49
+ def hwnd
50
+ @hwnd ||= Functions.window_hwnd(@locators)
51
+ end
52
+
53
+ #todo - replace with UIA version
54
+ # @see RAutomation::Window#pid
55
+ def pid
56
+ Functions.window_pid(hwnd)
57
+ end
58
+
59
+ #todo - replace with UIA version
60
+ # @see RAutomation::Window#title
61
+ def title
62
+ Functions.window_title(hwnd)
63
+ end
64
+
65
+ # @see RAutomation::Window#class_names
66
+ def class_names
67
+ root_element = UiaDll::element_from_handle(hwnd)
68
+
69
+ root_class = FFI::MemoryPointer.new :char, UiaDll::get_class_name(root_element, nil) + 1
70
+ UiaDll::get_class_name(root_element, root_class)
71
+
72
+ classes = gather_children_classes(root_element)
73
+ classes = classes.flatten
74
+ classes.delete("")
75
+ classes.sort
76
+ end
77
+
78
+ # @see RAutomation::Window#activate
79
+ def activate
80
+ return if !exists? || active?
81
+ restore if minimized?
82
+ Functions.activate_window(hwnd)
83
+ restore if minimized?
84
+ sleep 1
85
+ end
86
+
87
+ #todo - replace with UIA version
88
+ # @see RAutomation::Window#active?
89
+ def active?
90
+ exists? && Functions.foreground_window == hwnd
91
+ end
92
+
93
+ #todo - replace with UIA version
94
+ # @see RAutomation::Window#text
95
+ def text
96
+ Functions.window_text(hwnd)
97
+ end
98
+
99
+ #todo - replace with UIA version
100
+ # @see RAutomation::Window#exists?
101
+ def exists?
102
+ hwnd && Functions.window_exists(hwnd)
103
+ end
104
+
105
+ #todo - replace with UIA version
106
+ # @see RAutomation::Window#visible?
107
+ def visible?
108
+ Functions.window_visible(hwnd)
109
+ end
110
+
111
+ #todo - replace with UIA version
112
+ # @see RAutomation::Window#maximize
113
+ def maximize
114
+ Functions.show_window(hwnd, Constants::SW_MAXIMIZE)
115
+ sleep 1
116
+ end
117
+
118
+ #todo - replace with UIA version
119
+ # @see RAutomation::Window#minimize
120
+ def minimize
121
+ Functions.show_window(hwnd, Constants::SW_MINIMIZE)
122
+ sleep 1
123
+ end
124
+
125
+ #todo - replace with UIA version
126
+ # @see RAutomation::Window#minimized?
127
+ def minimized?
128
+ Functions.minimized(hwnd)
129
+ end
130
+
131
+ #todo - replace with UIA version
132
+ # @see RAutomation::Window#restore
133
+ def restore
134
+ Functions.show_window(hwnd, Constants::SW_RESTORE)
135
+ sleep 1
136
+ end
137
+
138
+ #todo - replace with UIA version if possible
139
+ # Activates the window and sends keys to it.
140
+ #
141
+ # Refer to KeystrokeConverter#convert_special_characters for the special keycodes.
142
+ # @see RAutomation::Window#send_keys
143
+ def send_keys(keys)
144
+ shift_pressed = false
145
+ KeystrokeConverter.convert(keys[0]).each do |key|
146
+ wait_until do
147
+ activate
148
+ active?
149
+ end
150
+ press_key key
151
+
152
+ if key == Constants::VK_LSHIFT
153
+ shift_pressed = true
154
+ next
155
+ end
156
+
157
+ release_key key
158
+
159
+ if shift_pressed
160
+ shift_pressed = false
161
+ release_key Constants::VK_LSHIFT
162
+ end
163
+ end
164
+ end
165
+
166
+ #todo - replace with UIA version
167
+ # @see RAutomation::Window#close
168
+ def close
169
+ Functions.close_window(hwnd)
170
+ end
171
+
172
+ # @see Button#initialize
173
+ # @see RAutomation::Window#button
174
+ def button(locator)
175
+ Button.new(self, locator)
176
+ end
177
+
178
+ # @see TextField#initialize
179
+ # @see RAutomation::Window#text_field
180
+ def text_field(locator)
181
+ TextField.new(self, locator)
182
+ end
183
+
184
+ # Redirects all method calls not part of the public API to the {Functions} directly.
185
+ # @see RAutomation::Window#method_missing
186
+ def method_missing(name, *args)
187
+ Functions.respond_to?(name) ? Functions.send(name, *args) : super
188
+ end
189
+
190
+ # MsUia adapter specific API methods
191
+ def element
192
+ case
193
+ when @locators[:focus]
194
+ uia_control = UiaDll::get_focused_element
195
+ when @locators[:id]
196
+ uia_control = UiaDll::find_window(@locators[:id].to_s)
197
+ raise UnknownElementException, "#{@locators[:id]} does not exist" if uia_control.nil?
198
+ when @locators[:point]
199
+ uia_control = UiaDll::element_from_point(@locators[:point][0], @locators[:point][1])
200
+ raise UnknownElementException, "#{@locators[:point]} does not exist" if uia_control.nil?
201
+ else
202
+ hwnd = find_hwnd(locators, window_hwnd) do |hwnd|
203
+ locators_match?(locators, control_properties(hwnd, locators))
204
+ end
205
+ raise UnknownElementException, "Element with #{locators.inspect} does not exist" if (hwnd == 0) or (hwnd == nil)
206
+ uia_control = UiaDll::element_from_handle(hwnd)
207
+ end
208
+ uia_control
209
+ end
210
+
211
+ def new_pid
212
+ UiaDll::current_process_id(uia_control())
213
+ end
214
+
215
+ def display_tree
216
+ root_element = UiaDll::element_from_handle(hwnd)
217
+
218
+ root_name = FFI::MemoryPointer.new :char, UiaDll::get_name(root_element, nil) + 1
219
+ UiaDll::get_name(root_element, root_name)
220
+
221
+ [root_name.read_string.inspect, gather_children(root_element)]
222
+ end
223
+
224
+ def gather_children(root_element)
225
+ element_tree = []
226
+
227
+ child_count = count_children(root_element)
228
+ children = FFI::MemoryPointer.new :pointer, child_count
229
+ UiaDll::find_children(root_element, children)
230
+
231
+ children.read_array_of_pointer(child_count).each do |child|
232
+ child_name = FFI::MemoryPointer.new :char, UiaDll::get_name(child, nil) + 1
233
+ UiaDll::get_name(child, child_name)
234
+
235
+ grandchild_count = count_children(child)
236
+
237
+ if grandchild_count > 0
238
+ element_tree << [child_name.read_string, gather_children(child)]
239
+ else
240
+ element_tree << child_name.read_string
241
+ end
242
+ end
243
+
244
+ element_tree
245
+ end
246
+
247
+ def count_children(element)
248
+ UiaDll::find_children(element, nil)
249
+ end
250
+
251
+ def gather_children_classes(root_element)
252
+ element_tree = []
253
+
254
+ child_count = count_children(root_element)
255
+ children = FFI::MemoryPointer.new :pointer, child_count
256
+ UiaDll::find_children(root_element, children)
257
+
258
+ children.read_array_of_pointer(child_count).each do |child|
259
+ child_name = FFI::MemoryPointer.new :char, UiaDll::get_class_name(child, nil) + 1
260
+ UiaDll::get_class_name(child, child_name)
261
+
262
+ grandchild_count = count_children(child)
263
+
264
+ if grandchild_count > 0
265
+ element_tree << [child_name.read_string, gather_children_classes(child)]
266
+ else
267
+ element_tree << child_name.read_string
268
+ end
269
+ end
270
+
271
+ element_tree
272
+ end
273
+
274
+ def get_focused_element
275
+ UiaDll::get_focused_element()
276
+ end
277
+
278
+ def bounding_rectangle
279
+ window = UiaDll::element_from_handle(hwnd)
280
+
281
+ boundary = FFI::MemoryPointer.new :long, 4
282
+ UiaDll::bounding_rectangle(window, boundary)
283
+
284
+ boundary.read_array_of_long(4)
285
+ end
286
+
287
+ def move_mouse(x, y)
288
+ UiaDll::move_mouse(x, y)
289
+ end
290
+
291
+ def click_mouse()
292
+ UiaDll::click_mouse
293
+ end
294
+
295
+ def label(locator)
296
+ @container.wait_until_present
297
+ Label.new(self, locator)
298
+ end
299
+
300
+ def control(locator)
301
+ @container.wait_until_present
302
+ Control.new(self, locator)
303
+ end
304
+
305
+ def controls(locator)
306
+ @container.wait_until_present
307
+ Controls.new(self, locator)
308
+ end
309
+
310
+ def list_box(locator)
311
+ @container.wait_until_present
312
+ ListBox.new(self, locator)
313
+ end
314
+
315
+ def list_item(locator)
316
+ @container.wait_until_present
317
+ ListItem.new(self, locator)
318
+ end
319
+
320
+ def select_list(locator)
321
+ @container.wait_until_present
322
+ SelectList.new(self, locator)
323
+ end
324
+
325
+ def checkbox(locator)
326
+ @container.wait_until_present
327
+ Checkbox.new(self, locator)
328
+ end
329
+
330
+ def radio(locator)
331
+ @container.wait_until_present
332
+ Radio.new(self, locator)
333
+ end
334
+
335
+ def table(locator)
336
+ @container.wait_until_present
337
+ Table.new(self, locator)
338
+ end
339
+
340
+ #todo - replace with UIA version
341
+ # Creates the child window object.
342
+ # @note This is an Win32 adapter specific method, not part of the public API
343
+ # @example
344
+ # RAutomation::Window.new(:title => /Windows Internet Explorer/i).
345
+ # child(:title => /some popup/)
346
+ # @param (see Window#initialize)
347
+ # @return [RAutomation::Window] child window, popup or regular window.
348
+ def child(locators)
349
+ RAutomation::Window.new Functions.child_window_locators(hwnd, locators)
350
+ end
351
+
352
+ private
353
+
354
+ def press_key key
355
+ Functions.send_key(key, 0, 0, nil)
356
+ end
357
+
358
+ def release_key key
359
+ Functions.send_key(key, 0, Constants::KEYEVENTF_KEYUP, nil)
360
+ end
361
+ end
362
+ end
363
+ end
364
+ end