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,121 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module Win32
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,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
+
@@ -1,6 +1,6 @@
1
1
  module RAutomation
2
2
  module Adapter
3
- module WinFfi
3
+ module Win32
4
4
  # @private
5
5
  module Locators
6
6
 
@@ -14,7 +14,7 @@ module RAutomation
14
14
 
15
15
  # control locator
16
16
  locators = self.class::DEFAULT_LOCATORS.merge(locators) if self.class.const_defined?(:DEFAULT_LOCATORS)
17
- @locators = locators
17
+ @locators = {:index => 0}.merge locators
18
18
  end
19
19
  end
20
20
  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
@@ -0,0 +1,97 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module Win32
4
+ class SelectList < Control
5
+ include WaitHelper
6
+ include Locators
7
+
8
+ # Default locators used for searching buttons.
9
+ DEFAULT_LOCATORS = {:class => /combobox/i}
10
+
11
+ class SelectListOption
12
+ attr_accessor :text, :index
13
+
14
+ def initialize(select_list, text, index)
15
+ @select_list = select_list
16
+ @text = text
17
+ @index = index
18
+ end
19
+
20
+ def selected?
21
+ selected_idx = Functions.send_message(@select_list.hwnd, Constants::CB_GETCURSEL, 0, nil)
22
+ return false if selected_idx == Constants::CB_ERR
23
+ @text == Functions.retrieve_combobox_item_text(@select_list.hwnd, selected_idx)
24
+ end
25
+
26
+ def select
27
+ @select_list.send :assert_enabled
28
+ Functions.send_message(@select_list.hwnd, Constants::CB_SETCURSEL, @index, nil) != Constants::CB_ERR
29
+ end
30
+
31
+ alias_method :set, :select
32
+ end
33
+
34
+ def options(options = {})
35
+ items = []
36
+
37
+ item_count.times do |item_no|
38
+ item = Functions.retrieve_combobox_item_text(hwnd, item_no)
39
+
40
+ if options[:text]
41
+ items.push(SelectListOption.new(self, item, item_no)) if options[:text] == item
42
+ else
43
+ items.push(SelectListOption.new(self, item, item_no))
44
+ end
45
+ end
46
+
47
+ items
48
+ end
49
+
50
+ def value
51
+ selected_option = options.find { |option| option.selected? }
52
+ selected_option ? selected_option.text : ""
53
+ end
54
+
55
+ def option(options)
56
+ item_count.times do |item_no|
57
+ item = Functions.retrieve_combobox_item_text(hwnd, item_no)
58
+ return SelectListOption.new(self, item, item_no) if options[:text] == item
59
+ end
60
+
61
+ nil
62
+ end
63
+
64
+ def select(index)
65
+ Functions.send_message(hwnd, Constants::CB_SETCURSEL, index, nil) != Constants::CB_ERR
66
+ end
67
+
68
+ def set(text)
69
+ option(:text => text).set
70
+ end
71
+
72
+ def list_item_height
73
+ Functions.send_message(hwnd, Constants::CB_GETITEMHEIGHT, 0 ,nil)
74
+ end
75
+
76
+ def dropbox_boundary
77
+ boundary = FFI::MemoryPointer.new :long, 4
78
+
79
+ Functions.send_message(hwnd, Constants::CB_GETDROPPEDCONTROLRECT, 0 ,boundary)
80
+
81
+ boundary.read_array_of_long(4)
82
+ end
83
+
84
+ def get_top_index
85
+ Functions.send_message(hwnd, Constants::CB_GETTOPINDEX, 0 ,nil)
86
+ end
87
+
88
+ private
89
+
90
+ def item_count
91
+ Functions.send_message(hwnd, Constants::CB_GETCOUNT, 0, nil)
92
+ end
93
+
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,22 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module Win32
4
+ class Table < Control
5
+ include WaitHelper
6
+ include Locators
7
+
8
+ # Default locators used for searching buttons.
9
+ DEFAULT_LOCATORS = {:class => /syslistview/i}
10
+
11
+ def select(row)
12
+ Functions.select_table_row(Window.oleacc_module_handle, Functions.control_hwnd(@window.hwnd, @locators), row)
13
+ end
14
+
15
+ def selected?(row)
16
+ state = Functions.get_table_row_state(Window.oleacc_module_handle, Functions.control_hwnd(@window.hwnd, @locators), row)
17
+ state & Constants::STATE_SYSTEM_SELECTED != 0
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,42 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module Win32
4
+ class TextField < Control
5
+ include WaitHelper
6
+ include Locators
7
+
8
+ # Default locators used for searching text fields.
9
+ DEFAULT_LOCATORS = {:class => /edit/i}
10
+
11
+ # @see RAutomation::TextField#set
12
+ def set(text)
13
+ raise "Cannot set value on a disabled text field" if disabled?
14
+
15
+ wait_until do
16
+ hwnd = Functions.control_hwnd(@window.hwnd, @locators)
17
+ @window.activate
18
+ @window.active? &&
19
+ focus &&
20
+ Functions.set_control_text(hwnd, text) &&
21
+ value == text
22
+ end
23
+ end
24
+
25
+ # @see RAutomation::TextField#clear
26
+ def clear
27
+ raise "Cannot set value on a disabled text field" if disabled?
28
+ set ""
29
+ end
30
+
31
+ # @see RAutomation::Window#send_keys
32
+ def send_keys(*keys)
33
+ @window.container.wait_until_present
34
+ assert_enabled
35
+ @window.activate
36
+ focus
37
+ @window.send_keys(keys)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -1,8 +1,6 @@
1
1
  module RAutomation
2
2
  module Adapter
3
- module WinFfi
4
- autoload :UiaDll, File.dirname(__FILE__) + "/ms_uia/uia_dll"
5
-
3
+ module Win32
6
4
  class Window
7
5
  include WaitHelper
8
6
  include Locators
@@ -20,6 +18,8 @@ module RAutomation
20
18
  end
21
19
  end
22
20
 
21
+ attr_reader :container
22
+
23
23
  # Locators of the window.
24
24
  attr_reader :locators
25
25
 
@@ -36,7 +36,8 @@ module RAutomation
36
36
  # @option locators [String, Fixnum] :index 0-based index to specify n-th window if all other criteria match
37
37
  # all other criteria match
38
38
  # @see RAutomation::Window#initialize
39
- def initialize(locators)
39
+ def initialize(container, locators)
40
+ @container = container
40
41
  extract(locators)
41
42
  end
42
43
 
@@ -57,12 +58,21 @@ module RAutomation
57
58
  Functions.window_title(hwnd)
58
59
  end
59
60
 
61
+ # @see RAutomation::Window#class_names
62
+ def class_names
63
+ classes = []
64
+ controls.each do |control|
65
+ classes << control.class_name
66
+ end
67
+ classes.sort
68
+ end
69
+
60
70
  # @see RAutomation::Window#activate
61
71
  def activate
62
72
  return if !exists? || active?
63
73
  restore if minimized?
64
74
  Functions.activate_window(hwnd)
65
- sleep 1
75
+ sleep 0.1
66
76
  end
67
77
 
68
78
  # @see RAutomation::Window#active?
@@ -111,29 +121,33 @@ module RAutomation
111
121
 
112
122
  # Activates the window and sends keys to it.
113
123
  #
114
- # Refer to KeystrokeConverter#convert_special_characters for the special keycodes.
124
+ # @example
125
+ # RAutomation::Window.new(:title => //).send_keys "hello!"
126
+ # RAutomation::Window.new(:title => //).send_keys [:control, "a"], "world!"
127
+ # Refer to Keys#KEYS for all the special keycodes.
115
128
  # @see RAutomation::Window#send_keys
116
- def send_keys(keys)
117
- shift_pressed = false
118
- KeystrokeConverter.convert(keys).each do |key|
129
+ def send_keys(args)
130
+ Keys.encode(args).each do |arg|
119
131
  wait_until do
120
132
  activate
121
133
  active?
122
134
  end
123
- press_key key
124
-
125
- if key == Constants::VK_LSHIFT
126
- shift_pressed = true
127
- next
128
- end
129
135
 
130
- release_key key
131
-
132
- if shift_pressed
133
- shift_pressed = false
134
- release_key Constants::VK_LSHIFT
136
+ if arg.is_a?(Array)
137
+ arg.reduce([]) do |pressed_keys, k|
138
+ if k == Keys[:null]
139
+ pressed_keys.each {|pressed_key| release_key pressed_key}
140
+ pressed_keys = []
141
+ else
142
+ pressed_keys << press_key(k)
143
+ end
144
+ pressed_keys
145
+ end
146
+ else
147
+ send_key arg
135
148
  end
136
149
  end
150
+ sleep 1
137
151
  end
138
152
 
139
153
  # @see RAutomation::Window#close
@@ -153,72 +167,75 @@ module RAutomation
153
167
  TextField.new(self, locator)
154
168
  end
155
169
 
156
- def label(locator)
157
- Label.new(self, locator)
170
+ # Redirects all method calls not part of the public API to the {Functions} directly.
171
+ # @see RAutomation::Window#method_missing
172
+ def method_missing(name, *args)
173
+ Functions.respond_to?(name) ? Functions.send(name, *args) : super
158
174
  end
159
175
 
160
- def control(locator)
161
- Control.new(self, locator)
176
+ # Win32 adapter specific API methods
177
+ def label(locator={})
178
+ @container.wait_until_present
179
+ Label.new(self, locator)
162
180
  end
163
181
 
164
- def controls(locator)
165
- Controls.new(self, locator)
182
+ def control(locator={})
183
+ @container.wait_until_present
184
+ Control.new(self, locator)
166
185
  end
167
186
 
168
- def list_box(locator)
187
+ def list_box(locator={})
188
+ @container.wait_until_present
169
189
  ListBox.new(self, locator)
170
190
  end
171
191
 
172
- # Redirects all method calls not part of the public API to the {Functions} directly.
173
- # @see RAutomation::Window#method_missing
174
- def method_missing(name, *args)
175
- Functions.respond_to?(name) ? Functions.send(name, *args) : super
192
+ def select_list(locator={})
193
+ @container.wait_until_present
194
+ SelectList.new(self, locator)
176
195
  end
177
196
 
178
- # extend public API
179
- RAutomation::Window.class_eval do
180
- def select_list(locator)
181
- wait_until_exists
182
- RAutomation::Adapter::WinFfi::SelectList.new(@window, locator)
183
- end
184
-
185
- def checkbox(locator)
186
- wait_until_exists
187
- RAutomation::Adapter::WinFfi::Checkbox.new(@window, locator)
188
- end
197
+ def checkbox(locator={})
198
+ @container.wait_until_present
199
+ Checkbox.new(self, locator)
200
+ end
189
201
 
190
- def radio(locator)
191
- wait_until_exists
192
- RAutomation::Adapter::WinFfi::Radio.new(@window, locator)
193
- end
202
+ def radio(locator={})
203
+ @container.wait_until_present
204
+ Radio.new(self, locator)
205
+ end
194
206
 
195
- def table(locator)
196
- wait_until_exists
197
- RAutomation::Adapter::WinFfi::Table.new(@window, locator)
198
- end
207
+ def table(locator={})
208
+ @container.wait_until_present
209
+ Table.new(self, locator)
210
+ end
199
211
 
200
- # Creates the child window object.
201
- # @note This is an WinFfi adapter specific method, not part of the public API
202
- # @example
203
- # RAutomation::Window.new(:title => /Windows Internet Explorer/i).
204
- # child(:title => /some popup/)
205
- # @param (see Window#initialize)
206
- # @return [RAutomation::Window] child window, popup or regular window.
207
- def child(locators)
208
- RAutomation::Window.new Functions.child_window_locators(@window.hwnd, locators)
209
- end
212
+ # Creates the child window object.
213
+ # @note This is an Win32 adapter specific method, not part of the public API
214
+ # @example
215
+ # RAutomation::Window.new(:title => /Windows Internet Explorer/i).
216
+ # child(:title => /some popup/)
217
+ # @param (see Window#initialize)
218
+ # @return [RAutomation::Window] child window, popup or regular window.
219
+ def child(locators)
220
+ RAutomation::Window.new Functions.child_window_locators(hwnd, locators)
210
221
  end
211
222
 
212
223
  private
213
224
 
214
225
  def press_key key
215
226
  Functions.send_key(key, 0, 0, nil)
216
- sleep 0.01
227
+ key
217
228
  end
218
229
 
219
230
  def release_key key
220
231
  Functions.send_key(key, 0, Constants::KEYEVENTF_KEYUP, nil)
221
- sleep 0.1
232
+ key
233
+ end
234
+
235
+ def send_key key
236
+ press_key key
237
+ release_key key
238
+ key
222
239
  end
223
240
  end
224
241
  end