rautomation 0.6.3 → 0.7.0
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.
- data/.gitignore +34 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +24 -0
- data/History.rdoc +21 -0
- data/LICENSE +1 -1
- data/README.rdoc +8 -7
- data/Rakefile +22 -32
- data/VERSION +1 -1
- data/ext/UiaDll/Release/UiaDll.dll +0 -0
- data/ext/UiaDll/UiaDll.suo +0 -0
- data/ext/UiaDll/UiaDll/UiaDll.cpp +236 -10
- data/lib/rautomation/adapter/autoit/locators.rb +1 -1
- data/lib/rautomation/adapter/autoit/text_field.rb +10 -1
- data/lib/rautomation/adapter/autoit/window.rb +50 -23
- data/lib/rautomation/adapter/helper.rb +6 -6
- data/lib/rautomation/adapter/ms_uia.rb +22 -0
- data/lib/rautomation/adapter/{win_ffi → ms_uia}/button.rb +3 -2
- data/lib/rautomation/adapter/ms_uia/button_helper.rb +25 -0
- data/lib/rautomation/adapter/ms_uia/checkbox.rb +27 -0
- data/lib/rautomation/adapter/{win_ffi → ms_uia}/constants.rb +20 -5
- data/lib/rautomation/adapter/ms_uia/control.rb +180 -0
- data/lib/rautomation/adapter/{win_ffi → ms_uia}/functions.rb +24 -26
- data/lib/rautomation/adapter/ms_uia/keystroke_converter.rb +122 -0
- data/lib/rautomation/adapter/{win_ffi → ms_uia}/label.rb +3 -2
- data/lib/rautomation/adapter/ms_uia/list_box.rb +91 -0
- data/lib/rautomation/adapter/ms_uia/list_item.rb +49 -0
- data/lib/rautomation/adapter/ms_uia/locators.rb +23 -0
- data/lib/rautomation/adapter/{win_ffi → ms_uia}/radio.rb +2 -2
- data/lib/rautomation/adapter/{win_ffi → ms_uia}/select_list.rb +41 -7
- data/lib/rautomation/adapter/ms_uia/table.rb +86 -0
- data/lib/rautomation/adapter/{win_ffi → ms_uia}/text_field.rb +5 -4
- data/lib/rautomation/adapter/ms_uia/uia_dll.rb +62 -0
- data/lib/rautomation/adapter/ms_uia/window.rb +364 -0
- data/lib/rautomation/adapter/win_32.rb +21 -0
- data/lib/rautomation/adapter/win_32/button.rb +14 -0
- data/lib/rautomation/adapter/{win_ffi → win_32}/button_helper.rb +1 -1
- data/lib/rautomation/adapter/win_32/checkbox.rb +14 -0
- data/lib/rautomation/adapter/win_32/constants.rb +68 -0
- data/lib/rautomation/adapter/{win_ffi → win_32}/control.rb +30 -23
- data/lib/rautomation/adapter/win_32/functions.rb +313 -0
- data/lib/rautomation/adapter/win_32/keys.rb +121 -0
- data/lib/rautomation/adapter/win_32/label.rb +10 -0
- data/lib/rautomation/adapter/win_32/list_box.rb +40 -0
- data/lib/rautomation/adapter/{win_ffi → win_32}/locators.rb +2 -2
- data/lib/rautomation/adapter/win_32/radio.rb +11 -0
- data/lib/rautomation/adapter/win_32/select_list.rb +97 -0
- data/lib/rautomation/adapter/win_32/table.rb +22 -0
- data/lib/rautomation/adapter/win_32/text_field.rb +42 -0
- data/lib/rautomation/adapter/{win_ffi → win_32}/window.rb +79 -62
- data/lib/rautomation/element_collections.rb +9 -1
- data/lib/rautomation/window.rb +17 -9
- data/rautomation.gemspec +24 -0
- data/spec/adapter/autoit/window_spec.rb +71 -0
- data/spec/adapter/{win_ffi → ms_uia}/button_spec.rb +1 -1
- data/spec/adapter/{win_ffi → ms_uia}/checkbox_spec.rb +9 -3
- data/spec/adapter/ms_uia/control_spec.rb +28 -0
- data/spec/adapter/ms_uia/keystroke_converter_spec.rb +50 -0
- data/spec/adapter/{win_ffi → ms_uia}/label_spec.rb +2 -2
- data/spec/adapter/ms_uia/list_item_spec.rb +14 -0
- data/spec/adapter/{win_ffi → ms_uia}/listbox_spec.rb +18 -5
- data/spec/adapter/{win_ffi → ms_uia}/radio_spec.rb +3 -1
- data/spec/adapter/ms_uia/select_list_spec.rb +109 -0
- data/spec/adapter/{win_ffi → ms_uia}/table_spec.rb +12 -1
- data/spec/adapter/{win_ffi → ms_uia}/text_field_spec.rb +2 -1
- data/spec/adapter/ms_uia/window_spec.rb +89 -0
- data/spec/adapter/win_32/button_spec.rb +30 -0
- data/spec/adapter/win_32/checkbox_spec.rb +48 -0
- data/spec/adapter/win_32/label_spec.rb +15 -0
- data/spec/adapter/win_32/listbox_spec.rb +42 -0
- data/spec/adapter/win_32/radio_spec.rb +32 -0
- data/spec/adapter/{win_ffi → win_32}/select_list_spec.rb +16 -16
- data/spec/adapter/win_32/table_spec.rb +28 -0
- data/spec/adapter/win_32/text_field_spec.rb +24 -0
- data/spec/adapter/{win_ffi → win_32}/window_spec.rb +19 -14
- data/spec/button_spec.rb +1 -0
- data/spec/buttons_spec.rb +4 -4
- data/spec/spec_helper.rb +30 -4
- data/spec/text_field_spec.rb +6 -7
- data/spec/window_spec.rb +12 -0
- data/spec/windows_spec.rb +19 -0
- metadata +116 -97
- data/lib/rautomation/adapter/win_ffi.rb +0 -21
- data/lib/rautomation/adapter/win_ffi/checkbox.rb +0 -19
- data/lib/rautomation/adapter/win_ffi/keystroke_converter.rb +0 -67
- data/lib/rautomation/adapter/win_ffi/list_box.rb +0 -60
- data/lib/rautomation/adapter/win_ffi/ms_uia/uia_dll.rb +0 -36
- data/lib/rautomation/adapter/win_ffi/table.rb +0 -57
- data/spec/adapter/win_ffi/keystroke_converter_spec.rb +0 -47
@@ -1,6 +1,9 @@
|
|
1
|
+
#todo - replace as much of this as possible with UIA versions
|
2
|
+
|
3
|
+
|
1
4
|
module RAutomation
|
2
5
|
module Adapter
|
3
|
-
module
|
6
|
+
module MsUia
|
4
7
|
# @private
|
5
8
|
module Functions
|
6
9
|
extend FFI::Library
|
@@ -128,20 +131,6 @@ module RAutomation
|
|
128
131
|
locators
|
129
132
|
end
|
130
133
|
|
131
|
-
def child_window_locators(parent_hwnd, locators)
|
132
|
-
child_hwnd = locators[:hwnd] || child_hwnd(parent_hwnd, locators)
|
133
|
-
if child_hwnd
|
134
|
-
locators.merge!(:hwnd => child_hwnd)
|
135
|
-
else
|
136
|
-
popup_hwnd = get_window(parent_hwnd, Constants::GW_ENABLEDPOPUP)
|
137
|
-
if popup_hwnd != parent_hwnd
|
138
|
-
popup_properties = window_properties(popup_hwnd, locators)
|
139
|
-
locators.merge!(:hwnd => popup_hwnd) if locators_match?(locators, popup_properties)
|
140
|
-
end
|
141
|
-
end
|
142
|
-
locators
|
143
|
-
end
|
144
|
-
|
145
134
|
def window_pid(hwnd)
|
146
135
|
pid = FFI::MemoryPointer.new :int
|
147
136
|
window_thread_process_id(hwnd, pid)
|
@@ -180,16 +169,25 @@ module RAutomation
|
|
180
169
|
end
|
181
170
|
|
182
171
|
def control_hwnd(window_hwnd, locators)
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
172
|
+
case
|
173
|
+
when locators[:id]
|
174
|
+
uia_window = UiaDll::element_from_handle(window_hwnd) # finds IUIAutomationElement for given parent window
|
175
|
+
uia_control = UiaDll::find_child_by_id(uia_window, locators[:id].to_s)
|
176
|
+
hwnd = UiaDll::current_native_window_handle(uia_control) # return HWND of UIA element
|
177
|
+
raise UnknownElementException, "#{locators[:id]} does not exist" if hwnd == 0
|
178
|
+
hwnd
|
179
|
+
when locators[:point]
|
180
|
+
uia_control = UiaDll::element_from_point(locators[:point][0], locators[:point][1])
|
181
|
+
hwnd = UiaDll::current_native_window_handle(uia_control) # return HWND of UIA element
|
182
|
+
raise UnknownElementException, "#{locators[:point]} does not exist" if hwnd == 0
|
183
|
+
hwnd
|
184
|
+
else
|
185
|
+
hwnd = find_hwnd(locators, window_hwnd) do |hwnd|
|
186
|
+
locators_match?(locators, control_properties(hwnd, locators))
|
187
|
+
end
|
188
|
+
|
189
|
+
raise UnknownElementException, "Element with #{locators.inspect} does not exist" if (hwnd == 0) or (hwnd == nil)
|
190
|
+
hwnd
|
193
191
|
end
|
194
192
|
end
|
195
193
|
|
@@ -243,7 +241,7 @@ module RAutomation
|
|
243
241
|
end
|
244
242
|
|
245
243
|
def retrieve_table_strings_for_row(control_hwnd, row)
|
246
|
-
hModule = load_library("oleacc.dll")
|
244
|
+
hModule = load_library("oleacc.dll") # TODO should be done only one time
|
247
245
|
|
248
246
|
strings_ptr = FFI::MemoryPointer.new :pointer
|
249
247
|
columns_ptr = FFI::MemoryPointer.new :pointer
|
@@ -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
|
@@ -1,16 +1,17 @@
|
|
1
1
|
module RAutomation
|
2
2
|
module Adapter
|
3
|
-
module
|
3
|
+
module MsUia
|
4
4
|
class Label < Control
|
5
5
|
include WaitHelper
|
6
6
|
include Locators
|
7
7
|
|
8
|
+
#todo - replace with UIA version
|
8
9
|
def value
|
9
10
|
Functions.control_value(Functions.control_hwnd(@window.hwnd, @locators))
|
10
11
|
end
|
11
12
|
|
12
13
|
def exist?
|
13
|
-
|
14
|
+
super && matches_type?(Constants::UIA_TEXT_CONTROL_TYPE)
|
14
15
|
end
|
15
16
|
|
16
17
|
alias_method :exists?, :exist?
|
@@ -0,0 +1,91 @@
|
|
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::find_children(uia_element, nil)
|
11
|
+
end
|
12
|
+
|
13
|
+
def items
|
14
|
+
list_items = []
|
15
|
+
children = FFI::MemoryPointer.new :pointer, self.count
|
16
|
+
length = UiaDll::find_children(uia_element, children)
|
17
|
+
|
18
|
+
children.read_array_of_pointer(length).each do |child|
|
19
|
+
if (UiaDll::current_control_type(child) == Constants::UIA_LIST_ITEM_CONTROL_TYPE) or (UiaDll::current_control_type(child) == Constants::UIA_DATA_ITEM_CONTROL_TYPE)
|
20
|
+
child_name = FFI::MemoryPointer.new :char, UiaDll::get_name(child, nil) + 1
|
21
|
+
UiaDll::get_name(child, child_name)
|
22
|
+
list_items.push(@window.list_item(:value => child_name.read_string))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
list_items
|
27
|
+
end
|
28
|
+
|
29
|
+
def strings
|
30
|
+
items.collect { |item| item.value}
|
31
|
+
end
|
32
|
+
|
33
|
+
def value
|
34
|
+
count.times do |index|
|
35
|
+
if selected?(index)
|
36
|
+
return strings[index]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
""
|
41
|
+
end
|
42
|
+
|
43
|
+
def exist?
|
44
|
+
super && matches_type?(Constants::UIA_LIST_CONTROL_TYPE)
|
45
|
+
end
|
46
|
+
|
47
|
+
alias_method :exists?, :exist?
|
48
|
+
|
49
|
+
def selected?(index)
|
50
|
+
if items[index]
|
51
|
+
return items[index].selected?
|
52
|
+
end
|
53
|
+
|
54
|
+
false
|
55
|
+
end
|
56
|
+
|
57
|
+
def select(index)
|
58
|
+
children = FFI::MemoryPointer.new :pointer, self.count
|
59
|
+
|
60
|
+
length = UiaDll::find_children(uia_element, children)
|
61
|
+
|
62
|
+
target_element = children.read_array_of_pointer(length)[index]
|
63
|
+
|
64
|
+
UiaDll::select(target_element)
|
65
|
+
end
|
66
|
+
|
67
|
+
def list_boundary
|
68
|
+
boundary = FFI::MemoryPointer.new :long, 4
|
69
|
+
|
70
|
+
Functions.send_message(hwnd, Constants::LB_GETITEMRECT, 0 ,boundary)
|
71
|
+
|
72
|
+
boundary.read_array_of_long(4)
|
73
|
+
end
|
74
|
+
|
75
|
+
def get_top_index
|
76
|
+
Functions.send_message(hwnd, Constants::LB_GETTOPINDEX, 0 ,nil)
|
77
|
+
end
|
78
|
+
|
79
|
+
def list_item_height
|
80
|
+
Functions.send_message(hwnd, Constants::LB_GETITEMHEIGHT, 0 ,nil)
|
81
|
+
end
|
82
|
+
|
83
|
+
def scroll_to_item(row)
|
84
|
+
Functions.send_message(hwnd, Constants::LB_SETTOPINDEX, row ,nil)
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module RAutomation
|
2
|
+
module Adapter
|
3
|
+
module MsUia
|
4
|
+
class ListItem < Control
|
5
|
+
include WaitHelper
|
6
|
+
include Locators
|
7
|
+
|
8
|
+
#Can't get by value without a handle or a bug fix in the new way of getting a control by value so this is a workaround
|
9
|
+
def uia_element
|
10
|
+
if @locators[:value]
|
11
|
+
uia_window = UiaDll::element_from_handle(@window.hwnd)
|
12
|
+
begin
|
13
|
+
uia_window.read_pointer
|
14
|
+
rescue FFI::NullPointerError => e
|
15
|
+
raise UnknownElementException, "Window with handle #{@window.hwnd} does not exist"
|
16
|
+
end
|
17
|
+
uia_control = UiaDll::find_child_by_name(uia_window, @locators[:value].to_s)
|
18
|
+
begin
|
19
|
+
uia_control.read_pointer
|
20
|
+
rescue FFI::NullPointerError => e
|
21
|
+
raise UnknownElementException, "#{@locators[:value]} does not exist"
|
22
|
+
end
|
23
|
+
uia_control
|
24
|
+
else
|
25
|
+
super
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def value
|
30
|
+
list_item = uia_element
|
31
|
+
item_value = FFI::MemoryPointer.new :char, UiaDll::get_name(list_item, nil) + 1
|
32
|
+
UiaDll::get_name(list_item, item_value)
|
33
|
+
item_value.read_string
|
34
|
+
end
|
35
|
+
|
36
|
+
def exist?
|
37
|
+
super && matches_type?(Constants::UIA_LIST_ITEM_CONTROL_TYPE)
|
38
|
+
end
|
39
|
+
|
40
|
+
def selected?
|
41
|
+
UiaDll::get_is_selected(uia_element)
|
42
|
+
end
|
43
|
+
|
44
|
+
alias_method :exists?, :exist?
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
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
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module RAutomation
|
2
2
|
module Adapter
|
3
|
-
module
|
3
|
+
module MsUia
|
4
4
|
class Radio < Control
|
5
5
|
include WaitHelper
|
6
6
|
include Locators
|
@@ -8,7 +8,7 @@ module RAutomation
|
|
8
8
|
|
9
9
|
|
10
10
|
def exist?
|
11
|
-
|
11
|
+
super && matches_type?(Constants::UIA_RADIO_BUTTON_CONTROL_TYPE)
|
12
12
|
end
|
13
13
|
|
14
14
|
alias_method :exists?, :exist?
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module RAutomation
|
2
2
|
module Adapter
|
3
|
-
module
|
3
|
+
module MsUia
|
4
4
|
|
5
5
|
class SelectList < Control
|
6
6
|
include WaitHelper
|
@@ -11,16 +11,18 @@ module RAutomation
|
|
11
11
|
|
12
12
|
def initialize(select_list, text, index)
|
13
13
|
@select_list = select_list
|
14
|
-
@text
|
15
|
-
@index
|
14
|
+
@text = text
|
15
|
+
@index = index
|
16
16
|
end
|
17
17
|
|
18
|
+
#todo - replace with UIA version
|
18
19
|
def selected?
|
19
20
|
selected_idx = Functions.send_message(@select_list.control_hwnd, Constants::CB_GETCURSEL, 0, nil)
|
20
21
|
return false if selected_idx == Constants::CB_ERR
|
21
22
|
@text == Functions.retrieve_combobox_item_text(@select_list.control_hwnd, selected_idx)
|
22
23
|
end
|
23
24
|
|
25
|
+
#todo - replace with UIA version
|
24
26
|
def select
|
25
27
|
@select_list.assert_enabled
|
26
28
|
Functions.send_message(@select_list.control_hwnd, Constants::CB_SETCURSEL, @index, nil) != Constants::CB_ERR
|
@@ -29,18 +31,25 @@ module RAutomation
|
|
29
31
|
alias_method :set, :select
|
30
32
|
end
|
31
33
|
|
34
|
+
#todo - replace with UIA version
|
32
35
|
def initialize(window, locators)
|
33
36
|
super
|
34
37
|
@hwnd = Functions.control_hwnd(@window.hwnd, @locators)
|
35
38
|
end
|
36
39
|
|
40
|
+
def set(value)
|
41
|
+
list = UiaDll::element_from_handle(@hwnd)
|
42
|
+
UiaDll::set_value(list, value)
|
43
|
+
end
|
44
|
+
|
45
|
+
#todo - replace with UIA version
|
37
46
|
def options(options = {})
|
38
47
|
items = []
|
39
48
|
|
40
49
|
item_count.times do |item_no|
|
41
50
|
item = Functions.retrieve_combobox_item_text(@hwnd, item_no)
|
42
51
|
|
43
|
-
if options[:text]
|
52
|
+
if options[:text]
|
44
53
|
items.push(SelectListOption.new(self, item, item_no)) if options[:text] == item
|
45
54
|
else
|
46
55
|
items.push(SelectListOption.new(self, item, item_no))
|
@@ -51,10 +60,11 @@ module RAutomation
|
|
51
60
|
end
|
52
61
|
|
53
62
|
def value
|
54
|
-
selected_option = options.find {|option| option.selected?}
|
63
|
+
selected_option = options.find { |option| option.selected? }
|
55
64
|
selected_option ? selected_option.text : ""
|
56
65
|
end
|
57
66
|
|
67
|
+
#todo - replace with UIA version
|
58
68
|
def option(options)
|
59
69
|
item_count.times do |item_no|
|
60
70
|
item = Functions.retrieve_combobox_item_text(@hwnd, item_no)
|
@@ -68,19 +78,43 @@ module RAutomation
|
|
68
78
|
@hwnd
|
69
79
|
end
|
70
80
|
|
81
|
+
def select(index)
|
82
|
+
Functions.send_message(@hwnd, Constants::CB_SETCURSEL, index, nil) != Constants::CB_ERR
|
83
|
+
end
|
84
|
+
|
85
|
+
def list_item_height
|
86
|
+
Functions.send_message(@hwnd, Constants::CB_GETITEMHEIGHT, 0 ,nil)
|
87
|
+
end
|
88
|
+
|
89
|
+
def dropbox_boundary
|
90
|
+
boundary = FFI::MemoryPointer.new :long, 4
|
91
|
+
|
92
|
+
Functions.send_message(@hwnd, Constants::CB_GETDROPPEDCONTROLRECT, 0 ,boundary)
|
93
|
+
|
94
|
+
boundary.read_array_of_long(4)
|
95
|
+
end
|
96
|
+
|
97
|
+
def get_top_index
|
98
|
+
Functions.send_message(@hwnd, Constants::CB_GETTOPINDEX, 0 ,nil)
|
99
|
+
end
|
100
|
+
|
101
|
+
def scroll_to_item(row)
|
102
|
+
Functions.send_message(@hwnd, Constants::CB_SETTOPINDEX , row ,nil)
|
103
|
+
end
|
104
|
+
|
71
105
|
def exist?
|
72
|
-
|
106
|
+
super && matches_type?(Constants::UIA_COMBOBOX_CONTROL_TYPE)
|
73
107
|
end
|
74
108
|
|
75
109
|
alias_method :exists?, :exist?
|
76
110
|
|
77
111
|
private
|
78
112
|
|
113
|
+
#todo - replace with UIA version
|
79
114
|
def item_count
|
80
115
|
Functions.send_message(@hwnd, Constants::CB_GETCOUNT, 0, nil)
|
81
116
|
end
|
82
117
|
|
83
|
-
|
84
118
|
end
|
85
119
|
end
|
86
120
|
end
|