win 0.0.6 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +45 -20
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/lib/win/dde.rb +13 -15
- data/lib/win/extensions.rb +1 -1
- data/lib/win/gui/convenience.rb +142 -0
- data/lib/win/gui/dialog.rb +15 -0
- data/lib/win/gui/input.rb +255 -0
- data/lib/win/gui/message.rb +22 -0
- data/lib/win/gui/window.rb +497 -0
- data/lib/win/gui.rb +17 -0
- data/lib/win/library.rb +10 -9
- data/spec/spec_helper.rb +53 -15
- data/spec/win/dde_spec.rb +1 -0
- data/spec/win/extensions_spec.rb +1 -1
- data/spec/win/{window/extra_spec.rb → gui/convenience_spec.rb} +19 -23
- data/spec/win/gui/dialog_spec.rb +42 -0
- data/spec/win/gui/input_spec.rb +39 -0
- data/spec/win/gui/message_spec.rb +43 -0
- data/spec/win/{window_spec.rb → gui/window_spec.rb} +7 -97
- data/spec/win/library_spec.rb +3 -6
- data/win.gemspec +21 -11
- metadata +20 -10
- data/lib/win/window/extra.rb +0 -113
- data/lib/win/window.rb +0 -608
@@ -1,16 +1,15 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
-
require 'win/
|
3
|
-
require 'win/window/extra'
|
2
|
+
require 'win/gui/convenience'
|
4
3
|
|
5
|
-
module
|
6
|
-
include
|
7
|
-
include Win::Window
|
4
|
+
module WinGuiTest
|
5
|
+
include WinTestApp
|
6
|
+
include Win::Gui::Window
|
7
|
+
include Win::Gui::Input
|
8
|
+
include Win::Gui::Convenience
|
8
9
|
|
9
|
-
describe Win::
|
10
|
+
describe Win::Gui::Convenience, ' defines convenience/service methods on top of Windows API' do
|
10
11
|
describe '#keystroke' do
|
11
12
|
spec{ use{ keystroke( vkey = 30, vkey = 30) }}
|
12
|
-
# this service method emulates combinations of (any amount of) keys pressed one after another (Ctrl+Alt+P) and then released
|
13
|
-
# vkey (int) - Specifies a virtual-key code. The code must be a value in the range 1 to 254. For a complete list, see msdn:Virtual Key Codes.
|
14
13
|
|
15
14
|
it 'emulates combinations of keys pressed (Ctrl+Alt+P+M, etc)' do
|
16
15
|
test_app do |app|
|
@@ -24,21 +23,19 @@ module WinWindowTest
|
|
24
23
|
|
25
24
|
describe '#type_in' do
|
26
25
|
spec{ use{ type_in(message = '') }}
|
27
|
-
# this service method types text message into window holding the focus
|
28
26
|
|
29
|
-
it 'types text message into window holding the focus' do
|
27
|
+
it 'types text message into the window holding the focus' do
|
30
28
|
test_app do |app|
|
31
|
-
text = '
|
29
|
+
text = '12 34'
|
32
30
|
type_in(text)
|
33
31
|
app.textarea.text.should =~ Regexp.new(text)
|
34
|
-
|
32
|
+
5.times {keystroke(VK_CONTROL, 'Z'.ord)} # dirty hack!
|
35
33
|
end
|
36
34
|
end
|
37
35
|
end
|
38
36
|
|
39
37
|
describe 'dialog' do
|
40
38
|
spec{ use{ dialog( title ='Dialog Title', timeout_sec = 0.001, &any_block) }}
|
41
|
-
# me od finds top-level dialog window by title and yields found dialog window to block if given
|
42
39
|
|
43
40
|
it 'finds top-level dialog window by title' do
|
44
41
|
pending 'Some problems (?with timeouts?) leave window open ~half of the runs'
|
@@ -58,18 +55,18 @@ module WinWindowTest
|
|
58
55
|
|
59
56
|
end
|
60
57
|
|
61
|
-
describe Win::
|
58
|
+
describe Win::Gui::Convenience::WrapWindow, ' thin wrapper class around window handle' do
|
62
59
|
before(:each) { @app = launch_test_app }
|
63
60
|
after(:each){ close_test_app }
|
64
61
|
|
65
62
|
context 'creating' do
|
66
63
|
it 'can be wrapped around any existing window' do
|
67
64
|
any_handle = find_window(nil, nil)
|
68
|
-
use{
|
65
|
+
use{ WrapWindow.new any_handle }
|
69
66
|
end
|
70
67
|
|
71
68
|
it 'can be wrapped around specific window' do
|
72
|
-
use{
|
69
|
+
use{ WrapWindow.new @app.handle }
|
73
70
|
end
|
74
71
|
end
|
75
72
|
|
@@ -77,7 +74,7 @@ module WinWindowTest
|
|
77
74
|
|
78
75
|
it 'has handle property equal to underlying window handle' do
|
79
76
|
any_handle = find_window(nil, nil)
|
80
|
-
any =
|
77
|
+
any = WrapWindow.new any_handle
|
81
78
|
any.handle.should == any_handle
|
82
79
|
end
|
83
80
|
|
@@ -88,26 +85,26 @@ module WinWindowTest
|
|
88
85
|
it 'closes when asked nicely' do
|
89
86
|
@app.close
|
90
87
|
sleep TEST_SLEEP_DELAY # needed to ensure window had enough time to close down
|
91
|
-
find_window(nil, TEST_WIN_TITLE).should == nil
|
88
|
+
find_window(nil, TEST_WIN_TITLE).should == nil #!!!!!
|
92
89
|
end
|
93
90
|
|
94
91
|
it 'waits f0r window to disappear (NB: this happens before handle is released!)' do
|
95
92
|
start = Time.now
|
96
93
|
@app.close
|
97
94
|
@app.wait_for_close
|
98
|
-
(Time.now - start).should be <= Win::
|
95
|
+
(Time.now - start).should be <= Win::Gui::Convenience::CLOSE_TIMEOUT
|
99
96
|
window_visible?(@app.handle).should be false
|
100
97
|
end
|
101
98
|
end
|
102
99
|
|
103
100
|
context '.top_level class method' do
|
104
101
|
it 'finds any top-level window (title = nil) and wraps it in a Window object' do
|
105
|
-
use { @win =
|
106
|
-
|
102
|
+
use { @win = WrapWindow.top_level(title = nil, timeout_sec = 3) }
|
103
|
+
@win.should be_a_kind_of WrapWindow
|
107
104
|
end
|
108
105
|
|
109
106
|
it 'finds top-level window by title and wraps it in a Window object' do
|
110
|
-
win =
|
107
|
+
win = WrapWindow.top_level( TEST_WIN_TITLE, 1)
|
111
108
|
win.handle.should == @app.handle
|
112
109
|
end
|
113
110
|
end
|
@@ -177,5 +174,4 @@ module WinWindowTest
|
|
177
174
|
it 'emulates clicking of the control identified by id'
|
178
175
|
end
|
179
176
|
end
|
180
|
-
|
181
177
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
require 'win/gui/input'
|
3
|
+
#require 'win/gui/window'
|
4
|
+
|
5
|
+
module WinWindowTest
|
6
|
+
|
7
|
+
include WinTestApp
|
8
|
+
include Win::Gui::Dialog
|
9
|
+
|
10
|
+
describe Win::Gui::Dialog do
|
11
|
+
|
12
|
+
describe '#get_dlg_item' do
|
13
|
+
spec{ use{ control_handle = get_dlg_item(handle = 0, item_id = 1) }}
|
14
|
+
# handle (L) - Handle of the dialog box that contains the control.
|
15
|
+
# item_id (I) - Specifies the identifier of the control to be retrieved.
|
16
|
+
# Returns (L) - handle of the specified control if success or nil for invalid dialog box handle or a nonexistent control.
|
17
|
+
# To get extended error information, call GetLastError.
|
18
|
+
# You can use the GetDlgItem function with any parent-child window pair, not just with dialog boxes. As long as the handle
|
19
|
+
# parameter specifies a parent window and the child window has a unique id (as specified by the hMenu parameter in the
|
20
|
+
# CreateWindow or CreateWindowEx function that created the child window), GetDlgItem returns a valid handle to the child window.
|
21
|
+
|
22
|
+
it 'returns handle to correctly specified control'
|
23
|
+
|
24
|
+
it 'does something else' do
|
25
|
+
pending
|
26
|
+
test_app do |app|
|
27
|
+
text = '123 456'
|
28
|
+
text.upcase.each_byte do |b| # upcase needed since user32 keybd_event expects upper case chars
|
29
|
+
keybd_event(b.ord, 0, KEYEVENTF_KEYDOWN, 0)
|
30
|
+
sleep TEST_KEY_DELAY
|
31
|
+
keybd_event(b.ord, 0, KEYEVENTF_KEYUP, 0)
|
32
|
+
sleep TEST_KEY_DELAY
|
33
|
+
end
|
34
|
+
app.textarea.text.should =~ Regexp.new(text)
|
35
|
+
7.times {keystroke(VK_CONTROL, 'Z'.ord)} # dirty hack!
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
require 'win/gui/input'
|
3
|
+
#require 'win/gui/window'
|
4
|
+
|
5
|
+
module WinWindowTest
|
6
|
+
|
7
|
+
include WinTestApp
|
8
|
+
include Win::Gui::Input
|
9
|
+
|
10
|
+
describe Win::Gui::Input do
|
11
|
+
|
12
|
+
describe '#keydb_event' do
|
13
|
+
spec{ use{ keybd_event(vkey = 0, bscan = 0, flags = 0, extra_info = 0) }}
|
14
|
+
|
15
|
+
it 'synthesizes a numeric keystrokes, emulating keyboard driver' do
|
16
|
+
test_app do |app|
|
17
|
+
text = '123 456'
|
18
|
+
text.upcase.each_byte do |b| # upcase needed since user32 keybd_event expects upper case chars
|
19
|
+
keybd_event(b.ord, 0, KEYEVENTF_KEYDOWN, 0)
|
20
|
+
sleep TEST_KEY_DELAY
|
21
|
+
keybd_event(b.ord, 0, KEYEVENTF_KEYUP, 0)
|
22
|
+
sleep TEST_KEY_DELAY
|
23
|
+
end
|
24
|
+
app.textarea.text.should =~ Regexp.new(text)
|
25
|
+
7.times {keystroke(VK_CONTROL, 'Z'.ord)} # dirty hack!
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#mouse_event' do
|
31
|
+
it 'Emulates Mouse clicks'
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#set_cursor_pos' do
|
35
|
+
it 'how to test set_cursor_pos?'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
require 'win/gui/input'
|
3
|
+
#require 'win/gui/window'
|
4
|
+
|
5
|
+
module WinGuiMessageTest
|
6
|
+
|
7
|
+
include WinTestApp
|
8
|
+
include Win::Gui::Message
|
9
|
+
|
10
|
+
describe Win::Gui::Message do
|
11
|
+
|
12
|
+
describe '#post_message' do
|
13
|
+
spec{ use{ success = post_message(handle = 0, msg = 0, w_param = 0, l_param = 0) }}
|
14
|
+
# handle (L) - Handle to the window whose window procedure will receive the message.
|
15
|
+
# If this parameter is HWND_BROADCAST, the message is sent to all top-level windows in the system, including disabled or
|
16
|
+
# invisible unowned windows, overlapped windows, and pop-up windows; but the message is not sent to child windows.
|
17
|
+
# msg (L) - Specifies the message to be posted.
|
18
|
+
# w_param (L) - Specifies additional message-specific information.
|
19
|
+
# l_param (L) - Specifies additional message-specific information.
|
20
|
+
# returns (L) - Nonzero if success, zero if function failed. To get extended error information, call GetLastError.
|
21
|
+
|
22
|
+
it 'places (posts) a message in the message queue associated with the thread that created the specified window'
|
23
|
+
it 'returns without waiting for the thread to process the message'
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#send_message' do
|
27
|
+
spec{ use{ success = send_message(handle = 0, msg = 0, w_param = 1024, l_param = "\x0"*1024) }}
|
28
|
+
# handle (L) - Handle to the window whose window procedure is to receive the message. The following values have special meanings.
|
29
|
+
# HWND_BROADCAST - The message is posted to all top-level windows in the system, including disabled or invisible unowned windows,
|
30
|
+
# overlapped windows, and pop-up windows. The message is not posted to child windows.
|
31
|
+
# NULL - The function behaves like a call to PostThreadMessage with the dwThreadId parameter set to the identifier of the current thread.
|
32
|
+
# msg (L) - Specifies the message to be posted.
|
33
|
+
# w_param (L) - Specifies additional message-specific information.
|
34
|
+
# l_param (L) - Specifies additional message-specific information.
|
35
|
+
# return (L) - Nonzero if success, zero if function failed. To get extended error information, call GetLastError.
|
36
|
+
|
37
|
+
it 'sends the specified message to a window or windows'
|
38
|
+
it 'calls the window procedure and does not return until the window procedure has processed the message'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
|
@@ -1,40 +1,10 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '
|
2
|
-
require 'win/window'
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
require 'win/gui/window'
|
3
3
|
|
4
4
|
module WinWindowTest
|
5
5
|
|
6
|
-
include
|
7
|
-
include Win::Window
|
8
|
-
|
9
|
-
def launch_test_app
|
10
|
-
system TEST_APP_START
|
11
|
-
sleep TEST_SLEEP_DELAY until (handle = find_window(nil, TEST_WIN_TITLE))
|
12
|
-
|
13
|
-
@launched_test_app = Window.new handle
|
14
|
-
# app = "Test app" #need to get rid of Window for JRuby
|
15
|
-
# class << app; self; end.send( :define_method, :handle, &lambda {handle})
|
16
|
-
# @launched_test_app = app
|
17
|
-
end
|
18
|
-
|
19
|
-
def close_test_app(app = @launched_test_app)
|
20
|
-
while app and app.respond_to? :handle and find_window(nil, TEST_WIN_TITLE)
|
21
|
-
post_message(app.handle, WM_SYSCOMMAND, SC_CLOSE, 0)
|
22
|
-
sleep TEST_SLEEP_DELAY
|
23
|
-
end
|
24
|
-
@launched_test_app = nil
|
25
|
-
end
|
26
|
-
|
27
|
-
# Creates test app object and yields it back to the block
|
28
|
-
def test_app
|
29
|
-
app = launch_test_app
|
30
|
-
|
31
|
-
def app.textarea #define singleton method retrieving app's text area
|
32
|
-
Window.new find_window_ex(self.handle, 0, TEST_TEXTAREA_CLASS, nil)
|
33
|
-
end
|
34
|
-
|
35
|
-
yield app
|
36
|
-
close_test_app
|
37
|
-
end
|
6
|
+
include WinTestApp
|
7
|
+
include Win::Gui::Window
|
38
8
|
|
39
9
|
def commands_should_show_window *cmds, tests
|
40
10
|
cmds.each do |cmd|
|
@@ -57,8 +27,7 @@ module WinWindowTest
|
|
57
27
|
end
|
58
28
|
end
|
59
29
|
|
60
|
-
|
61
|
-
describe Win::Window, ' defines a set user32 API functions related to Window manipulation' do
|
30
|
+
describe Win::Gui::Window, ' defines a set user32 API functions related to Window manipulation' do
|
62
31
|
describe '#window?' do
|
63
32
|
spec{ use{ IsWindow(any_handle) }}
|
64
33
|
spec{ use{ is_window(any_handle) }}
|
@@ -480,65 +449,6 @@ module WinWindowTest
|
|
480
449
|
end
|
481
450
|
end
|
482
451
|
end
|
483
|
-
|
484
|
-
describe '#keydb_event' do
|
485
|
-
spec{ use{ keybd_event(vkey = 0, bscan = 0, flags = 0, extra_info = 0) }}
|
486
|
-
|
487
|
-
it 'synthesizes a numeric keystrokes, emulating keyboard driver' do
|
488
|
-
test_app do |app|
|
489
|
-
text = '123 456'
|
490
|
-
text.upcase.each_byte do |b| # upcase needed since user32 keybd_event expects upper case chars
|
491
|
-
keybd_event(b.ord, 0, KEYEVENTF_KEYDOWN, 0)
|
492
|
-
sleep TEST_KEY_DELAY
|
493
|
-
keybd_event(b.ord, 0, KEYEVENTF_KEYUP, 0)
|
494
|
-
sleep TEST_KEY_DELAY
|
495
|
-
end
|
496
|
-
app.textarea.text.should =~ Regexp.new(text)
|
497
|
-
7.times {keystroke(VK_CONTROL, 'Z'.ord)} # dirty hack!
|
498
|
-
end
|
499
|
-
end
|
500
|
-
end
|
501
|
-
|
502
|
-
describe '#post_message' do
|
503
|
-
spec{ use{ success = post_message(handle = 0, msg = 0, w_param = 0, l_param = 0) }}
|
504
|
-
# handle (L) - Handle to the window whose window procedure will receive the message.
|
505
|
-
# If this parameter is HWND_BROADCAST, the message is sent to all top-level windows in the system, including disabled or
|
506
|
-
# invisible unowned windows, overlapped windows, and pop-up windows; but the message is not sent to child windows.
|
507
|
-
# msg (L) - Specifies the message to be posted.
|
508
|
-
# w_param (L) - Specifies additional message-specific information.
|
509
|
-
# l_param (L) - Specifies additional message-specific information.
|
510
|
-
# returns (L) - Nonzero if success, zero if function failed. To get extended error information, call GetLastError.
|
511
|
-
|
512
|
-
it 'places (posts) a message in the message queue associated with the thread that created the specified window'
|
513
|
-
it 'returns without waiting for the thread to process the message'
|
514
|
-
end
|
515
|
-
|
516
|
-
describe '#send_message' do
|
517
|
-
spec{ use{ success = send_message(handle = 0, msg = 0, w_param = 1024, l_param = "\x0"*1024) }}
|
518
|
-
# handle (L) - Handle to the window whose window procedure is to receive the message. The following values have special meanings.
|
519
|
-
# HWND_BROADCAST - The message is posted to all top-level windows in the system, including disabled or invisible unowned windows,
|
520
|
-
# overlapped windows, and pop-up windows. The message is not posted to child windows.
|
521
|
-
# NULL - The function behaves like a call to PostThreadMessage with the dwThreadId parameter set to the identifier of the current thread.
|
522
|
-
# msg (L) - Specifies the message to be posted.
|
523
|
-
# w_param (L) - Specifies additional message-specific information.
|
524
|
-
# l_param (L) - Specifies additional message-specific information.
|
525
|
-
# return (L) - Nonzero if success, zero if function failed. To get extended error information, call GetLastError.
|
526
|
-
|
527
|
-
it 'sends the specified message to a window or windows'
|
528
|
-
it 'calls the window procedure and does not return until the window procedure has processed the message'
|
529
|
-
end
|
530
|
-
|
531
|
-
describe '#get_dlg_item' do
|
532
|
-
spec{ use{ control_handle = get_dlg_item(handle = 0, item_id = 1) }}
|
533
|
-
# handle (L) - Handle of the dialog box that contains the control.
|
534
|
-
# item_id (I) - Specifies the identifier of the control to be retrieved.
|
535
|
-
# Returns (L) - handle of the specified control if success or nil for invalid dialog box handle or a nonexistent control.
|
536
|
-
# To get extended error information, call GetLastError.
|
537
|
-
# You can use the GetDlgItem function with any parent-child window pair, not just with dialog boxes. As long as the handle
|
538
|
-
# parameter specifies a parent window and the child window has a unique id (as specified by the hMenu parameter in the
|
539
|
-
# CreateWindow or CreateWindowEx function that created the child window), GetDlgItem returns a valid handle to the child window.
|
540
|
-
|
541
|
-
it 'returns handle to correctly specified control'
|
542
|
-
end
|
543
452
|
end
|
544
|
-
end
|
453
|
+
end
|
454
|
+
|
data/spec/win/library_spec.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
2
|
require 'win/library'
|
3
3
|
|
4
|
-
module
|
4
|
+
module WinLibraryTest
|
5
|
+
|
6
|
+
include WinTest
|
5
7
|
|
6
8
|
module MyLib # namespace for defined functions
|
7
9
|
include Win::Library
|
@@ -40,10 +42,6 @@ module WinTest
|
|
40
42
|
find_window(nil, nil)
|
41
43
|
end
|
42
44
|
|
43
|
-
def not_a_handle
|
44
|
-
123
|
45
|
-
end
|
46
|
-
|
47
45
|
def redefined_methods
|
48
46
|
[:FindWindow, :IsWindow, :EnumWindows, :GetComputerName, :GetForegroundWindow]
|
49
47
|
end
|
@@ -366,6 +364,5 @@ module WinTest
|
|
366
364
|
expect { enum_windows('Message'){|handle, message| true } }.to_not raise_error
|
367
365
|
end
|
368
366
|
end
|
369
|
-
|
370
367
|
end
|
371
368
|
end
|
data/win.gemspec
CHANGED
@@ -5,12 +5,12 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{win}
|
8
|
-
s.version = "0.0
|
8
|
+
s.version = "0.1.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["arvicco"]
|
12
|
-
s.date = %q{2010-02-
|
13
|
-
s.description = %q{
|
12
|
+
s.date = %q{2010-02-15}
|
13
|
+
s.description = %q{Rubyesque interfaces and wrappers for Windows API functions pre-defined using FFI }
|
14
14
|
s.email = %q{arvitallian@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"LICENSE",
|
@@ -28,31 +28,41 @@ Gem::Specification.new do |s|
|
|
28
28
|
"features/win.feature",
|
29
29
|
"lib/win/dde.rb",
|
30
30
|
"lib/win/extensions.rb",
|
31
|
+
"lib/win/gui.rb",
|
32
|
+
"lib/win/gui/convenience.rb",
|
33
|
+
"lib/win/gui/dialog.rb",
|
34
|
+
"lib/win/gui/input.rb",
|
35
|
+
"lib/win/gui/message.rb",
|
36
|
+
"lib/win/gui/window.rb",
|
31
37
|
"lib/win/library.rb",
|
32
|
-
"lib/win/window.rb",
|
33
|
-
"lib/win/window/extra.rb",
|
34
38
|
"spec/spec.opts",
|
35
39
|
"spec/spec_helper.rb",
|
36
40
|
"spec/test_apps/locknote/LockNote.exe",
|
37
41
|
"spec/win/dde_spec.rb",
|
38
42
|
"spec/win/extensions_spec.rb",
|
43
|
+
"spec/win/gui/convenience_spec.rb",
|
44
|
+
"spec/win/gui/dialog_spec.rb",
|
45
|
+
"spec/win/gui/input_spec.rb",
|
46
|
+
"spec/win/gui/message_spec.rb",
|
47
|
+
"spec/win/gui/window_spec.rb",
|
39
48
|
"spec/win/library_spec.rb",
|
40
|
-
"spec/win/window/extra_spec.rb",
|
41
|
-
"spec/win/window_spec.rb",
|
42
49
|
"win.gemspec"
|
43
50
|
]
|
44
51
|
s.homepage = %q{http://github.com/arvicco/win}
|
45
52
|
s.rdoc_options = ["--charset=UTF-8"]
|
46
53
|
s.require_paths = ["lib"]
|
47
54
|
s.rubygems_version = %q{1.3.5}
|
48
|
-
s.summary = %q{
|
55
|
+
s.summary = %q{Rubyesque interfaces and wrappers for Windows API functions pre-defined using FFI}
|
49
56
|
s.test_files = [
|
50
57
|
"spec/spec_helper.rb",
|
51
58
|
"spec/win/dde_spec.rb",
|
52
59
|
"spec/win/extensions_spec.rb",
|
53
|
-
"spec/win/
|
54
|
-
"spec/win/
|
55
|
-
"spec/win/
|
60
|
+
"spec/win/gui/convenience_spec.rb",
|
61
|
+
"spec/win/gui/dialog_spec.rb",
|
62
|
+
"spec/win/gui/input_spec.rb",
|
63
|
+
"spec/win/gui/message_spec.rb",
|
64
|
+
"spec/win/gui/window_spec.rb",
|
65
|
+
"spec/win/library_spec.rb"
|
56
66
|
]
|
57
67
|
|
58
68
|
if s.respond_to? :specification_version then
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: win
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- arvicco
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-02-
|
12
|
+
date: 2010-02-15 00:00:00 +03:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -42,7 +42,7 @@ dependencies:
|
|
42
42
|
- !ruby/object:Gem::Version
|
43
43
|
version: "0"
|
44
44
|
version:
|
45
|
-
description:
|
45
|
+
description: "Rubyesque interfaces and wrappers for Windows API functions pre-defined using FFI "
|
46
46
|
email: arvitallian@gmail.com
|
47
47
|
executables: []
|
48
48
|
|
@@ -63,17 +63,24 @@ files:
|
|
63
63
|
- features/win.feature
|
64
64
|
- lib/win/dde.rb
|
65
65
|
- lib/win/extensions.rb
|
66
|
+
- lib/win/gui.rb
|
67
|
+
- lib/win/gui/convenience.rb
|
68
|
+
- lib/win/gui/dialog.rb
|
69
|
+
- lib/win/gui/input.rb
|
70
|
+
- lib/win/gui/message.rb
|
71
|
+
- lib/win/gui/window.rb
|
66
72
|
- lib/win/library.rb
|
67
|
-
- lib/win/window.rb
|
68
|
-
- lib/win/window/extra.rb
|
69
73
|
- spec/spec.opts
|
70
74
|
- spec/spec_helper.rb
|
71
75
|
- spec/test_apps/locknote/LockNote.exe
|
72
76
|
- spec/win/dde_spec.rb
|
73
77
|
- spec/win/extensions_spec.rb
|
78
|
+
- spec/win/gui/convenience_spec.rb
|
79
|
+
- spec/win/gui/dialog_spec.rb
|
80
|
+
- spec/win/gui/input_spec.rb
|
81
|
+
- spec/win/gui/message_spec.rb
|
82
|
+
- spec/win/gui/window_spec.rb
|
74
83
|
- spec/win/library_spec.rb
|
75
|
-
- spec/win/window/extra_spec.rb
|
76
|
-
- spec/win/window_spec.rb
|
77
84
|
- win.gemspec
|
78
85
|
has_rdoc: true
|
79
86
|
homepage: http://github.com/arvicco/win
|
@@ -102,11 +109,14 @@ rubyforge_project:
|
|
102
109
|
rubygems_version: 1.3.5
|
103
110
|
signing_key:
|
104
111
|
specification_version: 3
|
105
|
-
summary:
|
112
|
+
summary: Rubyesque interfaces and wrappers for Windows API functions pre-defined using FFI
|
106
113
|
test_files:
|
107
114
|
- spec/spec_helper.rb
|
108
115
|
- spec/win/dde_spec.rb
|
109
116
|
- spec/win/extensions_spec.rb
|
117
|
+
- spec/win/gui/convenience_spec.rb
|
118
|
+
- spec/win/gui/dialog_spec.rb
|
119
|
+
- spec/win/gui/input_spec.rb
|
120
|
+
- spec/win/gui/message_spec.rb
|
121
|
+
- spec/win/gui/window_spec.rb
|
110
122
|
- spec/win/library_spec.rb
|
111
|
-
- spec/win/window/extra_spec.rb
|
112
|
-
- spec/win/window_spec.rb
|
data/lib/win/window/extra.rb
DELETED
@@ -1,113 +0,0 @@
|
|
1
|
-
require 'win/library'
|
2
|
-
require 'win/window'
|
3
|
-
|
4
|
-
module Win
|
5
|
-
module Window
|
6
|
-
# Wait delay quant
|
7
|
-
SLEEP_DELAY = 0.001
|
8
|
-
# Timeout waiting for Window to be closed
|
9
|
-
CLOSE_TIMEOUT = 1
|
10
|
-
|
11
|
-
# Convenience wrapper methods:
|
12
|
-
|
13
|
-
# emulates combinations of keys pressed (Ctrl+Alt+P+M, etc)
|
14
|
-
def keystroke(*keys)
|
15
|
-
return if keys.empty?
|
16
|
-
keybd_event keys.first, 0, KEYEVENTF_KEYDOWN, 0
|
17
|
-
sleep KEY_DELAY
|
18
|
-
keystroke *keys[1..-1]
|
19
|
-
sleep KEY_DELAY
|
20
|
-
keybd_event keys.first, 0, KEYEVENTF_KEYUP, 0
|
21
|
-
end
|
22
|
-
|
23
|
-
# types text message into window holding the focus
|
24
|
-
def type_in(message)
|
25
|
-
message.scan(/./m) do |char|
|
26
|
-
keystroke(*char.to_vkeys)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# finds top-level dialog window by title and yields it to given block
|
31
|
-
def dialog(title, seconds=3)
|
32
|
-
d = begin
|
33
|
-
win = Window.top_level(title, seconds)
|
34
|
-
yield(win) ? win : nil
|
35
|
-
rescue TimeoutError
|
36
|
-
end
|
37
|
-
d.wait_for_close if d
|
38
|
-
return d
|
39
|
-
end
|
40
|
-
|
41
|
-
|
42
|
-
# Thin class is a thin wrapper around window handle
|
43
|
-
class Window
|
44
|
-
include Win::Window
|
45
|
-
extend Win::Window
|
46
|
-
|
47
|
-
attr_reader :handle
|
48
|
-
|
49
|
-
# find top level window by title, return wrapped Window object
|
50
|
-
def self.top_level(title, seconds=3)
|
51
|
-
@handle = timeout(seconds) do
|
52
|
-
sleep SLEEP_DELAY while (h = find_window nil, title) == nil; h
|
53
|
-
end
|
54
|
-
Window.new @handle
|
55
|
-
end
|
56
|
-
|
57
|
-
def initialize(handle)
|
58
|
-
@handle = handle
|
59
|
-
end
|
60
|
-
|
61
|
-
# find child window (control) by title, window class, or control ID:
|
62
|
-
def child(id)
|
63
|
-
result = case id
|
64
|
-
when String
|
65
|
-
by_title = find_window_ex @handle, 0, nil, id.gsub('_', '&' )
|
66
|
-
by_class = find_window_ex @handle, 0, id, nil
|
67
|
-
by_title ? by_title : by_class
|
68
|
-
when Fixnum
|
69
|
-
get_dlg_item @handle, id
|
70
|
-
when nil
|
71
|
-
find_window_ex @handle, 0, nil, nil
|
72
|
-
else
|
73
|
-
nil
|
74
|
-
end
|
75
|
-
raise "Control '#{id}' not found" unless result
|
76
|
-
Window.new result
|
77
|
-
end
|
78
|
-
|
79
|
-
def children
|
80
|
-
enum_child_windows(@handle).map{|child_handle| Window.new child_handle}
|
81
|
-
end
|
82
|
-
|
83
|
-
# emulate click of the control identified by id
|
84
|
-
def click(id)
|
85
|
-
h = child(id).handle
|
86
|
-
rectangle = [0, 0, 0, 0].pack 'LLLL'
|
87
|
-
get_window_rect h, rectangle
|
88
|
-
left, top, right, bottom = rectangle.unpack 'LLLL'
|
89
|
-
center = [(left + right) / 2, (top + bottom) / 2]
|
90
|
-
set_cursor_pos *center
|
91
|
-
mouse_event MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
|
92
|
-
mouse_event MOUSEEVENTF_LEFTUP, 0, 0, 0, 0
|
93
|
-
end
|
94
|
-
|
95
|
-
def close
|
96
|
-
post_message @handle, WM_SYSCOMMAND, SC_CLOSE, 0
|
97
|
-
end
|
98
|
-
|
99
|
-
def wait_for_close
|
100
|
-
timeout(CLOSE_TIMEOUT) do
|
101
|
-
sleep SLEEP_DELAY while window_visible?(@handle)
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def text
|
106
|
-
buffer = "\x0" * 2048
|
107
|
-
length = send_message @handle, WM_GETTEXT, buffer.length, buffer
|
108
|
-
length == 0 ? '' : buffer[0..length - 1]
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
end
|
113
|
-
end
|