win 0.3.3 → 0.3.5
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY +8 -0
- data/VERSION +1 -1
- data/lib/win/gui/window.rb +127 -7
- data/lib/win/library.rb +9 -9
- data/spec/spec_helper.rb +27 -26
- data/spec/win/error_spec.rb +4 -4
- data/spec/win/extensions_spec.rb +8 -8
- data/spec/win/gui/input_spec.rb +2 -2
- data/spec/win/gui/message_spec.rb +4 -4
- data/spec/win/gui/window_spec.rb +146 -30
- data/spec/win/library_spec.rb +18 -18
- metadata +3 -3
data/HISTORY
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.5
|
data/lib/win/gui/window.rb
CHANGED
@@ -43,6 +43,20 @@ module Win
|
|
43
43
|
# flag when minimizing windows from a different thread.
|
44
44
|
SW_FORCEMINIMIZE = 11
|
45
45
|
|
46
|
+
# GetWindow constants:
|
47
|
+
GW_HWNDFIRST = 0
|
48
|
+
GW_HWNDLAST = 1
|
49
|
+
GW_HWNDNEXT = 2
|
50
|
+
GW_HWNDPREV = 3
|
51
|
+
GW_OWNER = 4
|
52
|
+
GW_CHILD = 5
|
53
|
+
GW_ENABLEDPOPUP = 6
|
54
|
+
|
55
|
+
# GetAncestor constants:
|
56
|
+
GA_PARENT = 1
|
57
|
+
GA_ROOT = 2
|
58
|
+
GA_ROOTOWNER = 3
|
59
|
+
|
46
60
|
class << self
|
47
61
|
# Def_block that calls API function expecting EnumWindowsProc callback (EnumWindows, EnumChildWindows, ...).
|
48
62
|
# Default callback pushes all passed handles into Array that is returned if Enum function call was successful.
|
@@ -227,7 +241,7 @@ module Win
|
|
227
241
|
|
228
242
|
##
|
229
243
|
# The FindWindowEx function retrieves a handle to a window whose class name and window name match the specified
|
230
|
-
# strings. The function searches child windows, beginning with the one following the specified child window.
|
244
|
+
# strings. The function searches only child windows, beginning with the one following the specified child window.
|
231
245
|
# This function does not perform a case-sensitive search.
|
232
246
|
#
|
233
247
|
# [*Syntax*] HWND FindWindowEx( HWND hwndParent, HWND hwndChildAfter, LPCTSTR lpszClass, LPCTSTR lpszWindow );
|
@@ -257,7 +271,11 @@ module Win
|
|
257
271
|
# call GetLastError.
|
258
272
|
# ---
|
259
273
|
# *Remarks*:
|
260
|
-
# -
|
274
|
+
# - Only DIRECT children of given parent window being searched, not ALL its the descendants. This behavior is
|
275
|
+
# different from EnumChildWindows which enumerates also non-direct descendants.
|
276
|
+
# - If the lpszWindow parameter is not nil, FindWindowEx calls the GetWindowText function to retrieve the window
|
277
|
+
# name for comparison. For a description of a potential problem that can arise, see the Remarks section of
|
278
|
+
# GetWindowText.
|
261
279
|
# - An application can call this function in the following way.
|
262
280
|
# find_window_ex( nil, nil, MAKEINTATOM(0x8000), nil )
|
263
281
|
# 0x8000 is the atom for a menu class. When an application calls this function, the function checks whether
|
@@ -470,11 +488,8 @@ module Win
|
|
470
488
|
function :GetWindowRect, [:HWND, :pointer], :int,
|
471
489
|
&->(api, handle) {
|
472
490
|
rect = FFI::MemoryPointer.new(:long, 4)
|
473
|
-
#rect.write_array_of_long([0, 0, 0, 0])
|
474
491
|
res = api.call handle, rect
|
475
492
|
res == 0 ? [nil, nil, nil, nil] : rect.read_array_of_long(4) }
|
476
|
-
# weird lambda literal instead of normal block is needed because current version of RDoc
|
477
|
-
# goes crazy if block is attached to meta-definition
|
478
493
|
|
479
494
|
##
|
480
495
|
# EnumWindowsProc is an application-defined callback function that receives top-level window handles
|
@@ -499,8 +514,8 @@ module Win
|
|
499
514
|
|
500
515
|
##
|
501
516
|
# The EnumWindows function enumerates all top-level windows on the screen by passing the handle to
|
502
|
-
#
|
503
|
-
#
|
517
|
+
# each window, in turn, to an application-defined callback function. EnumWindows continues until
|
518
|
+
# the last top-level window is enumerated or the callback function returns FALSE.
|
504
519
|
#
|
505
520
|
# [*Syntax*] BOOL EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam );
|
506
521
|
#
|
@@ -636,7 +651,112 @@ module Win
|
|
636
651
|
#
|
637
652
|
function :GetActiveWindow, [], :HWND, zeronil: true
|
638
653
|
|
654
|
+
##
|
655
|
+
# The GetWindow function retrieves a handle to a window that has the specified relationship (Z-Order or
|
656
|
+
# owner) to the specified window.
|
657
|
+
#
|
658
|
+
# [*Syntax*] HWND GetWindow( HWND hWnd, UINT uCmd );
|
659
|
+
#
|
660
|
+
# hWnd:: [in] Handle to a window. The window handle retrieved is relative to this window, based on the
|
661
|
+
# value of the uCmd parameter.
|
662
|
+
# uCmd:: [in] Specifies the relationship between the specified window and the window whose handle is to
|
663
|
+
# be retrieved. This parameter can be one of the following values.
|
664
|
+
# GW_CHILD - The retrieved handle identifies the child window at the top of the Z order, if the specified
|
665
|
+
# window is a parent window; otherwise, the retrieved handle is NULL. The function examines
|
666
|
+
# only child windows of the specified window. It does not examine descendant windows.
|
667
|
+
# GW_ENABLEDPOPUP - Windows 2000/XP: The retrieved handle identifies the enabled popup window owned by
|
668
|
+
# the specified window (the search uses the first such window found using GW_HWNDNEXT);
|
669
|
+
# otherwise, if there are no enabled popup windows, the retrieved handle is that of the
|
670
|
+
# specified window.
|
671
|
+
# GW_HWNDFIRST - The retrieved handle identifies the window of the same type that is highest in Z order.
|
672
|
+
# If the specified window is a topmost window, the handle identifies the topmost window
|
673
|
+
# that is highest in the Z order. If the specified window is a top-level window, the handle
|
674
|
+
# identifies the top-level window that is highest in the Z order. If the specified window
|
675
|
+
# is a child window, the handle identifies the sibling window that is highest in Z order.
|
676
|
+
# GW_HWNDLAST - The retrieved handle identifies the window of the same type that is lowest in the Z order.
|
677
|
+
# If the specified window is a topmost window, the handle identifies the topmost window that
|
678
|
+
# is lowest in the Z order. If the specified window is a top-level window, the handle
|
679
|
+
# identifies the top-level window that is lowest in the Z order. If the specified window is
|
680
|
+
# a child window, the handle identifies the sibling window that is lowest in the Z order.
|
681
|
+
# GW_HWNDNEXT - The retrieved handle identifies the window below the specified window in the Z order.
|
682
|
+
# If the specified window is a topmost window, the handle identifies the topmost window
|
683
|
+
# below the specified window. If the specified window is a top-level window, the handle
|
684
|
+
# identifies the top-level window below the specified window. If the specified window is
|
685
|
+
# a child window, the handle identifies the sibling window below the specified window.
|
686
|
+
# GW_HWNDPREV - The retrieved handle identifies the window above the specified window in the Z order.
|
687
|
+
# If the specified window is a topmost window, the handle identifies the topmost window
|
688
|
+
# above the specified window. If the specified window is a top-level window, the handle
|
689
|
+
# identifies the top-level window above the specified window. If the specified window is
|
690
|
+
# a child window, the handle identifies the sibling window above the specified window.
|
691
|
+
# GW_OWNER - The retrieved handle identifies the specified window's owner window, if any. For more
|
692
|
+
# information, see Owned Windows.
|
693
|
+
# *Returns*:: If the function succeeds, the return value is a window handle. If no window exists with
|
694
|
+
# the specified relationship to the specified window, the return value is NULL. To get
|
695
|
+
# extended error information, call GetLastError.
|
696
|
+
# ---
|
697
|
+
# *Remarks*:
|
698
|
+
# The EnumChildWindows function is more reliable than calling GetWindow in a loop. An application that
|
699
|
+
# calls GetWindow to perform this task risks being caught in an infinite loop or referencing a handle to
|
700
|
+
# a window that has been destroyed.
|
701
|
+
# Function Information
|
702
|
+
#
|
703
|
+
# ---
|
704
|
+
# <b>Enhanced (snake_case) API: returns nil instead of 0 in case of failure</b>
|
705
|
+
#
|
706
|
+
# :call-seq:
|
707
|
+
# window_handle = get_window(h_wnd, u_cmd)
|
708
|
+
#
|
709
|
+
function :GetWindow, [:HWND, :UINT], :HWND, zeronil: true
|
710
|
+
|
711
|
+
##
|
712
|
+
# The GetParent function retrieves a handle to the specified window's parent OR OWNER.
|
713
|
+
# To retrieve a handle to a specified ancestor, use the GetAncestor function.
|
714
|
+
#
|
715
|
+
# [*Syntax*] HWND GetParent( HWND hWnd );
|
716
|
+
#
|
717
|
+
# hWnd:: [in] Handle to the window whose parent window handle is to be retrieved.
|
718
|
+
#
|
719
|
+
# *Returns*:: If the window is a child window, the return value is a handle to the parent window. If the
|
720
|
+
# window is a top-level window, the return value is a handle to the owner window. If the
|
721
|
+
# window is a top-level unowned window or if the function fails, the return value is NULL.
|
722
|
+
# To get extended error information, call GetLastError. For example, this would determine,
|
723
|
+
# when the function returns NULL, if the function failed or the window was a top-level window.
|
724
|
+
# ---
|
725
|
+
# *Remarks*:
|
726
|
+
# Note that, despite its name, this function can return an owner window instead of a parent window. To
|
727
|
+
# obtain the parent window and not the owner, use GetAncestor with the GA_PARENT flag.
|
728
|
+
#
|
729
|
+
# ---
|
730
|
+
# <b>Enhanced (snake_case) API: returns nil instead of 0 in case of failure</b>
|
731
|
+
#
|
732
|
+
# :call-seq:
|
733
|
+
# parent = get_parent(h_wnd)
|
734
|
+
#
|
735
|
+
function :GetParent, [:HWND], :HWND, zeronil: true
|
736
|
+
|
737
|
+
##
|
738
|
+
# The GetAncestor function retrieves the handle to the ancestor of the specified window.
|
739
|
+
#
|
740
|
+
# [*Syntax*] HWND GetAncestor( HWND hwnd, UINT gaFlags );
|
741
|
+
#
|
742
|
+
# hwnd:: [in] Handle to the window whose ancestor is to be retrieved. If this parameter is the desktop
|
743
|
+
# window, the function returns NULL.
|
744
|
+
# gaFlags:: [in] Specifies the ancestor to be retrieved. This parameter can be one of the following values:
|
745
|
+
# GA_PARENT - Retrieves parent window. Unlike GetParent function, this does NOT include the owner.
|
746
|
+
# GA_ROOT - Retrieves the root window by walking the chain of parent windows.
|
747
|
+
# GA_ROOTOWNER - Retrieves the owned root window by walking the chain of parent and owner windows
|
748
|
+
# returned by GetParent.
|
749
|
+
#
|
750
|
+
# *Returns*:: The return value is the handle to the ancestor window.
|
751
|
+
# ---
|
752
|
+
# <b>Enhanced (snake_case) API: returns nil instead of 0 in case of failure</b>
|
753
|
+
#
|
754
|
+
# :call-seq:
|
755
|
+
# ancestor = get_ancestor(hwnd, ga_flags)
|
756
|
+
#
|
757
|
+
function :GetAncestor, [:HWND, :UINT], :HWND, zeronil: true
|
639
758
|
|
759
|
+
|
640
760
|
# Convenience wrapper methods:
|
641
761
|
|
642
762
|
##
|
data/lib/win/library.rb
CHANGED
@@ -365,8 +365,8 @@ module Win
|
|
365
365
|
|
366
366
|
define_method snake_name, &method_body # define snake_case instance method
|
367
367
|
|
368
|
-
|
369
|
-
|
368
|
+
eigen_class = class << self; self; end # Extracting eigenclass
|
369
|
+
eigen_class.class_eval do
|
370
370
|
define_method snake_name, &method_body # define snake_case class method
|
371
371
|
end
|
372
372
|
end
|
@@ -446,23 +446,23 @@ module Win
|
|
446
446
|
# Hook executed when Win::Library is included into class or module. It extends host class/module
|
447
447
|
# with both FFI::Library methods and Win::Library macro methods like 'function'.
|
448
448
|
#
|
449
|
-
def self.included(
|
450
|
-
|
449
|
+
def self.included(host_class)
|
450
|
+
host_class.extend FFI::Library
|
451
451
|
|
452
452
|
# Extracting host class's eigenclass
|
453
453
|
# :stopdoc:
|
454
|
-
|
454
|
+
eigen_class = class << host_class; self; end # :nodoc:
|
455
455
|
|
456
|
-
|
457
|
-
define_method(:namespace) {
|
456
|
+
eigen_class.class_eval do
|
457
|
+
define_method(:namespace) {host_class} # Defining new class method for host class pointing to itself
|
458
458
|
alias_method :attach_callback, :callback
|
459
459
|
|
460
460
|
include ClassMethods
|
461
461
|
end
|
462
462
|
# :startdoc:
|
463
463
|
|
464
|
-
|
465
|
-
|
464
|
+
host_class.ffi_lib 'user32', 'kernel32' # Default libraries
|
465
|
+
host_class.ffi_convention :stdcall
|
466
466
|
end
|
467
467
|
end
|
468
468
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -4,7 +4,7 @@ require 'spec'
|
|
4
4
|
require 'spec/autorun'
|
5
5
|
require 'win/gui'
|
6
6
|
|
7
|
-
$debug =
|
7
|
+
$debug = false
|
8
8
|
|
9
9
|
# Customize RSpec with my own extensions
|
10
10
|
module ClassMacros
|
@@ -13,7 +13,6 @@ module ClassMacros
|
|
13
13
|
# spec { use{ function(arg1 = 4, arg2 = 'string') }}
|
14
14
|
def spec &block
|
15
15
|
it description_from(caller[0]), &block # it description_from(*block.source_location), &block
|
16
|
-
#do lambda(&block).should_not raise_error end
|
17
16
|
end
|
18
17
|
|
19
18
|
# reads description line from source file and drops external brackets like its{}, use{}
|
@@ -46,11 +45,11 @@ Spec::Runner.configure do |config|
|
|
46
45
|
config.extend(ClassMacros)
|
47
46
|
config.include(InstanceMacros)
|
48
47
|
|
49
|
-
class << Spec::ExampleGroup
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
end
|
48
|
+
# class << Spec::ExampleGroup
|
49
|
+
## def spoc &block
|
50
|
+
## it description_from(caller[0]), &block
|
51
|
+
## end
|
52
|
+
# end
|
54
53
|
end
|
55
54
|
|
56
55
|
# Global test methods
|
@@ -72,17 +71,19 @@ end
|
|
72
71
|
|
73
72
|
module WinTest
|
74
73
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
74
|
+
KEY_DELAY = 0.001
|
75
|
+
IMPOSSIBLE = 'Impossible'
|
76
|
+
CONVERSION_ERROR = /Can.t convert/
|
77
|
+
SLEEP_DELAY = 0.02
|
78
|
+
APP_PATH = File.join(File.dirname(__FILE__), "test_apps/locknote/LockNote.exe" )
|
79
|
+
APP_START = cygwin? ? "cmd /c start `cygpath -w #{APP_PATH}`" : 'start "" "' + APP_PATH + '"'
|
80
|
+
WIN_TITLE = 'LockNote - Steganos LockNote'
|
81
|
+
WIN_RECT = [710, 400, 1210, 800]
|
82
|
+
WIN_CLASS = 'ATL:00434098'
|
83
|
+
STATUSBAR_CLASS = 'msctls_statusbar32'
|
84
|
+
TEXTAREA_CLASS = 'ATL:00434310'
|
85
|
+
DESKTOP_CLASS = '#32769'
|
86
|
+
MENU_CLASS = '#32768'
|
86
87
|
|
87
88
|
def any_handle
|
88
89
|
find_window(nil, nil)
|
@@ -104,14 +105,14 @@ module WinTestApp
|
|
104
105
|
#include Win::Gui::Convenience
|
105
106
|
|
106
107
|
def launch_test_app
|
107
|
-
system
|
108
|
-
sleep
|
108
|
+
system APP_START
|
109
|
+
sleep SLEEP_DELAY until (handle = find_window(nil, WIN_TITLE))
|
109
110
|
|
110
|
-
textarea = find_window_ex(handle, 0,
|
111
|
+
textarea = find_window_ex(handle, 0, TEXTAREA_CLASS, nil)
|
111
112
|
app = "Locknote" # App identifier
|
112
113
|
|
113
|
-
|
114
|
-
|
114
|
+
eigen_class = class << app; self; end # Extracting app's eigenclass
|
115
|
+
eigen_class.class_eval do # Defining singleton methods on app
|
115
116
|
define_method(:handle) {handle}
|
116
117
|
define_method(:textarea) {textarea}
|
117
118
|
end
|
@@ -120,9 +121,9 @@ module WinTestApp
|
|
120
121
|
end
|
121
122
|
|
122
123
|
def close_test_app(app = @launched_test_app)
|
123
|
-
while app && app.respond_to?( :handle) && find_window(nil,
|
124
|
+
while app && app.respond_to?( :handle) && find_window(nil, WIN_TITLE)
|
124
125
|
shut_window app.handle
|
125
|
-
sleep
|
126
|
+
sleep SLEEP_DELAY
|
126
127
|
end
|
127
128
|
@launched_test_app = nil
|
128
129
|
end
|
@@ -132,7 +133,7 @@ module WinTestApp
|
|
132
133
|
app = launch_test_app
|
133
134
|
|
134
135
|
# def app.textarea #define singleton method retrieving app's text area
|
135
|
-
# Window::Window.new find_window_ex(self.handle, 0,
|
136
|
+
# Window::Window.new find_window_ex(self.handle, 0, TEXTAREA_CLASS, nil)
|
136
137
|
# end
|
137
138
|
|
138
139
|
yield app
|
data/spec/win/error_spec.rb
CHANGED
@@ -21,14 +21,14 @@ module WinErrorTest
|
|
21
21
|
spec{ use{ err_message = get_last_error() }}
|
22
22
|
|
23
23
|
it "original api retrieves the calling thread's last-error code value" do
|
24
|
-
find_window(
|
24
|
+
find_window(IMPOSSIBLE, IMPOSSIBLE)
|
25
25
|
GetLastError().should == ERROR_FILE_NOT_FOUND
|
26
26
|
window_text(0)
|
27
27
|
GetLastError().should == ERROR_INVALID_WINDOW_HANDLE
|
28
28
|
end
|
29
29
|
|
30
30
|
it "enhanced api retrieves the message corresponding to last error code" do
|
31
|
-
find_window(
|
31
|
+
find_window(IMPOSSIBLE, IMPOSSIBLE)
|
32
32
|
get_last_error.should == "The system cannot find the file specified."
|
33
33
|
window_text(0)
|
34
34
|
get_last_error.should == "Invalid window handle."
|
@@ -40,7 +40,7 @@ module WinErrorTest
|
|
40
40
|
spec{ use{ message = format_message(sys_flags, source=nil, message_id=0, language_id=0, :int, 0) }}
|
41
41
|
|
42
42
|
it "original api formats a message string - system message" do
|
43
|
-
find_window(
|
43
|
+
find_window(IMPOSSIBLE, IMPOSSIBLE)
|
44
44
|
message_id = GetLastError()
|
45
45
|
buf = buffer()
|
46
46
|
num_chars = FormatMessage(sys_flags, nil, message_id, dw_language_id=0, buf, buf.size, :int, 0)
|
@@ -48,7 +48,7 @@ module WinErrorTest
|
|
48
48
|
end
|
49
49
|
|
50
50
|
it "snake_case api Formats a message string - system message" do
|
51
|
-
find_window(
|
51
|
+
find_window(IMPOSSIBLE, IMPOSSIBLE)
|
52
52
|
message = format_message(sys_flags, nil, dw_message_id=GetLastError())
|
53
53
|
message.should == "The system cannot find the file specified."
|
54
54
|
end
|
data/spec/win/extensions_spec.rb
CHANGED
@@ -53,20 +53,20 @@ module WinTest
|
|
53
53
|
end
|
54
54
|
|
55
55
|
it 'raises error if char is not implemented punctuation' do
|
56
|
-
('!'..'/').each {|char| lambda {char.to_vkeys}.should raise_error
|
57
|
-
(':'..'@').each {|char| lambda {char.to_vkeys}.should raise_error
|
58
|
-
('['..'`').each {|char| lambda {char.to_vkeys}.should raise_error
|
59
|
-
('{'..'~').each {|char| lambda {char.to_vkeys}.should raise_error
|
56
|
+
('!'..'/').each {|char| lambda {char.to_vkeys}.should raise_error CONVERSION_ERROR }
|
57
|
+
(':'..'@').each {|char| lambda {char.to_vkeys}.should raise_error CONVERSION_ERROR }
|
58
|
+
('['..'`').each {|char| lambda {char.to_vkeys}.should raise_error CONVERSION_ERROR }
|
59
|
+
('{'..'~').each {|char| lambda {char.to_vkeys}.should raise_error CONVERSION_ERROR }
|
60
60
|
end
|
61
61
|
|
62
62
|
it 'raises error if char is non-printable or non-ascii' do
|
63
|
-
lambda {1.chr.to_vkeys}.should raise_error
|
64
|
-
lambda {230.chr.to_vkeys}.should raise_error
|
63
|
+
lambda {1.chr.to_vkeys}.should raise_error CONVERSION_ERROR
|
64
|
+
lambda {230.chr.to_vkeys}.should raise_error CONVERSION_ERROR
|
65
65
|
end
|
66
66
|
|
67
67
|
it 'raises error if string is multi-char' do
|
68
|
-
lambda {'hello'.to_vkeys}.should raise_error
|
69
|
-
lambda {'23'.to_vkeys}.should raise_error
|
68
|
+
lambda {'hello'.to_vkeys}.should raise_error CONVERSION_ERROR
|
69
|
+
lambda {'23'.to_vkeys}.should raise_error CONVERSION_ERROR
|
70
70
|
end
|
71
71
|
end
|
72
72
|
end
|
data/spec/win/gui/input_spec.rb
CHANGED
@@ -17,9 +17,9 @@ module WinWindowTest
|
|
17
17
|
text = '12 34'
|
18
18
|
text.upcase.each_byte do |b| # upcase needed since user32 keybd_event expects upper case chars
|
19
19
|
keybd_event(b.ord, 0, KEYEVENTF_KEYDOWN, 0)
|
20
|
-
sleep
|
20
|
+
sleep KEY_DELAY
|
21
21
|
keybd_event(b.ord, 0, KEYEVENTF_KEYUP, 0)
|
22
|
-
sleep
|
22
|
+
sleep KEY_DELAY
|
23
23
|
end
|
24
24
|
text(app.textarea).should =~ Regexp.new(text)
|
25
25
|
5.times {keystroke(VK_CONTROL, 'Z'.ord)} # rolling back changes to allow window closing without dialog!
|
@@ -52,7 +52,7 @@ module WinGuiMessageTest
|
|
52
52
|
it 'places (posts) a message in the message queue associated with the thread that created the specified window' do
|
53
53
|
app = launch_test_app
|
54
54
|
post_message(app.handle, WM_SYSCOMMAND, SC_CLOSE, nil).should == true
|
55
|
-
sleep
|
55
|
+
sleep SLEEP_DELAY
|
56
56
|
window?(app.handle).should == false
|
57
57
|
end
|
58
58
|
|
@@ -80,7 +80,7 @@ module WinGuiMessageTest
|
|
80
80
|
buffer.get_bytes(0, num_chars).should =~ /Welcome to Steganos LockNote/
|
81
81
|
|
82
82
|
send_message(app.handle, WM_SYSCOMMAND, SC_CLOSE, nil)
|
83
|
-
sleep
|
83
|
+
sleep SLEEP_DELAY # delay to allow window close
|
84
84
|
window?(app.handle).should == false
|
85
85
|
end
|
86
86
|
end # describe '#send_message'
|
@@ -104,7 +104,7 @@ module WinGuiMessageTest
|
|
104
104
|
@data.should == nil
|
105
105
|
@result.should == nil
|
106
106
|
|
107
|
-
sleep
|
107
|
+
sleep SLEEP_DELAY # small delay to allow message delivery
|
108
108
|
peek_message # dispatching sent message (even though there is nothing in queue)
|
109
109
|
|
110
110
|
@handle.should == @app.handle
|
@@ -118,7 +118,7 @@ module WinGuiMessageTest
|
|
118
118
|
sent.should == true
|
119
119
|
@data.should == nil
|
120
120
|
|
121
|
-
sleep
|
121
|
+
sleep SLEEP_DELAY # small delay to allow message delivery
|
122
122
|
peek_message # dispatching sent message (even though there is nothing in queue)
|
123
123
|
|
124
124
|
@data.should == 0
|
data/spec/win/gui/window_spec.rb
CHANGED
@@ -135,16 +135,16 @@ module WinWindowTest
|
|
135
135
|
|
136
136
|
it 'returns either Integer Window handle or nil' do
|
137
137
|
find_window(nil, nil).should be_a_kind_of Integer
|
138
|
-
find_window(
|
138
|
+
find_window(IMPOSSIBLE, nil).should == nil
|
139
139
|
end
|
140
140
|
|
141
141
|
it 'returns nil if Window is not found' do
|
142
|
-
find_window(
|
143
|
-
find_window(nil,
|
144
|
-
find_window(
|
145
|
-
find_window_w(
|
146
|
-
find_window_w(nil,
|
147
|
-
find_window_w(
|
142
|
+
find_window(IMPOSSIBLE, nil).should == nil
|
143
|
+
find_window(nil, IMPOSSIBLE).should == nil
|
144
|
+
find_window(IMPOSSIBLE, IMPOSSIBLE).should == nil
|
145
|
+
find_window_w(IMPOSSIBLE, nil).should == nil
|
146
|
+
find_window_w(nil, IMPOSSIBLE).should == nil
|
147
|
+
find_window_w(IMPOSSIBLE, IMPOSSIBLE).should == nil
|
148
148
|
end
|
149
149
|
|
150
150
|
it 'finds at least one window if both args are nils' do
|
@@ -154,10 +154,10 @@ module WinWindowTest
|
|
154
154
|
|
155
155
|
it 'finds top-level window by window class or title' do
|
156
156
|
test_app do |app|
|
157
|
-
find_window(
|
158
|
-
find_window(nil,
|
159
|
-
find_window_w(
|
160
|
-
find_window_w(nil,
|
157
|
+
find_window(WIN_CLASS, nil).should == app.handle
|
158
|
+
find_window(nil, WIN_TITLE).should == app.handle
|
159
|
+
find_window_w(WIN_CLASS.to_w, nil).should == app.handle
|
160
|
+
find_window_w(nil, WIN_TITLE.to_w).should == app.handle
|
161
161
|
end
|
162
162
|
end
|
163
163
|
end
|
@@ -168,13 +168,13 @@ module WinWindowTest
|
|
168
168
|
|
169
169
|
it 'returns nil if wrong control is given' do
|
170
170
|
parent_handle = any_handle
|
171
|
-
find_window_ex(parent_handle, 0,
|
172
|
-
find_window_ex(parent_handle, 0, nil,
|
171
|
+
find_window_ex(parent_handle, 0, IMPOSSIBLE, nil).should == nil
|
172
|
+
find_window_ex(parent_handle, 0, nil, IMPOSSIBLE).should == nil
|
173
173
|
end
|
174
174
|
|
175
175
|
it 'finds child window/control by class' do
|
176
176
|
test_app do |app|
|
177
|
-
ta_handle = find_window_ex(app.handle, 0,
|
177
|
+
ta_handle = find_window_ex(app.handle, 0, TEXTAREA_CLASS, nil)
|
178
178
|
ta_handle.should_not == nil
|
179
179
|
ta_handle.should == app.textarea
|
180
180
|
end
|
@@ -252,10 +252,10 @@ module WinWindowTest
|
|
252
252
|
|
253
253
|
it 'returns correct window text' do
|
254
254
|
test_app do |app|
|
255
|
-
get_window_text(app.handle).should ==
|
256
|
-
get_window_text_w(app.handle).should ==
|
257
|
-
window_text(app.handle).should ==
|
258
|
-
window_text_w(app.handle).should ==
|
255
|
+
get_window_text(app.handle).should == WIN_TITLE
|
256
|
+
get_window_text_w(app.handle).should == WIN_TITLE
|
257
|
+
window_text(app.handle).should == WIN_TITLE
|
258
|
+
window_text_w(app.handle).should == WIN_TITLE
|
259
259
|
end
|
260
260
|
end
|
261
261
|
end
|
@@ -272,10 +272,10 @@ module WinWindowTest
|
|
272
272
|
|
273
273
|
it 'returns correct window class name' do
|
274
274
|
test_app do |app|
|
275
|
-
get_class_name(app.handle).should ==
|
276
|
-
class_name(app.handle).should ==
|
277
|
-
class_name_w(app.handle).should ==
|
278
|
-
get_class_name_w(app.handle).should ==
|
275
|
+
get_class_name(app.handle).should == WIN_CLASS
|
276
|
+
class_name(app.handle).should == WIN_CLASS
|
277
|
+
class_name_w(app.handle).should == WIN_CLASS #!!!!!!!!!!! nil?
|
278
|
+
get_class_name_w(app.handle).should == WIN_CLASS #!!!!!! nil?
|
279
279
|
end
|
280
280
|
end
|
281
281
|
end
|
@@ -310,7 +310,7 @@ module WinWindowTest
|
|
310
310
|
|
311
311
|
it 'returns window`s border rectangle' do
|
312
312
|
test_app do |app|
|
313
|
-
get_window_rect(app.handle).should ==
|
313
|
+
get_window_rect(app.handle).should == WIN_RECT
|
314
314
|
end
|
315
315
|
end
|
316
316
|
end
|
@@ -399,12 +399,128 @@ module WinWindowTest
|
|
399
399
|
end
|
400
400
|
end # describe 'destroy_window'
|
401
401
|
|
402
|
+
|
402
403
|
end # context 'ensuring test app closes'
|
403
404
|
|
404
405
|
context 'with single test app' do
|
405
406
|
before(:all){@app = launch_test_app}
|
406
407
|
after(:all){close_test_app}
|
407
408
|
|
409
|
+
describe "#get_parent" do
|
410
|
+
spec{ use{ parent = GetParent(any_handle) }}
|
411
|
+
spec{ use{ parent = get_parent(any_handle) }}
|
412
|
+
|
413
|
+
it "retrieves a handle to the specified window's parent or owner." do
|
414
|
+
child = find_window_ex(@app.handle, 0, nil, nil)
|
415
|
+
parent1 = GetParent(child)
|
416
|
+
parent2 = get_parent(child)
|
417
|
+
parent1.should == parent2
|
418
|
+
parent1.should == @app.handle
|
419
|
+
end
|
420
|
+
|
421
|
+
it "returns 0/nil if the specified window has no parent or owner." do
|
422
|
+
GetParent(@app.handle).should == 0
|
423
|
+
get_parent(@app.handle).should == nil
|
424
|
+
end
|
425
|
+
end # describe get_parent
|
426
|
+
|
427
|
+
describe "#get_ancestor" do
|
428
|
+
spec{ use{ ancestor = GetAncestor(any_handle, ga_flags=0) }}
|
429
|
+
spec{ use{ ancestor = get_ancestor(any_handle, ga_flags=0) }}
|
430
|
+
|
431
|
+
context 'GA_PARENT - Retrieves parent window. Unlike GetParent function, this does NOT include the owner.' do
|
432
|
+
it "retrieves a handle to the specified window's parent" do
|
433
|
+
child = find_window_ex(@app.handle, 0, nil, nil)
|
434
|
+
parent1 = GetAncestor(child, GA_PARENT)
|
435
|
+
parent2 = get_ancestor(child, GA_PARENT)
|
436
|
+
parent1.should == parent2
|
437
|
+
parent1.should == @app.handle
|
438
|
+
end
|
439
|
+
|
440
|
+
it "returns desktop handle for top-level window" do
|
441
|
+
parent = get_ancestor(@app.handle, GA_PARENT)
|
442
|
+
class_name(parent).should == DESKTOP_CLASS
|
443
|
+
end
|
444
|
+
|
445
|
+
it "returns 0/nil if the specified window is a desktop (has REALLY no parent)" do
|
446
|
+
desktop = get_ancestor(@app.handle, GA_PARENT)
|
447
|
+
GetAncestor(desktop, GA_PARENT).should == 0
|
448
|
+
get_ancestor(desktop, GA_PARENT).should == nil
|
449
|
+
end
|
450
|
+
end # context GA_PARENT
|
451
|
+
|
452
|
+
# GA_ROOT - Retrieves the root window by walking the chain of parent windows.
|
453
|
+
# GA_ROOTOWNER - Retrieves the owned root window by walking the chain of parent and owner windows
|
454
|
+
# returned by GetParent.
|
455
|
+
it "original api retrieves the handle to the ancestor of the specified window. " do
|
456
|
+
pending
|
457
|
+
success = GetAncestor(hwnd=0, ga_flags=0)
|
458
|
+
end
|
459
|
+
|
460
|
+
it "snake_case api retrieves the handle to the ancestor of the specified window. " do
|
461
|
+
pending
|
462
|
+
success = get_ancestor(hwnd=0, ga_flags=0)
|
463
|
+
end
|
464
|
+
|
465
|
+
end # describe get_ancestor
|
466
|
+
|
467
|
+
describe "#get_window" do
|
468
|
+
spec{ use{ handle = GetWindow(any_handle, command=0) }}
|
469
|
+
spec{ use{ handle = get_window(any_handle, command=0) }}
|
470
|
+
|
471
|
+
context "GW_CHILD retrieves a window handle to a first (top of the Z order) child of given window" do
|
472
|
+
before(:all) do
|
473
|
+
# GW_CHILD - The retrieved handle identifies the child window at the top of the Z order, if the specified
|
474
|
+
@child1 = GetWindow(@app.handle, GW_CHILD)
|
475
|
+
@child2 = get_window(@app.handle, GW_CHILD)
|
476
|
+
end
|
477
|
+
|
478
|
+
it 'returns active window handle' do
|
479
|
+
window?(@child1).should == true
|
480
|
+
end
|
481
|
+
it 'returns the same value for original and snake case API' do
|
482
|
+
@child1.should == @child2
|
483
|
+
end
|
484
|
+
it 'returns first direct child of a given window' do
|
485
|
+
@child1.should == find_window_ex(@app.handle, 0, nil, nil)
|
486
|
+
end
|
487
|
+
it 'returns nil/0 if no children for a given window' do
|
488
|
+
GetWindow(@child1, GW_CHILD).should == 0
|
489
|
+
get_window(@child1, GW_CHILD).should == nil
|
490
|
+
end
|
491
|
+
end # context GW_CHILD
|
492
|
+
|
493
|
+
context "GW_OWNER - retrieves a handle to an owner of a given Window" do
|
494
|
+
# GW_OWNER - The retrieved handle identifies the specified window's owner window, if any. For more
|
495
|
+
|
496
|
+
it 'returns owner (but NOT parent!) of a given window' do
|
497
|
+
pending
|
498
|
+
|
499
|
+
child = find_window_ex(@app.handle, 0, nil, nil)
|
500
|
+
p owner1 = GetWindow(child, GW_OWNER)
|
501
|
+
p owner2 = get_window(child, GW_OWNER)
|
502
|
+
owner1.should == owner2
|
503
|
+
owner1.should == @app.handle
|
504
|
+
end
|
505
|
+
|
506
|
+
it 'returns nil/0 if no owner for a given window' do
|
507
|
+
GetWindow(@app.handle, GW_OWNER).should == 0
|
508
|
+
get_window(@app.handle, GW_OWNER).should == nil
|
509
|
+
end
|
510
|
+
|
511
|
+
end
|
512
|
+
|
513
|
+
it "GW_OWNER - retrieves a handle to a window that has the specified relationship to given Window" do
|
514
|
+
pending
|
515
|
+
# GW_ENABLEDPOPUP - Windows 2000/XP: The retrieved handle identifies the enabled popup window owned by
|
516
|
+
# GW_HWNDFIRST - The retrieved handle identifies the window of the same type that is highest in Z order.
|
517
|
+
# GW_HWNDLAST - The retrieved handle identifies the window of the same type that is lowest in the Z order.
|
518
|
+
# GW_HWNDNEXT - The retrieved handle identifies the window below the specified window in the Z order.
|
519
|
+
# GW_HWNDPREV - The retrieved handle identifies the window above the specified window in the Z order.
|
520
|
+
# GW_OWNER - The retrieved handle identifies the specified window's owner window, if any. For more
|
521
|
+
end
|
522
|
+
end # describe get_window
|
523
|
+
|
408
524
|
describe '#enum_windows' do
|
409
525
|
# before(:each){@app = launch_test_app}
|
410
526
|
# after(:each){close_test_app}
|
@@ -460,8 +576,8 @@ module WinWindowTest
|
|
460
576
|
enum = enum_child_windows(@app.handle, 13)
|
461
577
|
enum.should be_a_kind_of Array
|
462
578
|
enum.should have(2).elements
|
463
|
-
class_name(enum.first).should ==
|
464
|
-
class_name(enum.last).should ==
|
579
|
+
class_name(enum.first).should == STATUSBAR_CLASS
|
580
|
+
class_name(enum.last).should == TEXTAREA_CLASS
|
465
581
|
end
|
466
582
|
|
467
583
|
it 'loops through all children of given window, passing each found window handle and a message to a given block' do
|
@@ -471,8 +587,8 @@ module WinWindowTest
|
|
471
587
|
message.should == 13
|
472
588
|
end
|
473
589
|
enum.should have(2).elements
|
474
|
-
class_name(enum.first).should ==
|
475
|
-
class_name(enum.last).should ==
|
590
|
+
class_name(enum.first).should == STATUSBAR_CLASS
|
591
|
+
class_name(enum.last).should == TEXTAREA_CLASS
|
476
592
|
end
|
477
593
|
|
478
594
|
it 'breaks loop if given block returns false' do
|
@@ -482,7 +598,7 @@ module WinWindowTest
|
|
482
598
|
false
|
483
599
|
end
|
484
600
|
enum.should have(1).element
|
485
|
-
class_name(enum.first).should ==
|
601
|
+
class_name(enum.first).should == STATUSBAR_CLASS
|
486
602
|
end
|
487
603
|
|
488
604
|
it 'defaults message to 0 if it is omitted from method call' do
|
@@ -528,7 +644,7 @@ module WinWindowTest
|
|
528
644
|
app = launch_test_app
|
529
645
|
|
530
646
|
shut_window(app.handle).should == true
|
531
|
-
sleep
|
647
|
+
sleep SLEEP_DELAY
|
532
648
|
|
533
649
|
window?(app.handle).should == false
|
534
650
|
end
|
@@ -540,7 +656,7 @@ module WinWindowTest
|
|
540
656
|
it 'returns text associated with window by sending WM_GETTEXT message to it' do
|
541
657
|
test_app do |app|
|
542
658
|
|
543
|
-
text(app.handle).should ==
|
659
|
+
text(app.handle).should == WIN_TITLE
|
544
660
|
text(app.textarea).should =~ /Welcome to Steganos LockNote/
|
545
661
|
end
|
546
662
|
end
|
data/spec/win/library_spec.rb
CHANGED
@@ -92,12 +92,12 @@ module WinLibraryTest
|
|
92
92
|
|
93
93
|
it 'constructs argument prototype from uppercase string, enforces the args count' do
|
94
94
|
expect { MyLib.function :FindWindow, 'PP', 'L' }.to_not raise_error
|
95
|
-
should_count_args :find_window, :FindWindow, [nil, nil], [nil,
|
95
|
+
should_count_args :find_window, :FindWindow, [nil, nil], [nil, IMPOSSIBLE, 'cmd']
|
96
96
|
end
|
97
97
|
|
98
98
|
it 'constructs argument prototype from (mixed) array, enforces the args count' do
|
99
99
|
expect { MyLib.function :FindWindow, [:pointer, 'P'], 'L' }.to_not raise_error
|
100
|
-
should_count_args :find_window, :FindWindow, [nil, nil], [nil,
|
100
|
+
should_count_args :find_window, :FindWindow, [nil, nil], [nil, IMPOSSIBLE, 'cmd']
|
101
101
|
end
|
102
102
|
|
103
103
|
it 'with :rename option, overrides snake_case name for defined method but leaves CamelCase intact' do
|
@@ -110,17 +110,17 @@ module WinLibraryTest
|
|
110
110
|
it 'defined snake_case method returns expected value when called' do
|
111
111
|
MyLib.function :FindWindow, 'PP', 'L'
|
112
112
|
find_window(nil, nil).should_not == 0
|
113
|
-
find_window(nil,
|
114
|
-
find_window(
|
115
|
-
find_window(
|
113
|
+
find_window(nil, IMPOSSIBLE).should == 0
|
114
|
+
find_window(IMPOSSIBLE, nil).should == 0
|
115
|
+
find_window(IMPOSSIBLE, IMPOSSIBLE).should == 0
|
116
116
|
end
|
117
117
|
|
118
118
|
it 'defined CamelCase method returns expected value when called' do
|
119
119
|
MyLib.function :FindWindow, 'PP', 'L'
|
120
120
|
FindWindow(nil, nil).should_not == 0
|
121
|
-
FindWindow(nil,
|
122
|
-
FindWindow(
|
123
|
-
FindWindow(
|
121
|
+
FindWindow(nil, IMPOSSIBLE).should == 0
|
122
|
+
FindWindow(IMPOSSIBLE, nil).should == 0
|
123
|
+
FindWindow(IMPOSSIBLE, IMPOSSIBLE).should == 0
|
124
124
|
end
|
125
125
|
|
126
126
|
# it 'returns underlying Win32::API object if defined method is called with (:api) argument ' do
|
@@ -172,17 +172,17 @@ module WinLibraryTest
|
|
172
172
|
|
173
173
|
it 'defined snake_case method returns false/true instead of zero/non-zero' do
|
174
174
|
find_window(nil, nil).should == true
|
175
|
-
find_window(nil,
|
175
|
+
find_window(nil, IMPOSSIBLE).should == false
|
176
176
|
end
|
177
177
|
|
178
178
|
it 'defined CamelCase method still returns zero/non-zero' do
|
179
179
|
FindWindow(nil, nil).should_not == true
|
180
180
|
FindWindow(nil, nil).should_not == 0
|
181
|
-
FindWindow(nil,
|
181
|
+
FindWindow(nil, IMPOSSIBLE).should == 0
|
182
182
|
end
|
183
183
|
|
184
184
|
it 'defined methods enforce the argument count' do
|
185
|
-
should_count_args :find_window, :FindWindow, [nil, nil], [nil,
|
185
|
+
should_count_args :find_window, :FindWindow, [nil, nil], [nil, IMPOSSIBLE, 'cmd']
|
186
186
|
end
|
187
187
|
end
|
188
188
|
|
@@ -197,12 +197,12 @@ module WinLibraryTest
|
|
197
197
|
it 'defined CamelCase method still returns zero/non-zero' do
|
198
198
|
FindWindow(nil, nil).should_not == true
|
199
199
|
FindWindow(nil, nil).should_not == 0
|
200
|
-
FindWindow(nil,
|
200
|
+
FindWindow(nil, IMPOSSIBLE).should == 0
|
201
201
|
end
|
202
202
|
|
203
203
|
it 'defined method returns nil (but NOT false) instead of zero' do
|
204
|
-
find_window(nil,
|
205
|
-
find_window(nil,
|
204
|
+
find_window(nil, IMPOSSIBLE).should_not == false
|
205
|
+
find_window(nil, IMPOSSIBLE).should == nil
|
206
206
|
end
|
207
207
|
|
208
208
|
it 'defined method does not return true when result is non-zero' do
|
@@ -211,7 +211,7 @@ module WinLibraryTest
|
|
211
211
|
end
|
212
212
|
|
213
213
|
it 'defined methods enforce the argument count' do
|
214
|
-
should_count_args :find_window, :FindWindow, [nil, nil], [nil,
|
214
|
+
should_count_args :find_window, :FindWindow, [nil, nil], [nil, IMPOSSIBLE, 'cmd']
|
215
215
|
end
|
216
216
|
end
|
217
217
|
|
@@ -292,18 +292,18 @@ module WinLibraryTest
|
|
292
292
|
context 'calling defined methods with attached block to preprocess the API function results' do
|
293
293
|
it 'defined method yields raw result to block attached to its invocation' do
|
294
294
|
MyLib.function :FindWindow, 'PP', 'L', zeronil: true
|
295
|
-
find_window(nil,
|
295
|
+
find_window(nil, IMPOSSIBLE) {|result| result.should == 0 }
|
296
296
|
end
|
297
297
|
|
298
298
|
it 'defined method returns result of block attached to its invocation' do
|
299
299
|
MyLib.function :FindWindow, 'PP', 'L', zeronil: true
|
300
|
-
return_value = find_window(nil,
|
300
|
+
return_value = find_window(nil, IMPOSSIBLE) {|result| 'Value'}
|
301
301
|
return_value.should == 'Value'
|
302
302
|
end
|
303
303
|
|
304
304
|
it 'defined method transforms result of block before returning it' do
|
305
305
|
MyLib.function :FindWindow, 'PP', 'L', zeronil: true
|
306
|
-
return_value = find_window(nil,
|
306
|
+
return_value = find_window(nil, IMPOSSIBLE) {|result| 0 }
|
307
307
|
return_value.should_not == 0
|
308
308
|
return_value.should == nil
|
309
309
|
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 3
|
8
|
-
-
|
9
|
-
version: 0.3.
|
8
|
+
- 5
|
9
|
+
version: 0.3.5
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- arvicco
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-05-28 00:00:00 +04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|