rdp-rautomation 0.6.3.1

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 (120) hide show
  1. data/.document +5 -0
  2. data/.rspec +2 -0
  3. data/.yardopts +6 -0
  4. data/History.rdoc +103 -0
  5. data/LICENSE +20 -0
  6. data/README.rdoc +114 -0
  7. data/Rakefile +43 -0
  8. data/VERSION +1 -0
  9. data/ext/AutoItX/AutoItX.chm +0 -0
  10. data/ext/AutoItX/AutoItX3.dll +0 -0
  11. data/ext/IAccessibleDLL/IAccessibleDLL.sln +20 -0
  12. data/ext/IAccessibleDLL/IAccessibleDLL.suo +0 -0
  13. data/ext/IAccessibleDLL/IAccessibleDLL/IAccessibleDLL.cpp +30 -0
  14. data/ext/IAccessibleDLL/IAccessibleDLL/IAccessibleDLL.vcxproj +102 -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/Release/IAccessibleDLL.dll +0 -0
  24. data/ext/ListViewExplorer/ListViewExplorer.sln +20 -0
  25. data/ext/ListViewExplorer/ListViewExplorer.suo +0 -0
  26. data/ext/ListViewExplorer/ListViewExplorer/ListViewExplorer.cpp +174 -0
  27. data/ext/ListViewExplorer/ListViewExplorer/ListViewExplorer.vcxproj +95 -0
  28. data/ext/ListViewExplorer/ListViewExplorer/ListViewExplorer.vcxproj.filters +42 -0
  29. data/ext/ListViewExplorer/ListViewExplorer/ListViewExplorer.vcxproj.user +3 -0
  30. data/ext/ListViewExplorer/ListViewExplorer/ReadMe.txt +40 -0
  31. data/ext/ListViewExplorer/ListViewExplorer/stdafx.cpp +8 -0
  32. data/ext/ListViewExplorer/ListViewExplorer/stdafx.h +17 -0
  33. data/ext/ListViewExplorer/ListViewExplorer/table_support.cpp +250 -0
  34. data/ext/ListViewExplorer/ListViewExplorer/table_support.h +2 -0
  35. data/ext/ListViewExplorer/ListViewExplorer/targetver.h +8 -0
  36. data/ext/UiaDll/Release/UiaDll.dll +0 -0
  37. data/ext/UiaDll/UiaDll.sln +20 -0
  38. data/ext/UiaDll/UiaDll.suo +0 -0
  39. data/ext/UiaDll/UiaDll/ReadMe.txt +48 -0
  40. data/ext/UiaDll/UiaDll/UiaDll.cpp +205 -0
  41. data/ext/UiaDll/UiaDll/UiaDll.vcxproj +104 -0
  42. data/ext/UiaDll/UiaDll/UiaDll.vcxproj.filters +42 -0
  43. data/ext/UiaDll/UiaDll/dllmain.cpp +39 -0
  44. data/ext/UiaDll/UiaDll/globals.h +3 -0
  45. data/ext/UiaDll/UiaDll/stdafx.cpp +8 -0
  46. data/ext/UiaDll/UiaDll/stdafx.h +19 -0
  47. data/ext/UiaDll/UiaDll/targetver.h +8 -0
  48. data/ext/WindowsForms/bin/WindowsForms.exe +0 -0
  49. data/ext/WindowsForms/src/WindowsForms/WindowsForms.sln +20 -0
  50. data/ext/WindowsForms/src/WindowsForms/WindowsForms.suo +0 -0
  51. data/ext/WindowsForms/src/WindowsForms/WindowsForms/AboutBox.Designer.cs +80 -0
  52. data/ext/WindowsForms/src/WindowsForms/WindowsForms/AboutBox.cs +103 -0
  53. data/ext/WindowsForms/src/WindowsForms/WindowsForms/AboutBox.resx +120 -0
  54. data/ext/WindowsForms/src/WindowsForms/WindowsForms/DataEntryForm.Designer.cs +187 -0
  55. data/ext/WindowsForms/src/WindowsForms/WindowsForms/DataEntryForm.cs +46 -0
  56. data/ext/WindowsForms/src/WindowsForms/WindowsForms/DataEntryForm.resx +120 -0
  57. data/ext/WindowsForms/src/WindowsForms/WindowsForms/MainFormWindow.Designer.cs +377 -0
  58. data/ext/WindowsForms/src/WindowsForms/WindowsForms/MainFormWindow.cs +78 -0
  59. data/ext/WindowsForms/src/WindowsForms/WindowsForms/MainFormWindow.resx +120 -0
  60. data/ext/WindowsForms/src/WindowsForms/WindowsForms/PersonForm.Designer.cs +119 -0
  61. data/ext/WindowsForms/src/WindowsForms/WindowsForms/PersonForm.cs +34 -0
  62. data/ext/WindowsForms/src/WindowsForms/WindowsForms/PersonForm.resx +120 -0
  63. data/ext/WindowsForms/src/WindowsForms/WindowsForms/Program.cs +21 -0
  64. data/ext/WindowsForms/src/WindowsForms/WindowsForms/Properties/AssemblyInfo.cs +36 -0
  65. data/ext/WindowsForms/src/WindowsForms/WindowsForms/Properties/Resources.Designer.cs +71 -0
  66. data/ext/WindowsForms/src/WindowsForms/WindowsForms/Properties/Resources.resx +117 -0
  67. data/ext/WindowsForms/src/WindowsForms/WindowsForms/Properties/Settings.Designer.cs +30 -0
  68. data/ext/WindowsForms/src/WindowsForms/WindowsForms/Properties/Settings.settings +7 -0
  69. data/ext/WindowsForms/src/WindowsForms/WindowsForms/SimpleElementsForm.Designer.cs +93 -0
  70. data/ext/WindowsForms/src/WindowsForms/WindowsForms/SimpleElementsForm.cs +19 -0
  71. data/ext/WindowsForms/src/WindowsForms/WindowsForms/SimpleElementsForm.resx +120 -0
  72. data/ext/WindowsForms/src/WindowsForms/WindowsForms/WindowsForms.csproj +123 -0
  73. data/ext/WindowsForms/src/WindowsForms/WindowsForms/bin/Release/WindowsForms.exe +0 -0
  74. data/lib/rautomation.rb +6 -0
  75. data/lib/rautomation/adapter/autoit.rb +5 -0
  76. data/lib/rautomation/adapter/autoit/button.rb +59 -0
  77. data/lib/rautomation/adapter/autoit/locators.rb +22 -0
  78. data/lib/rautomation/adapter/autoit/text_field.rb +61 -0
  79. data/lib/rautomation/adapter/autoit/window.rb +184 -0
  80. data/lib/rautomation/adapter/helper.rb +20 -0
  81. data/lib/rautomation/adapter/win_ffi.rb +21 -0
  82. data/lib/rautomation/adapter/win_ffi/button.rb +25 -0
  83. data/lib/rautomation/adapter/win_ffi/button_helper.rb +24 -0
  84. data/lib/rautomation/adapter/win_ffi/checkbox.rb +19 -0
  85. data/lib/rautomation/adapter/win_ffi/constants.rb +94 -0
  86. data/lib/rautomation/adapter/win_ffi/control.rb +79 -0
  87. data/lib/rautomation/adapter/win_ffi/functions.rb +333 -0
  88. data/lib/rautomation/adapter/win_ffi/keystroke_converter.rb +67 -0
  89. data/lib/rautomation/adapter/win_ffi/label.rb +21 -0
  90. data/lib/rautomation/adapter/win_ffi/list_box.rb +60 -0
  91. data/lib/rautomation/adapter/win_ffi/locators.rb +22 -0
  92. data/lib/rautomation/adapter/win_ffi/ms_uia/uia_dll.rb +36 -0
  93. data/lib/rautomation/adapter/win_ffi/radio.rb +19 -0
  94. data/lib/rautomation/adapter/win_ffi/select_list.rb +87 -0
  95. data/lib/rautomation/adapter/win_ffi/table.rb +57 -0
  96. data/lib/rautomation/adapter/win_ffi/text_field.rb +52 -0
  97. data/lib/rautomation/adapter/win_ffi/window.rb +226 -0
  98. data/lib/rautomation/button.rb +55 -0
  99. data/lib/rautomation/element_collections.rb +47 -0
  100. data/lib/rautomation/text_field.rb +60 -0
  101. data/lib/rautomation/wait_helper.rb +23 -0
  102. data/lib/rautomation/window.rb +234 -0
  103. data/spec/adapter/win_ffi/button_spec.rb +41 -0
  104. data/spec/adapter/win_ffi/checkbox_spec.rb +48 -0
  105. data/spec/adapter/win_ffi/keystroke_converter_spec.rb +47 -0
  106. data/spec/adapter/win_ffi/label_spec.rb +21 -0
  107. data/spec/adapter/win_ffi/listbox_spec.rb +52 -0
  108. data/spec/adapter/win_ffi/radio_spec.rb +37 -0
  109. data/spec/adapter/win_ffi/select_list_spec.rb +66 -0
  110. data/spec/adapter/win_ffi/table_spec.rb +39 -0
  111. data/spec/adapter/win_ffi/text_field_spec.rb +23 -0
  112. data/spec/adapter/win_ffi/window_spec.rb +43 -0
  113. data/spec/button_spec.rb +68 -0
  114. data/spec/buttons_spec.rb +21 -0
  115. data/spec/spec_helper.rb +96 -0
  116. data/spec/text_field_spec.rb +65 -0
  117. data/spec/text_fields_spec.rb +22 -0
  118. data/spec/window_spec.rb +122 -0
  119. data/spec/windows_spec.rb +55 -0
  120. metadata +207 -0
@@ -0,0 +1,67 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module WinFfi
4
+ class KeystrokeConverter
5
+ class << self
6
+ def convert(str)
7
+ special_characters = ""
8
+
9
+ str.split(/([{}])/).inject([]) do |converted_keys, str|
10
+ if str == "}"
11
+ converted_keys << convert_special_characters(special_characters << str)
12
+ special_characters = ""
13
+ elsif str == "{" || !special_characters.empty?
14
+ special_characters << str
15
+ else
16
+ converted_keys += convert_characters(str)
17
+ end
18
+ converted_keys
19
+ end.flatten
20
+ end
21
+
22
+ private
23
+
24
+ def convert_special_characters chars
25
+ case chars.downcase
26
+ when "{tab}"
27
+ Constants::VK_TAB
28
+ when "{backspace}"
29
+ Constants::VK_BACK
30
+ when "{enter}"
31
+ Constants::VK_RETURN
32
+ when "{left}"
33
+ Constants::VK_LEFT
34
+ when "{right}"
35
+ Constants::VK_RIGHT
36
+ when "{down}"
37
+ Constants::VK_DOWN
38
+ when "{up}"
39
+ Constants::VK_UP
40
+ else
41
+ # unsupported special tag, ignore the tag itself, but convert the
42
+ # characters inside the tag
43
+ convert_characters(chars.gsub(/[{}]/, ""))
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def convert_characters(element)
50
+ element.split(//).inject([]) do |chars, char|
51
+ char_code = char.upcase.unpack("c")[0]
52
+ if char =~ /[A-Z]/
53
+ chars += in_upcase(char_code)
54
+ else
55
+ chars << char_code
56
+ end
57
+ end
58
+ end
59
+
60
+ def in_upcase(char_code)
61
+ [Constants::VK_LSHIFT, char_code]
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,21 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module WinFfi
4
+ class Label < Control
5
+ include WaitHelper
6
+ include Locators
7
+
8
+ def value
9
+ Functions.control_value(Functions.control_hwnd(@window.hwnd, @locators))
10
+ end
11
+
12
+ def exist?
13
+ @locators[:id].nil? ? super : super && matches_type(Constants::UIA_LABEL_CONTROL_TYPE)
14
+ end
15
+
16
+ alias_method :exists?, :exist?
17
+
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,60 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module WinFfi
4
+
5
+ class ListBox < Control
6
+ include WaitHelper
7
+ include Locators
8
+
9
+ def count
10
+ UiaDll::find_children(uia_control(@locators[:id]), nil)
11
+ end
12
+
13
+ def items
14
+ list_items = []
15
+ children = FFI::MemoryPointer.new :pointer, self.count
16
+ length = UiaDll::find_children(uia_control(@locators[:id]), children)
17
+ children.read_array_of_pointer(length).each do |child|
18
+ child_name = FFI::MemoryPointer.new :char, UiaDll::get_name(child, nil) + 1
19
+ UiaDll::get_name(child, child_name)
20
+ list_items.push child_name.read_string
21
+ end
22
+ list_items
23
+ end
24
+
25
+ def exist?
26
+ @locators[:id].nil? ? super : super && matches_type(Constants::UIA_LIST_CONTROL_TYPE)
27
+ end
28
+
29
+ alias_method :exists?, :exist?
30
+
31
+ def selected?(index)
32
+ children = FFI::MemoryPointer.new :pointer, self.count
33
+ length = UiaDll::find_children(uia_control(@locators[:id]), children)
34
+ target_element = children.read_array_of_pointer(length)[index]
35
+ is_selected = FFI::MemoryPointer.new :int, 1
36
+
37
+ if UiaDll::get_is_selected(target_element, is_selected) == 1
38
+ return is_selected.read_int == 1
39
+ else
40
+ return false
41
+ end
42
+ end
43
+
44
+ def select(index)
45
+ children = FFI::MemoryPointer.new :pointer, self.count
46
+
47
+ length = UiaDll::find_children(uia_control(@locators[:id]), children)
48
+ target_element = children.read_array_of_pointer(length)[index]
49
+
50
+ UiaDll::select(target_element)
51
+ end
52
+
53
+ alias_method :strings, :items
54
+
55
+
56
+ end
57
+ end
58
+ end
59
+ end
60
+
@@ -0,0 +1,22 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module WinFfi
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 = locators
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,36 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module WinFfi
4
+ # @private
5
+ module UiaDll
6
+ extend FFI::Library
7
+
8
+ ffi_lib File.dirname(__FILE__) + '/../../../../../ext/UiaDll/Release/UiaDll.dll'
9
+ ffi_convention :stdcall
10
+
11
+ attach_function :find_window, :RA_FindWindow,
12
+ [:string], :pointer
13
+ attach_function :is_offscreen, :RA_IsOffscreen,
14
+ [:pointer], :bool
15
+ attach_function :element_from_handle, :RA_ElementFromHandle,
16
+ [:long], :pointer
17
+ attach_function :find_child_by_id, :RA_FindChildById,
18
+ [:pointer, :string], :pointer
19
+ attach_function :current_native_window_handle, :RA_CurrentNativeWindowHandle,
20
+ [:pointer], :long
21
+ attach_function :set_focus, :RA_SetFocus,
22
+ [:pointer], :bool
23
+ attach_function :current_control_type, :RA_GetCurrentControlType,
24
+ [:pointer], :int
25
+ attach_function :find_children, :RA_FindChildren,
26
+ [:pointer, :pointer], :int
27
+ attach_function :get_name, :RA_GetName,
28
+ [:pointer, :pointer], :int
29
+ attach_function :get_is_selected, :RA_GetIsSelected,
30
+ [:pointer, :pointer], :int
31
+ attach_function :select, :RA_Select,
32
+ [:pointer], :int
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,19 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module WinFfi
4
+ class Radio < Control
5
+ include WaitHelper
6
+ include Locators
7
+ include ButtonHelper
8
+
9
+
10
+ def exist?
11
+ @locators[:id].nil? ? super : super && matches_type(Constants::UIA_RADIO_BUTTON_CONTROL_TYPE)
12
+ end
13
+
14
+ alias_method :exists?, :exist?
15
+
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,87 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module WinFfi
4
+
5
+ class SelectList < Control
6
+ include WaitHelper
7
+ include Locators
8
+
9
+ class SelectListOption
10
+ attr_accessor :text, :index, :control_hwnd
11
+
12
+ def initialize(select_list, text, index)
13
+ @select_list = select_list
14
+ @text = text
15
+ @index = index
16
+ end
17
+
18
+ def selected?
19
+ selected_idx = Functions.send_message(@select_list.control_hwnd, Constants::CB_GETCURSEL, 0, nil)
20
+ return false if selected_idx == Constants::CB_ERR
21
+ @text == Functions.retrieve_combobox_item_text(@select_list.control_hwnd, selected_idx)
22
+ end
23
+
24
+ def select
25
+ @select_list.assert_enabled
26
+ Functions.send_message(@select_list.control_hwnd, Constants::CB_SETCURSEL, @index, nil) != Constants::CB_ERR
27
+ end
28
+
29
+ alias_method :set, :select
30
+ end
31
+
32
+ def initialize(window, locators)
33
+ super
34
+ @hwnd = Functions.control_hwnd(@window.hwnd, @locators)
35
+ end
36
+
37
+ def options(options = {})
38
+ items = []
39
+
40
+ item_count.times do |item_no|
41
+ item = Functions.retrieve_combobox_item_text(@hwnd, item_no)
42
+
43
+ if options[:text]
44
+ items.push(SelectListOption.new(self, item, item_no)) if options[:text] == item
45
+ else
46
+ items.push(SelectListOption.new(self, item, item_no))
47
+ end
48
+ end
49
+
50
+ items
51
+ end
52
+
53
+ def value
54
+ selected_option = options.find {|option| option.selected?}
55
+ selected_option ? selected_option.text : ""
56
+ end
57
+
58
+ def option(options)
59
+ item_count.times do |item_no|
60
+ item = Functions.retrieve_combobox_item_text(@hwnd, item_no)
61
+ return SelectListOption.new(self, item, item_no) if options[:text] == item
62
+ end
63
+
64
+ nil
65
+ end
66
+
67
+ def control_hwnd
68
+ @hwnd
69
+ end
70
+
71
+ def exist?
72
+ @locators[:id].nil? ? super : super && matches_type(Constants::UIA_COMBOBOX_CONTROL_TYPE)
73
+ end
74
+
75
+ alias_method :exists?, :exist?
76
+
77
+ private
78
+
79
+ def item_count
80
+ Functions.send_message(@hwnd, Constants::CB_GETCOUNT, 0, nil)
81
+ end
82
+
83
+
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,57 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module WinFfi
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_control(@locators[:id])) == Constants::UIA_LIST_CONTROL_TYPE
13
+
14
+ children_count = count_children(uia_control(@locators[:id]))
15
+ children = FFI::MemoryPointer.new :pointer, children_count
16
+ UiaDll::find_children(uia_control(@locators[:id]), children)
17
+ children.read_array_of_pointer(children_count).each do |child|
18
+ grandchildren_count = count_children(child)
19
+ grandchildren = FFI::MemoryPointer.new :pointer, grandchildren_count
20
+ UiaDll::find_children(child, grandchildren)
21
+ grandchildren.read_array_of_pointer(grandchildren_count).each do |grandchild|
22
+ grandchild_name = FFI::MemoryPointer.new :char, UiaDll::get_name(grandchild, nil) + 1
23
+ UiaDll::get_name(grandchild, grandchild_name)
24
+ header_columns.push grandchild_name.read_string
25
+ end
26
+
27
+ rows.push header_columns
28
+ header_columns = []
29
+ end
30
+
31
+ rows
32
+ end
33
+
34
+ def select(row)
35
+ Functions.select_table_row(Window.oleacc_module_handle, Functions.control_hwnd(@window.hwnd, @locators), row)
36
+ end
37
+
38
+ def selected?(row)
39
+ state = Functions.get_table_row_state(Window.oleacc_module_handle, Functions.control_hwnd(@window.hwnd, @locators), row)
40
+ state & Constants::STATE_SYSTEM_SELECTED != 0
41
+ end
42
+
43
+ def row_count
44
+ UiaDll::find_children(uia_control(@locators[:id]), nil)
45
+ end
46
+
47
+ private
48
+
49
+ def count_children(element)
50
+ UiaDll::find_children(element, nil)
51
+ end
52
+
53
+
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,52 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module WinFfi
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
+ Functions.set_control_focus(hwnd) &&
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::TextField#value
32
+ def value
33
+ Functions.control_value(hwnd)
34
+ end
35
+
36
+ # @see RAutomation::TextField#hwnd
37
+ def hwnd
38
+ Functions.control_hwnd(@window.hwnd, @locators)
39
+ end
40
+
41
+ def exist?
42
+ @locators[:id].nil? ? super : super && matches_type(Constants::UIA_EDIT_CONTROL_TYPE)
43
+ end
44
+
45
+ alias_method :exists?, :exist?
46
+
47
+
48
+
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,226 @@
1
+ module RAutomation
2
+ module Adapter
3
+ module WinFfi
4
+ autoload :UiaDll, File.dirname(__FILE__) + "/ms_uia/uia_dll"
5
+
6
+ class Window
7
+ include WaitHelper
8
+ include Locators
9
+ extend ElementCollections
10
+
11
+ has_many :controls
12
+
13
+ class << self
14
+ def oleacc_module_handle
15
+ @oleacc_module_handle ||= begin
16
+ oleacc = Functions.load_library "oleacc.dll"
17
+ Functions.co_initialize nil
18
+ oleacc
19
+ end
20
+ end
21
+ end
22
+
23
+ # Locators of the window.
24
+ attr_reader :locators
25
+
26
+ # Possible locators are :title, :text, :hwnd, :pid, :class and :index.
27
+
28
+ # Creates the window object.
29
+ # @note this method is not meant to be accessed directly, but only through {RAutomation::Window#initialize}!
30
+ # @param [Hash] locators for searching the window.
31
+ # @option locators [String, Regexp] :title Title of the window
32
+ # @option locators [String, Regexp] :text Visible text of the window
33
+ # @option locators [String, Regexp] :class Internal class name of the window
34
+ # @option locators [String, Fixnum] :hwnd Window handle in decimal format
35
+ # @option locators [String, Fixnum] :pid Window process ID (PID)
36
+ # @option locators [String, Fixnum] :index 0-based index to specify n-th window if all other criteria match
37
+ # all other criteria match
38
+ # @see RAutomation::Window#initialize
39
+ def initialize(locators)
40
+ extract(locators)
41
+ end
42
+
43
+ # Retrieves handle of the window.
44
+ # @note Searches only for visible windows.
45
+ # @see RAutomation::Window#hwnd
46
+ def hwnd
47
+ @hwnd ||= Functions.window_hwnd(@locators)
48
+ end
49
+
50
+ # @see RAutomation::Window#pid
51
+ def pid
52
+ Functions.window_pid(hwnd)
53
+ end
54
+
55
+ # @see RAutomation::Window#title
56
+ def title
57
+ Functions.window_title(hwnd)
58
+ end
59
+
60
+ # @see RAutomation::Window#activate
61
+ def activate
62
+ return if !exists? || active?
63
+ restore if minimized?
64
+ Functions.activate_window(hwnd)
65
+ sleep 1
66
+ end
67
+
68
+ # @see RAutomation::Window#active?
69
+ def active?
70
+ exists? && Functions.foreground_window == hwnd
71
+ end
72
+
73
+ # @see RAutomation::Window#text
74
+ def text
75
+ Functions.window_text(hwnd)
76
+ end
77
+
78
+ # @see RAutomation::Window#exists?
79
+ def exists?
80
+ result = hwnd && Functions.window_exists(hwnd)
81
+ !!result
82
+ end
83
+
84
+ # @see RAutomation::Window#visible?
85
+ def visible?
86
+ Functions.window_visible(hwnd)
87
+ end
88
+
89
+ # @see RAutomation::Window#maximize
90
+ def maximize
91
+ Functions.show_window(hwnd, Constants::SW_MAXIMIZE)
92
+ sleep 1
93
+ end
94
+
95
+ # @see RAutomation::Window#minimize
96
+ def minimize
97
+ Functions.show_window(hwnd, Constants::SW_MINIMIZE)
98
+ sleep 1
99
+ end
100
+
101
+ # @see RAutomation::Window#minimized?
102
+ def minimized?
103
+ Functions.minimized(hwnd)
104
+ end
105
+
106
+ # @see RAutomation::Window#restore
107
+ def restore
108
+ Functions.show_window(hwnd, Constants::SW_RESTORE)
109
+ sleep 1
110
+ end
111
+
112
+ # Activates the window and sends keys to it.
113
+ #
114
+ # Refer to KeystrokeConverter#convert_special_characters for the special keycodes.
115
+ # @see RAutomation::Window#send_keys
116
+ def send_keys(keys)
117
+ shift_pressed = false
118
+ KeystrokeConverter.convert(keys).each do |key|
119
+ wait_until do
120
+ activate
121
+ active?
122
+ end
123
+ press_key key
124
+
125
+ if key == Constants::VK_LSHIFT
126
+ shift_pressed = true
127
+ next
128
+ end
129
+
130
+ release_key key
131
+
132
+ if shift_pressed
133
+ shift_pressed = false
134
+ release_key Constants::VK_LSHIFT
135
+ end
136
+ end
137
+ end
138
+
139
+ # @see RAutomation::Window#close
140
+ def close
141
+ Functions.close_window(hwnd)
142
+ end
143
+
144
+ # @see Button#initialize
145
+ # @see RAutomation::Window#button
146
+ def button(locator)
147
+ Button.new(self, locator)
148
+ end
149
+
150
+ # @see TextField#initialize
151
+ # @see RAutomation::Window#text_field
152
+ def text_field(locator)
153
+ TextField.new(self, locator)
154
+ end
155
+
156
+ def label(locator)
157
+ Label.new(self, locator)
158
+ end
159
+
160
+ def control(locator)
161
+ Control.new(self, locator)
162
+ end
163
+
164
+ def controls(locator)
165
+ Controls.new(self, locator)
166
+ end
167
+
168
+ def list_box(locator)
169
+ ListBox.new(self, locator)
170
+ end
171
+
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
176
+ end
177
+
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
189
+
190
+ def radio(locator)
191
+ wait_until_exists
192
+ RAutomation::Adapter::WinFfi::Radio.new(@window, locator)
193
+ end
194
+
195
+ def table(locator)
196
+ wait_until_exists
197
+ RAutomation::Adapter::WinFfi::Table.new(@window, locator)
198
+ end
199
+
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
210
+ end
211
+
212
+ private
213
+
214
+ def press_key key
215
+ Functions.send_key(key, 0, 0, nil)
216
+ sleep 0.01
217
+ end
218
+
219
+ def release_key key
220
+ Functions.send_key(key, 0, Constants::KEYEVENTF_KEYUP, nil)
221
+ sleep 0.1
222
+ end
223
+ end
224
+ end
225
+ end
226
+ end