win 0.1.16 → 0.1.18

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.16
1
+ 0.1.18
data/lib/win/error.rb CHANGED
@@ -851,6 +851,13 @@ module Win
851
851
  FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000
852
852
  FORMAT_MESSAGE_MAX_WIDTH_MASK = 0x000000FF
853
853
 
854
+ # Set/GetErrorMode values:
855
+
856
+ SEM_FAILCRITICALERRORS = 0x0001
857
+ SEM_NOALIGNMENTFAULTEXCEPT = 0x0004
858
+ SEM_NOGPFAULTERRORBOX = 0x0002
859
+ SEM_NOOPENFILEERRORBOX = 0x8000
860
+
854
861
  ##
855
862
  # FormatMessage Function
856
863
  # Formats a message string. The function requires a message definition as input. The message definition
@@ -1011,12 +1018,11 @@ module Win
1011
1018
  function :FormatMessage, [:DWORD, :LPCVOID, :DWORD, :DWORD, :LPTSTR, :DWORD, :varargs], :DWORD,
1012
1019
  &->(api, flags=FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
1013
1020
  source=nil, message_id=0, language_id=0, *args){
1014
- buffer = FFI::MemoryPointer.new :char, 260
1021
+ buffer = FFI::MemoryPointer.new :char, 260
1015
1022
  args = [:int, 0] if args.empty?
1016
1023
  num_chars = api.call(flags, source, message_id, language_id, buffer, buffer.size, *args)
1017
1024
  num_chars == 0 ? nil : buffer.get_bytes(0, num_chars).strip }
1018
1025
 
1019
-
1020
1026
  ##
1021
1027
  # GetLastError Function
1022
1028
  # Retrieves the calling thread's last-error code value. The last-error code is maintained on a
@@ -1062,5 +1068,157 @@ module Win
1062
1068
  &->(api) { error_code = api.call
1063
1069
  flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY
1064
1070
  format_message(flags, nil, error_code)}
1071
+
1072
+ ##
1073
+ # SetLastError Function
1074
+ # Sets the last-error code for the calling thread.
1075
+ #
1076
+ # [*Syntax*] void WINAPI SetLastError( DWORD dwErrCode );
1077
+ #
1078
+ # dwErrCode:: [in] The last-error code for the thread.
1079
+ #
1080
+ # *Returns*:: This function does not return a value.
1081
+ # ---
1082
+ # *Remarks*:
1083
+ # - The last-error code is kept in thread local storage so that multiple threads do not overwrite each
1084
+ # other's values.
1085
+ # - This function is intended primarily for use by dynamic-link libraries (DLL). A DLL can provide the
1086
+ # applications that are using it with additional diagnostic information by calling this function after
1087
+ # an error occurs. Most functions call SetLastError or SetLastErrorEx only when they fail. However, some
1088
+ # system functions call SetLastError or SetLastErrorEx under conditions of success; those cases are
1089
+ # noted in each function's documentation.
1090
+ # - Applications can optionally retrieve the value set by this function by using the GetLastError function
1091
+ # immediately after a function fails.
1092
+ # - Error codes are 32-bit values (bit 31 is the most significant bit). Bit 29 is reserved for
1093
+ # application-defined error codes; no system error code has this bit set. If you are defining an error
1094
+ # code for your application, set this bit to indicate that the error code has been defined by your
1095
+ # application and to ensure that your error code does not conflict with any system-defined error codes.
1096
+ # ---
1097
+ # <b>Enhanced (snake_case) API: </b>
1098
+ #
1099
+ # :call-seq:
1100
+ # set_last_error(err_code)
1101
+ #
1102
+ function :SetLastError, [:DWORD], :void
1103
+
1104
+ ##
1105
+ # SetLastErrorEx Function sets the last-error code.
1106
+ # Currently, this function is identical to the SetLastError function. The second parameter is ignored.
1107
+ #
1108
+ # [*Syntax*] void WINAPI SetLastErrorEx( DWORD dwErrCode, DWORD dwType );
1109
+ #
1110
+ # dwErrCode:: The last-error code for the thread.
1111
+ # dwType:: This parameter is ignored.
1112
+ #
1113
+ # *Returns*:: This function does not return a value.
1114
+ # ---
1115
+ # *Remarks*:
1116
+ # The last-error code is kept in thread local storage so that multiple threads do not overwrite each
1117
+ # other's values.
1118
+ # This function is intended primarily for use by dynamic-link libraries (DLL). A DLL can provide the
1119
+ # applications that are using it with additional diagnostic information by calling this function after
1120
+ # an error occurs. Most functions call SetLastError or SetLastErrorEx only when they fail. However, some
1121
+ # system functions call SetLastError or SetLastErrorEx under conditions of success; those cases are
1122
+ # noted in each function's documentation.
1123
+ # Applications can optionally retrieve the value set by this function by using the GetLastError function
1124
+ # immediately after a function fails.
1125
+ # Error codes are 32-bit values (bit 31 is the most significant bit). Bit 29 is reserved for
1126
+ # application-defined error codes; no system error code has this bit set. If you are defining an error
1127
+ # code for your application, set this bit to indicate that the error code has been defined by the
1128
+ # application and to ensure that your error code does not conflict with any system-defined error codes.
1129
+ #
1130
+ # :call-seq:
1131
+ # set_last_error_ex(err_code, dw_type)
1132
+ #
1133
+ try_function :SetLastErrorEx, [:DWORD, :DWORD], :void
1134
+ # fails silently unless platform is XP++
1135
+
1136
+ ##
1137
+ # GetErrorMode Function
1138
+ # Retrieves the error mode for the current process.
1139
+ #
1140
+ # [*Syntax*] UINT WINAPI GetErrorMode( void );
1141
+ #
1142
+ # This function has no parameters.
1143
+ #
1144
+ # *Returns*:: The process error mode. This function returns one of the following values.
1145
+ # SEM_FAILCRITICALERRORS:: The system does not display the critical-error-handler message box. Instead,
1146
+ # the system sends the error to the calling process.
1147
+ # SEM_NOALIGNMENTFAULTEXCEPT:: The system automatically fixes memory alignment faults and makes them
1148
+ # invisible to the application. It does this for the calling process and any
1149
+ # descendant processes. This feature is only supported by certain processor
1150
+ # architectures. For more information, see the Remarks section.
1151
+ # After this value is set for a process, subsequent attempts to clear the
1152
+ # value are ignored.
1153
+ # SEM_NOGPFAULTERRORBOX:: The system does not display the general-protection-fault message box. This flag
1154
+ # should only be set by debugging applications that handle general protection (GP)
1155
+ # faults themselves with an exception handler.
1156
+ # SEM_NOOPENFILEERRORBOX:: The system does not display a message box when it fails to find a file. Instead,
1157
+ # the error is returned to the calling process.
1158
+ # ---
1159
+ # *Remarks*:
1160
+ # Each process has an associated error mode that indicates to the system how the application is going to
1161
+ # respond to serious errors. A child process inherits the error mode of its parent process.
1162
+ # To change the error mode for the process, use the SetErrorMode function.
1163
+ # ------
1164
+ # <b> Only works in Vista++! </b>
1165
+ # ------
1166
+ # :call-seq:
1167
+ # mode = get_error_mode()
1168
+ #
1169
+ try_function :GetErrorMode, [], :UINT
1170
+ # fails silently unless platform is Vista++
1171
+
1172
+ ##
1173
+ # SetErrorMode Function controls whether the system will handle the specified types of serious errors or whether
1174
+ # the process will handle them.
1175
+ #
1176
+ # [*Syntax*] UINT WINAPI SetErrorMode( UINT uMode );
1177
+ #
1178
+ # uMode:: The process error mode. This parameter can be one or more of the following values.
1179
+ # 0:: Use the system default, which is to display all error dialog boxes.
1180
+ # SEM_FAILCRITICALERRORS:: The system does not display the critical-error-handler message box. Instead,
1181
+ # the system sends the error to the calling process.
1182
+ # SEM_NOALIGNMENTFAULTEXCEPT:: The system automatically fixes memory alignment faults and makes them
1183
+ # invisible to the application. It does this for the calling process and any
1184
+ # descendant processes. This feature is only supported by certain processor
1185
+ # architectures. For more information, see the Remarks section.
1186
+ # After this value is set for a process, subsequent attempts to clear the
1187
+ # value are ignored.
1188
+ # SEM_NOGPFAULTERRORBOX:: The system does not display the general-protection-fault message box. This flag
1189
+ # should only be set by debugging applications that handle general protection (GP)
1190
+ # faults themselves with an exception handler.
1191
+ # SEM_NOOPENFILEERRORBOX:: The system does not display a message box when it fails to find a file. Instead,
1192
+ # the error is returned to the calling process.
1193
+ #
1194
+ # *Returns*:: The return value is the previous state of the error-mode bit flags.
1195
+ # ---
1196
+ # *Remarks*:
1197
+ # Each process has an associated error mode that indicates to the system how the application is going to
1198
+ # respond to serious errors. A child process inherits the error mode of its parent process. To retrieve
1199
+ # the process error mode, use the GetErrorMode function.
1200
+ # Because the error mode is set for the entire process, you must ensure that multi-threaded applications
1201
+ # do not set different error-mode flags. Doing so can lead to inconsistent error handling.
1202
+ # The system does not make alignment faults visible to an application on all processor architectures.
1203
+ # Therefore, specifying SEM_NOALIGNMENTFAULTEXCEPT is not an error on such architectures, but the system
1204
+ # is free to silently ignore the request. This means that code sequences such as the following are not
1205
+ # always valid on x86 computers:
1206
+ #
1207
+ # SetErrorMode(SEM_NOALIGNMENTFAULTEXCEPT);
1208
+ # fuOldErrorMode = SetErrorMode(0);
1209
+ # ASSERT(fuOldErrorMode == SEM_NOALIGNMENTFAULTEXCEPT);
1210
+ #
1211
+ # Itanium:: An application must explicitly call SetErrorMode with SEM_NOALIGNMENTFAULTEXCEPT to have the
1212
+ # system automatically fix alignment faults. The default setting is for the system to make alignment
1213
+ # faults visible to an application.
1214
+ # Visual Studio 2005:: When declaring a pointer to a structure that may not have aligned data, you can use
1215
+ # __unaligned keyword to indicate that the type must be read one byte at a time. For more
1216
+ # information, see Windows Data Alignment.
1217
+ #
1218
+ # :call-seq:
1219
+ # success = set_error_mode(mode)
1220
+ #
1221
+ function :SetErrorMode, [:UINT], :UINT
1222
+
1065
1223
  end
1066
1224
  end
data/lib/win/gui.rb CHANGED
@@ -2,7 +2,6 @@ require 'win/gui/window'
2
2
  require 'win/gui/input'
3
3
  require 'win/gui/message'
4
4
  require 'win/gui/dialog'
5
- require 'win/gui/window/window'
6
5
 
7
6
  module Win
8
7
 
@@ -33,15 +33,15 @@ module Win
33
33
  # Convenience methods:
34
34
 
35
35
  # finds top-level dialog window by title and yields found dialog window to block if given
36
- def dialog(title, seconds=3)
37
- d = begin
38
- win = Window::Window.top_level(title, seconds)
39
- yield(win) ? win : nil
40
- rescue TimeoutError
41
- end
42
- d.wait_for_close if d
43
- return d
44
- end
36
+ # def dialog(title, seconds=3)
37
+ # d = begin
38
+ # win = Window::Window.top_level(title, seconds)
39
+ # yield(win) ? win : nil
40
+ # rescue TimeoutError
41
+ # end
42
+ # d.wait_for_close if d
43
+ # return d
44
+ # end
45
45
  end
46
46
  end
47
47
  end
data/lib/win/gui/input.rb CHANGED
@@ -288,6 +288,38 @@ module Win
288
288
  #
289
289
  function :SetCursorPos, [:int, :int], :int, boolean: true
290
290
 
291
+ ##
292
+ # GetCursorPos Function retrieves the cursor's position, in screen coordinates.
293
+ #
294
+ # [*Syntax*] BOOL GetCursorPos( LPPOINT lpPoint );
295
+ #
296
+ # lpPoint:: [out] Pointer to a POINT structure that receives the screen coordinates of the cursor.
297
+ #
298
+ # *Returns*:: Returns nonzero if successful or zero otherwise. To get extended error information, call
299
+ # GetLastError.
300
+ # ---
301
+ # *Remarks*:
302
+ # The cursor position is always specified in screen coordinates and is not affected by the mapping mode
303
+ # of the window that contains the cursor.
304
+ # The calling process must have WINSTA_READATTRIBUTES access to the window station.
305
+ # The input desktop must be the current desktop when you call GetCursorPos. Call OpenInputDesktop to
306
+ # determine whether the current desktop is the input desktop. If it is not, call SetThreadDesktop with
307
+ # the HDESK returned by OpenInputDesktop to switch to that desktop.
308
+ # ---
309
+ # <b>Enhanced (snake_case) API: accepts no args, returns a pair (x, y) of cursor coordinates</b>
310
+ #
311
+ # :call-seq:
312
+ # x, y = get_cursor_pos()
313
+ #
314
+ function :GetCursorPos, [:pointer], :int8,
315
+ &->(api) {
316
+ point = FFI::MemoryPointer.new(:long, 2)
317
+ res = api.call point
318
+ res == 0 ? [nil, nil] : point.read_array_of_long(2) }
319
+ # weird lambda literal instead of normal block is needed because current version of RDoc
320
+ # goes crazy if block is attached to meta-definition
321
+
322
+
291
323
  # Convenience methods
292
324
 
293
325
  ##
@@ -416,7 +416,7 @@ module Win
416
416
  #:call-seq:
417
417
  # success = post_message(handle, msg, w_param, l_param)
418
418
  #
419
- function :PostMessage, [:ulong, :uint, :long, :uint], :int, boolean: true
419
+ function :PostMessage, [:ulong, :uint, :long, :pointer], :int, boolean: true
420
420
 
421
421
  ##
422
422
  # The SendMessage function sends the specified message to a window or windows. It calls the window procedure for
@@ -530,7 +530,7 @@ module Win
530
530
  # :call-seq:
531
531
  # handles = enum_windows( [value=0] ) {|handle, value| your callback procedure }
532
532
  #
533
- function :EnumWindows, [:EnumWindowsProc, :long], :bool, &return_enum
533
+ function :EnumWindows, [:EnumWindowsProc, :long], :int8, &return_enum
534
534
 
535
535
  ##
536
536
  # EnumDesktopWindows Function enumerates all top-level windows associated with the specified desktop.
@@ -568,7 +568,7 @@ module Win
568
568
  # :call-seq:
569
569
  # handles = enum_desktop_windows( desktop_handle, [value=0] ) {|handle, value| your callback procedure }
570
570
  #
571
- function :EnumDesktopWindows, [:ulong, :EnumWindowsProc, :long], :bool, &return_enum
571
+ function :EnumDesktopWindows, [:ulong, :EnumWindowsProc, :long], :int8, &return_enum
572
572
 
573
573
  ##
574
574
  # The EnumChildWindows function enumerates the child windows that belong to the specified parent window by
@@ -602,7 +602,7 @@ module Win
602
602
  #:call-seq:
603
603
  # handles = enum_child_windows( parent_handle, [value=0] ) {|handle, value| your callback procedure }
604
604
  #
605
- function :EnumChildWindows, [:HWND, :EnumWindowsProc, :long], :bool, &return_enum
605
+ function :EnumChildWindows, [:HWND, :EnumWindowsProc, :long], :int8, &return_enum
606
606
 
607
607
  ##
608
608
  # GetForegroundWindow function returns a handle to the foreground window (the window with which the user
@@ -660,7 +660,7 @@ module Win
660
660
  # I have not find so far how to REALLY destroy window in different thread without it asking user anything.
661
661
  #
662
662
  def shut_window( win_handle)
663
- post_message(win_handle, Win::GUI::Message::WM_SYSCOMMAND, Win::GUI::Message::SC_CLOSE, 0)
663
+ post_message(win_handle, Win::GUI::Message::WM_SYSCOMMAND, Win::GUI::Message::SC_CLOSE, nil)
664
664
  end
665
665
 
666
666
  ##
data/lib/win/library.rb CHANGED
@@ -374,7 +374,16 @@ module Win
374
374
  api #return api object from function declaration
375
375
  end
376
376
 
377
- ##
377
+ # Try to define platform-specific function, rescue error, return message
378
+ #
379
+ def try_function(name, params, returns, options={}, &def_block)
380
+ begin
381
+ function name, params, returns, options={}, &def_block
382
+ rescue Win::Errors::NotFoundError
383
+ "This platform does not support function #{name}"
384
+ end
385
+ end
386
+
378
387
  # Generates possible effective names for function in Win32 dll (name+A/W),
379
388
  # Rubyesque name and aliases for method(s) defined based on function name,
380
389
  #
data/spec/spec_helper.rb CHANGED
@@ -9,6 +9,18 @@ $debug = true
9
9
  # Customize RSpec with my own extensions
10
10
  module ClassMacros
11
11
 
12
+ def os
13
+ `ver`
14
+ end
15
+
16
+ def vista?
17
+ os =~ /Version 6/
18
+ end
19
+
20
+ def xp?
21
+ os =~ /XP/
22
+ end
23
+
12
24
  # wrapper for it method that extracts description from example source code, such as:
13
25
  # spec { use{ function(arg1 = 4, arg2 = 'string') }}
14
26
  def spec &block
@@ -8,7 +8,11 @@ module WinErrorTest
8
8
  include Win::GUI::Window
9
9
 
10
10
  def buffer
11
- FFI::MemoryPointer.new(:char, 1024)
11
+ FFI::MemoryPointer.new(:char, 260)
12
+ end
13
+
14
+ def sys_flags
15
+ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY
12
16
  end
13
17
 
14
18
  describe Win::Error, ' contains a set of pre-defined Windows API functions' do
@@ -29,25 +33,80 @@ module WinErrorTest
29
33
  window_text(0)
30
34
  get_last_error.should == "Invalid window handle."
31
35
  end
32
-
33
36
  end # describe "#get_last_error"
34
37
 
35
38
  describe "#format_message" do
36
- spec{ use{ num_chars = FormatMessage(dw_flags=0, lp_source=nil, dw_message_id=0, dw_language_id=0, buffer, buffer.size, :int, 0) }}
37
- spec{ use{ message = format_message(dw_flags=0, lp_source=nil, dw_message_id=0, dw_language_id=0, :int, 0) }}
39
+ spec{ use{ num_chars = FormatMessage(sys_flags, source=nil, message_id=0, language_id=0, buffer, buffer.size, :int, 0) }}
40
+ spec{ use{ message = format_message(sys_flags, source=nil, message_id=0, language_id=0, :int, 0) }}
38
41
 
39
- it "original api Formats a message string. The function requires a message definition as input. The message definition " do
40
- pending
41
- num_chars = FormatMessage(dw_flags=0, nil, dw_message_id=0, dw_language_id=0, buffer, buffer.size, :int, 0)
42
+ it "original api formats a message string - system message" do
43
+ find_window(TEST_IMPOSSIBLE, TEST_IMPOSSIBLE)
44
+ message_id = GetLastError()
45
+ buf = buffer()
46
+ num_chars = FormatMessage(sys_flags, nil, message_id, dw_language_id=0, buf, buf.size, :int, 0)
47
+ buf.get_bytes(0, num_chars).strip.should == "The system cannot find the file specified."
42
48
  end
43
49
 
44
- it "snake_case api Formats a message string. The function requires a message definition as input. The message definition " do
45
- pending
46
- message = format_message(dw_flags=0, nil, dw_message_id=0, dw_language_id=0, lp_buffer=0, n_size=0,:int, 0)
50
+ it "snake_case api Formats a message string - system message" do
51
+ find_window(TEST_IMPOSSIBLE, TEST_IMPOSSIBLE)
52
+ message = format_message(sys_flags, nil, dw_message_id=GetLastError())
53
+ message.should == "The system cannot find the file specified."
47
54
  end
48
-
49
55
  end # describe format_message
50
56
 
57
+ describe "#set_last_error" do
58
+ spec{ use{ SetLastError(err_code=0) }}
59
+ spec{ use{ set_last_error(err_code=0) }}
60
+
61
+ it "original api sets the last-error code for the calling thread." do
62
+ SetLastError(dw_err_code=0xF000)
63
+ GetLastError().should == ERROR_USER_DEFINED_BASE
64
+ end
65
+
66
+ it "snake_case api also sets the last-error code for the calling thread." do
67
+ set_last_error(3000)
68
+ get_last_error.should == "The specified print monitor is unknown."
69
+ end
70
+ end # describe set_last_error
71
+
72
+ if xp? || vista? # This function works only on XP++
73
+ describe "#set_last_error_ex" do
74
+ spec{ use{ SetLastErrorEx(dw_err_code=0, dw_type=0) }}
75
+ spec{ use{ set_last_error_ex(dw_err_code=0, dw_type=0) }}
76
+
77
+ it "original api sets the last-error code for the calling thread." do
78
+ SetLastErrorEx(dw_err_code=0xF000, dw_type=0)
79
+ GetLastError().should == ERROR_USER_DEFINED_BASE
80
+ end
81
+
82
+ it "snake_case api also sets the last-error code for the calling thread." do
83
+ set_last_error_ex(3000,0)
84
+ get_last_error.should == "The specified print monitor is unknown."
85
+ end
86
+ end # describe set_last_error_ex
87
+ end
88
+
89
+ if vista? # This function works only on Vista++
90
+ describe "#get_error_mode" do
91
+ spec{ use{ mode = GetErrorMode() }}
92
+ spec{ use{ mode = get_error_mode() }}
93
+
94
+ it "original api retrieves the error mode for the current process." do
95
+ p mode = GetErrorMode()
96
+ end
97
+
98
+ it "snake_case api also retrieves the error mode for the current process." do
99
+ p mode = get_error_mode()
100
+ end
101
+ end # describe get_error_mode
102
+ end
103
+
104
+ describe "#set_error_mode" do
105
+ spec{ use{ success = SetErrorMode(u_mode=0) }}
106
+ spec{ use{ success = set_error_mode(u_mode=0) }}
107
+
108
+ it "controls whether the system OR process will handle the specified types of serious errors"
109
+ end # describe set_error_mode
51
110
 
52
111
  end # describe Win::Error
53
112
  end
@@ -14,43 +14,29 @@ module WinWindowTest
14
14
 
15
15
  it 'returns handle to correctly specified control'
16
16
 
17
- it 'does something else' do
18
- pending
19
- test_app do |app|
20
- text = '123 456'
21
- text.upcase.each_byte do |b| # upcase needed since user32 keybd_event expects upper case chars
22
- keybd_event(b.ord, 0, KEYEVENTF_KEYDOWN, 0)
23
- sleep TEST_KEY_DELAY
24
- keybd_event(b.ord, 0, KEYEVENTF_KEYUP, 0)
25
- sleep TEST_KEY_DELAY
26
- end
27
- app.textarea.text.should =~ Regexp.new(text)
28
- 7.times {keystroke(VK_CONTROL, 'Z'.ord)} # dirty hack!
29
- end
30
- end
31
17
  end
32
18
 
33
19
  describe Win::GUI::Dialog, ' defines convenience/service methods on top of Windows API' do
34
- describe 'dialog' do
35
- spec{ use{ dialog( title ='Dialog Title', timeout_sec = 0.001, &any_block) }}
36
-
37
- it 'finds top-level dialog window by title' do
38
- pending 'Some problems (?with timeouts?) leave window open ~half of the runs'
39
- test_app do |app|
40
- keystroke(VK_ALT, 'F'.ord, 'A'.ord)
41
- @found = false
42
- dialog('Save As', 0.5) do |dialog_window|
43
- @found = true
44
- keystroke(VK_ESCAPE)
45
- dialog_window
46
- end
47
- @found.should == true
48
- end
49
- end
50
-
51
- it 'yields found dialog window to a given block'
52
-
53
- end
20
+ # describe 'dialog' do
21
+ # spec{ use{ dialog( title ='Dialog Title', timeout_sec = 0.001, &any_block) }}
22
+ #
23
+ # it 'finds top-level dialog window by title' do
24
+ # pending 'Some problems (?with timeouts?) leave window open ~half of the runs'
25
+ # test_app do |app|
26
+ # keystroke(VK_ALT, 'F'.ord, 'A'.ord)
27
+ # @found = false
28
+ # dialog('Save As', 0.5) do |dialog_window|
29
+ # @found = true
30
+ # keystroke(VK_ESCAPE)
31
+ # dialog_window
32
+ # end
33
+ # @found.should == true
34
+ # end
35
+ # end
36
+ #
37
+ # it 'yields found dialog window to a given block'
38
+ #
39
+ # end
54
40
  end
55
41
  end
56
42
  end
@@ -7,7 +7,7 @@ module WinWindowTest
7
7
  include WinTestApp
8
8
  include Win::GUI::Input
9
9
 
10
- describe Win::GUI::Input do
10
+ describe Win::GUI::Input, ' defines a set of API functions related to user input' do
11
11
 
12
12
  describe '#keydb_event' do
13
13
  spec{ use{ keybd_event(vkey = 0, bscan = 0, flags = 0, extra_info = 0) }}
@@ -25,18 +25,49 @@ module WinWindowTest
25
25
  5.times {keystroke(VK_CONTROL, 'Z'.ord)} # rolling back changes to allow window closing without dialog!
26
26
  end
27
27
  end
28
- end
28
+ end # describe '#keydb_event'
29
29
 
30
30
  describe '#mouse_event' do
31
31
  spec { use {mouse_event( flags = MOUSEEVENTF_ABSOLUTE , dx = 0, dy = 0, data=0, extra_info=0 )}}
32
32
  it 'Emulates Mouse clicks'
33
- end
33
+ end # describe '#mouse_event'
34
+
35
+ describe "#get_cursor_pos" do
36
+ spec{ use{ success = GetCursorPos(lp_point=FFI::MemoryPointer.new(:long, 2)) }}
37
+ spec{ use{ x, y = get_cursor_pos() }}
38
+
39
+ it "original api returns success code and puts cursor's screen coordinates into supplied buffer" do
40
+ success = GetCursorPos(lp_point=FFI::MemoryPointer.new(:long, 2))
41
+ success.should_not == 0
42
+ x, y = lp_point.read_array_of_long(2)
43
+ x.should be_an Integer
44
+ x.should be >= 0
45
+ y.should be_an Integer
46
+ y.should be >= 0
47
+ end
48
+
49
+ it "snake_case api returns the cursor's position, in screen coordinates" do
50
+ x, y = get_cursor_pos()
51
+ x.should be_an Integer
52
+ x.should be >= 0
53
+ y.should be_an Integer
54
+ y.should be >= 0
55
+ end
56
+ end # describe get_cursor_pos
34
57
 
35
58
  describe '#set_cursor_pos' do
59
+ spec { use {success = SetCursorPos(x=0, y=0)}}
36
60
  spec { use {success = set_cursor_pos(x=0, y=0)}}
37
- it 'how to test set_cursor_pos?'
38
- end
39
- end
61
+
62
+ it 'sets cursor`s position, in screen coordinates' do
63
+ SetCursorPos(x=600, y=600).should be_true
64
+ get_cursor_pos().should == [600,600]
65
+ set_cursor_pos(x=0, y=0).should be_true
66
+ get_cursor_pos().should == [0,0]
67
+ end
68
+ end # describe '#set_cursor_pos'
69
+
70
+ end # Win::GUI::Input, ' defines a set of API functions related to user input'
40
71
 
41
72
  describe Win::GUI::Input, ' defines convenience/service methods on top of Windows API' do
42
73
  describe '#keystroke' do
@@ -50,7 +81,7 @@ module WinWindowTest
50
81
  2.times {keystroke(VK_CONTROL, 'Z'.ord)} # rolling back changes to allow window closing without dialog!
51
82
  end
52
83
  end
53
- end
84
+ end # describe '#keystroke'
54
85
 
55
86
  describe '#type_in' do
56
87
  spec{ use{ type_in(message = '') }}
@@ -63,7 +94,8 @@ module WinWindowTest
63
94
  5.times {keystroke(VK_CONTROL, 'Z'.ord)} # rolling back changes to allow window closing without dialog!
64
95
  end
65
96
  end
66
- end
67
- end
97
+ end # describe '#type_in'
98
+
99
+ end # Win::GUI::Input, ' defines convenience/service methods on top of Windows API'
68
100
  end
69
101
 
@@ -6,33 +6,44 @@ module WinGUIMessageTest
6
6
 
7
7
  include WinTestApp
8
8
  include Win::GUI::Message
9
+ include Win::GUI::Window
9
10
 
10
- describe Win::GUI::Message do
11
+ describe Win::GUI::Message, ' defines a set of API functions related to Window messaging' do
12
+ after(:each){close_test_app if @launched_test_app}
11
13
 
12
14
  describe '#post_message' do
13
- spec{ use{ success = PostMessage(handle = 0, msg = 0, w_param = 0, l_param = 0) }}
14
- spec{ use{ success = post_message(handle = 0, msg = 0, w_param = 0, l_param = 0) }}
15
+ spec{ use{ success = PostMessage(handle = 0, msg = 0, w_param = 0, l_param = nil) }}
16
+ spec{ use{ success = post_message(handle = 0, msg = 0, w_param = 0, l_param = nil) }}
17
+
18
+ it 'places (posts) a message in the message queue associated with the thread that created the specified window' do
19
+ app = launch_test_app
20
+ post_message(app.handle, WM_SYSCOMMAND, SC_CLOSE, nil)
21
+ sleep TEST_SLEEP_DELAY
22
+ window?(app.handle).should == false
23
+ end
15
24
 
16
- it 'places (posts) a message in the message queue associated with the thread that created the specified window'
17
25
  it 'returns without waiting for the thread to process the message'
18
- end
26
+ end # describe '#post_message'
19
27
 
20
28
  describe '#send_message' do
21
29
  spec{ use{ success = SendMessage(handle = 0, msg = 0, w_param = 1024, l_param = "\x0"*1024) }}
22
30
  spec{ use{ success = send_message(handle = 0, msg = 0, w_param = 1024, l_param = "\x0"*1024) }}
23
- # handle (L) - Handle to the window whose window procedure is to receive the message. The following values have special meanings.
24
- # HWND_BROADCAST - The message is posted to all top-level windows in the system, including disabled or invisible unowned windows,
25
- # overlapped windows, and pop-up windows. The message is not posted to child windows.
26
- # NULL - The function behaves like a call to PostThreadMessage with the dwThreadId parameter set to the identifier of the current thread.
27
- # msg (L) - Specifies the message to be posted.
28
- # w_param (L) - Specifies additional message-specific information.
29
- # l_param (L) - Specifies additional message-specific information.
30
- # return (L) - Nonzero if success, zero if function failed. To get extended error information, call GetLastError.
31
-
32
- it 'sends the specified message to a window or windows'
33
- it 'calls the window procedure and does not return until the window procedure has processed the message'
34
- end
35
- end
31
+
32
+ it 'sends the specified message to a window or windows' do
33
+ app = launch_test_app
34
+ buffer = FFI::MemoryPointer.new :char, 1024
35
+ num_chars = send_message app.handle, WM_GETTEXT, buffer.size, buffer
36
+ buffer.get_bytes(0, num_chars).should == "LockNote - Steganos LockNote"
37
+
38
+ num_chars = send_message app.textarea, WM_GETTEXT, buffer.size, buffer
39
+ buffer.get_bytes(0, num_chars).should =~ /Welcome to Steganos LockNote/
40
+
41
+ send_message(app.handle, WM_SYSCOMMAND, SC_CLOSE, nil)
42
+ sleep TEST_SLEEP_DELAY
43
+ window?(app.handle).should == false
44
+ end
45
+ end # describe '#send_message'
46
+ end # Win::GUI::Message, ' defines a set of API functions related to Window messaging'
36
47
  end
37
48
 
38
49
 
@@ -31,7 +31,7 @@ module WinWindowTest
31
31
  end
32
32
  end
33
33
 
34
- describe Win::GUI::Window, ' defines a set user32 API functions related to Window manipulation' do
34
+ describe Win::GUI::Window, ' defines a set of API functions related to Window manipulation' do
35
35
  context 'ensuring test app closes' do
36
36
  after(:each){close_test_app if @launched_test_app}
37
37
 
@@ -15,7 +15,7 @@ module WinLibraryTest
15
15
  when :find_window
16
16
  #api.dll_name.should == 'user32' # The name of the DLL that exports the API function
17
17
  api.effective_function_name.should == 'FindWindowA' # Actual function returned by the constructor: 'GetUserName' ->'GetUserNameA' or 'GetUserNameW'
18
- api.function_name.should == 'FindWindow' # The name of the function passed to the constructor
18
+ api.function_name.should == :FindWindow # The name of the function passed to the constructor
19
19
  api.prototype.should == [:pointer, :pointer] # The prototype, returned as an array of characters
20
20
  api.return_type.should == :ulong # The prototype, returned as an array of characters
21
21
  end
@@ -29,16 +29,16 @@ module WinLibraryTest
29
29
  if n == rights.size
30
30
  expect {send method, *rights}.to_not raise_error
31
31
  else
32
- args = (1..n).map {wrongs[rand(wrongs.size)]}
33
- expect {send method, *args}.
34
- to raise_error "wrong number of arguments (#{args.size} for #{rights.size})"
32
+ args = (1..n).map {wrongs[rand(wrongs.size)]}
33
+ expect {send method, *args}.
34
+ to raise_error "wrong number of arguments (#{args.size} for #{rights.size})"
35
35
  end
36
36
  end
37
37
  end
38
38
  end
39
39
 
40
40
  def any_handle
41
- MyLib.function 'FindWindow', 'PP', 'L' unless respond_to? :find_window
41
+ MyLib.function :FindWindow, 'PP', 'L' unless respond_to? :find_window
42
42
  find_window(nil, nil)
43
43
  end
44
44
 
@@ -80,262 +80,263 @@ module WinLibraryTest
80
80
 
81
81
  before(:each) { hide_method *redefined_methods } # hide original methods if defined
82
82
  after(:each) { restore_method *redefined_methods } # restore original methods if hidden
83
+ context '::function' do
84
+ context 'defining enhanced API function method' do
85
+ spec{ use{ MyLib.function(:FindWindow, 'PP', 'l', rename: nil, aliases: nil, boolean: nil, zeronil: nil, &any_block) }}
86
+
87
+ it 'defines new instance methods with appropriate names' do
88
+ MyLib.function :FindWindow, 'PP', 'L'
89
+ respond_to?(:FindWindow).should be_true
90
+ respond_to?(:find_window).should be_true
91
+ end
83
92
 
84
- context 'defining enhanced API function method' do
85
- spec{ use{ MyLib.function('FindWindow', 'PP', 'l', rename: nil, aliases: nil, boolean: nil, zeronil: nil, &any_block) }}
86
-
87
- it 'defines new instance methods with appropriate names' do
88
- MyLib.function 'FindWindow', 'PP', 'L'
89
- respond_to?(:FindWindow).should be_true
90
- respond_to?(:find_window).should be_true
91
- end
92
-
93
- it 'constructs argument prototype from uppercase string, enforces the args count' do
94
- expect { MyLib.function 'FindWindow', 'PP', 'L' }.to_not raise_error
95
- should_count_args :find_window, :FindWindow, [nil, nil], [nil, TEST_IMPOSSIBLE, 'cmd']
96
- end
93
+ it 'constructs argument prototype from uppercase string, enforces the args count' do
94
+ expect { MyLib.function :FindWindow, 'PP', 'L' }.to_not raise_error
95
+ should_count_args :find_window, :FindWindow, [nil, nil], [nil, TEST_IMPOSSIBLE, 'cmd']
96
+ end
97
97
 
98
- it 'constructs argument prototype from (mixed) array, enforces the args count' do
99
- expect { MyLib.function 'FindWindow', [:pointer, 'P'], 'L' }.to_not raise_error
100
- should_count_args :find_window, :FindWindow, [nil, nil], [nil, TEST_IMPOSSIBLE, 'cmd']
101
- end
98
+ it 'constructs argument prototype from (mixed) array, enforces the args count' do
99
+ expect { MyLib.function :FindWindow, [:pointer, 'P'], 'L' }.to_not raise_error
100
+ should_count_args :find_window, :FindWindow, [nil, nil], [nil, TEST_IMPOSSIBLE, 'cmd']
101
+ end
102
102
 
103
- it 'with :rename option, overrides snake_case name for defined method but leaves CamelCase intact' do
104
- MyLib.function 'FindWindow', 'PP', 'L', :rename=> 'my_own_find'
105
- expect {find_window(nil, nil)}.to raise_error NoMethodError
106
- expect {FindWindow(nil, nil)}.to_not raise_error
107
- expect {my_own_find(nil, nil)}.to_not raise_error
108
- end
103
+ it 'with :rename option, overrides snake_case name for defined method but leaves CamelCase intact' do
104
+ MyLib.function :FindWindow, 'PP', 'L', :rename=> 'my_own_find'
105
+ expect {find_window(nil, nil)}.to raise_error NoMethodError
106
+ expect {FindWindow(nil, nil)}.to_not raise_error
107
+ expect {my_own_find(nil, nil)}.to_not raise_error
108
+ end
109
109
 
110
- it 'defined snake_case method returns expected value when called' do
111
- MyLib.function 'FindWindow', 'PP', 'L'
112
- find_window(nil, nil).should_not == 0
113
- find_window(nil, TEST_IMPOSSIBLE).should == 0
114
- find_window(TEST_IMPOSSIBLE, nil).should == 0
115
- find_window(TEST_IMPOSSIBLE, TEST_IMPOSSIBLE).should == 0
116
- end
110
+ it 'defined snake_case method returns expected value when called' do
111
+ MyLib.function :FindWindow, 'PP', 'L'
112
+ find_window(nil, nil).should_not == 0
113
+ find_window(nil, TEST_IMPOSSIBLE).should == 0
114
+ find_window(TEST_IMPOSSIBLE, nil).should == 0
115
+ find_window(TEST_IMPOSSIBLE, TEST_IMPOSSIBLE).should == 0
116
+ end
117
117
 
118
- it 'defined CamelCase method returns expected value when called' do
119
- MyLib.function 'FindWindow', 'PP', 'L'
120
- FindWindow(nil, nil).should_not == 0
121
- FindWindow(nil, TEST_IMPOSSIBLE).should == 0
122
- FindWindow(TEST_IMPOSSIBLE, nil).should == 0
123
- FindWindow(TEST_IMPOSSIBLE, TEST_IMPOSSIBLE).should == 0
124
- end
118
+ it 'defined CamelCase method returns expected value when called' do
119
+ MyLib.function :FindWindow, 'PP', 'L'
120
+ FindWindow(nil, nil).should_not == 0
121
+ FindWindow(nil, TEST_IMPOSSIBLE).should == 0
122
+ FindWindow(TEST_IMPOSSIBLE, nil).should == 0
123
+ FindWindow(TEST_IMPOSSIBLE, TEST_IMPOSSIBLE).should == 0
124
+ end
125
125
 
126
126
  # it 'returns underlying Win32::API object if defined method is called with (:api) argument ' do
127
- # MyLib.function 'FindWindow', 'PP', 'L'
127
+ # MyLib.function :FindWindow, 'PP', 'L'
128
128
  # expect {find_window(:api)}.to_not raise_error
129
129
  # should_be :find_window, find_window(:api)
130
130
  # end
131
131
 
132
- it 'returns underlying Win32::API object' do
133
- FWAPI = MyLib.function 'FindWindow', 'PP', 'L'
134
- should_be :find_window, FWAPI
132
+ it 'returns underlying Win32::API object' do
133
+ FWAPI = MyLib.function :FindWindow, 'PP', 'L'
134
+ should_be :find_window, FWAPI
135
+ end
135
136
  end
136
- end
137
137
 
138
- context 'defining aliases' do
139
- it 'adds alias for defined method with :alias option' do
140
- MyLib.function( 'FindWindow', 'PP', 'L', :alias => 'my_own_find')
141
- expect {find_window(nil, nil)}.to_not raise_error
142
- expect {my_own_find(nil, nil)}.to_not raise_error
143
- end
138
+ context 'defining aliases' do
139
+ it 'adds alias for defined method with :alias option' do
140
+ MyLib.function( :FindWindow, 'PP', 'L', :alias => 'my_own_find')
141
+ expect {find_window(nil, nil)}.to_not raise_error
142
+ expect {my_own_find(nil, nil)}.to_not raise_error
143
+ end
144
144
 
145
- it 'adds aliases for defined method with :aliases option' do
146
- MyLib.function 'FindWindow', 'PP', 'L', :aliases => ['my_own_find', 'my_own_find1']
147
- expect {find_window(nil, nil)}.to_not raise_error
148
- expect {my_own_find(nil, nil)}.to_not raise_error
149
- expect {my_own_find1(nil, nil)}.to_not raise_error
150
- end
145
+ it 'adds aliases for defined method with :aliases option' do
146
+ MyLib.function :FindWindow, 'PP', 'L', :aliases => ['my_own_find', 'my_own_find1']
147
+ expect {find_window(nil, nil)}.to_not raise_error
148
+ expect {my_own_find(nil, nil)}.to_not raise_error
149
+ expect {my_own_find1(nil, nil)}.to_not raise_error
150
+ end
151
151
 
152
- it 'adds Rubyesque alias to IsXxx API test function' do
153
- MyLib.function 'IsWindow', 'L', 'B'
154
- respond_to?(:window?).should be_true
155
- respond_to?(:is_window).should be_true
156
- end
152
+ it 'adds Rubyesque alias to IsXxx API test function' do
153
+ MyLib.function 'IsWindow', 'L', 'B'
154
+ respond_to?(:window?).should be_true
155
+ respond_to?(:is_window).should be_true
156
+ end
157
157
 
158
- it 'adds Rubyesque alias to GetXxx API getter function' do
159
- MyLib.function 'GetComputerName', 'PP', 'I', :dll=> 'kernel32'
160
- respond_to?(:get_computer_name).should be_true
161
- respond_to?(:computer_name).should be_true
158
+ it 'adds Rubyesque alias to GetXxx API getter function' do
159
+ MyLib.function 'GetComputerName', 'PP', 'I', :dll=> 'kernel32'
160
+ respond_to?(:get_computer_name).should be_true
161
+ respond_to?(:computer_name).should be_true
162
+ end
162
163
  end
163
- end
164
164
 
165
- context 'defining API with :boolean option converts result to boolean' do
166
- before(:each) { MyLib.function 'FindWindow', 'PP', 'L', :boolean => true }
165
+ context 'defining API with :boolean option converts result to boolean' do
166
+ before(:each) { MyLib.function :FindWindow, 'PP', 'L', :boolean => true }
167
167
 
168
- it 'defines new instance method' do
169
- respond_to?(:find_window).should be_true
170
- respond_to?(:FindWindow).should be_true
171
- end
168
+ it 'defines new instance method' do
169
+ respond_to?(:find_window).should be_true
170
+ respond_to?(:FindWindow).should be_true
171
+ end
172
172
 
173
- it 'defined snake_case method returns false/true instead of zero/non-zero' do
174
- find_window(nil, nil).should == true
175
- find_window(nil, TEST_IMPOSSIBLE).should == false
176
- end
173
+ it 'defined snake_case method returns false/true instead of zero/non-zero' do
174
+ find_window(nil, nil).should == true
175
+ find_window(nil, TEST_IMPOSSIBLE).should == false
176
+ end
177
177
 
178
- it 'defined CamelCase method still returns zero/non-zero' do
179
- FindWindow(nil, nil).should_not == true
180
- FindWindow(nil, nil).should_not == 0
181
- FindWindow(nil, TEST_IMPOSSIBLE).should == 0
182
- end
178
+ it 'defined CamelCase method still returns zero/non-zero' do
179
+ FindWindow(nil, nil).should_not == true
180
+ FindWindow(nil, nil).should_not == 0
181
+ FindWindow(nil, TEST_IMPOSSIBLE).should == 0
182
+ end
183
183
 
184
- it 'defined methods enforce the argument count' do
185
- should_count_args :find_window, :FindWindow, [nil, nil], [nil, TEST_IMPOSSIBLE, 'cmd']
184
+ it 'defined methods enforce the argument count' do
185
+ should_count_args :find_window, :FindWindow, [nil, nil], [nil, TEST_IMPOSSIBLE, 'cmd']
186
+ end
186
187
  end
187
- end
188
188
 
189
- context 'defining API with :zeronil option converts zero result to nil' do
190
- before(:each) {MyLib.function 'FindWindow', 'PP', 'L', :zeronil => true}
189
+ context 'defining API with :zeronil option converts zero result to nil' do
190
+ before(:each) {MyLib.function :FindWindow, 'PP', 'L', :zeronil => true}
191
191
 
192
- it 'defines new instance method' do
193
- respond_to?(:find_window).should be_true
194
- respond_to?(:FindWindow).should be_true
195
- end
192
+ it 'defines new instance method' do
193
+ respond_to?(:find_window).should be_true
194
+ respond_to?(:FindWindow).should be_true
195
+ end
196
196
 
197
- it 'defined CamelCase method still returns zero/non-zero' do
198
- FindWindow(nil, nil).should_not == true
199
- FindWindow(nil, nil).should_not == 0
200
- FindWindow(nil, TEST_IMPOSSIBLE).should == 0
201
- end
197
+ it 'defined CamelCase method still returns zero/non-zero' do
198
+ FindWindow(nil, nil).should_not == true
199
+ FindWindow(nil, nil).should_not == 0
200
+ FindWindow(nil, TEST_IMPOSSIBLE).should == 0
201
+ end
202
202
 
203
- it 'defined method returns nil (but NOT false) instead of zero' do
204
- find_window(nil, TEST_IMPOSSIBLE).should_not == false
205
- find_window(nil, TEST_IMPOSSIBLE).should == nil
206
- end
203
+ it 'defined method returns nil (but NOT false) instead of zero' do
204
+ find_window(nil, TEST_IMPOSSIBLE).should_not == false
205
+ find_window(nil, TEST_IMPOSSIBLE).should == nil
206
+ end
207
207
 
208
- it 'defined method does not return true when result is non-zero' do
209
- find_window(nil, nil).should_not == true
210
- find_window(nil, nil).should_not == 0
211
- end
208
+ it 'defined method does not return true when result is non-zero' do
209
+ find_window(nil, nil).should_not == true
210
+ find_window(nil, nil).should_not == 0
211
+ end
212
212
 
213
- it 'defined methods enforce the argument count' do
214
- should_count_args :find_window, :FindWindow, [nil, nil], [nil, TEST_IMPOSSIBLE, 'cmd']
213
+ it 'defined methods enforce the argument count' do
214
+ should_count_args :find_window, :FindWindow, [nil, nil], [nil, TEST_IMPOSSIBLE, 'cmd']
215
+ end
215
216
  end
216
- end
217
217
 
218
- context 'using DLL other than default user32 with :dll option' do
219
- before(:each) {MyLib.function 'GetComputerName', 'PP', 'I', :dll=> 'kernel32'}
218
+ context 'using DLL other than default user32 with :dll option' do
219
+ before(:each) {MyLib.function 'GetComputerName', 'PP', 'I', :dll=> 'kernel32'}
220
220
 
221
- it 'defines new instance method with appropriate name' do
222
- respond_to?(:GetComputerName).should be_true
223
- respond_to?(:get_computer_name).should be_true
224
- respond_to?(:computer_name).should be_true
225
- end
221
+ it 'defines new instance method with appropriate name' do
222
+ respond_to?(:GetComputerName).should be_true
223
+ respond_to?(:get_computer_name).should be_true
224
+ respond_to?(:computer_name).should be_true
225
+ end
226
226
 
227
- it 'returns expected result' do
228
- MyLib.function 'GetComputerName', ['P', 'P'], 'I', :dll=> 'kernel32'
229
- hostname = `hostname`.strip.upcase
230
- name = " " * 128
231
- get_computer_name(name, "128")
232
- name.unpack("A*").first.should == hostname
227
+ it 'returns expected result' do
228
+ MyLib.function 'GetComputerName', ['P', 'P'], 'I', :dll=> 'kernel32'
229
+ hostname = `hostname`.strip.upcase
230
+ name = " " * 128
231
+ get_computer_name(name, "128")
232
+ name.unpack("A*").first.should == hostname
233
+ end
233
234
  end
234
- end
235
235
 
236
- context 'trying to define an invalid API function' do
237
- it 'raises error when trying to define function with a wrong function name' do
238
- expect { MyLib.function 'FindWindowImpossible', 'PP', 'L' }.
239
- to raise_error( /Function 'FindWindowImpossible' not found/ )
236
+ context 'trying to define an invalid API function' do
237
+ it 'raises error when trying to define function with a wrong function name' do
238
+ expect { MyLib.function 'FindWindowImpossible', 'PP', 'L' }.
239
+ to raise_error( /Function 'FindWindowImpossible' not found/ )
240
+ end
240
241
  end
241
- end
242
242
 
243
- context 'defining API function using definition block' do
244
- it 'defines new instance method' do
245
- MyLib.function( 'FindWindow', 'PP', 'L' ){|api, *args|}
246
- respond_to?(:find_window).should be_true
247
- respond_to?(:FindWindow).should be_true
248
- end
243
+ context 'defining API function using definition block' do
244
+ it 'defines new instance method' do
245
+ MyLib.function( :FindWindow, 'PP', 'L' ){|api, *args|}
246
+ respond_to?(:find_window).should be_true
247
+ respond_to?(:FindWindow).should be_true
248
+ end
249
249
 
250
- it 'does not enforce argument count outside of block' do
251
- MyLib.function( 'FindWindow', 'PP', 'L' ){|api, *args|}
252
- expect { find_window }.to_not raise_error
253
- expect { find_window(nil) }.to_not raise_error
254
- expect { find_window(nil, 'Str', 1) }.to_not raise_error
255
- end
250
+ it 'does not enforce argument count outside of block' do
251
+ MyLib.function( :FindWindow, 'PP', 'L' ){|api, *args|}
252
+ expect { find_window }.to_not raise_error
253
+ expect { find_window(nil) }.to_not raise_error
254
+ expect { find_window(nil, 'Str', 1) }.to_not raise_error
255
+ end
256
256
 
257
- it 'returns block return value when defined method is called' do
258
- MyLib.function( 'FindWindow', 'PP', 'L' ){|api, *args| 'Value'}
259
- find_window(nil).should == 'Value'
260
- end
257
+ it 'returns block return value when defined method is called' do
258
+ MyLib.function( :FindWindow, 'PP', 'L' ){|api, *args| 'Value'}
259
+ find_window(nil).should == 'Value'
260
+ end
261
261
 
262
- it 'passes arguments and underlying Win32::API object to the block' do
263
- MyLib.function( 'FindWindow', 'PP', 'L' ) do |api, *args|
264
- @api = api
265
- @args = args
262
+ it 'passes arguments and underlying Win32::API object to the block' do
263
+ MyLib.function( :FindWindow, 'PP', 'L' ) do |api, *args|
264
+ @api = api
265
+ @args = args
266
+ end
267
+ expect {find_window(1, 2, 3) }.to_not raise_error
268
+ @args.should == [1, 2, 3]
269
+ should_be :find_window, @api
266
270
  end
267
- expect {find_window(1, 2, 3) }.to_not raise_error
268
- @args.should == [1, 2, 3]
269
- should_be :find_window, @api
270
- end
271
271
 
272
- it ':rename option overrides standard name for defined method' do
273
- MyLib.function( 'FindWindow', 'PP', 'L', :rename => 'my_own_find' ){|api, *args|}
274
- expect {find_window(nil, nil, nil)}.to raise_error
275
- expect {my_own_find(nil, nil)}.to_not raise_error
276
- end
272
+ it ':rename option overrides standard name for defined method' do
273
+ MyLib.function( :FindWindow, 'PP', 'L', :rename => 'my_own_find' ){|api, *args|}
274
+ expect {find_window(nil, nil, nil)}.to raise_error
275
+ expect {my_own_find(nil, nil)}.to_not raise_error
276
+ end
277
277
 
278
- it 'adds alias for defined method with :alias option' do
279
- MyLib.function( 'FindWindow', 'PP', 'L', :alias => 'my_own_find' ){|api, *args|}
280
- expect {find_window(nil, nil)}.to_not raise_error
281
- expect {my_own_find(nil, nil)}.to_not raise_error
282
- end
278
+ it 'adds alias for defined method with :alias option' do
279
+ MyLib.function( :FindWindow, 'PP', 'L', :alias => 'my_own_find' ){|api, *args|}
280
+ expect {find_window(nil, nil)}.to_not raise_error
281
+ expect {my_own_find(nil, nil)}.to_not raise_error
282
+ end
283
283
 
284
- it 'adds aliases for defined method with :aliases option' do
285
- MyLib.function( 'FindWindow', 'PP', 'L', :aliases => ['my_own_find', 'my_own_find1'] ) {|api, *args|}
286
- expect {find_window(nil, nil)}.to_not raise_error
287
- expect {my_own_find(nil, nil)}.to_not raise_error
288
- expect {my_own_find1(nil, nil)}.to_not raise_error
284
+ it 'adds aliases for defined method with :aliases option' do
285
+ MyLib.function( :FindWindow, 'PP', 'L', :aliases => ['my_own_find', 'my_own_find1'] ) {|api, *args|}
286
+ expect {find_window(nil, nil)}.to_not raise_error
287
+ expect {my_own_find(nil, nil)}.to_not raise_error
288
+ expect {my_own_find1(nil, nil)}.to_not raise_error
289
+ end
289
290
  end
290
- end
291
291
 
292
- context 'calling defined methods with attached block to preprocess the API function results' do
293
- it 'defined method yields raw result to block attached to its invocation' do
294
- MyLib.function 'FindWindow', 'PP', 'L', zeronil: true
295
- find_window(nil, TEST_IMPOSSIBLE) {|result| result.should == 0 }
296
- end
292
+ context 'calling defined methods with attached block to preprocess the API function results' do
293
+ it 'defined method yields raw result to block attached to its invocation' do
294
+ MyLib.function :FindWindow, 'PP', 'L', zeronil: true
295
+ find_window(nil, TEST_IMPOSSIBLE) {|result| result.should == 0 }
296
+ end
297
297
 
298
- it 'defined method returns result of block attached to its invocation' do
299
- MyLib.function 'FindWindow', 'PP', 'L', zeronil: true
300
- return_value = find_window(nil, TEST_IMPOSSIBLE) {|result| 'Value'}
301
- return_value.should == 'Value'
302
- end
298
+ it 'defined method returns result of block attached to its invocation' do
299
+ MyLib.function :FindWindow, 'PP', 'L', zeronil: true
300
+ return_value = find_window(nil, TEST_IMPOSSIBLE) {|result| 'Value'}
301
+ return_value.should == 'Value'
302
+ end
303
303
 
304
- it 'defined method transforms result of block before returning it' do
305
- MyLib.function 'FindWindow', 'PP', 'L', zeronil: true
306
- return_value = find_window(nil, TEST_IMPOSSIBLE) {|result| 0 }
307
- return_value.should_not == 0
308
- return_value.should == nil
304
+ it 'defined method transforms result of block before returning it' do
305
+ MyLib.function :FindWindow, 'PP', 'L', zeronil: true
306
+ return_value = find_window(nil, TEST_IMPOSSIBLE) {|result| 0 }
307
+ return_value.should_not == 0
308
+ return_value.should == nil
309
+ end
309
310
  end
310
- end
311
311
 
312
- context 'defining API function without arguments - f(VOID)' do
313
- it 'should enforce argument count to 0, NOT 1' do
314
- MyLib.function 'GetForegroundWindow', [], 'L', zeronil: true
315
- should_count_args :GetForegroundWindow, :get_foreground_window, :foreground_window, [], [nil, 0, 123]
312
+ context 'defining API function without arguments - f(VOID)' do
313
+ it 'should enforce argument count to 0, NOT 1' do
314
+ MyLib.function :GetForegroundWindow, [], 'L', zeronil: true
315
+ should_count_args :GetForegroundWindow, :get_foreground_window, :foreground_window, [], [nil, 0, 123]
316
+ end
316
317
  end
317
- end
318
+ end
318
319
 
319
- context 'working with API function callbacks' do
320
- it '#callback method creates a valid callback object' do
321
- pending 'What about callbacks?'
322
- expect { @callback = WinGui.callback('LP', 'I') {|handle, message| true} }.to_not raise_error
323
- @callback.should be_a_kind_of(Win32::API::Callback)
320
+ context '::callback defining API callback TYPES' do
321
+ it '#callback macro creates a valid callback definition' do
322
+ expect { MyLib.callback :MyEnumWindowsProc, [:HWND, :long], :bool}.to_not raise_error
324
323
  end
325
324
 
326
- it 'created callback object can be used as a valid arg of API function expecting callback' do
327
- pending 'What about callbacks?'
328
- MyLib.function 'EnumWindows', 'KP', 'L'
329
- @callback = WinGui.callback('LP', 'I'){|handle, message| true }
330
- expect { enum_windows(@callback, 'Message') }.to_not raise_error
325
+ it 'created callback definition can be used to define API function expecting callback' do
326
+ expect {MyLib.function :EnumWindows, [:MyEnumWindowsProc, :long], :long}.to_not raise_error
327
+ expect { enum_windows(lambda{|handle, message| true }, 0) }.to_not raise_error
331
328
  end
329
+ end
332
330
 
333
- it 'defined API functions expecting callback convert given block into callback' do
334
- pending 'What about callbacks?'
335
- pending ' What about prototype!? API is not exactly clear atm (.with_callback method?)'
336
- MyLib.function 'EnumWindows', 'KP', 'L'
337
- expect { enum_windows('Message'){|handle, message| true } }.to_not raise_error
331
+ context '::try_function to define API function that are platform-specific' do
332
+ if xp?
333
+ it 'should silently fail to define function not present on current platform' do
334
+ expect {MyLib.function :GetErrorMode, [], :UINT}.to raise_error /Function 'GetErrorMode' not found/
335
+ expect {MyLib.try_function :GetErrorMode, [], :UINT}.to_not raise_error
336
+ expect { GetErrorMode() }.to raise_error /undefined method `GetErrorMode'/
337
+ expect { get_error_mode() }.to raise_error /undefined method `get_error_mode'/
338
+ end
338
339
  end
339
340
  end
340
341
  end
341
- end
342
+ end
data/win.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{win}
8
- s.version = "0.1.16"
8
+ s.version = "0.1.18"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["arvicco"]
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.1.16
4
+ version: 0.1.18
5
5
  platform: ruby
6
6
  authors:
7
7
  - arvicco