watir 1.6.2 → 1.6.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (178) hide show
  1. data/CHANGES +326 -188
  2. data/bin/watir-console +7 -8
  3. data/lib/changes.rb +3 -3
  4. data/lib/license.rb +38 -38
  5. data/lib/readme.rb +140 -140
  6. data/lib/watir/WindowHelper.rb +49 -49
  7. data/lib/watir/camel_case.rb +66 -45
  8. data/lib/watir/clickJSDialog.rb +19 -19
  9. data/lib/watir/close_all.rb +37 -37
  10. data/lib/watir/collections.rb +344 -312
  11. data/lib/watir/container.rb +815 -753
  12. data/lib/watir/contrib/enabled_popup.rb +20 -20
  13. data/lib/watir/contrib/ie-new-process.rb +27 -27
  14. data/lib/watir/contrib/page_checker.rb +29 -29
  15. data/lib/watir/cookiemanager.rb +55 -55
  16. data/lib/watir/core_ext.rb +18 -0
  17. data/lib/watir/datahandler.rb +107 -107
  18. data/lib/watir/dialog.rb +46 -46
  19. data/lib/watir/element.rb +343 -312
  20. data/lib/watir/element_collections.rb +97 -81
  21. data/lib/watir/form.rb +170 -170
  22. data/lib/watir/frame.rb +59 -59
  23. data/lib/watir/ie-class.rb +1009 -1003
  24. data/lib/watir/ie-process.rb +39 -39
  25. data/lib/watir/ie.rb +133 -132
  26. data/lib/watir/image.rb +130 -130
  27. data/lib/watir/input_elements.rb +572 -539
  28. data/lib/watir/irb-history.rb +30 -30
  29. data/lib/watir/link.rb +64 -64
  30. data/lib/watir/locator.rb +176 -161
  31. data/lib/watir/logger.rb +19 -19
  32. data/lib/watir/modal_dialog.rb +122 -122
  33. data/lib/watir/non_control_elements.rb +145 -127
  34. data/lib/watir/page-container.rb +107 -105
  35. data/lib/watir/popup.rb +29 -29
  36. data/lib/watir/process.rb +19 -19
  37. data/lib/watir/screen_capture.rb +115 -115
  38. data/lib/watir/setFileDialog.rb +16 -16
  39. data/lib/watir/table.rb +362 -362
  40. data/lib/watir/utils.rb +19 -19
  41. data/lib/watir/version.rb +5 -5
  42. data/lib/watir/watir_simple.rb +475 -475
  43. data/lib/watir/win32.rb +35 -28
  44. data/lib/watir/win32ole.rb +14 -6
  45. data/lib/watir/winClicker.rb +496 -479
  46. data/unittests/all_tests.rb +10 -10
  47. data/unittests/buttons_xpath_test.rb +69 -69
  48. data/unittests/checkbox_test.rb +179 -176
  49. data/unittests/checkbox_xpath_test.rb +107 -107
  50. data/unittests/core_tests.rb +17 -16
  51. data/unittests/css_test.rb +35 -35
  52. data/unittests/defer_test.rb +46 -46
  53. data/unittests/dialog_test.rb +77 -77
  54. data/unittests/div2_xpath_test.rb +21 -21
  55. data/unittests/div_test.rb +188 -183
  56. data/unittests/div_xpath_test.rb +96 -96
  57. data/unittests/errorchecker_test.rb +22 -22
  58. data/unittests/filefield_test.rb +39 -40
  59. data/unittests/filefield_xpath_test.rb +33 -33
  60. data/unittests/form_test.rb +280 -293
  61. data/unittests/form_xpath_test.rb +252 -253
  62. data/unittests/frame_test.rb +155 -157
  63. data/unittests/google_form_test.rb +15 -15
  64. data/unittests/html/JavascriptClick.html +39 -39
  65. data/unittests/html/blankpage.html +11 -11
  66. data/unittests/html/buttons1.html +40 -40
  67. data/unittests/html/checkboxes1.html +89 -89
  68. data/unittests/html/complex_table.html +36 -36
  69. data/unittests/html/cssTest.html +42 -42
  70. data/unittests/html/depot_store.html +51 -51
  71. data/unittests/html/div.html +93 -93
  72. data/unittests/html/div_xml.html +20 -20
  73. data/unittests/html/fileupload.html +45 -45
  74. data/unittests/html/formTest1.html +38 -38
  75. data/unittests/html/forms2.html +44 -44
  76. data/unittests/html/forms3.html +131 -131
  77. data/unittests/html/forms4.html +27 -27
  78. data/unittests/html/frame_buttons.html +3 -3
  79. data/unittests/html/frame_links.html +3 -3
  80. data/unittests/html/frame_multi.html +4 -4
  81. data/unittests/html/google_india.html +107 -107
  82. data/unittests/html/iframeTest.html +12 -12
  83. data/unittests/html/iframeTest1.html +6 -6
  84. data/unittests/html/iframeTest2.html +5 -5
  85. data/unittests/html/images1.html +66 -66
  86. data/unittests/html/javascriptevents.html +35 -35
  87. data/unittests/html/link_pass.html +10 -10
  88. data/unittests/html/links1.html +38 -38
  89. data/unittests/html/links2.html +10 -10
  90. data/unittests/html/links_multi.html +14 -14
  91. data/unittests/html/list_matters.html +720 -720
  92. data/unittests/html/lists.html +17 -17
  93. data/unittests/html/map_test.html +31 -31
  94. data/unittests/html/modal_dialog.html +10 -10
  95. data/unittests/html/modal_dialog_launcher.html +11 -11
  96. data/unittests/html/nestedFrames.html +6 -6
  97. data/unittests/html/new_browser.html +16 -16
  98. data/unittests/html/pass.html +12 -12
  99. data/unittests/html/popups1.html +59 -59
  100. data/unittests/html/pre.html +27 -27
  101. data/unittests/html/radioButtons1.html +71 -71
  102. data/unittests/html/select_tealeaf.html +54 -54
  103. data/unittests/html/selectboxes1.html +52 -55
  104. data/unittests/html/simple_table.html +26 -26
  105. data/unittests/html/simple_table_buttons.html +104 -104
  106. data/unittests/html/simple_table_columns.html +76 -76
  107. data/unittests/html/table1.html +181 -181
  108. data/unittests/html/tableCell_using_xpath.html +19 -19
  109. data/unittests/html/textarea.html +30 -30
  110. data/unittests/html/textfields1.html +88 -88
  111. data/unittests/html/textsearch.html +44 -44
  112. data/unittests/html/wallofcheckboxes.html +1003 -1003
  113. data/unittests/html/xpath_nbsp.html +12 -12
  114. data/unittests/ie_exists_test.rb +33 -33
  115. data/unittests/ie_mock.rb +94 -94
  116. data/unittests/ie_test.rb +51 -50
  117. data/unittests/images_test.rb +157 -157
  118. data/unittests/images_xpath_test.rb +91 -91
  119. data/unittests/links_multi_test.rb +48 -48
  120. data/unittests/links_test.rb +175 -177
  121. data/unittests/links_xpath_test.rb +39 -39
  122. data/unittests/map_test.rb +98 -98
  123. data/unittests/minmax_test.rb +31 -31
  124. data/unittests/navigate_test.rb +39 -39
  125. data/unittests/nbsp_xpath_test.rb +16 -16
  126. data/unittests/non_core_tests.rb +12 -12
  127. data/unittests/other/WindowLogonExample.rb +27 -27
  128. data/unittests/other/WindowLogonExtra.rb +6 -6
  129. data/unittests/other/all_tests_concurrent.rb +57 -57
  130. data/unittests/{windows → other}/jscriptExtraAlert.rb +6 -6
  131. data/unittests/{windows → other}/jscriptExtraConfirmCancel.rb +6 -6
  132. data/unittests/{windows → other}/jscriptExtraConfirmOk.rb +6 -6
  133. data/unittests/{windows → other}/jscriptPushButton.rb +6 -6
  134. data/unittests/{windows → other}/jscript_test.rb +63 -63
  135. data/unittests/other/navigate_exception_test.rb +24 -24
  136. data/unittests/other/rexml_unit_test.rb +27 -24
  137. data/unittests/other/screen_capture_test.rb +54 -54
  138. data/unittests/other/testcase_method_order_test.rb +35 -35
  139. data/unittests/other/testcase_verify_test.rb +24 -24
  140. data/unittests/other/wait_until_test.rb +99 -99
  141. data/unittests/pagecontainstext_test.rb +69 -69
  142. data/unittests/parent_child_test.rb +43 -43
  143. data/unittests/perf_test.rb +20 -20
  144. data/unittests/popups_test.rb +43 -43
  145. data/unittests/pre_test.rb +53 -53
  146. data/unittests/radios_test.rb +212 -212
  147. data/unittests/radios_xpath_test.rb +101 -101
  148. data/unittests/security_setting_test.rb +23 -23
  149. data/unittests/selectbox_test.rb +148 -139
  150. data/unittests/selectbox_xpath_test.rb +113 -113
  151. data/unittests/setup.rb +77 -75
  152. data/unittests/speed_settings_test.rb +67 -65
  153. data/unittests/table_cell_using_xpath_test.rb +35 -35
  154. data/unittests/table_test.rb +376 -362
  155. data/unittests/table_xpath_test.rb +110 -110
  156. data/unittests/test_tests.rb +9 -9
  157. data/unittests/textarea_test.rb +92 -92
  158. data/unittests/textarea_xpath_test.rb +78 -78
  159. data/unittests/textfield_for_ch_char_test.rb +31 -29
  160. data/unittests/textfields_test.rb +218 -218
  161. data/unittests/textfields_xpath_test.rb +111 -111
  162. data/unittests/window_tests.rb +10 -7
  163. data/unittests/windows/attach_to_existing_window_test.rb +53 -52
  164. data/unittests/windows/attach_to_new_window_test.rb +83 -82
  165. data/unittests/windows/close_window_test.rb +20 -20
  166. data/unittests/windows/frame_links_test.rb +25 -25
  167. data/unittests/windows/ie-each_test.rb +47 -47
  168. data/unittests/windows/iedialog_test.rb +54 -54
  169. data/unittests/windows/js_events_test.rb +55 -55
  170. data/unittests/windows/modal_dialog_test.rb +128 -126
  171. data/unittests/windows/new_test.rb +57 -55
  172. data/unittests/windows/open_close_test.rb +18 -18
  173. data/unittests/windows/send_keys_test.rb +33 -32
  174. data/unittests/xpath_tests.rb +10 -10
  175. metadata +20 -20
  176. data/lib/watir/contrib/visible.rb +0 -47
  177. data/unittests/iostring.rb +0 -30
  178. data/unittests/iostring_test.rb +0 -48
@@ -1,29 +1,36 @@
1
- module Watir
2
- module Win32
3
- # this will find the IEDialog.dll file in its build location
4
- @@iedialog_file = (File.expand_path(File.dirname(__FILE__) + '/..') + "/watir/IEDialog/Release/IEDialog.dll").gsub('/', '\\')
5
-
6
- GetUnknown = Win32API.new(@@iedialog_file, 'GetUnknown', ['l', 'p'], 'v')
7
- User32 = DL.dlopen('user32')
8
- FindWindowEx = User32['FindWindowEx', 'LLLpp']
9
- # method for this found in wet-winobj/wet/winobjects/WinUtils.rb
10
- GetWindow = User32['GetWindow', 'ILL']
11
-
12
- ## GetWindows Constants
13
- GW_HWNDFIRST = 0
14
- GW_HWNDLAST = 1
15
- GW_HWNDNEXT = 2
16
- GW_HWNDPREV = 3
17
- GW_OWNER = 4
18
- GW_CHILD = 5
19
- GW_ENABLEDPOPUP = 6
20
- GW_MAX = 6
21
-
22
- IsWindow = User32['IsWindow', 'II']
23
- # Does the window with the specified window handle (hwnd) exist?
24
- def self.window_exists? hwnd
25
- rtn, junk = IsWindow[hwnd]
26
- rtn == 1
27
- end
28
- end
1
+ module Watir
2
+ module Win32
3
+ # this will find the IEDialog.dll file in its build location
4
+ @@iedialog_file = (File.expand_path(File.dirname(__FILE__) + '/..') + "/watir/IEDialog/Release/IEDialog.dll").gsub('/', '\\')
5
+
6
+ GetUnknown = Win32API.new(@@iedialog_file, 'GetUnknown', ['l', 'p'], 'v')
7
+ User32 = DL.dlopen('user32')
8
+ if RUBY_VERSION =~ /^1\.8/
9
+ FindWindowEx = User32['FindWindowEx', 'LLLpp']
10
+ # method for this found in wet-winobj/wet/winobjects/WinUtils.rb
11
+ GetWindow = User32['GetWindow', 'ILL']
12
+ IsWindow = User32['IsWindow', 'II']
13
+ else
14
+ FindWindowEx = GetWindow = IsWindow = lambda do |*args|
15
+ raise NotImplementedError, "1.9's DL API not compatible with 1.8, see http://www.ruby-forum.com/topic/138277"
16
+ end
17
+ end
18
+
19
+ ## GetWindows Constants
20
+ GW_HWNDFIRST = 0
21
+ GW_HWNDLAST = 1
22
+ GW_HWNDNEXT = 2
23
+ GW_HWNDPREV = 3
24
+ GW_OWNER = 4
25
+ GW_CHILD = 5
26
+ GW_ENABLEDPOPUP = 6
27
+ GW_MAX = 6
28
+
29
+
30
+ # Does the window with the specified window handle (hwnd) exist?
31
+ def self.window_exists? hwnd
32
+ rtn, junk = IsWindow[hwnd]
33
+ rtn == 1
34
+ end
35
+ end
29
36
  end
@@ -1,6 +1,14 @@
1
- # load the correct version of win32ole
2
-
3
- # Use our modified win32ole library
4
- $LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), '..', 'watir', 'win32ole'))
5
- require 'win32ole'
6
-
1
+ # load the correct version of win32ole
2
+
3
+ # Use our modified win32ole library
4
+
5
+ if RUBY_VERSION =~ /^1\.8/
6
+ $LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), '..', 'watir', 'win32ole'))
7
+ else
8
+ # loading win32ole from stdlib on 1.9
9
+ end
10
+
11
+
12
+ require 'win32ole'
13
+
14
+ WIN32OLE.codepage = WIN32OLE::CP_UTF8
@@ -1,479 +1,496 @@
1
- =begin
2
- license
3
- ---------------------------------------------------------------------------
4
- Copyright (c) 2004-2006, Paul Rogers and Bret Pettichord
5
- All rights reserved.
6
-
7
- Redistribution and use in source and binary forms, with or without
8
- modification, are permitted provided that the following conditions are met:
9
-
10
- 1. Redistributions of source code must retain the above copyright notice,
11
- this list of conditions and the following disclaimer.
12
-
13
- 2. Redistributions in binary form must reproduce the above copyright
14
- notice, this list of conditions and the following disclaimer in the
15
- documentation and/or other materials provided with the distribution.
16
-
17
- 3. Neither the names Paul Rogers, nor Bret Pettichord nor the names of any
18
- other contributors to this software may be used to endorse or promote
19
- products derived from this software without specific prior written
20
- permission.
21
-
22
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
23
- IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24
- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25
- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
26
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29
- OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31
- OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
- --------------------------------------------------------------------------
34
- (based on BSD Open Source License)
35
- =end
36
-
37
- =begin rdoc
38
- This is Watir's window clicker helper class, uses Win32 api
39
- calls to access buttons and windows.
40
-
41
- Typical usage:
42
- # include this file in your script
43
- require "watir/winClicker.rb"
44
-
45
- # create a new instance of WinClicker and use it
46
- wc = WinClicker.new
47
- wc.clickWindowsButton("My Window", "Click Me", 30)
48
-
49
- =end
50
-
51
- #
52
- # class to click javascript dialog boxes, file requester dialogs etc
53
- require 'dl/import'
54
- require 'dl/struct'
55
- require "timeout"
56
- require 'Win32API'
57
-
58
- class WinClicker
59
-
60
- WM_CLOSE = 0x0010
61
- WM_KEYDOWN = 0x0100
62
- WM_KEYUP = 0x0101
63
- WM_CHAR = 0x0102
64
- BM_CLICK = 0x00F5
65
- WM_COMMAND = 0x0111
66
- WM_SETTEXT = 0x000C
67
- WM_GETTEXT = 0x000D
68
-
69
- HWND_TOP = 0
70
- HWND_BOTTOM = 1
71
- HWND_TOPMOST = -1
72
- HWND_NOTOPMOST = -2
73
-
74
- SWP_SHOWWINDOW = 0x40
75
- SWP_NOSIZE = 1
76
- SWP_NOMOVE = 2
77
-
78
- TRUE_1 = 1
79
-
80
- # these are constants for commonly used windows windows
81
- WINCLASS_DIALOG = "32770"
82
-
83
- # these are the most used methods
84
-
85
- def initialize
86
- @User32 = DL.dlopen("user32")
87
- # we must determine the path we are in
88
- @path_to_clicker = '"' + File.expand_path(File.dirname(__FILE__)) + '"'
89
- end
90
-
91
-
92
- # The system function passes command to the command interpreter, which executes the string as an operating-system command
93
- # http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/_crt_system.2c_._wsystem.asp
94
- # using win32api
95
- def winsystem(command)
96
- pid = Win32API.new("crtdll", "system", ['P'], 'L').Call(command)
97
- end
98
-
99
- # returns the short path version of a long path
100
- # 8.3 style
101
- def getShortFileName(longName)
102
- size = 255
103
- buffer = " " * 255
104
- returnSize = Win32API.new("kernel32" , "GetShortPathNameA" , 'ppl' , 'L').Call(longName , buffer , size )
105
- a = ""
106
- a = a + buffer[0...returnSize]
107
- return a
108
- end
109
-
110
- # Set the first edit box in the Choose file dialog to textToSet
111
- # we may need to play with the default try count. 3 is a reasonably safe value.
112
- def setFileRequesterFileName( textToSet, tryCount = 3 )
113
- for i in (1..tryCount)
114
- # first set the Choose File Window to be active
115
- hWnd = getWindowHandle("Choose file" )
116
- if hWnd != -1
117
- makeWindowActive(hWnd)
118
- setTextValueForFileNameField( hWnd , textToSet)
119
- clickWindowsButton_hwnd(hWnd, "&Open")
120
- return true
121
- end
122
- end
123
- return false
124
- end
125
-
126
- # fire off setting the file name for the Choose file dialog
127
- # in a new process
128
- def setFileRequesterFileName_newProcess ( textToSet )
129
- myapp = "rubyw #{@path_to_clicker}/setFileDialog.rb #{textToSet}"
130
- # first argument to system call is a window title, in this case blank ""
131
- winsystem( "start \"\" #{myapp}" )
132
- end
133
-
134
- # Return the text value from the first combo box
135
- # on the Choose file dialog or nil if not found
136
- def getFileRequesterFileName()
137
- # first set the Choose File Window to be active
138
- hWnd = getWindowHandle("Choose file" )
139
- if hWnd != -1
140
- makeWindowActive(hWnd)
141
- return getTextValueForFileNameField( hWnd )
142
- else
143
- return nil
144
- end
145
- end
146
-
147
- # Click on a dialog with title of "Internet Explorer"
148
- # Default button to click is "OK"
149
- # parenthWnd not used
150
- def clickJavaScriptDialog(button="OK" , parenthWnd = -1)
151
- clickWindowsButton("Internet Explorer" , button )
152
- end
153
-
154
- # Calls system to launch a new process to click on the button
155
- # defaults to "OK" button
156
- def clickJSDialog_NewProcess(button = "OK" )
157
- myapp = "rubyw #{@path_to_clicker}/clickJSDialog.rb #{button}"
158
- log "Starting win clicker in a new process. Looking for button #{button}"
159
- log "Starting app: #{myapp}"
160
- # first argument to system call is a window title, in this case blank ""
161
- winsystem( "start \"\" #{myapp}" )
162
- end
163
-
164
-
165
- # as a thread
166
- def clickJSDialog_Thread(button = "OK" )
167
- sleep 3
168
- n = 0
169
- while n < 3
170
- sleep 1
171
- clickWindowsButton("Internet Explorer" , button )
172
- n=n+1
173
- end
174
- end
175
-
176
- # Looks for a window titled "Security Alert", clicks
177
- # on Yes button
178
- def clearSecurityAlertBox
179
- clickWindowsButton("Security Alert" , "&Yes" )
180
- end
181
- alias :clear_security_alert :clearSecurityAlertBox
182
-
183
- # Returns the parent handle for the given child handle
184
- def getParent (childhWnd )
185
- # pass a hWnd into this function and it will return the parent hWnd
186
- getParentWindow = @User32['GetParent' , 'II' ]
187
- a , b = getParentWindow.call(childhWnd )
188
- return a
189
- end
190
- alias :get_parent :getParent
191
-
192
- # Enumerates open windows and
193
- # returns a window handle from a given title and window class
194
- # Window class and title are matched regexes
195
- def getWindowHandle(title, winclass = "" )
196
- enum_windows = @User32['EnumWindows', 'IPL']
197
- get_class_name = @User32['GetClassName', 'ILpI']
198
- get_caption_length = @User32['GetWindowTextLengthA' ,'LI' ] # format here - return value type (Long) followed by parameter types - int in this case - see http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/~checkout~/ruby/ext/dl/doc/dl.txt?
199
- get_caption = @User32['GetWindowTextA', 'iLsL' ]
200
-
201
- len = 32
202
- buff = " " * len
203
- classMatch = false
204
-
205
- bContinueEnum = -1 # Windows "true" to continue enum_windows.
206
- found_hwnd = -1
207
- enum_windows_proc = DL.callback('ILL') {|hwnd,lparam|
208
- sleep 0.05
209
- r,rs = get_class_name.call(hwnd, buff, buff.size)
210
-
211
- if winclass != "" then
212
- if /#{winclass}/ =~ rs[1].to_s
213
- classMatch = true
214
- end
215
- else
216
- classMatch = true
217
- end
218
-
219
- if classMatch ==true
220
- textLength, a = get_caption_length.call(hwnd)
221
- captionBuffer = " " * (textLength+1)
222
- t , textCaption = get_caption.call(hwnd, captionBuffer , textLength+1)
223
- if /#{title}/ =~ textCaption[1].to_s
224
- found_hwnd = hwnd
225
- bContinueEnum = 0 # False, discontinue enum_windows
226
- end
227
- bContinueEnum
228
- else
229
- bContinueEnum
230
- end
231
- }
232
- r,rs = enum_windows.call(enum_windows_proc, 0)
233
- DL.remove_callback(enum_windows_proc)
234
- return found_hwnd
235
- end
236
- alias :get_window_handle :getWindowHandle
237
-
238
- # Call SwitchToThisWindow win32api which will
239
- # The SwitchToThisWindow function is called to switch focus to a specified window
240
- # and bring it to the foreground
241
- def makeWindowActive (hWnd)
242
- switch_to_window = @User32['SwitchToThisWindow' , 'pLI' ]
243
- # set it to be the one with focus
244
- switch_to_window.call(hWnd , 1)
245
- end
246
- alias :make_window_active :makeWindowActive
247
-
248
- # Posts a message to the handle passed in to click
249
- def clickButtonWithHandle(buttonhWnd)
250
- post_message = @User32['PostMessage', 'ILILL']
251
- r,rs = post_message.call(buttonhWnd, BM_CLICK, 0, 0)
252
- end
253
- alias :click_button_with_handle :clickButtonWithHandle
254
-
255
- # Based on the parent window handle passed in,
256
- # click on the button with the given caption.
257
- def clickWindowsButton_hwnd (hwnd , buttonCaption )
258
- makeWindowActive(hwnd)
259
- d = getChildHandle( hwnd , buttonCaption )
260
- if d != -1
261
- makeWindowActive(hwnd)
262
- clickButtonWithHandle(d)
263
- else
264
- return false
265
- end
266
- return true
267
- end
268
- alias :click_windows_button_hwnd :clickWindowsButton_hwnd
269
-
270
- # this clicks the button with the name in the window with the caption. It keeps looking for the button until
271
- # until the timeout expires
272
- def clickWindowsButton (windowCaption , buttonCaption , maxWaitTime=30 )
273
- sleep 1
274
- hwnd = -1
275
- begin
276
- timeout(maxWaitTime) do
277
- hwnd = getWindowHandle(windowCaption)
278
- while hwnd == -1
279
- hwnd = getWindowHandle(windowCaption)
280
- sleep 0.5
281
- end
282
- makeWindowActive(hwnd)
283
- end
284
- rescue
285
- return false
286
- end
287
- if hwnd != -1
288
- makeWindowActive(hwnd)
289
- else
290
- end
291
- d = getChildHandle( hwnd , buttonCaption )
292
- if d != -1
293
- makeWindowActive(hwnd)
294
- clickButtonWithHandle(d)
295
- else
296
- return false
297
- end
298
- return true
299
- end
300
- alias :click_windows_button :clickWindowsButton
301
-
302
- # Enumerate through children of the parent hwnd, pass back
303
- # the handle for the control with the given caption
304
- # the caption is compared as a regex
305
- def getChildHandle ( hWnd , childCaption )
306
- enum_childWindows = @User32['EnumChildWindows' , 'IIPL' ]
307
- get_caption_length = @User32['GetWindowTextLengthA' ,'LI' ] # format here - return value type (Long) followed by parameter types - int in this case - see http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/~checkout~/ruby/ext/dl/doc/dl.txt?
308
- get_caption = @User32['GetWindowTextA', 'iLsL' ]
309
- match_hwnd = -1 # hWnd of handle matching childCaption
310
- buff = " " * 16
311
- get_class_name = @User32['GetClassName', 'ILpI']
312
-
313
- bContinueEnum = -1
314
- enum_childWindows_proc = DL.callback('ILL') {|chwnd,lparam|
315
- r,rs = get_class_name.call(chwnd, buff, buff.size)
316
- textLength, a = get_caption_length.call(chwnd)
317
- captionBuffer = " " * (textLength+1)
318
-
319
- t , textCaption = get_caption.call(chwnd, captionBuffer , textLength+1)
320
- if /#{childCaption}/ =~ textCaption[1].to_s then
321
- match_hwnd = chwnd
322
- bContinueEnum = 0 # Windows "false" to discontinue enum_childWindow
323
- end
324
- bContinueEnum
325
- }
326
- r = enum_childWindows.call(hWnd, enum_childWindows_proc ,0)
327
- DL.remove_callback(enum_childWindows_proc)
328
- return match_hwnd
329
- end
330
- alias :get_chwnd :getChildHandle
331
-
332
- # Convenience method to return Static text for
333
- # children of the window with the given caption
334
- def getStaticText(caption)
335
- return getStaticTextFromWindow(caption, -1)
336
- end
337
- alias :get_static_text :getStaticText
338
-
339
- # Convenience method to return Static text for
340
- # children of the window handle
341
- def getStaticText_hWnd (hWnd)
342
- return getStaticTextFromWindow("" , hWnd)
343
- end
344
- alias :get_static_text_hwnd :getStaticText_hWnd
345
-
346
- # Return text as an array from child controls of the window
347
- # given as either a handle or with the given caption
348
- # that have a class type of Static
349
- def getStaticTextFromWindow( windowCaption , hWnd)
350
- enum_childWindows = @User32['EnumChildWindows' , 'IIPL' ]
351
- get_caption_length = @User32['GetWindowTextLengthA' ,'LI' ] # format here - return value type (Long) followed by parameter types - int in this case - see http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/~checkout~/ruby/ext/dl/doc/dl.txt?
352
- get_caption = @User32['GetWindowTextA', 'iLsL' ]
353
-
354
- staticText = []
355
- buff = " " * 16
356
- get_class_name = @User32['GetClassName', 'ILpI']
357
-
358
- if hWnd == -1
359
- hWnd = getWindowHandle(windowCaption)
360
- end
361
-
362
- if hWnd == -1
363
- return staticText
364
- end
365
-
366
- bContinueEnum = -1
367
- enum_childWindows_proc = DL.callback('ILL') {|hWnd,lparam|
368
- r,rs = get_class_name.call(hWnd, buff, buff.size)
369
- if rs[1].to_s == "Static" # there must be a better way of detecting this
370
- textLength, a = get_caption_length.call(hWnd)
371
- captionBuffer = " " * (textLength+1)
372
- t , textCaption = get_caption.call(hWnd, captionBuffer , textLength+1)
373
- staticText << textCaption[1].to_s
374
- end
375
- bContinueEnum
376
- }
377
- r = enum_childWindows.call(hWnd, enum_childWindows_proc ,0)
378
- DL.remove_callback(enum_childWindows_proc)
379
- return staticText
380
- end
381
- alias :get_static_text_from_window :getStaticTextFromWindow
382
-
383
- # returns the handle (or -1 if its not found) of the
384
- # nth control of this class in the parent window specified
385
- # by the window handle
386
- def getHandleOfControl (hWnd , controlClass, position )
387
- enum_childWindows = @User32['EnumChildWindows' , 'IIPL' ]
388
- get_caption_length = @User32['GetWindowTextLengthA' ,'LI' ] # format here - return value type (Long) followed by parameter types - int in this case - see http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/~checkout~/ruby/ext/dl/doc/dl.txt?
389
- get_caption = @User32['GetWindowTextA', 'iLsL' ]
390
- control_hWnd = []
391
- buff = " " * 16
392
- get_class_name = @User32['GetClassName', 'ILpI']
393
-
394
- bContinueEnum = -1
395
- enum_childWindows_proc = DL.callback('ILL') {|hWnd,lparam|
396
- r,rs = get_class_name.call(hWnd, buff, buff.size)
397
- if rs[1].to_s == controlClass # there must be a better way of detecting this
398
- control_hWnd << hWnd
399
- end
400
- bContinueEnum
401
- }
402
- r = enum_childWindows.call(hWnd, enum_childWindows_proc ,0)
403
- DL.remove_callback(enum_childWindows_proc)
404
- controlHwnd = control_hWnd[position]
405
- if controlHwnd == nil then
406
- controlHwnd = -1
407
- end
408
- return controlHwnd
409
- end
410
- alias :get_handle_of_ctrl :getHandleOfControl
411
-
412
- # Call set text on the given window handle
413
- def setComboBoxText(hWnd , textToSet)
414
- set_text(hWnd, textToSet)
415
- end
416
- alias :set_combo_txt :setComboBoxText
417
-
418
- # Call set text on the given window handle
419
- def setTextBoxText(hWnd , textToSet)
420
- set_text(hWnd, textToSet)
421
- end
422
- alias :set_textbox_txt :setTextBoxText
423
-
424
- # Private method to set text called by the two methods above
425
- def set_text(hWnd, textToSet)
426
- send_message = @User32['SendMessage', 'ILISS']
427
- r ,rs = send_message.call(hWnd , WM_SETTEXT ,'',textToSet)
428
- end
429
- private :set_text
430
-
431
- # Get the text in the handle for the given control
432
- def getControlText(hWnd)
433
- buff = " " * 256
434
- send_message = @User32['SendMessage', 'ILIIS']
435
- r ,rs = send_message.call(hWnd , WM_GETTEXT , 256 , buff )
436
- return buff.to_s
437
- end
438
- alias :get_ctrl_txt :getControlText
439
-
440
- # get the title for the specified hwnd
441
- def getWindowTitle(hWnd)
442
- buff = " " * 256
443
- getWindowText = @User32['GetWindowText' , 'ILSI']
444
- r , rs = getWindowText.call( hWnd , buff , 256 )
445
- return buff.to_s
446
- end
447
- alias :get_win_title :getWindowTitle
448
-
449
- # Get the text in the first combo box
450
- # file requester methods returns nil on failure to
451
- # locate the 1st combobox
452
- def getTextValueForFileNameField(parenthWnd)
453
- f = getHandleOfControl(parenthWnd, "ComboBox", 1)
454
- if f == -1 then
455
- # unable to find the first combobox
456
- return nil
457
- else
458
- # we have the control and now
459
- # can send it some messages
460
- return getWinText(f )
461
- end
462
- end
463
- alias :get_file_name :getTextValueForFileNameField
464
-
465
- # this sets the filename field to text to set
466
- def setTextValueForFileNameField( parenthWnd , textToSet )
467
- # get the handle of the nth control that is an Edit box
468
- f = getHandleOfControl(parenthWnd, "Edit" , 0 )
469
- if f == -1 then
470
- # unable to get a handle on the first edit control
471
- return false
472
- else
473
- # we found the control and can now send it some messages
474
- setComboBoxText(f , textToSet)
475
- return true
476
- end
477
- end
478
- alias :set_file_name :setTextValueForFileNameField
479
- end
1
+ =begin
2
+ license
3
+ ---------------------------------------------------------------------------
4
+ Copyright (c) 2004-2006, Paul Rogers and Bret Pettichord
5
+ All rights reserved.
6
+
7
+ Redistribution and use in source and binary forms, with or without
8
+ modification, are permitted provided that the following conditions are met:
9
+
10
+ 1. Redistributions of source code must retain the above copyright notice,
11
+ this list of conditions and the following disclaimer.
12
+
13
+ 2. Redistributions in binary form must reproduce the above copyright
14
+ notice, this list of conditions and the following disclaimer in the
15
+ documentation and/or other materials provided with the distribution.
16
+
17
+ 3. Neither the names Paul Rogers, nor Bret Pettichord nor the names of any
18
+ other contributors to this software may be used to endorse or promote
19
+ products derived from this software without specific prior written
20
+ permission.
21
+
22
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
23
+ IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
26
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29
+ OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
+ --------------------------------------------------------------------------
34
+ (based on BSD Open Source License)
35
+ =end
36
+
37
+ =begin rdoc
38
+ This is Watir's window clicker helper class, uses Win32 api
39
+ calls to access buttons and windows.
40
+
41
+ Typical usage:
42
+ # include this file in your script
43
+ require "watir/winClicker.rb"
44
+
45
+ # create a new instance of WinClicker and use it
46
+ wc = WinClicker.new
47
+ wc.clickWindowsButton("My Window", "Click Me", 30)
48
+
49
+ =end
50
+
51
+ #
52
+ # class to click javascript dialog boxes, file requester dialogs etc
53
+ require 'dl/import'
54
+ require 'dl/struct'
55
+ require "timeout"
56
+ require 'Win32API'
57
+
58
+ class WinClicker
59
+
60
+ WM_CLOSE = 0x0010
61
+ WM_KEYDOWN = 0x0100
62
+ WM_KEYUP = 0x0101
63
+ WM_CHAR = 0x0102
64
+ BM_CLICK = 0x00F5
65
+ WM_COMMAND = 0x0111
66
+ WM_SETTEXT = 0x000C
67
+ WM_GETTEXT = 0x000D
68
+
69
+ HWND_TOP = 0
70
+ HWND_BOTTOM = 1
71
+ HWND_TOPMOST = -1
72
+ HWND_NOTOPMOST = -2
73
+
74
+ SWP_SHOWWINDOW = 0x40
75
+ SWP_NOSIZE = 1
76
+ SWP_NOMOVE = 2
77
+
78
+ TRUE_1 = 1
79
+
80
+ # these are constants for commonly used windows windows
81
+ WINCLASS_DIALOG = "32770"
82
+
83
+ # these are the most used methods
84
+
85
+ def initialize
86
+ @User32 = DL.dlopen("user32")
87
+ # we must determine the path we are in
88
+ @path_to_clicker = '"' + File.expand_path(File.dirname(__FILE__)) + '"'
89
+ end
90
+
91
+
92
+ # The system function passes command to the command interpreter, which executes the string as an operating-system command
93
+ # http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/_crt_system.2c_._wsystem.asp
94
+ # using win32api
95
+ def winsystem(command)
96
+ pid = Win32API.new("crtdll", "system", ['P'], 'L').Call(command)
97
+ end
98
+
99
+ # returns the short path version of a long path
100
+ # 8.3 style
101
+ def getShortFileName(longName)
102
+ size = 255
103
+ buffer = " " * 255
104
+ returnSize = Win32API.new("kernel32" , "GetShortPathNameA" , 'ppl' , 'L').Call(longName , buffer , size )
105
+ a = ""
106
+ a = a + buffer[0...returnSize]
107
+ return a
108
+ end
109
+
110
+ # Set the first edit box in the Choose file dialog to textToSet
111
+ # we may need to play with the default try count. 3 is a reasonably safe value.
112
+ def setFileRequesterFileName( textToSet, tryCount = 3 )
113
+ for i in (1..tryCount)
114
+ # first set the Choose File Window to be active
115
+ hWnd = getWindowHandle("Choose file" )
116
+ if hWnd != -1
117
+ makeWindowActive(hWnd)
118
+ setTextValueForFileNameField( hWnd , textToSet)
119
+ clickWindowsButton_hwnd(hWnd, "&Open")
120
+ return true
121
+ end
122
+ end
123
+ return false
124
+ end
125
+
126
+ # fire off setting the file name for the Choose file dialog
127
+ # in a new process
128
+ def setFileRequesterFileName_newProcess ( textToSet )
129
+ myapp = "rubyw #{@path_to_clicker}/setFileDialog.rb #{textToSet}"
130
+ # first argument to system call is a window title, in this case blank ""
131
+ winsystem( "start \"\" #{myapp}" )
132
+ end
133
+
134
+ # Return the text value from the first combo box
135
+ # on the Choose file dialog or nil if not found
136
+ def getFileRequesterFileName()
137
+ # first set the Choose File Window to be active
138
+ hWnd = getWindowHandle("Choose file" )
139
+ if hWnd != -1
140
+ makeWindowActive(hWnd)
141
+ return getTextValueForFileNameField( hWnd )
142
+ else
143
+ return nil
144
+ end
145
+ end
146
+
147
+ # Click on a dialog with title of "Internet Explorer"
148
+ # Default button to click is "OK"
149
+ # parenthWnd not used
150
+ def clickJavaScriptDialog(button="OK" , parenthWnd = -1)
151
+ clickWindowsButton("Internet Explorer" , button )
152
+ end
153
+
154
+ # Calls system to launch a new process to click on the button
155
+ # defaults to "OK" button
156
+ def clickJSDialog_NewProcess(button = "OK" )
157
+ myapp = "rubyw #{@path_to_clicker}/clickJSDialog.rb #{button}"
158
+ log "Starting win clicker in a new process. Looking for button #{button}"
159
+ log "Starting app: #{myapp}"
160
+ # first argument to system call is a window title, in this case blank ""
161
+ winsystem( "start \"\" #{myapp}" )
162
+ end
163
+
164
+
165
+ # as a thread
166
+ def clickJSDialog_Thread(button = "OK" )
167
+ sleep 3
168
+ n = 0
169
+ while n < 3
170
+ sleep 1
171
+ clickWindowsButton("Internet Explorer" , button )
172
+ n=n+1
173
+ end
174
+ end
175
+
176
+ # Looks for a window titled "Security Alert", clicks
177
+ # on Yes button
178
+ def clearSecurityAlertBox
179
+ clickWindowsButton("Security Alert" , "&Yes" )
180
+ end
181
+ alias :clear_security_alert :clearSecurityAlertBox
182
+
183
+ # Returns the parent handle for the given child handle
184
+ def getParent (childhWnd )
185
+ # pass a hWnd into this function and it will return the parent hWnd
186
+ getParentWindow = @User32['GetParent' , 'II' ]
187
+ a , b = getParentWindow.call(childhWnd )
188
+ return a
189
+ end
190
+ alias :get_parent :getParent
191
+
192
+ def with_dl_callback(type, prc)
193
+ callback = DL.callback(type, &prc)
194
+ error = nil
195
+ begin
196
+ yield callback
197
+ ensure
198
+ DL.remove_callback(callback)
199
+ end
200
+ end
201
+
202
+ # Enumerates open windows and
203
+ # returns a window handle from a given title and window class
204
+ # Window class and title are matched regexes
205
+ def getWindowHandle(title, winclass = "" )
206
+ enum_windows = @User32['EnumWindows', 'IPL']
207
+ get_class_name = @User32['GetClassName', 'ILpI']
208
+ get_caption_length = @User32['GetWindowTextLengthA' ,'LI' ] # format here - return value type (Long) followed by parameter types - int in this case - see http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/~checkout~/ruby/ext/dl/doc/dl.txt?
209
+ get_caption = @User32['GetWindowTextA', 'iLsL' ]
210
+
211
+ len = 32
212
+ buff = " " * len
213
+ classMatch = false
214
+
215
+ bContinueEnum = -1 # Windows "true" to continue enum_windows.
216
+ found_hwnd = -1
217
+
218
+ enum_windows_proc = lambda {|hwnd,lparam|
219
+ sleep 0.05
220
+ r,rs = get_class_name.call(hwnd, buff, buff.size)
221
+
222
+ if winclass != "" then
223
+ if /#{winclass}/ =~ rs[1].to_s
224
+ classMatch = true
225
+ end
226
+ else
227
+ classMatch = true
228
+ end
229
+
230
+ if classMatch ==true
231
+ textLength, a = get_caption_length.call(hwnd)
232
+ captionBuffer = " " * (textLength+1)
233
+ t , textCaption = get_caption.call(hwnd, captionBuffer , textLength+1)
234
+ if /#{title}/ =~ textCaption[1].to_s
235
+ found_hwnd = hwnd
236
+ bContinueEnum = 0 # False, discontinue enum_windows
237
+ end
238
+ bContinueEnum
239
+ else
240
+ bContinueEnum
241
+ end
242
+ }
243
+ with_dl_callback('ILL',enum_windows_proc) do |callback|
244
+ r,rs = enum_windows.call(callback, 0)
245
+ end
246
+ return found_hwnd
247
+ end
248
+ alias :get_window_handle :getWindowHandle
249
+
250
+ # Call SwitchToThisWindow win32api which will
251
+ # The SwitchToThisWindow function is called to switch focus to a specified window
252
+ # and bring it to the foreground
253
+ def makeWindowActive (hWnd)
254
+ switch_to_window = @User32['SwitchToThisWindow' , 'pLI' ]
255
+ # set it to be the one with focus
256
+ switch_to_window.call(hWnd , 1)
257
+ end
258
+ alias :make_window_active :makeWindowActive
259
+
260
+ # Posts a message to the handle passed in to click
261
+ def clickButtonWithHandle(buttonhWnd)
262
+ post_message = @User32['PostMessage', 'ILILL']
263
+ r,rs = post_message.call(buttonhWnd, BM_CLICK, 0, 0)
264
+ end
265
+ alias :click_button_with_handle :clickButtonWithHandle
266
+
267
+ # Based on the parent window handle passed in,
268
+ # click on the button with the given caption.
269
+ def clickWindowsButton_hwnd (hwnd , buttonCaption )
270
+ makeWindowActive(hwnd)
271
+ d = getChildHandle( hwnd , buttonCaption )
272
+ if d != -1
273
+ makeWindowActive(hwnd)
274
+ clickButtonWithHandle(d)
275
+ else
276
+ return false
277
+ end
278
+ return true
279
+ end
280
+ alias :click_windows_button_hwnd :clickWindowsButton_hwnd
281
+
282
+ # this clicks the button with the name in the window with the caption. It keeps looking for the button until
283
+ # until the timeout expires
284
+ def clickWindowsButton (windowCaption , buttonCaption , maxWaitTime=30 )
285
+ sleep 1
286
+ hwnd = -1
287
+ begin
288
+ timeout(maxWaitTime) do
289
+ hwnd = getWindowHandle(windowCaption)
290
+ while hwnd == -1
291
+ hwnd = getWindowHandle(windowCaption)
292
+ sleep 0.5
293
+ end
294
+ makeWindowActive(hwnd)
295
+ end
296
+ rescue Timeout::Error
297
+ return false
298
+ rescue => e
299
+ raise e
300
+ end
301
+ if hwnd != -1
302
+ makeWindowActive(hwnd)
303
+ else
304
+ end
305
+ d = getChildHandle( hwnd , buttonCaption )
306
+ if d != -1
307
+ makeWindowActive(hwnd)
308
+ clickButtonWithHandle(d)
309
+ else
310
+ return false
311
+ end
312
+ return true
313
+ end
314
+ alias :click_windows_button :clickWindowsButton
315
+
316
+ # Enumerate through children of the parent hwnd, pass back
317
+ # the handle for the control with the given caption
318
+ # the caption is compared as a regex
319
+ def getChildHandle ( hWnd , childCaption )
320
+ enum_childWindows = @User32['EnumChildWindows' , 'IIPL' ]
321
+ get_caption_length = @User32['GetWindowTextLengthA' ,'LI' ] # format here - return value type (Long) followed by parameter types - int in this case - see http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/~checkout~/ruby/ext/dl/doc/dl.txt?
322
+ get_caption = @User32['GetWindowTextA', 'iLsL' ]
323
+ match_hwnd = -1 # hWnd of handle matching childCaption
324
+ buff = " " * 16
325
+ get_class_name = @User32['GetClassName', 'ILpI']
326
+
327
+ bContinueEnum = -1
328
+ enum_childWindowsProc = lambda {|chwnd,lparam|
329
+ r,rs = get_class_name.call(chwnd, buff, buff.size)
330
+ textLength, a = get_caption_length.call(chwnd)
331
+ captionBuffer = " " * (textLength+1)
332
+
333
+ t , textCaption = get_caption.call(chwnd, captionBuffer , textLength+1)
334
+ if /#{childCaption}/ =~ textCaption[1].to_s then
335
+ match_hwnd = chwnd
336
+ bContinueEnum = 0 # Windows "false" to discontinue enum_childWindow
337
+ end
338
+ bContinueEnum
339
+ }
340
+ with_dl_callback('ILL',enum_childWindowsProc) do |callback|
341
+ r = enum_childWindows.call(hWnd, callback ,0)
342
+ end
343
+ return match_hwnd
344
+ end
345
+ alias :get_chwnd :getChildHandle
346
+
347
+ # Convenience method to return Static text for
348
+ # children of the window with the given caption
349
+ def getStaticText(caption)
350
+ return getStaticTextFromWindow(caption, -1)
351
+ end
352
+ alias :get_static_text :getStaticText
353
+
354
+ # Convenience method to return Static text for
355
+ # children of the window handle
356
+ def getStaticText_hWnd (hWnd)
357
+ return getStaticTextFromWindow("" , hWnd)
358
+ end
359
+ alias :get_static_text_hwnd :getStaticText_hWnd
360
+
361
+ # Return text as an array from child controls of the window
362
+ # given as either a handle or with the given caption
363
+ # that have a class type of Static
364
+ def getStaticTextFromWindow( windowCaption , hWnd)
365
+ enum_childWindows = @User32['EnumChildWindows' , 'IIPL' ]
366
+ get_caption_length = @User32['GetWindowTextLengthA' ,'LI' ] # format here - return value type (Long) followed by parameter types - int in this case - see http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/~checkout~/ruby/ext/dl/doc/dl.txt?
367
+ get_caption = @User32['GetWindowTextA', 'iLsL' ]
368
+
369
+ staticText = []
370
+ buff = " " * 16
371
+ get_class_name = @User32['GetClassName', 'ILpI']
372
+
373
+ if hWnd == -1
374
+ hWnd = getWindowHandle(windowCaption)
375
+ end
376
+
377
+ if hWnd == -1
378
+ return staticText
379
+ end
380
+
381
+ bContinueEnum = -1
382
+ enum_childWindows_proc = lambda {|hWnd,lparam|
383
+ r,rs = get_class_name.call(hWnd, buff, buff.size)
384
+ if rs[1].to_s == "Static" # there must be a better way of detecting this
385
+ textLength, a = get_caption_length.call(hWnd)
386
+ captionBuffer = " " * (textLength+1)
387
+ t , textCaption = get_caption.call(hWnd, captionBuffer , textLength+1)
388
+ staticText << textCaption[1].to_s
389
+ end
390
+ bContinueEnum
391
+ }
392
+ with_dl_callback('ILL',enum_childWindows_proc) do |callback|
393
+ r = enum_childWindows.call(hWnd, callback ,0)
394
+ end
395
+ return staticText
396
+ end
397
+ alias :get_static_text_from_window :getStaticTextFromWindow
398
+
399
+ # returns the handle (or -1 if its not found) of the
400
+ # nth control of this class in the parent window specified
401
+ # by the window handle
402
+ def getHandleOfControl (hWnd , controlClass, position )
403
+ enum_childWindows = @User32['EnumChildWindows' , 'IIPL' ]
404
+ get_caption_length = @User32['GetWindowTextLengthA' ,'LI' ] # format here - return value type (Long) followed by parameter types - int in this case - see http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/~checkout~/ruby/ext/dl/doc/dl.txt?
405
+ get_caption = @User32['GetWindowTextA', 'iLsL' ]
406
+ control_hWnd = []
407
+ buff = " " * 16
408
+ get_class_name = @User32['GetClassName', 'ILpI']
409
+
410
+ bContinueEnum = -1
411
+ enum_childWindows_proc = lambda {|hWnd,lparam|
412
+ r,rs = get_class_name.call(hWnd, buff, buff.size)
413
+ if rs[1].to_s == controlClass # there must be a better way of detecting this
414
+ control_hWnd << hWnd
415
+ end
416
+ bContinueEnum
417
+ }
418
+ with_dl_callback('ILL',enum_childWindows_proc) do |callback|
419
+ r = enum_childWindows.call(hWnd, callback ,0)
420
+ end
421
+ controlHwnd = control_hWnd[position]
422
+ if controlHwnd == nil then
423
+ controlHwnd = -1
424
+ end
425
+ return controlHwnd
426
+ end
427
+ alias :get_handle_of_ctrl :getHandleOfControl
428
+
429
+ # Call set text on the given window handle
430
+ def setComboBoxText(hWnd , textToSet)
431
+ set_text(hWnd, textToSet)
432
+ end
433
+ alias :set_combo_txt :setComboBoxText
434
+
435
+ # Call set text on the given window handle
436
+ def setTextBoxText(hWnd , textToSet)
437
+ set_text(hWnd, textToSet)
438
+ end
439
+ alias :set_textbox_txt :setTextBoxText
440
+
441
+ # Private method to set text called by the two methods above
442
+ def set_text(hWnd, textToSet)
443
+ send_message = @User32['SendMessage', 'ILISS']
444
+ r ,rs = send_message.call(hWnd , WM_SETTEXT ,'',textToSet)
445
+ end
446
+ private :set_text
447
+
448
+ # Get the text in the handle for the given control
449
+ def getControlText(hWnd)
450
+ buff = " " * 256
451
+ send_message = @User32['SendMessage', 'ILIIS']
452
+ r ,rs = send_message.call(hWnd , WM_GETTEXT , 256 , buff )
453
+ return buff.to_s
454
+ end
455
+ alias :get_ctrl_txt :getControlText
456
+
457
+ # get the title for the specified hwnd
458
+ def getWindowTitle(hWnd)
459
+ buff = " " * 256
460
+ getWindowText = @User32['GetWindowText' , 'ILSI']
461
+ r , rs = getWindowText.call( hWnd , buff , 256 )
462
+ return buff.to_s
463
+ end
464
+ alias :get_win_title :getWindowTitle
465
+
466
+ # Get the text in the first combo box
467
+ # file requester methods returns nil on failure to
468
+ # locate the 1st combobox
469
+ def getTextValueForFileNameField(parenthWnd)
470
+ f = getHandleOfControl(parenthWnd, "ComboBox", 1)
471
+ if f == -1 then
472
+ # unable to find the first combobox
473
+ return nil
474
+ else
475
+ # we have the control and now
476
+ # can send it some messages
477
+ return getWinText(f )
478
+ end
479
+ end
480
+ alias :get_file_name :getTextValueForFileNameField
481
+
482
+ # this sets the filename field to text to set
483
+ def setTextValueForFileNameField( parenthWnd , textToSet )
484
+ # get the handle of the nth control that is an Edit box
485
+ f = getHandleOfControl(parenthWnd, "Edit" , 0 )
486
+ if f == -1 then
487
+ # unable to get a handle on the first edit control
488
+ return false
489
+ else
490
+ # we found the control and can now send it some messages
491
+ setComboBoxText(f , textToSet)
492
+ return true
493
+ end
494
+ end
495
+ alias :set_file_name :setTextValueForFileNameField
496
+ end