win_gui 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -1,6 +1,6 @@
1
1
  = win_gui
2
2
  by: Arvicco
3
- url: http://github.com/arvicco/git_hub
3
+ url: http://github.com/arvicco/win_gui
4
4
 
5
5
  == DESCRIPTION:
6
6
 
@@ -12,30 +12,32 @@ In addition to straightforward API wrappers, it also defines more Ruby-like
12
12
  abstractions and convenience methods for manipulating windows and other GUI
13
13
  elements (such as WinGui::Window class and its methods).
14
14
 
15
- It is still work in progress, only a small number of API functions wrapped so far...
15
+ It is still work in progress, only a small number of user32 API functions wrapped so far...
16
16
 
17
17
  == SUMMARY
18
18
 
19
19
  So you want to write a simple program that makes some Win32 API function calls.
20
- You searched MSDN and you know what functions you'll need. Now you just want to
21
- put those calls into your Ruby code. You'd love it to be a natural extension of
22
- Ruby code, preferably not turning your code base into a ugly C++ like spaghetty
20
+ You searched MSDN high and low and you now know exactly what functions you need.
21
+ All you want is just putting those function calls into your Ruby code without too
22
+ much pain. You'd love this to be more or less natural extension of your Ruby code,
23
+ preferably not turning your code base into an ugly C++ like spaghetty
23
24
  of CamelCase calls, String/Array pack/unpack gymnastics, buffer allocations,
24
25
  extracting return values from [in/out] parameters and checking return codes for 0.
26
+
25
27
  You can definitely use excellent 'win32-api' gem by Daniel J. Berger and Park Heesob
26
28
  that allows you to define Win32 API objects for any function you can find on MSDN,
27
29
  execute calls on them and even define callback objects that some of those API functions expect.
28
30
 
29
- However, this gem will only take you so far. You'll still have to handle (somewhat)
31
+ However, that gem will only take you so far. You'll still have to handle (somewhat)
30
32
  gory details of argument preparation, mimicking pointers with Strings and stuff.
31
33
  For example, consider the amount of code needed to complete a task as simple as
32
34
  getting unicode title text for the window that you already have handle for:
33
35
 
34
36
  api = Win32::API.new( 'GetWindowTextW', ['L', 'P', 'I'], 'L', 'user32' )
35
- buffer = "\x00" * 1024
37
+ buffer = "\x00" * 1024 # I just hope it will be enough...
36
38
  num_chars = api.call( window_handle, buffer, buffer.size)
37
39
  title = if num_chars == 0
38
- nil
40
+ nil
39
41
  else
40
42
  buffer.force_encoding('utf-16LE').encode('utf-8').rstrip
41
43
  end
@@ -45,7 +47,7 @@ Ew, ugly. What about getting information about process id for a known window?
45
47
  api = Win32::API.new( 'GetWindowThreadProcessId', ['L', 'P'], 'L' , 'user32' )
46
48
  process_packed = [1].pack('L')
47
49
  thread = api.call(window_handle, process_packed)
48
- process = process.unpack('L').first
50
+ process = process_packed.unpack('L').first
49
51
 
50
52
  Wow, packing and unpacking arrays into String to get hold of a simple integer id.
51
53
  Just great. Now, wouldn't it be MUCH better if you can just say something like this:
@@ -57,9 +59,9 @@ What about API functions expecting callbacks? Well, something like this may be n
57
59
 
58
60
  enum_child_windows( parent_handle, message ){|child_handle, message| puts child_handle }
59
61
 
60
- If you think about it, callbacks are not much than more than code blocks, so let's not
61
- be afraid to treat them as such. It would be also good if test functions return true/false
62
- instead of zero/nonzero, find functions return nil if nothing was found etc...
62
+ If you think about it, callbacks are not much more than code blocks, so let's not be afraid
63
+ to treat them as such. It would be also good if test functions return true/false instead of
64
+ zero/nonzero, find functions return nil if nothing was found etc...
63
65
 
64
66
  So this is an idea behind WinGui library - make Win32 API functions more fun to use
65
67
  and feel more natural inside Ruby code. Following the principle of least surprise, we
@@ -70,7 +72,12 @@ Well, we even keep a backup solution for those diehard Win32 API longtimers who
70
72
  allocate their buffer strings by hand and mess with obscure return codes. If you use original
71
73
  CamelCase method name instead of Rubyesque snake_case one, it will expect those standard
72
74
  parameters you know and love from MSDN, return your zeroes instead of nils and support no
73
- other enhancements. Enjoy!
75
+ other enhancements.
76
+
77
+ And if you do not see your favorite Windows API function amoung those already defined, it is
78
+ quite easy to define new one with def_api class method that does a lot of heavy lifting for
79
+ you and can be customized with options and code blocks to give you reusable API wrapper method
80
+ with the exact behavior you need.
74
81
 
75
82
  == DOCUMENTATION:
76
83
 
@@ -83,7 +90,7 @@ arguments given to block, etc...)
83
90
 
84
91
  == FEATURES/PROBLEMS:
85
92
 
86
- This project is quite new, so it's may be not suitable for production-quality systems
93
+ This project is quite new, so it may be not suitable for production-quality systems yet.
87
94
  Contributors always welcome!
88
95
 
89
96
  == INSTALL:
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.3
1
+ 0.1.4
@@ -33,37 +33,53 @@ module WinGui
33
33
  # :zeronil:: Forces method to return nil if function result is zero
34
34
  #
35
35
  def def_api(function, params, returns, options={}, &define_block)
36
+ name, aliases = generate_names(function, options)
37
+ boolean = options[:boolean]
38
+ zeronil = options[:zeronil]
39
+ proto = params.respond_to?(:join) ? params.join : params # Convert params into prototype string
40
+ api = Win32::API.new(function, proto.upcase, returns.upcase, options[:dll] || DEFAULT_DLL)
41
+
42
+ define_method(function) {|*args| api.call(*args)} # define CamelCase method wrapper for api call
43
+
44
+ define_method(name) do |*args, &runtime_block| # define snake_case method with enhanced api
45
+ return api if args == [:api]
46
+ return define_block[api, *args, &runtime_block] if define_block
47
+ WinGui.enforce_count(args, proto)
48
+ result = api.call(*args)
49
+ result = runtime_block[result] if runtime_block
50
+ return result != 0 if boolean # Boolean function returns true/false instead of nonzero/zero
51
+ return nil if zeronil && result == 0 # Zeronil function returns nil instead of zero
52
+ result
53
+ end
54
+ aliases.each {|ali| alias_method ali, name } # define aliases
55
+ end
56
+
57
+ # Generates name and aliases for defined method based on function name,
58
+ # sets boolean flag for test functions (Is...)
59
+ #
60
+ def generate_names(function, options)
36
61
  aliases = ([options[:alias]] + [options[:aliases]]).flatten.compact
37
62
  name = options[:rename] || function.snake_case
38
63
  case name
39
64
  when /^is_/
40
65
  aliases << name.sub(/^is_/, '') + '?'
41
- boolean = true
66
+ options[:boolean] = true
42
67
  when /^set_/
43
68
  aliases << name.sub(/^set_/, '')+ '='
44
69
  when /^get_/
45
70
  aliases << name.sub(/^get_/, '')
46
71
  end
47
- boolean ||= options[:boolean]
48
- zeronil = options[:zeronil]
49
- proto = params.respond_to?(:join) ? params.join : params # Converts params into prototype string
50
- api = Win32::API.new(function, proto.upcase, returns.upcase, options[:dll] || DEFAULT_DLL)
51
-
52
- define_method(function) {|*args| api.call(*args)} # defines CamelCase method wrapper for api call
72
+ [name, aliases]
73
+ end
53
74
 
54
- define_method(name) do |*args, &runtime_block| # defines snake_case method with enhanced api
55
- return api if args == [:api]
56
- return define_block.call(api, *args, &runtime_block) if define_block
57
- unless args.size == params.size
58
- raise ArgumentError, "wrong number of parameters: expected #{params.size}, got #{args.size}"
59
- end
60
- result = api.call(*args)
61
- result = runtime_block[result] if runtime_block
62
- return result != 0 if boolean # Boolean function returns true/false instead of nonzero/zero
63
- return nil if zeronil && result == 0
64
- result
75
+ # Ensures that args count is equal to params count plus diff
76
+ #
77
+ def enforce_count(args, params, diff = 0)
78
+ num_args = args.size
79
+ num_params = params == 'V' ? 0 : params.size + diff
80
+ if num_args != num_params
81
+ raise ArgumentError, "wrong number of parameters: expected #{num_params}, got #{num_args}"
65
82
  end
66
- aliases.each {|ali| alias_method ali, name } unless aliases == []
67
83
  end
68
84
 
69
85
  # Converts block into API::Callback object that can be used as API callback argument
@@ -80,15 +96,19 @@ module WinGui
80
96
  code * size
81
97
  end
82
98
 
99
+ # Returns array of given args if none of them is zero,
100
+ # if any arg is zero, returns array of nils
101
+ #
102
+ def nonzero_array(*args)
103
+ args.any?{|arg| arg == 0 } ? args.map{||nil} : args
104
+ end
105
+
83
106
  # Procedure that returns (possibly encoded) string as a result of api function call
84
107
  # or nil if zero characters was returned by api call
85
108
  #
86
109
  def return_string( encode = nil )
87
110
  lambda do |api, *args|
88
- num_params = api.prototype.size-2
89
- unless args.size == num_params
90
- raise ArgumentError, "wrong number of parameters: expected #{num_params}, got #{args.size}"
91
- end
111
+ WinGui.enforce_count( args, api.prototype, -2)
92
112
  args += [string = buffer, string.length]
93
113
  num_chars = api.call(*args)
94
114
  return nil if num_chars == 0
@@ -103,10 +123,7 @@ module WinGui
103
123
  #
104
124
  def return_enum
105
125
  lambda do |api, *args, &block|
106
- num_params = api.prototype.size-1
107
- unless args.size == num_params
108
- raise ArgumentError, "wrong number of parameters: expected #{num_params}, got #{args.size}"
109
- end
126
+ WinGui.enforce_count( args, api.prototype, -1)
110
127
  handles = []
111
128
  cb = if block
112
129
  callback('LP', 'I', &block)
@@ -131,10 +148,9 @@ module WinGui
131
148
  lambda do |api, id=0, cmd, &block|
132
149
  raise ArgumentError, 'No callback block' unless block
133
150
  callback = callback 'IIPPPPPP', 'L', &block
134
- id = [id].pack('L')
135
151
 
136
- status = api.call(id, callback, cmd, 0)
137
- [*id.unpack('L'), status]
152
+ status = api.call(id = [id].pack('L'), callback, cmd, 0)
153
+ nonzero_array(*id.unpack('L'), status)
138
154
  end
139
155
  end
140
156
 
@@ -15,7 +15,6 @@ require 'window'
15
15
  module WinGui
16
16
  extend DefApi
17
17
 
18
-
19
18
  # Windows GUI API definitions:
20
19
 
21
20
  ##
@@ -78,7 +77,7 @@ module WinGui
78
77
  # title matches the win_title parameter.
79
78
  # win_name (P) - String that specifies the window name (title). If nil, all names match.
80
79
  # Return Value (L): found window handle or NIL if nothing found
81
-
80
+ #
82
81
  # :call-seq:
83
82
  # win_handle = find_window( class_name, win_name )
84
83
  #
@@ -107,7 +106,7 @@ module WinGui
107
106
  # win_class (P), win_title (P) - Strings that specify window class and name(title). If nil, anything matches.
108
107
  # Returns (L): found child window handle or NIL if nothing found
109
108
  #
110
- #:call-seq:
109
+ # :call-seq:
111
110
  # win_handle = find_window_ex( win_handle, after_child, class_name, win_name )
112
111
  #
113
112
  def_api 'FindWindowEx', 'LLPP', 'L', zeronil: true
@@ -221,7 +220,7 @@ module WinGui
221
220
  SW_SHOWMINIMIZED = 2
222
221
  # Activates the window and displays it as a maximized window.
223
222
  SW_SHOWMAXIMIZED = 3
224
- # Maximizes the specified window.
223
+ # Activates the window and displays it as a maximized window.
225
224
  SW_MAXIMIZE = 3
226
225
  # Displays a window in its most recent size and position. Similar to SW_SHOWNORMAL, but the window is not activated.
227
226
  SW_SHOWNOACTIVATE = 4
@@ -243,8 +242,15 @@ module WinGui
243
242
  # flag when minimizing windows from a different thread.
244
243
  SW_FORCEMINIMIZE = 11
245
244
 
246
- def hide_window(handle)
247
- show_window(handle, SW_HIDE)
245
+ # Hides the window and activates another window
246
+ def hide_window(win_handle)
247
+ show_window(win_handle, SW_HIDE)
248
+ end
249
+
250
+ return_thread_process = lambda do |api, *args|
251
+ WinGui.enforce_count( args, api.prototype, -1)
252
+ thread = api.call(args.first, process = [1].pack('L'))
253
+ nonzero_array(thread, *process.unpack('L'))
248
254
  end
249
255
 
250
256
  ##
@@ -265,10 +271,13 @@ module WinGui
265
271
  #:call-seq:
266
272
  # thread, process_id = get_window_tread_process_id( win_handle )
267
273
  #
268
- def_api 'GetWindowThreadProcessId', 'LP', 'L' do |api, *args|
269
- raise 'Invalid args count' unless args.size == api.prototype.size-1
270
- thread = api.call(args.first, process = [1].pack('L'))
271
- [thread, *process.unpack('L')]
274
+ def_api 'GetWindowThreadProcessId', 'LP', 'L', &return_thread_process
275
+
276
+ return_rect = lambda do |api, *args|
277
+ WinGui.enforce_count( args, api.prototype, -1)
278
+ rectangle = [0, 0, 0, 0].pack('L*')
279
+ res = api.call args.first, rectangle
280
+ res == 0 ? [nil, nil, nil, nil] : rectangle.unpack('L*')
272
281
  end
273
282
 
274
283
  ##
@@ -293,12 +302,7 @@ module WinGui
293
302
  #:call-seq:
294
303
  # rect = get_window_rect( win_handle )
295
304
  #
296
- def_api 'GetWindowRect', 'LP', 'I' do |api, *args|
297
- raise 'Invalid args count' unless args.size == api.prototype.size-1
298
- rectangle = [0, 0, 0, 0].pack 'L*'
299
- api.call args.first, rectangle
300
- rectangle.unpack 'L*'
301
- end
305
+ def_api 'GetWindowRect', 'LP', 'I', &return_rect
302
306
 
303
307
  ##
304
308
  # The EnumWindows function enumerates all top-level windows on the screen by passing the handle to
@@ -356,9 +360,43 @@ module WinGui
356
360
  #
357
361
  #:call-seq:
358
362
  # enum_windows( parent_handle, message ) {|win_handle, message| callback procedure }
363
+ #
359
364
  def_api 'EnumChildWindows', 'LKP', 'L', &return_enum
360
365
 
366
+ ##
367
+ # GetForegroundWindow function returns a handle to the foreground window (the window with which the user
368
+ # is currently working). The system assigns a slightly higher priority to the thread that creates the
369
+ # foreground window than it does to other threads.
370
+ #
371
+ # Syntax: HWND GetForegroundWindow(VOID);
372
+ #
373
+ # Return Value: The return value is a handle to the foreground window. The foreground window can be NULL in
374
+ # certain circumstances, such as when a window is losing activation.
375
+ #
376
+ #:call-seq:
377
+ # win_handle = (get_)foreground_window()
378
+ #
361
379
  def_api 'GetForegroundWindow', 'V', 'L'
380
+
381
+ def foreground?(win_handle)
382
+ win_handle == foreground_window
383
+ end
384
+
385
+ ##
386
+ # The GetActiveWindow function retrieves the window handle to the active window attached to
387
+ # the calling thread's message queue.
388
+ #
389
+ # Syntax: HWND GetActiveWindow(VOID);
390
+ #
391
+ # Return Value: The return value is the handle to the active window attached to the calling
392
+ # thread's message queue. Otherwise, the return value is NULL.
393
+ #
394
+ # Remarks: To get the handle to the foreground window, you can use GetForegroundWindow.
395
+ # To get the window handle to the active window in the message queue for another thread, use GetGUIThreadInfo.
396
+ #
397
+ #:call-seq:
398
+ # win_handle = (get_)active_window()
399
+ #
362
400
  def_api 'GetActiveWindow', 'V', 'L'
363
401
 
364
402
  def_api 'keybd_event', 'IILL', 'V'
data/spec/spec_helper.rb CHANGED
@@ -38,6 +38,7 @@ module GuiTest
38
38
  TEST_MAX_RECT = [-4, -4, 1924, 1204] # on my 1920x1200 display
39
39
  TEST_MIN_RECT = [-32000, -32000, -31840, -31976]
40
40
  TEST_TEXTAREA_CLASS = 'ATL:00434310'
41
+ TEST_STATUSBAR_CLASS = 'msctls_statusbar32'
41
42
  TEST_IMPOSSIBLE = 'Impossible'
42
43
  TEST_ERROR_CONVERSION = /Can.t convert/
43
44
 
@@ -60,23 +61,29 @@ module GuiTest
60
61
  end
61
62
 
62
63
  def hide_method(*names) # hide original method(s) if it is defined
63
- names.each do |name|
64
+ names.map(&:to_s).each do |name|
64
65
  WinGui.module_eval do
65
- if method_defined? name.to_sym
66
- alias_method "orig_#{name.to_s}".to_sym, name.to_sym
67
- remove_method name.to_sym
66
+ aliases = generate_names(name, {}).flatten + [name]
67
+ aliases.map(&:to_s).each do |ali|
68
+ if method_defined? ali
69
+ alias_method "orig_#{ali}".to_sym, ali
70
+ remove_method ali
71
+ end
68
72
  end
69
73
  end
70
74
  end
71
75
  end
72
76
 
73
77
  def restore_method(*names) # restore original method if it was hidden
74
- names.each do |name|
78
+ names.map(&:to_s).each do |name|
75
79
  WinGui.module_eval do
76
- temp = "orig_#{name.to_s}".to_sym
77
- if method_defined? temp
78
- alias_method name.to_sym, temp
79
- remove_method temp
80
+ aliases = generate_names(name, {}).flatten + [name]
81
+ aliases.map(&:to_s).each do |ali|
82
+ temp = "orig_#{ali}".to_sym
83
+ if method_defined? temp
84
+ alias_method ali, temp
85
+ remove_method temp
86
+ end
80
87
  end
81
88
  end
82
89
  end
@@ -13,14 +13,14 @@ module GuiTest
13
13
  end
14
14
 
15
15
  def redefined_methods
16
- [:find_window, :is_window, :window?, :enum_windows, :get_computer_name, :computer_name]
16
+ [:FindWindow, :IsWindow, :EnumWindows, :GetComputerName, :GetForegroundWindow]
17
17
  end
18
18
 
19
19
  def should_count_args(*methods, rights, wrongs)
20
20
  rights = [rights].flatten
21
21
  wrongs = [wrongs].flatten
22
22
  methods.each do |method|
23
- (1..8).each do |n|
23
+ (0..8).each do |n|
24
24
  if n == rights.size
25
25
  expect {send method, *rights}.to_not raise_error
26
26
  else
@@ -302,6 +302,21 @@ module GuiTest
302
302
  end
303
303
  end
304
304
 
305
+ context 'defining API function without arguments - f(VOID)' do
306
+ it 'should enforce argument count to 0, NOT 1 (enhanced methods)' do
307
+ WinGui.def_api 'GetForegroundWindow', 'V', 'L', zeronil: true
308
+ should_count_args :get_foreground_window, :foreground_window, [], [nil, 0, 123]
309
+ end
310
+
311
+ it 'should NOT enforce argument count (raw method)' do
312
+ WinGui.def_api 'GetForegroundWindow', 'V', 'L', zeronil: true
313
+ expect {GetForegroundWindow()}.to_not raise_error
314
+ expect {GetForegroundWindow(nil)}.to_not raise_error
315
+ expect {GetForegroundWindow(1,2)}.to_not raise_error
316
+ expect {GetForegroundWindow(1,2,3)}.to_not raise_error
317
+ end
318
+ end
319
+
305
320
  context 'working with API function callbacks' do
306
321
  it '#callback method creates a valid callback object' do
307
322
  expect { @callback = WinGui.callback('LP', 'I') {|handle, message| true} }.to_not raise_error
@@ -1,41 +1,64 @@
1
1
  require File.join(File.dirname(__FILE__), "..", "spec_helper" )
2
2
 
3
3
  module GuiTest
4
+ def test_show_window *cmds, tests
5
+ cmds.each do |cmd|
6
+ test_app do |app|
7
+ show_window(app.handle, cmd)
8
+ tests.each{|test, result| send(test.to_sym, app.handle).should == result}
9
+
10
+ hide_window(app.handle) # hiding window first
11
+ show_window(app.handle, cmd)
12
+ tests.each{|test, result| send(test.to_sym, app.handle).should == result}
13
+
14
+ show_window(app.handle, SW_MAXIMIZE) # now maximizing window
15
+ show_window(app.handle, cmd)
16
+ tests.each{|test, result| send(test.to_sym, app.handle).should == result}
17
+
18
+ show_window(app.handle, SW_MINIMIZE) # now minimizing window
19
+ show_window(app.handle, cmd)
20
+ tests.each{|test, result| send(test.to_sym, app.handle).should == result}
21
+ end
22
+ end
23
+ end
24
+
4
25
  describe WinGui, ' contains a set of pre-defined GUI functions' do
5
26
  describe '#window?' do
6
- spec{ use{ window?(handle = 0) }}
27
+ spec{ use{ IsWindow(any_handle) }}
28
+ spec{ use{ is_window(any_handle) }}
29
+ spec{ use{ window?(any_handle) }}
7
30
 
8
31
  it 'returns true if window exists' do
9
- test_app do |app|
10
- window?(app.handle).should == true
11
- window?(app.textarea.handle).should == true
12
- end
32
+ window?(any_handle).should == true
33
+ end
34
+
35
+ it 'returns false for invalid window handle' do
36
+ window?(not_a_handle).should == false
13
37
  end
14
38
 
15
- it 'returns false if window does not exist' do
39
+ it 'changes from true to false when existing window is closed' do
16
40
  test_app do |app|
17
41
  @app_handle = app.handle
18
42
  @ta_handle = app.textarea.handle
43
+ window?(@app_handle).should == true
44
+ window?(@ta_handle).should == true
19
45
  end
20
46
  window?(@app_handle).should == false
21
47
  window?(@ta_handle).should == false
22
48
  end
23
49
  end
24
50
 
25
- describe '#window_visible?' do
26
- spec{ use{ window_visible?(handle = any_handle) }}
27
- spec{ use{ visible?(handle = any_handle) }}
51
+ describe '#window_visible?' do
52
+ spec{ use{ IsWindowVisible(any_handle) }}
53
+ spec{ use{ is_window_visible(any_handle) }}
54
+ spec{ use{ window_visible?(any_handle) }}
55
+ spec{ use{ visible?(any_handle) }}
28
56
 
29
- it 'returns true if window is visible' do
57
+ it 'returns true when window is visible, false when window is hidden' do
30
58
  test_app do |app|
31
59
  visible?(app.handle).should == true
32
60
  window_visible?(app.handle).should == true
33
61
  window_visible?(app.textarea.handle).should == true
34
- end
35
- end
36
-
37
- it 'returns false if window is not visible' do
38
- test_app do |app|
39
62
  hide_window(app.handle)
40
63
  visible?(app.handle).should == false
41
64
  window_visible?(app.handle).should == false
@@ -45,19 +68,15 @@ module GuiTest
45
68
  end
46
69
 
47
70
  describe '#maximized?' do
48
- spec{ use{ zoomed?(handle = 0) }}
49
- spec{ use{ maximized?(handle = 0) }}
50
- # Tests whether the specified window is maximized.
71
+ spec{ use{ IsZoomed(any_handle) }}
72
+ spec{ use{ is_zoomed(any_handle) }}
73
+ spec{ use{ zoomed?(any_handle) }}
74
+ spec{ use{ maximized?(any_handle) }}
51
75
 
52
- it 'returns false if window is not maximized' do
76
+ it 'returns true if the window is maximized, false otherwise' do
53
77
  test_app do |app|
54
78
  zoomed?(app.handle).should == false
55
79
  maximized?(app.handle).should == false
56
- end
57
- end
58
-
59
- it 'returns true if the window is maximized' do
60
- test_app do |app|
61
80
  show_window(app.handle, SW_MAXIMIZE)
62
81
  maximized?(app.handle).should == true
63
82
  zoomed?(app.handle).should == true
@@ -66,19 +85,15 @@ module GuiTest
66
85
  end
67
86
 
68
87
  describe '#minimized?' do
69
- spec{ use{ iconic?(handle = 0) }}
70
- spec{ use{ minimized?(handle = 0) }}
71
- # Tests whether the specified window is minimized.
88
+ spec{ use{ IsIconic(any_handle) }}
89
+ spec{ use{ is_iconic(any_handle) }}
90
+ spec{ use{ iconic?(any_handle) }}
91
+ spec{ use{ minimized?(any_handle) }}
72
92
 
73
- it 'returns false if window is not minimized' do
93
+ it 'returns true if the window is minimized, false otherwise' do
74
94
  test_app do |app|
75
95
  iconic?(app.handle).should == false
76
96
  minimized?(app.handle).should == false
77
- end
78
- end
79
-
80
- it 'returns true if the window is minimized' do
81
- test_app do |app|
82
97
  show_window(app.handle, SW_MINIMIZE)
83
98
  iconic?(app.handle).should == true
84
99
  minimized?(app.handle).should == true
@@ -87,74 +102,57 @@ module GuiTest
87
102
  end
88
103
 
89
104
  describe '#child?' do
105
+ spec{ use{ IsChild(parent_handle = any_handle, handle = any_handle) }}
106
+ spec{ use{ is_child(parent_handle = any_handle, handle = any_handle) }}
90
107
  spec{ use{ child?(parent_handle = any_handle, handle = any_handle) }}
91
- # Tests whether a window is a child (or descendant) window of a specified parent window. A child window is the direct descendant
92
- # of a specified parent window if that parent window is in the chain of parent windows; the chain of parent windows leads from
93
- # the original overlapped or pop-up window to the child window.
94
108
 
95
- it 'returns true if the window is a child' do
109
+ it 'returns true if the window is a child of given parent, false otherwise' do
96
110
  test_app do |app|
97
111
  child?(app.handle, app.textarea.handle).should == true
98
- end
99
- end
100
- it 'returns false if window is not a child' do
101
- test_app do |app|
102
112
  child?(app.handle, any_handle).should == false
103
113
  end
104
114
  end
105
115
  end
106
116
 
107
- describe '#find_window' do
117
+ describe '#find_window(w)' do
118
+ spec{ use{ FindWindow(class_name = nil, win_name = nil) }}
108
119
  spec{ use{ find_window(class_name = nil, win_name = nil) }}
120
+ # Widebyte (unicode) version
121
+ spec{ use{ FindWindowW(class_name = nil, win_name = nil) }}
122
+ spec{ use{ find_window_w(class_name = nil, win_name = nil) }}
109
123
 
110
124
  it 'returns either Integer Window handle or nil' do
111
125
  find_window(nil, nil).should be_a_kind_of Integer
112
- nil.class.should === find_window(TEST_IMPOSSIBLE, nil)
126
+ find_window(TEST_IMPOSSIBLE, nil).should == nil
113
127
  end
114
128
 
115
129
  it 'returns nil if Window is not found' do
116
130
  find_window(TEST_IMPOSSIBLE, nil).should == nil
117
131
  find_window(nil, TEST_IMPOSSIBLE).should == nil
118
132
  find_window(TEST_IMPOSSIBLE, TEST_IMPOSSIBLE).should == nil
119
- end
120
-
121
- it 'finds at least one window if both args are nils' do
122
- find_window(nil, nil).should_not == nil
123
- end
124
-
125
- it 'finds top-level window by window class' do
126
- test_app {|app| find_window(TEST_WIN_CLASS, nil).should == app.handle }
127
- end
128
-
129
- it 'finds top-level window by title' do
130
- test_app {|app| find_window(nil, TEST_WIN_TITLE).should == app.handle }
131
- end
132
- end
133
-
134
- describe '#find_window_w' do
135
- spec{ use{ find_window_w(class_name = nil, win_name = nil) }}
136
-
137
- it 'returns zero if Window is not found' do
138
133
  find_window_w(TEST_IMPOSSIBLE, nil).should == nil
139
134
  find_window_w(nil, TEST_IMPOSSIBLE).should == nil
140
135
  find_window_w(TEST_IMPOSSIBLE, TEST_IMPOSSIBLE).should == nil
141
136
  end
142
137
 
143
- it 'finds at least one window if given two nils' do
138
+ it 'finds at least one window if both args are nils' do
139
+ find_window(nil, nil).should_not == nil
144
140
  find_window_w(nil, nil).should_not == nil
145
141
  end
146
142
 
147
- it 'finds top-level window by window class' do
148
- test_app {|app| find_window_w(TEST_WIN_CLASS.to_w, nil).should == app.handle }
149
- end
150
-
151
- it 'finds top-level window by title' do
152
- test_app {|app| find_window_w(nil, TEST_WIN_TITLE.to_w).should == app.handle }
143
+ it 'finds top-level window by window class or title' do
144
+ test_app do |app|
145
+ find_window(TEST_WIN_CLASS, nil).should == app.handle
146
+ find_window(nil, TEST_WIN_TITLE).should == app.handle
147
+ find_window_w(TEST_WIN_CLASS.to_w, nil).should == app.handle
148
+ find_window_w(nil, TEST_WIN_TITLE.to_w).should == app.handle
149
+ end
153
150
  end
154
151
  end
155
152
 
156
153
  describe '#find_window_ex' do
157
- spec{ use{ control_handle = find_window_ex(parent = any_handle, after_child = 0, win_class = nil, win_title = nil) }}
154
+ spec{ use{ FindWindowEx(parent = any_handle, after_child = 0, win_class = nil, win_title = nil) }}
155
+ spec{ use{ find_window_ex(parent = any_handle, after_child = 0, win_class = nil, win_title = nil) }}
158
156
 
159
157
  it 'returns nil if wrong control is given' do
160
158
  parent_handle = any_handle
@@ -182,67 +180,115 @@ module GuiTest
182
180
  end
183
181
  end
184
182
 
185
- describe '#get_window_thread_process_id' do
186
- spec{ use{ thread, process = get_window_thread_process_id(handle = any_handle) }}
187
- # Improved with block to accept window handle as a single arg and return a pair of [thread, process]
183
+ describe '#get_foreground_window' do
184
+ # ! Different from GetActiveWindow !
185
+ spec{ use{ handle = GetForegroundWindow() }}
186
+ spec{ use{ handle = get_foreground_window }}
187
+ spec{ use{ handle = foreground_window }}
188
188
 
189
- it 'returns a pair of nonzero Integer ids (window thread and process)' do
190
- thread, process = get_window_thread_process_id(handle = any_handle)
191
- thread.should be_a_kind_of Integer
192
- thread.should be > 0
193
- process.should be_a_kind_of Integer
194
- process.should be > 0
189
+ it 'returns handle to window that is currently in foreground' do
190
+ test_app do |app|
191
+ @app_handle = app.handle
192
+ fg1 = foreground_window
193
+ @app_handle.should == fg1
194
+ end
195
+ fg2 = foreground_window
196
+ @app_handle.should_not == fg2
195
197
  end
196
- end
197
-
198
- describe '#get_window_text' do
199
- spec{ use{ text = get_window_text(handle = 0)}}
200
- # Improved with block to accept window handle as a single arg and return (rstripped) text string
201
198
 
202
- it 'returns nil if incorrect window handle given' do
203
- get_window_text(0).should == nil
199
+ it 'defines #foreground? test function ' do
200
+ test_app do |app|
201
+ @app_handle = app.handle
202
+ foreground?(@app_handle).should == true
203
+ end
204
+ foreground?(@app_handle).should == false
204
205
  end
206
+ end
205
207
 
206
- it 'returns correct window text' do
207
- test_app {|app| get_window_text(app.handle).should == TEST_WIN_TITLE }
208
+ describe '#get_active_window' do
209
+ # ! Different from GetForegroundWindow !
210
+ spec{ use{ handle = GetActiveWindow() }}
211
+ spec{ use{ handle = get_active_window }}
212
+ spec{ use{ handle = active_window }}
213
+
214
+ it 'returns handle to the active window attached to the calling thread`s message queue' do
215
+ pending 'No idea how to test it'
216
+ test_app do |app|
217
+ @app_handle = app.handle
218
+ fg1 = active_window
219
+ @app_handle.should == fg1
220
+ end
221
+ fg2 = active_window
222
+ @app_handle.should_not == fg2
208
223
  end
209
224
  end
210
225
 
211
- describe '#get_window_text_w' do
212
- spec{ use{ class_name = get_window_text_w(handle = 0)}} # result encoded as utf-8
226
+ describe '#get_window_text(w)' do
227
+ spec{ use{ GetWindowText(any_handle, buffer = "\00"* 1024, buffer.size)}}
228
+ # Improved with block to accept window handle as a single arg and return (rstripped) text string
229
+ spec{ use{ text = get_window_text(handle = 0)}}
213
230
  # Unicode version of get_window_text (strings returned encoded as utf-8)
231
+ spec{ use{ GetWindowTextW(any_handle, buffer = "\00"* 1024, buffer.size)}}
232
+ spec{ use{ text = get_window_text_w(any_handle)}} # result encoded as utf-8
214
233
 
215
234
  it 'returns nil if incorrect window handle given' do
216
- get_window_text(0).should == nil
235
+ get_window_text(not_a_handle).should == nil
236
+ get_window_text_w(not_a_handle).should == nil
217
237
  end
218
238
 
219
239
  it 'returns correct window text' do
220
- test_app {|app| get_window_text_w(app.handle).should == TEST_WIN_TITLE }
240
+ test_app do |app|
241
+ get_window_text(app.handle).should == TEST_WIN_TITLE
242
+ get_window_text_w(app.handle).should == TEST_WIN_TITLE
243
+ end
221
244
  end
222
245
  end
223
246
 
224
- describe '#get_class_name' do
225
- spec{ use{ class_name = get_class_name(handle = 0)}}
226
- # Improved with block to accept window handle as a single arg and return class name string
247
+ describe '#get_class_name(w)' do
248
+ spec{ use{ GetClassName(any_handle, buffer = "\00"* 1024, buffer.size)}}
249
+ # Improved with block to accept window handle as a single arg and return class name string
250
+ spec{ use{ class_name = get_class_name(any_handle)}}
251
+ # Unicode version of get_class_name (strings returned encoded as utf-8)
252
+ spec{ use{ GetClassNameW(any_handle, buffer = "\00"* 1024, buffer.size)}}
253
+ spec{ use{ class_name = get_class_name_w(handle = 0)}} # result encoded as utf-8
227
254
 
228
255
  it 'returns correct window class name' do
229
- test_app {|app| get_class_name(app.handle).should == TEST_WIN_CLASS }
256
+ test_app do |app|
257
+ get_class_name(app.handle).should == TEST_WIN_CLASS
258
+ get_class_name_w(app.handle).should == TEST_WIN_CLASS
259
+ end
230
260
  end
231
261
  end
232
262
 
233
- describe '#get_class_name_w' do
234
- spec{ use{ class_name = get_class_name_w(handle = 0)}} # result encoded as utf-8
235
- # Unicode version of get_class_name (strings returned encoded as utf-8)
263
+ describe '#get_window_thread_process_id' do
264
+ spec{ use{ thread = GetWindowThreadProcessId(any_handle, process_buffer = [1].pack('L')) }}
265
+ spec{ use{ thread, process = get_window_thread_process_id(any_handle) }}
266
+ # Improved with block to accept window handle as a single arg and return a pair of [thread, process]
236
267
 
237
- it 'returns correct window class name' do
238
- test_app {|app| get_class_name_w(app.handle).should == TEST_WIN_CLASS }
268
+ it 'returns a pair of nonzero Integer ids (thread and process) for valid window' do
269
+ thread, process = get_window_thread_process_id(any_handle)
270
+ thread.should be_a_kind_of Integer
271
+ thread.should be > 0
272
+ process.should be_a_kind_of Integer
273
+ process.should be > 0
274
+ end
275
+
276
+ it 'returns a pair of nils (thread and process) for invalid window' do
277
+ thread, process = get_window_thread_process_id(not_a_handle)
278
+ thread.should == nil
279
+ process.should == nil
239
280
  end
240
281
  end
241
282
 
242
283
  describe '#get_window_rect' do
284
+ spec{ use{ success = GetWindowRect(any_handle, rectangle = [0, 0, 0, 0].pack('L*'))}}
243
285
  spec{ use{ left, top, right, bottom = get_window_rect(any_handle)}}
244
286
 
245
- it 'returns windows rectangle' do
287
+ it 'returns array of nils for invalid window' do
288
+ get_window_rect(not_a_handle).should == [nil, nil, nil, nil]
289
+ end
290
+
291
+ it 'returns window`s border rectangle' do
246
292
  test_app do |app|
247
293
  get_window_rect(app.handle).should == TEST_WIN_RECT
248
294
  end
@@ -252,84 +298,66 @@ module GuiTest
252
298
  describe '#show_window ', 'LI', 'I' do
253
299
  spec{ use{ was_visible = show_window(handle = any_handle, cmd = SW_SHOWNA) }}
254
300
 
255
- it 'was_visible = hide_window(handle = any_handle) # alias method (not a separate API function)' do
301
+ it 'was_visible = hide_window(handle = any_handle) # derived method (not a separate API function)' do
256
302
  test_app do |app|
257
- use{ hide_window(app.handle) }
303
+ use{ @was_visible = hide_window(app.handle) }
304
+ @was_visible.should == true
305
+ visible?(app.handle).should == false
306
+ hide_window(app.handle).should == false
258
307
  visible?(app.handle).should == false
259
308
  end
260
309
  end
261
310
 
262
- it 'returns true if the window was PREVIOUSLY visible' do
263
- test_app {|app| show_window(app.handle, SW_HIDE).should == true }
264
- end
265
-
266
- it 'returns false if the window was PREVIOUSLY not visible' do
311
+ it 'returns true if the window was PREVIOUSLY visible, false otherwise' do
267
312
  test_app do |app|
268
- show_window(app.handle, SW_HIDE)
313
+ show_window(app.handle, SW_HIDE).should == true
269
314
  show_window(app.handle, SW_HIDE).should == false
270
315
  end
271
316
  end
272
317
 
273
- it 'SW_HIDE command hides window' do
318
+ it 'hides window with SW_HIDE command ' do
274
319
  test_app do |app|
275
320
  show_window(app.handle, SW_HIDE)
276
321
  visible?(app.handle).should == false
277
322
  end
278
323
  end
279
324
 
280
- it 'SW_SHOW command shows hidden window' do
325
+ it 'shows hidden window with SW_SHOW command' do
281
326
  test_app do |app|
282
- show_window(app.handle, SW_HIDE)
327
+ hide_window(app.handle)
283
328
  show_window(app.handle, SW_SHOW)
284
329
  visible?(app.handle).should == true
285
330
  end
286
331
  end
287
332
 
288
- it 'SW_MAXIMIZE maximizes window' do
289
- test_app do |app|
290
- show_window(app.handle, SW_MAXIMIZE)
291
- maximized?(app.handle).should == true
292
- end
293
- pending 'Need to make sure window is maximized but NOT activated '
333
+ it 'SW_MAXIMIZE, SW_SHOWMAXIMIZED maximize window and activate it' do
334
+ test_show_window SW_MAXIMIZE, SW_SHOWMAXIMIZED,
335
+ :minimized? => false, :maximized? => true, :visible? => true, :foreground? => true
294
336
  end
295
337
 
296
338
  it 'SW_MINIMIZE minimizes window and activates the next top-level window in the Z order' do
297
- test_app do |app|
298
- show_window(app.handle, SW_MINIMIZE)
299
- minimized?(app.handle).should == true
300
- end
339
+ test_show_window SW_MINIMIZE,
340
+ :minimized? => true, :maximized? => false, :visible? => true, :foreground? => false
301
341
  end
302
342
 
303
- it 'SW_SHOWMAXIMIZED activates the window and displays it as a maximized window' do
304
- pending 'Need to make sure window is maximized AND activated '
305
- test_app do |app|
306
- show_window(app.handle, SW_SHOWMAXIMIZED)
307
- get_window_rect(app.handle)
308
- #.should == TEST_MAX_RECT
309
- end
310
-
343
+ it 'SW_SHOWMINNOACTIVE, SW_SHOWMINIMIZED displays the window as a minimized foreground window' do
344
+ test_show_window SW_SHOWMINNOACTIVE, SW_SHOWMINIMIZED,
345
+ :minimized? => true, :maximized? => false, :visible? => true, :foreground? => true
311
346
  end
312
- it 'SW_SHOWMINIMIZED activates the window and displays it as a minimized window' do
313
- pending 'Need to make sure window is minimized AND activated '
314
- test_app do |app|
315
- show_window(app.handle, SW_SHOWMINIMIZED)
316
- p get_window_rect(app.handle)
317
- #.should == TEST_MAX_RECT
318
- end
319
347
 
348
+ it 'SW_SHOWNORMAL, SW_RESTORE, SW_SHOWNOACTIVATE activate/display a window(if min/maximized it is restored' do
349
+ test_show_window SW_SHOWNORMAL, SW_RESTORE, SW_SHOWNOACTIVATE,
350
+ :minimized? => false, :maximized? => false, :visible? => true, :foreground? => true
320
351
  end
321
- it 'SW_SHOWMINNOACTIVE displays the window as a minimized window (similar to SW_SHOWMINIMIZED, but window is not activated)'
352
+
322
353
  it 'SW_SHOWNA displays the window in its current size and position (similar to SW_SHOW, but window is not activated)'
323
- it 'SW_SHOWNOACTIVATE displays the window in its current size and position (similar to SW_SHOW, but window is not activated)'
324
- it 'SW_SHOWNORMAL activates and displays a window. Restores minimized/maximized window to original size/position. Use it to show window for the first time'
325
- it 'SW_RESTORE activates and displays the window. Restores minimized/maximized window to original size/position. Use it to restore minimized windows'
326
354
  it 'SW_SHOWDEFAULT sets the show state based on the SW_ value specified in the STARTUPINFO structure passed to the CreateProcess function by the program that started the application'
327
355
  it 'SW_FORCEMINIMIZE minimizes a window, even if the thread that owns the window is not responding - only Win2000/XP'
328
356
  end
329
357
 
330
358
  describe '#keydb_event' do
331
359
  spec{ use{ keybd_event(vkey = 0, bscan = 0, flags = 0, extra_info = 0) }}
332
- # vkey (I) - 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.
360
+ # vkey (I) - 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.
333
361
  # bscan (I) - Specifies a hardware scan code for the key.
334
362
  # flags (L) - Specifies various aspects of function operation. This parameter can be one or more of the following values.
335
363
  # KEYEVENTF_EXTENDEDKEY - If specified, the scan code was preceded by a prefix byte having the value 0xE0 (224).
@@ -337,10 +365,10 @@ module GuiTest
337
365
  # extra_info (L) - Specifies an additional value associated with the key stroke.
338
366
  # no return value
339
367
 
340
- it 'synthesizes a numeric keystroke, emulating keyboard driver' do
368
+ it 'synthesizes a numeric keystrokes, emulating keyboard driver' do
341
369
  test_app do |app|
342
370
  text = '123 456'
343
- text.upcase.each_byte do |b| # upcase needed since user32 keybd_event expects upper case chars
371
+ text.upcase.each_byte do |b| # upcase needed since user32 keybd_event expects upper case chars
344
372
  keybd_event(b.ord, 0, KEYEVENTF_KEYDOWN, 0)
345
373
  sleep TEST_KEY_DELAY
346
374
  keybd_event(b.ord, 0, KEYEVENTF_KEYUP, 0)
@@ -356,8 +384,8 @@ module GuiTest
356
384
 
357
385
  describe '#post_message' do
358
386
  spec{ use{ success = post_message(handle = 0, msg = 0, w_param = 0, l_param = 0) }}
359
- # handle (L) - Handle to the window whose window procedure will receive the message.
360
- # If this parameter is HWND_BROADCAST, the message is sent to all top-level windows in the system, including disabled or
387
+ # handle (L) - Handle to the window whose window procedure will receive the message.
388
+ # If this parameter is HWND_BROADCAST, the message is sent to all top-level windows in the system, including disabled or
361
389
  # invisible unowned windows, overlapped windows, and pop-up windows; but the message is not sent to child windows.
362
390
  # msg (L) - Specifies the message to be posted.
363
391
  # w_param (L) - Specifies additional message-specific information.
@@ -371,7 +399,7 @@ module GuiTest
371
399
  describe '#send_message' do
372
400
  spec{ use{ success = send_message(handle = 0, msg = 0, w_param = 1024, l_param = "\x0"*1024) }}
373
401
  # handle (L) - Handle to the window whose window procedure is to receive the message. The following values have special meanings.
374
- # HWND_BROADCAST - The message is posted to all top-level windows in the system, including disabled or invisible unowned windows,
402
+ # HWND_BROADCAST - The message is posted to all top-level windows in the system, including disabled or invisible unowned windows,
375
403
  # overlapped windows, and pop-up windows. The message is not posted to child windows.
376
404
  # NULL - The function behaves like a call to PostThreadMessage with the dwThreadId parameter set to the identifier of the current thread.
377
405
  # msg (L) - Specifies the message to be posted.
@@ -385,13 +413,13 @@ module GuiTest
385
413
 
386
414
  describe '#get_dlg_item' do
387
415
  spec{ use{ control_handle = get_dlg_item(handle = 0, item_id = 1) }}
388
- # handle (L) - Handle of the dialog box that contains the control.
389
- # item_id (I) - Specifies the identifier of the control to be retrieved.
416
+ # handle (L) - Handle of the dialog box that contains the control.
417
+ # item_id (I) - Specifies the identifier of the control to be retrieved.
390
418
  # Returns (L) - handle of the specified control if success or nil for invalid dialog box handle or a nonexistent control.
391
419
  # To get extended error information, call GetLastError.
392
- # You can use the GetDlgItem function with any parent-child window pair, not just with dialog boxes. As long as the handle
393
- # parameter specifies a parent window and the child window has a unique id (as specified by the hMenu parameter in the
394
- # CreateWindow or CreateWindowEx function that created the child window), GetDlgItem returns a valid handle to the child window.
420
+ # You can use the GetDlgItem function with any parent-child window pair, not just with dialog boxes. As long as the handle
421
+ # parameter specifies a parent window and the child window has a unique id (as specified by the hMenu parameter in the
422
+ # CreateWindow or CreateWindowEx function that created the child window), GetDlgItem returns a valid handle to the child window.
395
423
 
396
424
  it 'returns handle to correctly specified control'
397
425
  end
@@ -400,13 +428,15 @@ module GuiTest
400
428
  spec{ use{ enum_windows(message = 'Message') }}
401
429
 
402
430
  it 'return an array of top-level window handles if block is not given' do
403
- enum = enum_windows(message = 'Message')
404
- enum.should be_a_kind_of Array
405
- enum.should_not be_empty
406
- enum.should have_at_least(60).elements # typical number of top windows in WinXP system?
407
- enum.compact.size.should == enum.size # should not contain nils
431
+ test_app do |app|
432
+ enum = enum_windows(message = 'Message')
433
+ enum.should be_a_kind_of Array
434
+ enum.should_not be_empty
435
+ enum.should have_at_least(60).elements # typical number of top windows in WinXP system?
436
+ enum.each{|handle| handle.should be_an Integer }
437
+ enum.any?{|handle| handle == app.handle}.should == true
438
+ end
408
439
  end
409
-
410
440
  it 'iterates through all the top-level windows, passing each found window handle and message to a given block'
411
441
 
412
442
  end
@@ -418,25 +448,46 @@ module GuiTest
418
448
  test_app do |app|
419
449
  enum = enum_child_windows(app.handle, message = 'Message')
420
450
  enum.should be_a_kind_of Array
421
- enum.should_not be_empty
422
451
  enum.should have(2).elements
423
- p get_class_name(enum.first), get_class_name(enum.last)
424
- get_class_name(enum.last).should == TEST_TEXTAREA_CLASS
452
+ class_name(enum.first).should == TEST_STATUSBAR_CLASS
453
+ class_name(enum.last).should == TEST_TEXTAREA_CLASS
425
454
  end
426
455
  end
427
456
 
428
- it 'loops through all children of given window, passing each found window handle and a message to a given block'
429
- end
457
+ it 'loops through all children of given window, passing each found window handle and a message to a given block' do
458
+ test_app do |app|
459
+ enum = []
460
+ enum_child_windows(app.handle, 'Message') do |handle, message|
461
+ enum << handle
462
+ message.should == 'Message'
463
+ end
464
+ enum.should have(2).elements
465
+ class_name(enum.first).should == TEST_STATUSBAR_CLASS
466
+ class_name(enum.last).should == TEST_TEXTAREA_CLASS
467
+ end
468
+ end
430
469
 
431
- it 'GetForegroundWindow ', 'V', 'L'
432
- it 'GetActiveWindow ', 'V', 'L'
470
+ it 'breaks loop if given block returns false' do
471
+ pending
472
+ test_app do |app|
473
+ enum = []
474
+ enum_child_windows(app.handle, 'Message') do |handle, message|
475
+ enum << handle
476
+ 1
477
+ end
478
+ enum.should have(1).element
479
+ class_name(enum.first).should == TEST_STATUSBAR_CLASS
480
+ # class_name(enum.last).should == TEST_TEXTAREA_CLASS
481
+ end
482
+ end
483
+ end
433
484
  end
434
485
 
435
486
  describe WinGui, ' convenience wrapper methods' do
436
487
  describe '#keystroke' do
437
488
  spec{ use{ keystroke( vkey = 30, vkey = 30) }}
438
489
  # this service method emulates combinations of (any amount of) keys pressed one after another (Ctrl+Alt+P) and then released
439
- # 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.
490
+ # 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.
440
491
 
441
492
  it 'emulates combinations of keys pressed (Ctrl+Alt+P+M, etc)' do
442
493
  test_app do |app|
data/win_gui.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{win_gui}
8
- s.version = "0.1.3"
8
+ s.version = "0.1.4"
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-01-29}
12
+ s.date = %q{2010-02-04}
13
13
  s.description = %q{Rubyesque interfaces and wrappers for Win32 API GUI functions}
14
14
  s.email = %q{arvitallian@gmail.com}
15
15
  s.extra_rdoc_files = [
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: win_gui
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
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-01-29 00:00:00 +03:00
12
+ date: 2010-02-04 00:00:00 +03:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency