watir 1.6.5 → 1.6.6.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (186) hide show
  1. data/CHANGES +461 -326
  2. data/VERSION +1 -0
  3. data/bin/watir-console +6 -6
  4. data/lib/changes.rb +3 -3
  5. data/lib/license.rb +38 -38
  6. data/lib/readme.rb +140 -140
  7. data/lib/watir/WindowHelper.rb +49 -49
  8. data/lib/watir/camel_case.rb +66 -66
  9. data/lib/watir/clickJSDialog.rb +19 -19
  10. data/lib/watir/close_all.rb +37 -37
  11. data/lib/watir/collections.rb +392 -344
  12. data/lib/watir/container.rb +857 -815
  13. data/lib/watir/contrib/enabled_popup.rb +20 -20
  14. data/lib/watir/contrib/ie-new-process.rb +27 -27
  15. data/lib/watir/contrib/page_checker.rb +29 -29
  16. data/lib/watir/cookiemanager.rb +55 -55
  17. data/lib/watir/core.rb +28 -0
  18. data/lib/watir/core_ext.rb +17 -17
  19. data/lib/watir/datahandler.rb +107 -107
  20. data/lib/watir/dialog.rb +46 -46
  21. data/lib/watir/element.rb +351 -343
  22. data/lib/watir/element_collections.rb +97 -97
  23. data/lib/watir/form.rb +170 -170
  24. data/lib/watir/frame.rb +59 -59
  25. data/lib/watir/html_element.rb +22 -0
  26. data/lib/watir/ie-class.rb +1006 -1009
  27. data/lib/watir/ie-process.rb +39 -39
  28. data/lib/watir/ie.rb +70 -133
  29. data/lib/watir/image.rb +130 -130
  30. data/lib/watir/input_elements.rb +614 -572
  31. data/lib/watir/irb-history.rb +30 -30
  32. data/lib/watir/link.rb +64 -64
  33. data/lib/watir/locator.rb +200 -176
  34. data/lib/watir/logger.rb +19 -19
  35. data/lib/watir/modal_dialog.rb +122 -122
  36. data/lib/watir/module.rb +37 -0
  37. data/lib/watir/non_control_elements.rb +145 -145
  38. data/lib/watir/page-container.rb +116 -107
  39. data/lib/watir/popup.rb +29 -29
  40. data/lib/watir/process.rb +19 -19
  41. data/lib/watir/screen_capture.rb +115 -115
  42. data/lib/watir/setFileDialog.rb +16 -16
  43. data/lib/watir/table.rb +395 -362
  44. data/lib/watir/watir_simple.rb +475 -475
  45. data/lib/watir/win32.rb +35 -35
  46. data/lib/watir/win32ole.rb +14 -14
  47. data/lib/watir/winClicker.rb +496 -496
  48. data/rakefile.rb +70 -0
  49. data/unittests/all_tests.rb +10 -10
  50. data/unittests/buttons_xpath_test.rb +69 -69
  51. data/unittests/checkbox_test.rb +179 -179
  52. data/unittests/checkbox_xpath_test.rb +107 -107
  53. data/unittests/click_no_wait_test.rb +21 -0
  54. data/unittests/core_tests.rb +17 -17
  55. data/unittests/css_test.rb +42 -35
  56. data/unittests/defer_test.rb +46 -46
  57. data/unittests/dialog_test.rb +77 -77
  58. data/unittests/div2_xpath_test.rb +21 -21
  59. data/unittests/div_test.rb +188 -188
  60. data/unittests/div_xpath_test.rb +96 -96
  61. data/unittests/element_test.rb +49 -0
  62. data/unittests/errorchecker_test.rb +32 -22
  63. data/unittests/filefield_test.rb +39 -39
  64. data/unittests/filefield_xpath_test.rb +33 -33
  65. data/unittests/form_test.rb +280 -280
  66. data/unittests/form_xpath_test.rb +252 -252
  67. data/unittests/frame_test.rb +155 -155
  68. data/unittests/google_form_test.rb +15 -15
  69. data/unittests/html/JavascriptClick.html +39 -39
  70. data/unittests/html/blankpage.html +11 -11
  71. data/unittests/html/buttons1.html +40 -40
  72. data/unittests/html/checkboxes1.html +89 -89
  73. data/unittests/html/click_no_wait.html +14 -0
  74. data/unittests/html/complex_table.html +36 -36
  75. data/unittests/html/cssTest.html +42 -42
  76. data/unittests/html/depot_store.html +59 -59
  77. data/unittests/html/div.html +93 -93
  78. data/unittests/html/div_xml.html +20 -20
  79. data/unittests/html/fileupload.html +45 -45
  80. data/unittests/html/formTest1.html +38 -38
  81. data/unittests/html/forms2.html +44 -44
  82. data/unittests/html/forms3.html +131 -131
  83. data/unittests/html/forms4.html +27 -27
  84. data/unittests/html/frame_buttons.html +3 -3
  85. data/unittests/html/frame_links.html +3 -3
  86. data/unittests/html/frame_multi.html +4 -4
  87. data/unittests/html/google_india.html +119 -119
  88. data/unittests/html/iframeTest.html +12 -12
  89. data/unittests/html/iframeTest1.html +6 -6
  90. data/unittests/html/iframeTest2.html +5 -5
  91. data/unittests/html/images1.html +66 -66
  92. data/unittests/html/javascriptevents.html +35 -35
  93. data/unittests/html/link_pass.html +10 -10
  94. data/unittests/html/links1.html +38 -38
  95. data/unittests/html/links2.html +10 -10
  96. data/unittests/html/links_multi.html +14 -14
  97. data/unittests/html/list_matters.html +720 -720
  98. data/unittests/html/lists.html +17 -17
  99. data/unittests/html/map_test.html +31 -31
  100. data/unittests/html/modal_dialog.html +10 -10
  101. data/unittests/html/modal_dialog_launcher.html +11 -11
  102. data/unittests/html/nestedFrames.html +6 -6
  103. data/unittests/html/new_browser.html +16 -16
  104. data/unittests/html/pass.html +12 -12
  105. data/unittests/html/popups1.html +59 -59
  106. data/unittests/html/pre.html +27 -27
  107. data/unittests/html/radioButtons1.html +71 -71
  108. data/unittests/html/select_tealeaf.html +54 -54
  109. data/unittests/html/selectboxes1.html +52 -52
  110. data/unittests/html/simple_table.html +26 -26
  111. data/unittests/html/simple_table_buttons.html +104 -104
  112. data/unittests/html/simple_table_columns.html +76 -76
  113. data/unittests/html/table1.html +181 -181
  114. data/unittests/html/tableCell_using_xpath.html +19 -19
  115. data/unittests/html/table_and_tablerow_to_a.html +174 -0
  116. data/unittests/html/textarea.html +30 -30
  117. data/unittests/html/textfields1.html +88 -88
  118. data/unittests/html/textsearch.html +44 -44
  119. data/unittests/html/wallofcheckboxes.html +1003 -1003
  120. data/unittests/html/xpath_nbsp.html +12 -12
  121. data/unittests/ie_exists_test.rb +33 -33
  122. data/unittests/ie_mock.rb +94 -94
  123. data/unittests/ie_test.rb +51 -51
  124. data/unittests/images_test.rb +157 -157
  125. data/unittests/images_xpath_test.rb +91 -91
  126. data/unittests/links_multi_test.rb +48 -48
  127. data/unittests/links_test.rb +175 -175
  128. data/unittests/links_xpath_test.rb +39 -39
  129. data/unittests/lists_test.rb +32 -32
  130. data/unittests/map_test.rb +98 -98
  131. data/unittests/minmax_test.rb +31 -31
  132. data/unittests/navigate_test.rb +39 -39
  133. data/unittests/nbsp_xpath_test.rb +16 -16
  134. data/unittests/non_core_tests.rb +12 -12
  135. data/unittests/other/WindowLogonExample.rb +27 -27
  136. data/unittests/other/WindowLogonExtra.rb +6 -6
  137. data/unittests/other/all_tests_concurrent.rb +57 -57
  138. data/unittests/other/jscriptExtraAlert.rb +6 -6
  139. data/unittests/other/jscriptExtraConfirmCancel.rb +6 -6
  140. data/unittests/other/jscriptExtraConfirmOk.rb +6 -6
  141. data/unittests/other/jscriptPushButton.rb +6 -6
  142. data/unittests/other/jscript_test.rb +63 -63
  143. data/unittests/other/navigate_exception_test.rb +24 -24
  144. data/unittests/other/rexml_unit_test.rb +27 -27
  145. data/unittests/other/screen_capture_test.rb +54 -54
  146. data/unittests/other/testcase_method_order_test.rb +35 -35
  147. data/unittests/other/testcase_verify_test.rb +24 -24
  148. data/unittests/other/wait_until_test.rb +99 -99
  149. data/unittests/pagecontainstext_test.rb +69 -69
  150. data/unittests/parent_child_test.rb +43 -43
  151. data/unittests/perf_test.rb +20 -20
  152. data/unittests/popups_test.rb +43 -43
  153. data/unittests/pre_test.rb +53 -53
  154. data/unittests/radios_test.rb +212 -212
  155. data/unittests/radios_xpath_test.rb +101 -101
  156. data/unittests/security_setting_test.rb +23 -23
  157. data/unittests/selectbox_test.rb +148 -148
  158. data/unittests/selectbox_xpath_test.rb +113 -113
  159. data/unittests/setup.rb +87 -77
  160. data/unittests/speed_settings_test.rb +67 -67
  161. data/unittests/table_and_tablerow_to_a_test.rb +117 -0
  162. data/unittests/table_cell_using_xpath_test.rb +35 -35
  163. data/unittests/table_test.rb +376 -376
  164. data/unittests/table_xpath_test.rb +110 -110
  165. data/unittests/test_tests.rb +9 -9
  166. data/unittests/textarea_test.rb +92 -92
  167. data/unittests/textarea_xpath_test.rb +78 -78
  168. data/unittests/textfield_for_ch_char_test.rb +31 -31
  169. data/unittests/textfields_test.rb +218 -218
  170. data/unittests/textfields_xpath_test.rb +111 -111
  171. data/unittests/window_tests.rb +10 -10
  172. data/unittests/windows/attach_to_existing_window_test.rb +53 -53
  173. data/unittests/windows/attach_to_new_window_test.rb +83 -83
  174. data/unittests/windows/close_window_test.rb +20 -20
  175. data/unittests/windows/frame_links_test.rb +25 -25
  176. data/unittests/windows/ie-each_test.rb +47 -47
  177. data/unittests/windows/iedialog_test.rb +54 -54
  178. data/unittests/windows/js_events_test.rb +42 -55
  179. data/unittests/windows/modal_dialog_test.rb +128 -128
  180. data/unittests/windows/new_test.rb +57 -57
  181. data/unittests/windows/open_close_test.rb +18 -18
  182. data/unittests/windows/send_keys_test.rb +33 -33
  183. data/unittests/xpath_tests.rb +10 -10
  184. metadata +85 -31
  185. data/lib/watir/utils.rb +0 -20
  186. data/lib/watir/version.rb +0 -5
@@ -1,36 +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
- 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
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
36
36
  end
@@ -1,14 +1,14 @@
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
+ # 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,496 +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
- 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
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