Permalink
Browse files

Merge branch 'get_window_text'

* get_window_text:
  version bump to 0.5.2
  add default window timeouts to specs to minimize spec failures due to timing issues
  whitespace cleanup
  changed to use GetWindowText which is less likely to hang
  • Loading branch information...
2 parents 8728ee1 + 6527e09 commit 571c0ddc28462fcfe1eec5cf3341267dcf41e249 @robertwahler committed Jun 5, 2012
View
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
- win32-autogui (0.5.1)
+ win32-autogui (0.5.2)
log4r (>= 1.1.9)
win32-clipboard (~> 0.5.2)
win32-process (~> 0.6.5)
View
@@ -5,6 +5,10 @@ Most recent changes are at the top
Changes
-------
+### 0.5.2 - 06/01/2012 ###
+
+* Retrieving the text of windows and controls is now more robust. Issue #5. (ebertech)
+
### 0.5.1 - 08/20/2011 ###
* Rebuild gem without psych to work-around the 'invalid gemspec date' issue
View
@@ -1 +1 @@
-0.5.1
+0.5.2
@@ -15,6 +15,11 @@ def initialize(options = {})
super defaults.merge(options)
end
+ # timeout in seconds to wait for desktop windows to appear
+ def default_window_timeout
+ 1
+ end
+
def edit_window
main_window.children.find {|w| w.window_class == 'TMemo'}
end
@@ -24,18 +29,21 @@ def status_bar
end
def dialog_about(options={})
+ options[:timeout] = default_window_timeout unless options[:timeout]
Autogui::EnumerateDesktopWindows.new(options).find do |w|
w.title.match(/^About QuickNote/) && (w.pid == pid)
end
end
def splash(options={})
+ options[:timeout] = default_window_timeout unless options[:timeout]
Autogui::EnumerateDesktopWindows.new(options).find do |w|
w.title.match(/^FormSplash/) && (w.pid == pid)
end
end
def message_dialog_confirm(options={})
+ options[:timeout] = default_window_timeout unless options[:timeout]
Autogui::EnumerateDesktopWindows.new(options).find do |w|
w.title.match(/^Confirm/) && (w.pid == pid)
end
@@ -44,6 +52,7 @@ def message_dialog_confirm(options={})
# Title and class are the same as dialog_overwrite_confirm
# Use child windows to differentiate
def dialog_overwrite_confirm(options={})
+ options[:timeout] = default_window_timeout unless options[:timeout]
Autogui::EnumerateDesktopWindows.new(options).find do |w|
w.title.match(/^Text File Save$/) &&
(w.pid == pid) &&
@@ -54,6 +63,7 @@ def dialog_overwrite_confirm(options={})
# Title and class are the same as dialog_overwrite_confirm
def file_save_as_dialog(options={})
+ options[:timeout] = default_window_timeout unless options[:timeout]
Autogui::EnumerateDesktopWindows.new(options).find do |w|
w.title.match(/^Text File Save/) &&
(w.pid == pid) &&
@@ -63,12 +73,14 @@ def file_save_as_dialog(options={})
end
def file_open_dialog(options={})
+ options[:timeout] = default_window_timeout unless options[:timeout]
Autogui::EnumerateDesktopWindows.new(options).find do |w|
w.title.match(/^Text File Open/) && (w.pid == pid)
end
end
def error_dialog(options={})
+ options[:timeout] = default_window_timeout unless options[:timeout]
Autogui::EnumerateDesktopWindows.new(options).find do |w|
w.title.match(/^QuickNote$/) && (w.pid == pid) && (w.window_class == "#32770")
end
@@ -78,22 +90,22 @@ def error_dialog(options={})
def file_new(options={})
set_focus
keystroke(VK_MENU, VK_F, VK_N)
- if message_dialog_confirm
+ if message_dialog_confirm(:timeout => 0)
options[:save] == true ? keystroke(VK_Y) : keystroke(VK_N)
end
# sanity check
- raise "confirm dialog is still here" if message_dialog_confirm
+ raise "confirm dialog is still here" if message_dialog_confirm(:timeout => 0)
end
# menu action File, New
def file_open(filename, options={})
set_focus
keystroke(VK_MENU, VK_F, VK_O)
- if message_dialog_confirm
+ if message_dialog_confirm(:timeout => 0)
options[:save] == true ? keystroke(VK_Y) : keystroke(VK_N)
end
- raise "sanity check, confirm dialog is still here" if message_dialog_confirm
+ raise "sanity check, confirm dialog is still here" if message_dialog_confirm(:timeout => 0)
raise "sanity check, file_open_dialog not found" unless file_open_dialog
# Paste in filename for speed, much faster than 'type_in(filename)'
@@ -106,10 +118,10 @@ def file_open(filename, options={})
# menu action File, Exit
def file_exit
set_focus
- keystroke(VK_N) if message_dialog_confirm
- keystroke(VK_ESCAPE) if file_open_dialog
+ keystroke(VK_N) if message_dialog_confirm(:timeout => 0)
+ keystroke(VK_ESCAPE) if file_open_dialog(:timeout => 0)
keystroke(VK_MENU, VK_F, VK_X)
- keystroke(VK_N) if message_dialog_confirm
+ keystroke(VK_N) if message_dialog_confirm(:timeout => 0)
end
# menu action File, Save
@@ -132,7 +144,7 @@ def file_save_as(filename, options={})
if dialog_overwrite_confirm
options[:overwrite] == true ? keystroke(VK_Y) : keystroke(VK_N)
end
- raise "sanity check, overwrite confirm dialog is still here" if dialog_overwrite_confirm
+ raise "sanity check, overwrite confirm dialog is still here" if dialog_overwrite_confirm(:timeout => 0)
end
@@ -14,7 +14,7 @@
end
before(:each) do
- @application.dialog_about.should be_nil
+ @application.dialog_about(:timeout => 0).should be_nil
@application.set_focus
keystroke(VK_MENU, VK_H, VK_A)
@dialog_about = @application.dialog_about
@@ -34,7 +34,7 @@
it "should close by hitting return" do
@dialog_about.set_focus
keystroke(VK_RETURN)
- @application.dialog_about.should be_nil
+ @application.dialog_about(:timeout => 0).should be_nil
end
it "should have the title 'About QuickNote'" do
@@ -28,8 +28,8 @@
end
after(:each) do
if @application.running?
- keystroke(VK_N) if @application.message_dialog_confirm || @application.dialog_overwrite_confirm
- keystroke(VK_ESCAPE) if @application.error_dialog
+ keystroke(VK_N) if @application.message_dialog_confirm(:timeout => 0) || @application.dialog_overwrite_confirm(:timeout => 0)
+ keystroke(VK_ESCAPE) if @application.error_dialog(:timeout => 0)
end
puts "FormMain after(:each)" if @debug
end
@@ -67,8 +67,14 @@
@application.file_new(:save => false)
end
after(:each) do
- keystroke(VK_N) if @application.message_dialog_confirm
- keystroke(VK_ESCAPE) if @application.file_open_dialog
+ if @application.message_dialog_confirm(:timeout => 0)
+ @application.message_dialog_confirm.set_focus
+ keystroke(VK_N)
+ end
+ if @application.file_open_dialog(:timeout => 0)
+ @application.file_open_dialog.set_focus
+ keystroke(VK_ESCAPE)
+ end
end
it "should prompt to save with modified text" do
@@ -80,7 +86,7 @@
it "should not prompt to save with unmodified text" do
@application.main_window.title.should_not match(/\+/)
keystroke(VK_MENU, VK_F, VK_O)
- @application.message_dialog_confirm.should be_nil
+ @application.message_dialog_confirm(:timeout => 0).should be_nil
end
describe "succeeding" do
@@ -122,7 +128,7 @@
@application.file_new(:save => false)
@application.main_window.title.should_not match(/\+/)
keystroke(VK_MENU, VK_F, VK_N)
- @application.message_dialog_confirm.should be_nil
+ @application.message_dialog_confirm(:timeout => 0).should be_nil
end
it "should add the filename 'untitled.txt' to the title" do
filename = "input_file.txt"
@@ -222,8 +228,8 @@
@application.file_open(fullpath(@filename), :save => false)
end
after(:each) do
- keystroke(VK_N) if @application.dialog_overwrite_confirm
- keystroke(VK_ESCAPE) if @application.file_save_as_dialog
+ keystroke(VK_N) if @application.dialog_overwrite_confirm(:timeout => 0)
+ keystroke(VK_ESCAPE) if @application.file_save_as_dialog(:timeout => 0)
end
it "should prompt for filename" do
@@ -266,7 +272,7 @@
end
it "should not prompt to save with unmodified text" do
keystroke(VK_MENU, VK_F, VK_X)
- @application.message_dialog_confirm.should be_nil
+ @application.message_dialog_confirm(:timeout => 0).should be_nil
@application.main_window.is_window?.should == false
@application.should_not be_running
end
@@ -6,7 +6,7 @@
describe "FormSplash" do
after(:each) do
if @application && @application.running?
- @application.splash.wait_for_close if @application.splash
+ @application.splash.wait_for_close if @application.splash(:timeout => 0)
@application.file_exit
# still running? force it to close
@application.close(:wait_for_close => true)
@@ -30,15 +30,15 @@
timeout(seconds) do
@application.splash.wait_for_close
end
- @application.splash.should be_nil
+ @application.splash(:timeout => 0).should be_nil
end
end
describe "startup with '--nosplash' command line parameter" do
it "should not show" do
@application = Quicknote.new :parameters => '--nosplash'
@application.should be_running
- @application.splash.should be_nil
+ @application.splash(:timeout => 0).should be_nil
end
end
@@ -141,19 +141,32 @@ def window_class
length == 0 ? '' : buffer[0..length - 1]
end
- # Window text (WM_GETTEXT)
+ # Window text (GetWindowText or WM_GETTEXT)
#
# @param [Number] max_length (2048)
#
# @return [String] of max_length (2048)
#
def text(max_length = 2048)
buffer = "\0" * max_length
- length = SendMessageA(handle, WM_GETTEXT, buffer.length, buffer)
+ length = if is_control?
+ SendMessageA(handle, WM_GETTEXT, buffer.length, buffer)
+ else
+ GetWindowText(handle, buffer, buffer.length)
+ end
+
length == 0 ? '' : buffer[0..length - 1]
end
alias :title :text
+ # Determines whether the specified window handle identifies a window or a control
+ #
+ # @return [Boolean]
+ #
+ def is_control?
+ (handle != 0) && (GetDlgCtrlID(handle) != 0)
+ end
+
# Determines whether the specified window handle identifies an existing window
#
# @return [Boolean]
@@ -17,6 +17,7 @@ module Window
API.new('SetForegroundWindow', 'L', 'I', 'user32')
API.new('SendMessageA', 'LIIP', 'I', 'user32')
API.new('IsWindowVisible', 'L', 'I', 'user32')
+ API.new('GetDlgCtrlID', 'L', 'I', 'user32')
end
end
@@ -19,8 +19,14 @@ def edit_window
main_window.children.find {|w| w.window_class == 'Edit'}
end
+ # timeout in seconds to wait for desktop windows to appear
+ def default_window_timeout
+ 1
+ end
+
# About dialog, hotkey (VK_MENU, VK_H, VK_A)
def dialog_about(options = {})
+ options[:timeout] = default_window_timeout unless options[:timeout]
Autogui::EnumerateDesktopWindows.new(options).find do |w|
w.title.match(/About Calculator/) && (w.pid == pid)
end
@@ -14,19 +14,26 @@ def initialize(options = {})
super defaults.merge(options)
end
+ # timeout in seconds to wait for desktop windows to appear
+ def default_window_timeout
+ 1
+ end
+
# the notepad's results window
def edit_window
main_window.children.find {|w| w.window_class == 'Edit'}
end
# About dialog, hotkey (VK_MENU, VK_H, VK_A)
def dialog_about(options = {})
+ options[:timeout] = default_window_timeout unless options[:timeout]
Autogui::EnumerateDesktopWindows.new(options).find do |w|
w.title.match(/About Notepad/) && (w.pid == pid)
end
end
def message_dialog_confirm(options={})
+ options[:timeout] = default_window_timeout unless options[:timeout]
Autogui::EnumerateDesktopWindows.new(options).find do |w|
w.title.match(/Notepad/) && (w.pid == pid) && (w.window_class == "#32770")
end
@@ -36,8 +43,8 @@ def message_dialog_confirm(options={})
def file_exit
set_focus
keystroke(VK_MENU, VK_F, VK_X)
- if message_dialog_confirm
- keystroke(VK_N) if message_dialog_confirm
+ if message_dialog_confirm(:timeout => 0)
+ keystroke(VK_N)
end
end
@@ -71,13 +71,13 @@
it "should open and close the 'About Calculator' dialog via (VK_MENU, VK_H, VK_A)" do
@calculator.set_focus
- dialog_about = @calculator.dialog_about
+ dialog_about = @calculator.dialog_about(:timeout => 0)
dialog_about.should be_nil
keystroke(VK_MENU, VK_H, VK_A)
dialog_about = @calculator.dialog_about
dialog_about.title.should == "About Calculator"
dialog_about.close
- @calculator.dialog_about.should be_nil
+ @calculator.dialog_about(:timeout => 0).should be_nil
end
describe "calculations" do

0 comments on commit 571c0dd

Please sign in to comment.