win 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -1,21 +1,16 @@
1
1
  = win
2
2
 
3
3
  by: Arvicco
4
- url: http://github.com/arvicco/win_gui
4
+ url: http://github.com/arvicco/win
5
5
 
6
6
  == DESCRIPTION
7
7
 
8
- A collection of Windows functions predefined for you using FFI. In addition to
8
+ A collection of Windows API functions predefined for you using FFI. In addition to
9
9
  straightforward (CamelCase) API wrappers, it also strives to provide more Ruby-like
10
10
  snake_case methods that take a minimum of arguments with sensible defaults and have
11
11
  sensible return values (false/true instead of 0/nonzero for test functions, etc).
12
12
 
13
- Windows functions are grouped by topics and defined in separate namespaces (modules),
14
- that also contain related constants and convenience methods. For example, win/dde.rb
15
- file contains functions related to DDE protocol, such as DdeInitialize() as well as
16
- constants such as DMLERR_NO_ERROR, APPCLASS_STANDARD, etc.
17
-
18
- It is still work in progress, only a small number of Windows API functions wrapped so far...
13
+ This is still work in progress, only a small portion of Windows API wrapped so far...
19
14
 
20
15
  == SUMMARY
21
16
 
@@ -79,7 +74,7 @@ But still, does not it look like TOO MUCH code for something that should (ideall
79
74
  title = window_text_w(window_handle)
80
75
 
81
76
  This is an idea behind this library - make Windows API functions easier to use and feel more
82
- natural inside Ruby code. Following the principle of least surprise, we define methods that:
77
+ natural inside Ruby code. Following the principle of least surprise, we define wrapper methods that:
83
78
  * Have Rubyesque names (minimized? instead of IsMinimized, etc)
84
79
  * Require minimum arguments with sensible defaults
85
80
  * Return appropriate values explicitly (several return values if necessary)
@@ -93,10 +88,17 @@ CamelCase method name instead of Rubyesque snake_case one, it will expect those
93
88
  parameters you know and love from MSDN, return your zeroes instead of nils and support no
94
89
  other enhancements.
95
90
 
91
+ Related Windows API functions are grouped by topic and defined in separate namespaces (modules),
92
+ that also contain related constants and convenience methods. For example, win/dde.rb file
93
+ contains only functions related to DDE protocol such as DdeInitialize() as well as constants
94
+ such as DMLERR_NO_ERROR, APPCLASS_STANDARD, etc. So if you need only DDE-related functions,
95
+ there is no need to load all the other modules, clogging your namespaces - just require 'win/dde'
96
+ and be done with it.
97
+
96
98
  And if you do not see your favorite Windows API functions amoung those already defined, it is
97
- quite easy to define new ones with 'function' macro method from Win::Library class - it does a
98
- lot of heavy lifting for you and can be customized with options and code blocks to give you
99
- reusable API wrapper methods with the exact behavior you need.
99
+ quite easy to 'include Win::Library' into your module and define new ones with 'function'
100
+ class method (macro) - it does a lot of heavy lifting for you and can be customized with options
101
+ and code blocks to give you reusable API wrapper methods with the exact behavior you need.
100
102
 
101
103
  == REQUIREMENTS:
102
104
 
@@ -116,11 +118,11 @@ Contributors always welcome!
116
118
 
117
119
  require 'win/window'
118
120
 
119
- class Foo
121
+ class MyClass
120
122
  include Win::Window
121
123
 
122
124
  fg_window = foreground_window
123
- puts window_text_w(fg_window)
125
+ puts window_text(fg_window)
124
126
  show_window(fg_window) unless minimized?(fg_window)
125
127
  hide_window(fg_window) if maximized?(fg_window)
126
128
  ...
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.0.3
data/lib/win/library.rb CHANGED
@@ -3,22 +3,24 @@ require 'win/extensions'
3
3
 
4
4
  module Win
5
5
 
6
- class NotFoundError < NameError
7
- def initialize(name=nil, libs=nil)
8
- super %Q[Function #{name ? "'#{name}' ": ""}not found#{libs ? " in #{libs}" : ""}"]
6
+ module Errors # :nodoc:
7
+ class NotFoundError < NameError # :nodoc:
8
+ def initialize(name=nil, libs=nil)
9
+ super %Q[Function #{name ? "'#{name}' ": ""}not found#{libs ? " in #{libs}" : ""}"]
10
+ end
9
11
  end
10
12
  end
11
13
 
12
14
  module Library
13
15
 
14
- # Class Win::Library::API mimics Win32::API
16
+ # API wrapper for Class Win::Library::API mimics Win32::API
15
17
  class API
16
18
 
17
19
  # The name of the DLL that exports the API function
18
20
  attr_reader :dll_name
19
21
 
20
- # Ruby (library) module to which this function is attached
21
- attr_reader :lib_module
22
+ # Ruby namespace (module) where this API function is attached
23
+ attr_reader :namespace
22
24
 
23
25
  # The name of the function passed to the constructor
24
26
  attr_reader :function_name
@@ -34,22 +36,26 @@ module Win
34
36
  # The return type (:void for no return value)
35
37
  attr_reader :return_type
36
38
 
37
- def initialize( lib_module, function, effective_function_name, prototype, return_type )
38
- @lib_module = lib_module
39
- @function_name = function
39
+ def initialize( namespace, function_name, effective_function_name, prototype, return_type, dll_name )
40
+ @namespace = namespace
41
+ @function_name = function_name
40
42
  @effective_function_name = effective_function_name
41
43
  @prototype = prototype
42
44
  @return_type = return_type
45
+ @dll_name = dll_name
43
46
  end
44
47
 
45
48
  def call( *args )
46
- @lib_module.send(@effective_function_name.to_sym, *args)
49
+ @namespace.send(@function_name.to_sym, *args)
47
50
  end
51
+
52
+ alias_method :[], :call
48
53
  end
49
54
 
50
55
  # Contains class methods (macros) to be used in Win::Libraries
51
56
  module ClassMethods
52
57
  TYPES = {
58
+ # FFI type shortcuts
53
59
  V: :void, # For functions that return nothing (return type void).
54
60
  v: :void, # For functions that return nothing (return type void).
55
61
  C: :uchar, #– 8-bit unsigned character (byte)
@@ -74,12 +80,193 @@ module Win
74
80
  D: :double, # 64-bit floating point (double-precision)
75
81
  P: :pointer, # pointer – platform-specific size
76
82
  p: :string, # C-style (NULL-terminated) character string (Win32API: S)
77
- B: :bool # (?? 1 byte in C++)
83
+ B: :bool, # (?? 1 byte in C++)
78
84
  #For function argument type only:
79
85
  # :buffer_in – Similar to :pointer, but optimized for Buffers that the function can only read (not write).
80
86
  # :buffer_out – Similar to :pointer, but optimized for Buffers that the function can only write (not read).
81
87
  # :buffer_inout – Similar to :pointer, but may be optimized for Buffers.
82
88
  # :varargs – Variable arguments
89
+
90
+ # Windows-specific typedefs:
91
+ ATOM: :ushort, # Atom ~= Symbol: Atom table stores strings and corresponding identifiers. Application
92
+ # places a string in an atom table and receives a 16-bit integer, called an atom, that
93
+ # can be used to access the string. Placed string is called an atom name.
94
+ # See: http://msdn.microsoft.com/en-us/library/ms648708%28VS.85%29.aspx
95
+ BOOL: :bool,
96
+ BOOLEAN: :bool,
97
+ BYTE: :uchar, # Byte (8 bits). Declared as unsigned char
98
+ #CALLBACK: K, # Win32.API gem-specific ?? MSDN: #define CALLBACK __stdcall
99
+ CHAR: :char, # 8-bit Windows (ANSI) character. See http://msdn.microsoft.com/en-us/library/dd183415%28VS.85%29.aspx
100
+ COLORREF: :uint32, # Red, green, blue (RGB) color value (32 bits). See COLORREF for more info.
101
+ DWORD: :uint32, # 32-bit unsigned integer. The range is 0 through 4,294,967,295 decimal.
102
+ DWORDLONG: :uint64, # 64-bit unsigned integer. The range is 0 through 18,446,744,073,709,551,615 decimal.
103
+ DWORD_PTR: :ulong, # Unsigned long type for pointer precision. Use when casting a pointer to a long type
104
+ # to perform pointer arithmetic. (Also commonly used for general 32-bit parameters that have
105
+ # been extended to 64 bits in 64-bit Windows.) BaseTsd.h: #typedef ULONG_PTR DWORD_PTR;
106
+ DWORD32: :uint32,
107
+ DWORD64: :uint64,
108
+ HALF_PTR: :int, # Half the size of a pointer. Use within a structure that contains a pointer and two small fields.
109
+ # BaseTsd.h: #ifdef (_WIN64) typedef int HALF_PTR; #else typedef short HALF_PTR;
110
+ HACCEL: :ulong, # (L) Handle to an accelerator table. WinDef.h: #typedef HANDLE HACCEL;
111
+ # See http://msdn.microsoft.com/en-us/library/ms645526%28VS.85%29.aspx
112
+ HANDLE: :ulong, # (L) Handle to an object. WinNT.h: #typedef PVOID HANDLE;
113
+ HBITMAP: :ulong, # (L) Handle to a bitmap: http://msdn.microsoft.com/en-us/library/dd183377%28VS.85%29.aspx
114
+ HBRUSH: :ulong, # (L) Handle to a brush. http://msdn.microsoft.com/en-us/library/dd183394%28VS.85%29.aspx
115
+ HCOLORSPACE: :ulong,# (L) Handle to a color space. http://msdn.microsoft.com/en-us/library/ms536546%28VS.85%29.aspx
116
+ HCURSOR: :ulong, # (L) Handle to a cursor. http://msdn.microsoft.com/en-us/library/ms646970%28VS.85%29.aspx
117
+ HCONV: :ulong, # (L) Handle to a dynamic data exchange (DDE) conversation.
118
+ HCONVLIST: :ulong, # (L) Handle to a DDE conversation list. HANDLE - L ?
119
+ HDDEDATA: :ulong, # (L) Handle to DDE data (structure?)
120
+ HDC: :ulong, # (L) Handle to a device context (DC). http://msdn.microsoft.com/en-us/library/dd183560%28VS.85%29.aspx
121
+ HDESK: :ulong, # (L) Handle to a desktop. http://msdn.microsoft.com/en-us/library/ms682573%28VS.85%29.aspx
122
+ HDROP: :ulong, # (L) Handle to an internal drop structure.
123
+ HDWP: :ulong, # (L) Handle to a deferred window position structure.
124
+ HENHMETAFILE: :ulong,#(L) Handle to an enhanced metafile. http://msdn.microsoft.com/en-us/library/dd145051%28VS.85%29.aspx
125
+ HFILE: :uint, # (I) Special file handle to a file opened by OpenFile, not CreateFile.
126
+ # WinDef.h: #typedef int HFILE;
127
+ HFONT: :ulong, # (L) Handle to a font. http://msdn.microsoft.com/en-us/library/dd162470%28VS.85%29.aspx
128
+ HGDIOBJ: :ulong, # (L) Handle to a GDI object.
129
+ HGLOBAL: :ulong, # (L) Handle to a global memory block.
130
+ HHOOK: :ulong, # (L) Handle to a hook. http://msdn.microsoft.com/en-us/library/ms632589%28VS.85%29.aspx
131
+ HICON: :ulong, # (L) Handle to an icon. http://msdn.microsoft.com/en-us/library/ms646973%28VS.85%29.aspx
132
+ HINSTANCE: :ulong, # (L) Handle to an instance. This is the base address of the module in memory.
133
+ # HMODULE and HINSTANCE are the same today, but were different in 16-bit Windows.
134
+ HKEY: :ulong, # (L) Handle to a registry key.
135
+ HKL: :ulong, # (L) Input locale identifier.
136
+ HLOCAL: :ulong, # (L) Handle to a local memory block.
137
+ HMENU: :ulong, # (L) Handle to a menu. http://msdn.microsoft.com/en-us/library/ms646977%28VS.85%29.aspx
138
+ HMETAFILE: :ulong, # (L) Handle to a metafile. http://msdn.microsoft.com/en-us/library/dd145051%28VS.85%29.aspx
139
+ HMODULE: :ulong, # (L) Handle to an instance. Same as HINSTANCE today, but was different in 16-bit Windows.
140
+ HMONITOR: :ulong, # (L) Рandle to a display monitor. WinDef.h: if(WINVER >= 0x0500) typedef HANDLE HMONITOR;
141
+ HPALETTE: :ulong, # (L) Handle to a palette.
142
+ HPEN: :ulong, # (L) Handle to a pen. http://msdn.microsoft.com/en-us/library/dd162786%28VS.85%29.aspx
143
+ HRESULT: :long, # Return code used by COM interfaces. For more info, Structure of the COM Error Codes.
144
+ # To test an HRESULT value, use the FAILED and SUCCEEDED macros.
145
+ HRGN: :ulong, # (L) Handle to a region. http://msdn.microsoft.com/en-us/library/dd162913%28VS.85%29.aspx
146
+ HRSRC: :ulong, # (L) Handle to a resource.
147
+ HSZ: :ulong, # (L) Handle to a DDE string.
148
+ HWINSTA: :ulong, # (L) Handle to a window station. http://msdn.microsoft.com/en-us/library/ms687096%28VS.85%29.aspx
149
+ HWND: :ulong, # (L) Handle to a window. http://msdn.microsoft.com/en-us/library/ms632595%28VS.85%29.aspx
150
+ INT: :int, # 32-bit signed integer. The range is -2147483648 through 2147483647 decimal.
151
+ INT_PTR: :int, # Signed integer type for pointer precision. Use when casting a pointer to an integer
152
+ # to perform pointer arithmetic. BaseTsd.h:
153
+ #if defined(_WIN64) typedef __int64 INT_PTR; #else typedef int INT_PTR;
154
+ INT32: :int32, # 32-bit signed integer. The range is -2,147,483,648 through +...647 decimal.
155
+ INT64: :int64, # 64-bit signed integer. The range is –9,223,372,036,854,775,808 through +...807
156
+ LANGID: :ushort, # Language identifier. For more information, see Locales. WinNT.h: #typedef WORD LANGID;
157
+ # See http://msdn.microsoft.com/en-us/library/dd318716%28VS.85%29.aspx
158
+ LCID: :uint32, # Locale identifier. For more information, see Locales.
159
+ LCTYPE: :uint32, # Locale information type. For a list, see Locale Information Constants.
160
+ LGRPID: :uint32, # Language group identifier. For a list, see EnumLanguageGroupLocales.
161
+ LONG: :long, # 32-bit signed integer. The range is -2,147,483,648 through +...647 decimal.
162
+ LONG32: :long, # 32-bit signed integer. The range is -2,147,483,648 through +...647 decimal.
163
+ LONG64: :int64, # 64-bit signed integer. The range is –9,223,372,036,854,775,808 through +...807
164
+ LONGLONG: :int64, # 64-bit signed integer. The range is –9,223,372,036,854,775,808 through +...807
165
+ LONG_PTR: :long, # Signed long type for pointer precision. Use when casting a pointer to a long to
166
+ # perform pointer arithmetic. BaseTsd.h:
167
+ #if defined(_WIN64) typedef __int64 LONG_PTR; #else typedef long LONG_PTR;
168
+ LPARAM: :long, # Message parameter. WinDef.h as follows: #typedef LONG_PTR LPARAM;
169
+ LPBOOL: :pointer, # Pointer to a BOOL. WinDef.h as follows: #typedef BOOL far *LPBOOL;
170
+ LPBYTE: :pointer, # Pointer to a BYTE. WinDef.h as follows: #typedef BYTE far *LPBYTE;
171
+ LPCOLORREF: :pointer,# Pointer to a COLORREF value. WinDef.h as follows: #typedef DWORD *LPCOLORREF;
172
+ LPCSTR: :pointer, # Pointer to a constant null-terminated string of 8-bit Windows (ANSI) characters.
173
+ # See Character Sets Used By Fonts. http://msdn.microsoft.com/en-us/library/dd183415%28VS.85%29.aspx
174
+ LPCTSTR: :pointer, # An LPCWSTR if UNICODE is defined, an LPCSTR otherwise.
175
+ LPCVOID: :pointer, # Pointer to a constant of any type. WinDef.h as follows: typedef CONST void *LPCVOID;
176
+ LPCWSTR: :pointer, # Pointer to a constant null-terminated string of 16-bit Unicode characters.
177
+ LPDWORD: :pointer, # Pointer to a DWORD. WinDef.h as follows: typedef DWORD *LPDWORD;
178
+ LPHANDLE: :pointer, # Pointer to a HANDLE. WinDef.h as follows: typedef HANDLE *LPHANDLE;
179
+ LPINT: :pointer, # Pointer to an INT.
180
+ LPLONG: :pointer, # Pointer to an LONG.
181
+ LPSTR: :pointer, # Pointer to a null-terminated string of 8-bit Windows (ANSI) characters.
182
+ LPTSTR: :pointer, # An LPWSTR if UNICODE is defined, an LPSTR otherwise.
183
+ LPVOID: :pointer, # Pointer to any type.
184
+ LPWORD: :pointer, # Pointer to a WORD.
185
+ LPWSTR: :pointer, # Pointer to a null-terminated string of 16-bit Unicode characters.
186
+ LRESULT: :long, # Signed result of message processing. WinDef.h: typedef LONG_PTR LRESULT;
187
+ PBOOL: :pointer, # Pointer to a BOOL.
188
+ PBOOLEAN: :pointer, # Pointer to a BOOL.
189
+ PBYTE: :pointer, # Pointer to a BYTE.
190
+ PCHAR: :pointer, # Pointer to a CHAR.
191
+ PCSTR: :pointer, # Pointer to a constant null-terminated string of 8-bit Windows (ANSI) characters.
192
+ PCTSTR: :pointer, # A PCWSTR if UNICODE is defined, a PCSTR otherwise.
193
+ PCWSTR: :pointer, # Pointer to a constant null-terminated string of 16-bit Unicode characters.
194
+ PDWORD: :pointer, # Pointer to a DWORD.
195
+ PDWORDLONG: :pointer,# Pointer to a DWORDLONG.
196
+ PDWORD_PTR: :pointer,# Pointer to a DWORD_PTR.
197
+ PDWORD32: :pointer, # Pointer to a DWORD32.
198
+ PDWORD64: :pointer, # Pointer to a DWORD64.
199
+ PFLOAT: :pointer, # Pointer to a FLOAT.
200
+ PHALF_PTR: :pointer, # Pointer to a HALF_PTR.
201
+ PHANDLE: :pointer, # Pointer to a HANDLE.
202
+ PHKEY: :pointer, # Pointer to an HKEY.
203
+ PINT: :pointer, # Pointer to an INT.
204
+ PINT_PTR: :pointer, # Pointer to an INT_PTR.
205
+ PINT32: :pointer, # Pointer to an INT32.
206
+ PINT64: :pointer, # Pointer to an INT64.
207
+ PLCID: :pointer, # Pointer to an LCID.
208
+ PLONG: :pointer, # Pointer to a LONG.
209
+ PLONGLONG: :pointer, # Pointer to a LONGLONG.
210
+ PLONG_PTR: :pointer, # Pointer to a LONG_PTR.
211
+ PLONG32: :pointer, # Pointer to a LONG32.
212
+ PLONG64: :pointer, # Pointer to a LONG64.
213
+ POINTER_32: :pointer, # 32-bit pointer. On a 32-bit system, this is a native pointer. On a 64-bit system, this is a truncated 64-bit pointer.
214
+ POINTER_64: :pointer, # 64-bit pointer. On a 64-bit system, this is a native pointer. On a 32-bit system, this is a sign-extended 32-bit pointer.
215
+ POINTER_SIGNED: :pointer, # A signed pointer.
216
+ POINTER_UNSIGNED: :pointer, # An unsigned pointer.
217
+ PSHORT: :pointer, # Pointer to a SHORT.
218
+ PSIZE_T: :pointer, # Pointer to a SIZE_T.
219
+ PSSIZE_T: :pointer, # Pointer to a SSIZE_T.
220
+ PSTR: :pointer, # Pointer to a null-terminated string of 8-bit Windows (ANSI) characters. For more information, see Character Sets Used By Fonts.
221
+ PTBYTE: :pointer, # Pointer to a TBYTE.
222
+ PTCHAR: :pointer, # Pointer to a TCHAR.
223
+ PTSTR: :pointer, # A PWSTR if UNICODE is defined, a PSTR otherwise.
224
+ PUCHAR: :pointer, # Pointer to a UCHAR.
225
+ PUHALF_PTR: :pointer, # Pointer to a UHALF_PTR.
226
+ PUINT: :pointer, # Pointer to a UINT.
227
+ PUINT_PTR: :pointer, # Pointer to a UINT_PTR.
228
+ PUINT32: :pointer, # Pointer to a UINT32.
229
+ PUINT64: :pointer, # Pointer to a UINT64.
230
+ PULONG: :pointer, # Pointer to a ULONG.
231
+ PULONGLONG: :pointer, # Pointer to a ULONGLONG.
232
+ PULONG_PTR: :pointer, # Pointer to a ULONG_PTR.
233
+ PULONG32: :pointer, # Pointer to a ULONG32.
234
+ PULONG64: :pointer, # Pointer to a ULONG64.
235
+ PUSHORT: :pointer, # Pointer to a USHORT.
236
+ PVOID: :pointer, # Pointer to any type.
237
+ PWCHAR: :pointer, # Pointer to a WCHAR.
238
+ PWORD: :pointer, # Pointer to a WORD.
239
+ PWSTR: :pointer, # Pointer to a null- terminated string of 16-bit Unicode characters.
240
+ # For more information, see Character Sets Used By Fonts.
241
+ SC_HANDLE: :ulong, # (L) Handle to a service control manager database.
242
+ # See SCM Handles http://msdn.microsoft.com/en-us/library/ms685104%28VS.85%29.aspx
243
+ SC_LOCK: :pointer, # Lock to a service control manager database. For more information, see SCM Handles.
244
+ SERVICE_STATUS_HANDLE: :ulong, # (L) Handle to a service status value. See SCM Handles.
245
+ SHORT: :short, # A 16-bit integer. The range is –32768 through 32767 decimal.
246
+ SIZE_T: :ulong, # The maximum number of bytes to which a pointer can point. Use for a count that must span the full range of a pointer.
247
+ SSIZE_T: :long, # Signed SIZE_T.
248
+ TBYTE: :short, # A WCHAR if UNICODE is defined, a CHAR otherwise.TCHAR:
249
+ TCHAR: :short, # A WCHAR if UNICODE is defined, a CHAR otherwise.TCHAR:
250
+ UCHAR: :uchar, # Unsigned CHAR (8 bit)
251
+ UHALF_PTR: :uint, # Unsigned HALF_PTR. Use within a structure that contains a pointer and two small fields.
252
+ UINT: :uint, # Unsigned INT. The range is 0 through 4294967295 decimal.
253
+ UINT_PTR: :uint, # Unsigned INT_PTR.
254
+ UINT32: :uint32, # Unsigned INT32. The range is 0 through 4294967295 decimal.
255
+ UINT64: :uint64, # Unsigned INT64. The range is 0 through 18446744073709551615 decimal.
256
+ ULONG: :ulong, # Unsigned LONG. The range is 0 through 4294967295 decimal.
257
+ ULONGLONG: :ulong_long, # 64-bit unsigned integer. The range is 0 through 18446744073709551615 decimal.
258
+ ULONG_PTR: :ulong, # Unsigned LONG_PTR.
259
+ ULONG32: :uint32, # Unsigned INT32. The range is 0 through 4294967295 decimal.
260
+ ULONG64: :uint64, # Unsigned LONG64. The range is 0 through 18446744073709551615 decimal.
261
+ UNICODE_STRING: :pointer,# Pointer to some string structure??
262
+ USHORT: :ushort, # Unsigned SHORT. The range is 0 through 65535 decimal.
263
+ USN: :ulong_long, # Update sequence number (USN).
264
+ VOID: :void, # Any type ?
265
+ WCHAR: :ushort, # 16-bit Unicode character. For more information, see Character Sets Used By Fonts.
266
+ # In WinNT.h: typedef wchar_t WCHAR;
267
+ #WINAPI: K, # Calling convention for system functions. WinDef.h: define WINAPI __stdcall
268
+ WORD: :ushort, # 16-bit unsigned integer. The range is 0 through 65535 decimal.
269
+ WPARAM: :uint # Message parameter. WinDef.h as follows: typedef UINT_PTR WPARAM;
83
270
  }
84
271
 
85
272
  ##
@@ -110,58 +297,60 @@ module Win
110
297
  # :boolean:: Forces method to return true/false instead of nonzero/zero
111
298
  # :zeronil:: Forces method to return nil if function result is zero
112
299
  #
113
- def function(function, params, returns, options={}, &define_block)
114
- method_name, effective_names, aliases = generate_names(function, options)
300
+ def function(name, params, returns, options={}, &def_block)
301
+ method_name, effective_names, aliases = generate_names(name, options)
302
+ params, returns = generate_signature(params, returns, options)
303
+ libs = ffi_libraries.map(&:name)
115
304
  boolean = options[:boolean]
116
305
  zeronil = options[:zeronil]
117
- params = params.split(//) if params.respond_to?(:split) # Convert params string into array
118
- #puts "#{method_name}, #{effective_names}, #{aliases}"
119
- params.map! {|param| TYPES[param.to_sym] || param} # Convert chars into FFI type symbols
120
- returns = TYPES[returns.to_sym] || returns # Convert chars into FFI type symbols
121
306
 
122
- effective = effective_names.inject(nil) do |func, ename|
307
+ effective_name = effective_names.inject(nil) do |func, ename|
123
308
  func || begin
124
- #p ename, params, returns
125
- attach_function(ename, params.dup, returns)
309
+ attach_function(name, ename, params.dup, returns) # creates basic CamelCase method via FFI
126
310
  ename
127
311
  rescue FFI::NotFoundError
128
312
  nil
129
313
  end
130
314
  end
131
315
 
132
- raise Win::NotFoundError.new(function, ffi_libraries.map(&:name)) unless effective
316
+ raise Win::Errors::NotFoundError.new(name, libs) unless effective_name
133
317
 
134
- api = API.new(self, function, effective, params, returns)
318
+ # Create API object that holds information about function names, params, etc
319
+ api = API.new(namespace, name, effective_name, params, returns, libs)
135
320
 
136
- define_method(function) {|*args| api.call(*args)} # define CamelCase method wrapper for api call
137
-
138
- if define_block
139
- define_method(method_name) do |*args, &runtime_block|
140
- define_block[api, *args, &runtime_block]
321
+ method_body = if def_block
322
+ if zeronil
323
+ ->(*args, &block){ (res = def_block.(api, *args, &block)) != 0 ? res : nil }
324
+ elsif boolean
325
+ ->(*args, &block){ def_block.(api, *args, &block) != 0 }
326
+ else
327
+ ->(*args, &block){ def_block.(api, *args, &block) }
141
328
  end
142
329
  else
143
- define_method(method_name) do |*args, &runtime_block| # define snake_case method with enhanced api
144
- namespace.enforce_count(args, params)
145
- result = api.call(*args)
146
- result = runtime_block[result] if runtime_block
147
- return result != 0 if boolean # Boolean function returns true/false instead of nonzero/zero
148
- return nil if zeronil && result == 0 # Zeronil function returns nil instead of zero
149
- result
330
+ if zeronil
331
+ ->(*args, &block){ (res = block ? block[api[*args]] : api[*args]) != 0 ? res : nil }
332
+ elsif boolean
333
+ ->(*args, &block){ block ? block[api[*args]] : api[*args] != 0 }
334
+ else
335
+ ->(*args, &block){ block ? block[api[*args]] : api[*args] }
150
336
  end
151
337
  end
152
- aliases.each {|ali| alias_method ali, method_name } # define aliases
153
- api # return API object
338
+
339
+ define_method method_name, &method_body # define snake_case method
340
+
341
+ aliases.each {|ali| alias_method ali, method_name } # define aliases
342
+ api #return api object from function declaration
154
343
  end
155
344
 
156
- # Generates possible effective names for function in Win32 dll (function+A/W),
345
+ # Generates possible effective names for function in Win32 dll (name+A/W),
157
346
  # Rubyesque name and aliases for method(s) defined based on function name,
158
347
  # sets boolean flag for test functions (Is...)
159
348
  #
160
- def generate_names(function, options={})
161
- effective_names = [function]
162
- effective_names += ["#{function}A", "#{function}W"] unless function =~ /[WA]$/
349
+ def generate_names(name, options={})
350
+ effective_names = [name]
351
+ effective_names += ["#{name}A", "#{name}W"] unless name =~ /[WA]$/
163
352
  aliases = ([options[:alias]] + [options[:aliases]]).flatten.compact
164
- method_name = options[:rename] || function.snake_case
353
+ method_name = options[:rename] || name.snake_case
165
354
  case method_name
166
355
  when /^is_/
167
356
  aliases << method_name.sub(/^is_/, '') + '?'
@@ -174,7 +363,16 @@ module Win
174
363
  [method_name, effective_names, aliases]
175
364
  end
176
365
 
177
- # Ensures that args count is equal to params count plus diff
366
+ # Generates params and returns (signature) containing only FFI-compliant types
367
+ #
368
+ def generate_signature(params, returns, options={})
369
+ params = params.split(//) if params.respond_to?(:split) # Convert params string into array
370
+ params.map! {|param| TYPES[param.to_sym] || param} # Convert chars into FFI type symbols
371
+ returns = TYPES[returns.to_sym] || returns # Convert chars into FFI type symbols
372
+ [params, returns]
373
+ end
374
+
375
+ # Ensures that args count is equal to params count plus diff
178
376
  #
179
377
  def enforce_count(args, params, diff = 0)
180
378
  num_args = args.size
@@ -183,16 +381,29 @@ module Win
183
381
  raise ArgumentError, "wrong number of arguments (#{num_args} for #{num_params})"
184
382
  end
185
383
  end
186
- end
187
384
 
188
- #extend ClassMethods
385
+ # Returns string buffer - used to supply string pointer reference to API functions
386
+ #
387
+ def buffer(size = 1024, code = "\x00")
388
+ code * size
389
+ end
390
+
391
+ # Returns array of given args if none of them is zero,
392
+ # if any arg is zero, returns array of nils
393
+ #
394
+ def nonzero_array(*args)
395
+ args.any?{|arg| arg == 0 } ? args.map{||nil} : args
396
+ end
397
+
398
+ end
189
399
 
190
400
  def self.included(klass)
191
401
  klass.extend ClassMethods
192
402
  klass.extend FFI::Library
193
403
  klass.ffi_lib 'user32', 'kernel32' # Default libraries
194
404
  klass.ffi_convention :stdcall
195
- klass.class_eval "def namespace; #{klass}; end"
405
+ klass.instance_eval "def namespace; #{klass}; end"
196
406
  end
407
+
197
408
  end
198
409
  end