win 0.1.9 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +5 -4
- data/VERSION +1 -1
- data/lib/win/dde.rb +105 -27
- data/lib/win/extensions.rb +4 -0
- data/lib/win/gui/dialog.rb +2 -2
- data/lib/win/gui/input.rb +1 -1
- data/lib/win/gui/message.rb +1 -1
- data/lib/win/gui/window/window.rb +6 -5
- data/lib/win/gui/window.rb +3 -2
- data/lib/win/gui.rb +6 -5
- data/lib/win/library.rb +35 -31
- data/spec/spec_helper.rb +2 -2
- data/spec/win/dde_spec.rb +6 -0
- data/spec/win/gui/dialog_spec.rb +3 -3
- data/spec/win/gui/input_spec.rb +3 -3
- data/spec/win/gui/message_spec.rb +3 -3
- data/spec/win/gui/window/window_spec.rb +5 -5
- data/spec/win/gui/window_spec.rb +16 -14
- data/win.gemspec +2 -2
- metadata +2 -2
data/README.rdoc
CHANGED
@@ -116,10 +116,10 @@ Contributors always welcome!
|
|
116
116
|
== SYNOPSIS
|
117
117
|
=== Using pre-defined Windows API functions:
|
118
118
|
|
119
|
-
require 'win/gui'
|
119
|
+
require 'win/gui/window'
|
120
120
|
|
121
121
|
class MyClass
|
122
|
-
include Win::
|
122
|
+
include Win::GUI::Window
|
123
123
|
|
124
124
|
fg_window = foreground_window
|
125
125
|
puts window_text(fg_window)
|
@@ -134,6 +134,9 @@ Contributors always welcome!
|
|
134
134
|
module YourLibModule
|
135
135
|
include Win::Library
|
136
136
|
|
137
|
+
# Customizing method behavior: zeronil forces function to return nil instead of 0, rename renames method
|
138
|
+
function :FindWindow, [:pointer, :pointer], :ulong, zeronil: true, rename: :my_find
|
139
|
+
|
137
140
|
# Customizing even further: your own method extension in attached block
|
138
141
|
function :GetWindowText, [ :ulong, :pointer, :int ], :int do |api, handle|
|
139
142
|
buffer = FFI::MemoryPointer.new :char, 512
|
@@ -142,8 +145,6 @@ Contributors always welcome!
|
|
142
145
|
num_chars == 0 ? nil : buffer.get_bytes(0, num_chars)
|
143
146
|
end
|
144
147
|
|
145
|
-
# Customizing method behavior: zeronil forces function to return nil instead of 0, rename renames method
|
146
|
-
function :FindWindow, [:pointer, :pointer], :ulong, zeronil: true, rename: :my_find
|
147
148
|
end
|
148
149
|
|
149
150
|
include YourLibModule
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.11
|
data/lib/win/dde.rb
CHANGED
@@ -13,10 +13,8 @@ module Win
|
|
13
13
|
# DDE name service afCmd commands used by DdeNameService function:
|
14
14
|
|
15
15
|
# Registers the service name.
|
16
|
-
|
17
16
|
DNS_REGISTER = 1
|
18
|
-
# Unregisters the service name.
|
19
|
-
# unregistered.
|
17
|
+
# Unregisters the service name. When hsz1 == 0L, ALL service names registered by the server will be unregistered.
|
20
18
|
DNS_UNREGISTER = 2
|
21
19
|
# Turns on service name initiation filtering. The filter prevents a server from receiving
|
22
20
|
# XTYP_CONNECT transactions for service names it has not registered. This is the default
|
@@ -30,28 +28,51 @@ module Win
|
|
30
28
|
|
31
29
|
# Transaction types:
|
32
30
|
|
31
|
+
XTYPF_NOBLOCK = 0x0002
|
32
|
+
XTYPF_NODATA = 0x0004
|
33
|
+
XTYPF_ACKREQ = 0x0008
|
34
|
+
|
35
|
+
XCLASS_MASK = 0xFC00
|
36
|
+
XCLASS_BOOL = 0x1000
|
37
|
+
XCLASS_DATA = 0x2000
|
38
|
+
XCLASS_FLAGS = 0x4000
|
39
|
+
XCLASS_NOTIFICATION = 0x8000
|
40
|
+
|
41
|
+
XTYP_ERROR = XCLASS_NOTIFICATION | XTYPF_NOBLOCK
|
42
|
+
XTYP_ADVDATA = 0x0010 | XCLASS_FLAGS
|
43
|
+
XTYP_ADVREQ = 0x0020 | XCLASS_DATA | XTYPF_NOBLOCK
|
44
|
+
XTYP_ADVSTART = 0x0030 | XCLASS_BOOL
|
45
|
+
XTYP_ADVSTOP = 0x0040 | XCLASS_NOTIFICATION
|
46
|
+
XTYP_EXECUTE = 0x0050 | XCLASS_FLAGS
|
33
47
|
# A client uses the XTYP_CONNECT transaction to establish a conversation. A DDE server callback function,
|
34
48
|
# DdeCallback, receives this transaction when a client specifies a service name that the server supports
|
35
49
|
# (and a topic name that is not NULL) in a call to the DdeConnect function.
|
36
|
-
XTYP_CONNECT
|
37
|
-
|
38
|
-
|
39
|
-
# A client uses the XTYP_POKE transaction to send unsolicited data to the server. DDE server callback function,
|
50
|
+
XTYP_CONNECT = 0x0060 | XCLASS_BOOL | XTYPF_NOBLOCK
|
51
|
+
XTYP_CONNECT_CONFIRM = 0x0070 | XCLASS_NOTIFICATION | XTYPF_NOBLOCK
|
52
|
+
XTYP_XACT_COMPLETE = 0x0080 | XCLASS_NOTIFICATION
|
53
|
+
# A client uses the XTYP_POKE transaction to send unsolicited data to the server. DDE server callback function,
|
40
54
|
# DdeCallback, receives this transaction when a client specifies XTYP_POKE in the DdeClientTransaction function.
|
41
|
-
XTYP_POKE
|
42
|
-
|
55
|
+
XTYP_POKE = 0x0090 | XCLASS_FLAGS
|
56
|
+
XTYP_REGISTER = 0x00A0 | XCLASS_NOTIFICATION | XTYPF_NOBLOCK
|
57
|
+
XTYP_REQUEST = 0x00B0 | XCLASS_DATA
|
58
|
+
XTYP_DISCONNECT = 0x00C0 | XCLASS_NOTIFICATION | XTYPF_NOBLOCK
|
59
|
+
XTYP_UNREGISTER = 0x00D0 | XCLASS_NOTIFICATION | XTYPF_NOBLOCK
|
60
|
+
XTYP_WILDCONNECT = 0x00E0 | XCLASS_DATA | XTYPF_NOBLOCK
|
61
|
+
XTYP_MONITOR = 0X00F0 | XCLASS_NOTIFICATION | XTYPF_NOBLOCK
|
62
|
+
XTYP_MASK = 0x00F0
|
63
|
+
XTYP_SHIFT = 0x0004
|
43
64
|
|
44
65
|
# Transaction confirmations:
|
45
66
|
|
46
67
|
# Transaction confirmation
|
47
|
-
DDE_FACK
|
68
|
+
DDE_FACK = 0x8000
|
48
69
|
# Server is too busy to process transaction
|
49
|
-
DDE_FBUSY
|
50
|
-
DDE_FDEFERUPD
|
51
|
-
DDE_FACKREQ
|
70
|
+
DDE_FBUSY = 0x4000
|
71
|
+
DDE_FDEFERUPD = 0x4000
|
72
|
+
DDE_FACKREQ = 0x8000
|
52
73
|
DDE_FRELEASE = 0x2000
|
53
|
-
DDE_FREQUESTED
|
54
|
-
DDE_FAPPSTATUS
|
74
|
+
DDE_FREQUESTED = 0x1000
|
75
|
+
DDE_FAPPSTATUS = 0x00ff
|
55
76
|
# Transaction rejected
|
56
77
|
DDE_FNOTPROCESSED = 0
|
57
78
|
|
@@ -130,10 +151,23 @@ module Win
|
|
130
151
|
|
131
152
|
# Returned if DDE Init successful
|
132
153
|
DMLERR_NO_ERROR = 0x00
|
154
|
+
# First (lowest) error code
|
155
|
+
DMLERR_FIRST = 0x4000
|
156
|
+
# A request for a synchronous advise transaction has timed out.
|
157
|
+
DMLERR_ADVACKTIMEOUT = DMLERR_FIRST
|
158
|
+
# The response to the transaction caused the DDE_FBUSY flag to be set
|
159
|
+
DMLERR_BUSY = 0x4001
|
160
|
+
# A request for a synchronous data transaction has timed out.
|
161
|
+
DMLERR_DATAACKTIMEOUT = 0x4002
|
162
|
+
# A DDEML function was called without first calling the DdeInitialize function, or an invalid instance
|
163
|
+
# identifier was passed to a DDEML function.
|
164
|
+
DMLERR_DLL_NOT_INITIALIZED = 0x4003
|
133
165
|
# An application initialized as APPCLASS_MONITOR has attempted to perform a Dynamic Data Exchange (DDE) transaction,
|
134
|
-
# or an application initialized as APPCMD_CLIENTONLY has attempted to perform server transactions.
|
166
|
+
# or an application initialized as APPCMD_CLIENTONLY has attempted to perform server transactions.
|
135
167
|
DMLERR_DLL_USAGE = 0x4004
|
136
|
-
#
|
168
|
+
# A request for a synchronous execute transaction has timed out.
|
169
|
+
DMLERR_EXECACKTIMEOUT = 0x4005
|
170
|
+
# A parameter failed to be validated by the DDEML. Some of the possible causes follow:
|
137
171
|
# - The application used a data handle initialized with a different item name handle than was required by the
|
138
172
|
# transaction.
|
139
173
|
# - The application used a data handle that was initialized with a different clipboard data format than was
|
@@ -142,24 +176,68 @@ module Win
|
|
142
176
|
# - The application used a freed data handle or string handle.
|
143
177
|
# - More than one instance of the application used the same object.
|
144
178
|
DMLERR_INVALIDPARAMETER = 0x4006
|
145
|
-
# DMLERR_SYS_ERROR An internal error has occurred in the DDEML.
|
146
|
-
DMLERR_SYS_ERROR = 0x400f
|
147
|
-
# DMLERR_ADVACKTIMEOUT A request for a synchronous advise transaction has timed out.
|
148
|
-
# DMLERR_BUSY The response to the transaction caused the DDE_FBUSY flag to be set.
|
149
|
-
# DMLERR_DATAACKTIMEOUT A request for a synchronous data transaction has timed out.
|
150
|
-
# DMLERR_DLL_NOT_INITIALIZED A DDEML function was called without first calling the DdeInitialize function, or an invalid instance identifier was passed to a DDEML function.
|
151
|
-
# DMLERR_DLL_USAGE
|
152
|
-
# DMLERR_EXECACKTIMEOUT A request for a synchronous execute transaction has timed out.
|
153
179
|
# DMLERR_LOW_MEMORY A DDEML application has created a prolonged race condition (in which the server application outruns the client), causing large amounts of memory to be consumed.
|
180
|
+
DMLERR_LOW_MEMORY = 0x4007
|
154
181
|
# DMLERR_MEMORY_ERROR A memory allocation has failed.
|
155
|
-
|
182
|
+
DMLERR_MEMORY_ERROR = 0x4008
|
156
183
|
# DMLERR_NOTPROCESSED A transaction has failed.
|
184
|
+
DMLERR_NOTPROCESSED = 0x4009
|
185
|
+
# DMLERR_NO_CONV_ESTABLISHED A client's attempt to establish a conversation has failed.
|
186
|
+
DMLERR_NO_CONV_ESTABLISHED = 0x400a
|
157
187
|
# DMLERR_POKEACKTIMEOUT A request for a synchronous poke transaction has timed out.
|
188
|
+
DMLERR_POKEACKTIMEOUT = 0x400b
|
158
189
|
# DMLERR_POSTMSG_FAILED An internal call to the PostMessage function has failed.
|
190
|
+
DMLERR_POSTMSG_FAILED = 0x400c
|
159
191
|
# DMLERR_REENTRANCY An application instance with a synchronous transaction already in progress attempted to initiate another synchronous transaction, or the DdeEnableCallback function was called from within a DDEML callback function.
|
192
|
+
DMLERR_REENTRANCY = 0x400d
|
160
193
|
# DMLERR_SERVER_DIED A server-side transaction was attempted on a conversation terminated by the client, or the server terminated before completing a transaction.
|
194
|
+
DMLERR_SERVER_DIED = 0x400e
|
195
|
+
# DMLERR_SYS_ERROR An internal error has occurred in the DDEML.
|
196
|
+
DMLERR_SYS_ERROR = 0x400f
|
161
197
|
# DMLERR_UNADVACKTIMEOUT A request to end an advise transaction has timed out.
|
198
|
+
DMLERR_UNADVACKTIMEOUT = 0x4010
|
162
199
|
# DMLERR_UNFOUND_QUEUE_ID An invalid transaction identifier was passed to a DDEML function. Once the application has returned from an XTYP_XACT_COMPLETE callback, the transaction identifier for that callback function is no longer valid.
|
200
|
+
DMLERR_UNFOUND_QUEUE_ID = 0x4011
|
201
|
+
# Last (highest) error code
|
202
|
+
DMLERR_LAST = DMLERR_UNFOUND_QUEUE_ID
|
203
|
+
|
204
|
+
# Hash {ERROR_CODE=>'Error description')}
|
205
|
+
ERRORS = {
|
206
|
+
DMLERR_ADVACKTIMEOUT => 'A request for a synchronous advise transaction has timed out.',
|
207
|
+
DMLERR_BUSY => 'The response to the transaction caused the DDE_FBUSY flag to be set.',
|
208
|
+
DMLERR_DATAACKTIMEOUT => 'A request for a synchronous data transaction has timed out.',
|
209
|
+
DMLERR_DLL_NOT_INITIALIZED => 'A DDEML function was called without first calling the DdeInitialize ' +
|
210
|
+
'function, or an invalid instance identifier was passed to a DDEML function.',
|
211
|
+
DMLERR_DLL_USAGE => 'An application initialized as APPCLASS_MONITOR has attempted to perform a DDE ' +
|
212
|
+
'transaction, or an application initialized as APPCMD_CLIENTONLY has attempted to perform ' +
|
213
|
+
'server transactions.',
|
214
|
+
DMLERR_EXECACKTIMEOUT => 'A request for a synchronous execute transaction has timed out.',
|
215
|
+
DMLERR_INVALIDPARAMETER => 'A parameter failed to be validated by the DDEML. Possible causes: ' +
|
216
|
+
'Application used a data handle initialized with a different item name handle than was required ' +
|
217
|
+
'by the transaction.' +
|
218
|
+
'The application used a data handle that was initialized with a different clipboard data format ' +
|
219
|
+
'than was required by the transaction. ' +
|
220
|
+
'The application used a client-side conversation handle with server-side function or vice versa. ' +
|
221
|
+
'The application used a freed data handle or string handle. ' +
|
222
|
+
'More than one instance of the application used the same object.',
|
223
|
+
DMLERR_LOW_MEMORY => 'A DDEML application has created a prolonged race condition (in which the server ' +
|
224
|
+
'application outruns the client), causing large amounts of memory to be consumed.',
|
225
|
+
DMLERR_MEMORY_ERROR => 'A memory allocation has failed.',
|
226
|
+
DMLERR_NO_CONV_ESTABLISHED => 'A client`s attempt to establish a conversation has failed.',
|
227
|
+
DMLERR_NOTPROCESSED => 'A transaction has failed.',
|
228
|
+
DMLERR_POKEACKTIMEOUT => 'A request for a synchronous poke transaction has timed out.',
|
229
|
+
DMLERR_POSTMSG_FAILED => 'An internal call to the PostMessage function has failed.',
|
230
|
+
DMLERR_REENTRANCY => 'An application instance with a synchronous transaction already in progress ' +
|
231
|
+
'attempted to initiate another synchronous transaction, or the DdeEnableCallback function ' +
|
232
|
+
'was called from within a DDEML callback function.',
|
233
|
+
DMLERR_SERVER_DIED => 'A server-side transaction was attempted on a conversation terminated by the ' +
|
234
|
+
'client, or the server terminated before completing a transaction.',
|
235
|
+
DMLERR_SYS_ERROR => 'An internal error has occurred in the DDEML.',
|
236
|
+
DMLERR_UNADVACKTIMEOUT => 'A request to end an advise transaction has timed out.',
|
237
|
+
DMLERR_UNFOUND_QUEUE_ID => 'An invalid transaction identifier was passed to a DDEML function. Once the ' +
|
238
|
+
'application has returned from an XTYP_XACT_COMPLETE callback, the transaction identifier for ' +
|
239
|
+
'that callback function is no longer valid.'
|
240
|
+
}
|
163
241
|
|
164
242
|
##
|
165
243
|
# The RegisterClipboardFormat function registers a new clipboard format.
|
@@ -575,7 +653,7 @@ module Win
|
|
575
653
|
# during the XTYP_REGISTER and XTYP_UNREGISTER transactions.
|
576
654
|
# - All members of the default CONVCONTEXT structure are set to zero except cb, which specifies the size of the
|
577
655
|
# structure, and iCodePage, which specifies CP_WINANSI (the default code page) or CP_WINUNICODE, depending on
|
578
|
-
# whether the ANSI or Unicode version of the DdeInitialize function was called by the client application.
|
656
|
+
# whether the ANSI or Unicode version of the DdeInitialize function was called by the client application.
|
579
657
|
#
|
580
658
|
# :call-seq:
|
581
659
|
# conversation_handle = dde_connect( instance_id, [service = nil, topic = nil, context = nil] )
|
data/lib/win/extensions.rb
CHANGED
@@ -1,12 +1,16 @@
|
|
1
1
|
class String
|
2
|
+
# returns snake_case representation of string
|
2
3
|
def snake_case
|
3
4
|
gsub(/([a-z])([A-Z0-9])/, '\1_\2' ).downcase
|
4
5
|
end
|
5
6
|
|
7
|
+
# converts string to 'wide char' (Windows Unicode) format
|
6
8
|
def to_w
|
7
9
|
(self+"\x00").encode('utf-16LE')
|
8
10
|
end
|
9
11
|
|
12
|
+
# converts one-char string into keyboard-scan 'Virtual key' code
|
13
|
+
# only letters and numbers convertable so far, need to be extended
|
10
14
|
def to_vkeys
|
11
15
|
unless size == 1
|
12
16
|
raise "Can't convert but a single character: #{self}"
|
data/lib/win/gui/dialog.rb
CHANGED
@@ -2,12 +2,12 @@ require 'win/library'
|
|
2
2
|
require 'win/gui/window'
|
3
3
|
|
4
4
|
module Win
|
5
|
-
module
|
5
|
+
module GUI
|
6
6
|
# Contains constants and Win32API functions related to dialog manipulation
|
7
7
|
#
|
8
8
|
module Dialog
|
9
9
|
include Win::Library
|
10
|
-
include Win::
|
10
|
+
include Win::GUI::Window
|
11
11
|
|
12
12
|
# The GetDlgItem function retrieves a handle to a control in the specified dialog box.
|
13
13
|
#
|
data/lib/win/gui/input.rb
CHANGED
data/lib/win/gui/message.rb
CHANGED
@@ -4,19 +4,20 @@ require 'win/gui/message'
|
|
4
4
|
require 'win/gui/input'
|
5
5
|
|
6
6
|
module Win
|
7
|
-
module
|
7
|
+
module GUI
|
8
8
|
module Window
|
9
9
|
# This class is a thin wrapper around window handle
|
10
|
+
# It should be probably moved out of this lib since it's supposed to be "close to metal"
|
10
11
|
class Window
|
11
12
|
# Wait delay
|
12
13
|
SLEEP_DELAY = 0.001
|
13
14
|
# Timeout waiting for Window to be closed
|
14
15
|
CLOSE_TIMEOUT = 1
|
15
16
|
|
16
|
-
include Win::
|
17
|
-
extend Win::
|
18
|
-
include Win::
|
19
|
-
include Win::
|
17
|
+
include Win::GUI::Window
|
18
|
+
extend Win::GUI::Window
|
19
|
+
include Win::GUI::Message
|
20
|
+
include Win::GUI::Input
|
20
21
|
|
21
22
|
attr_reader :handle
|
22
23
|
|
data/lib/win/gui/window.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'win/library'
|
2
2
|
|
3
3
|
module Win
|
4
|
-
module
|
4
|
+
module GUI
|
5
5
|
# Contains constants and Win32API functions related to window manipulation
|
6
6
|
#
|
7
7
|
module Window
|
@@ -367,7 +367,8 @@ module Win
|
|
367
367
|
#:call-seq:
|
368
368
|
# was_visible = show_window( win_handle, cmd )
|
369
369
|
#
|
370
|
-
function :ShowWindow, [:ulong, :int], :int, boolean: true
|
370
|
+
function :ShowWindow, [:ulong, :int], :int, boolean: true,
|
371
|
+
&->(api, handle, cmd=SW_SHOW) { api.call handle, cmd }
|
371
372
|
|
372
373
|
##
|
373
374
|
# GetWindowThreadProcessId retrieves the identifier of the thread that created the specified window
|
data/lib/win/gui.rb
CHANGED
@@ -5,12 +5,13 @@ require 'win/gui/dialog'
|
|
5
5
|
require 'win/gui/window/window'
|
6
6
|
|
7
7
|
module Win
|
8
|
+
|
8
9
|
# Contains several modules defining Win32 API functions and constants related to Windows GUI (Graphical User Interface)
|
9
10
|
#
|
10
|
-
module
|
11
|
-
include Win::
|
12
|
-
include Win::
|
13
|
-
include Win::
|
14
|
-
include Win::
|
11
|
+
module GUI
|
12
|
+
include Win::GUI::Window
|
13
|
+
include Win::GUI::Input
|
14
|
+
include Win::GUI::Message
|
15
|
+
include Win::GUI::Dialog
|
15
16
|
end
|
16
17
|
end
|
data/lib/win/library.rb
CHANGED
@@ -5,8 +5,9 @@ require 'win/extensions'
|
|
5
5
|
# that also contain related constants and convenience methods. For example, Win::DDE module
|
6
6
|
# contains only functions related to DDE protocol such as DdeInitialize() as well as constants
|
7
7
|
# such as DMLERR_NO_ERROR, APPCLASS_STANDARD, etc. So if you need only DDE-related functions,
|
8
|
-
# there is no need to load all the other modules, clogging your namespaces - just require 'win/dde'
|
9
|
-
# and be done with it. Win is just a top level namespace (container) that holds all the other modules.
|
8
|
+
# there is no need to load all the other modules, clogging your namespaces - just <b> require 'win/dde' </b>
|
9
|
+
# and be done with it. Win is just a top level namespace (container) that holds all the other modules.
|
10
|
+
#
|
10
11
|
module Win
|
11
12
|
|
12
13
|
module Errors # :nodoc:
|
@@ -23,6 +24,7 @@ module Win
|
|
23
24
|
# and declare them using ‘function’ class method (macro) - it does a lot of heavy lifting for you and
|
24
25
|
# can be customized with options and code blocks to give you reusable API wrapper methods with the exact
|
25
26
|
# behavior you need.
|
27
|
+
#
|
26
28
|
module Library
|
27
29
|
|
28
30
|
# Win::Library::API is a wrapper for callable function API object that mimics Win32::API
|
@@ -287,34 +289,34 @@ module Win
|
|
287
289
|
|
288
290
|
##
|
289
291
|
# Defines new method wrappers for Windows API function call:
|
290
|
-
#
|
291
|
-
#
|
292
|
-
#
|
293
|
-
#
|
294
|
-
#
|
295
|
-
#
|
296
|
-
#
|
297
|
-
#
|
298
|
-
#
|
299
|
-
# You may modify default behavior of defined method by providing optional
|
300
|
-
#
|
301
|
-
#
|
302
|
-
#
|
303
|
-
#
|
304
|
-
#
|
305
|
-
#
|
306
|
-
#
|
307
|
-
#
|
308
|
-
#
|
309
|
-
#
|
310
|
-
#
|
311
|
-
#
|
292
|
+
# - Defines method with original (CamelCase) API function name and original signature (matches MSDN description)
|
293
|
+
# - Defines method with snake_case name (converted from CamelCase function name) with enhanced API signature
|
294
|
+
# When defined snake_case method is called, it converts the arguments you provided into ones required by
|
295
|
+
# original API (adding defaults, mute and transitory args as necessary), executes API function call
|
296
|
+
# and (optionally) transforms the result before returning it. If a block is attached to
|
297
|
+
# method invocation, raw result is yielded to this block before final transformation take place
|
298
|
+
# - Defines aliases for enhanced method with more Rubyesque names for getters, setters and tests:
|
299
|
+
# GetWindowText -> window_test, SetWindowText -> window_text=, IsZoomed -> zoomed?
|
300
|
+
# ---
|
301
|
+
# You may modify default behavior of defined method by providing optional *def_block* to function definition.
|
302
|
+
# If you do so, snake_case method is defined based on your *def_block*. It receives callable API
|
303
|
+
# object for function being defined, arguments and (optional) runtime block with which the method
|
304
|
+
# will be called. Results coming from &def_block are then transformed and returned.
|
305
|
+
# So, your *def_block* should specify all the behavior of the method being defined. You can use *def_block* to:
|
306
|
+
# - Change original signature of API function, provide argument defaults, check argument types
|
307
|
+
# - Pack arguments into strings/structs for [in] or [in/out] parameters that expect a pointer
|
308
|
+
# - Allocate buffers/structs for pointers required by API functions [out] parameters
|
309
|
+
# - Unpack [out] and [in/out] parameters returned as pointers
|
310
|
+
# - Explicitly return results of API call that are returned in [out] and [in/out] parameters
|
311
|
+
# - Convert attached runtime blocks into callback functions and stuff them into [in] callback parameters
|
312
|
+
# - do other stuff that you think is appropriate to make Windows API function behavior more Ruby-like...
|
313
|
+
# ---
|
312
314
|
# Accepts following options:
|
313
|
-
#
|
314
|
-
#
|
315
|
-
#
|
316
|
-
#
|
317
|
-
#
|
315
|
+
# :dll:: Use this dll instead of default 'user32'
|
316
|
+
# :rename:: Use this name instead of standard (conventional) function name
|
317
|
+
# :alias(es):: Provides additional alias(es) for defined method
|
318
|
+
# :boolean:: Forces method to return true/false instead of nonzero/zero
|
319
|
+
# :zeronil:: Forces method to return nil if function result is zero
|
318
320
|
#
|
319
321
|
def function(name, params, returns, options={}, &def_block)
|
320
322
|
method_name, effective_names, aliases = generate_names(name, options)
|
@@ -395,6 +397,7 @@ module Win
|
|
395
397
|
##
|
396
398
|
# Wrapper for FFI::Library#callback() that converts Win32/shortcut argument types into FFI-compliant types.
|
397
399
|
# This method overrides FFI.callback which must be aliased to FFI.attach_callback
|
400
|
+
#
|
398
401
|
def callback(name, params, returns)
|
399
402
|
params, returns = generate_signature(params, returns)
|
400
403
|
attach_callback name.to_sym, params, returns
|
@@ -402,8 +405,8 @@ module Win
|
|
402
405
|
|
403
406
|
##
|
404
407
|
# :method: namespace
|
405
|
-
# This method is meta-generated when Win::Library module is included into other module/class
|
406
|
-
# It returns reference to including (host) module for use by Win::Library::API and class methods.
|
408
|
+
# This method is meta-generated when Win::Library module is included into other module/class.
|
409
|
+
# It returns reference to including (host) class/module for use by Win::Library::API and class methods.
|
407
410
|
|
408
411
|
##
|
409
412
|
# Ensures that args count is equal to params count plus diff
|
@@ -421,6 +424,7 @@ module Win
|
|
421
424
|
##
|
422
425
|
# Hook executed when Win::Library is included into class or module. It extends host class/module
|
423
426
|
# with both FFI::Library methods and Win::Library macro methods like 'function'.
|
427
|
+
#
|
424
428
|
def self.included(klass)
|
425
429
|
klass.extend FFI::Library
|
426
430
|
|
data/spec/spec_helper.rb
CHANGED
data/spec/win/dde_spec.rb
CHANGED
@@ -127,6 +127,12 @@ module WinDDETest
|
|
127
127
|
end
|
128
128
|
end
|
129
129
|
|
130
|
+
it 'created different handles for two different strings ' do
|
131
|
+
string_handle1 = dde_create_string_handle(@instance_id, 'My String')
|
132
|
+
string_handle2 = dde_create_string_handle(@instance_id, 'My String1')
|
133
|
+
string_handle1.should_not == string_handle2
|
134
|
+
end
|
135
|
+
|
130
136
|
it 'returns nil if unable to register handle to a string' do
|
131
137
|
string_handle = dde_create_string_handle(@instance_id, "", CP_WINANSI)
|
132
138
|
string_handle.should == nil
|
data/spec/win/gui/dialog_spec.rb
CHANGED
@@ -5,9 +5,9 @@ require 'win/gui/input'
|
|
5
5
|
module WinWindowTest
|
6
6
|
|
7
7
|
include WinTestApp
|
8
|
-
include Win::
|
8
|
+
include Win::GUI::Dialog
|
9
9
|
|
10
|
-
describe Win::
|
10
|
+
describe Win::GUI::Dialog do
|
11
11
|
|
12
12
|
describe '#get_dlg_item' do
|
13
13
|
spec{ use{ control_handle = get_dlg_item(handle = 0, item_id = 1) }}
|
@@ -30,7 +30,7 @@ module WinWindowTest
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
describe Win::
|
33
|
+
describe Win::GUI::Dialog, ' defines convenience/service methods on top of Windows API' do
|
34
34
|
describe 'dialog' do
|
35
35
|
spec{ use{ dialog( title ='Dialog Title', timeout_sec = 0.001, &any_block) }}
|
36
36
|
|
data/spec/win/gui/input_spec.rb
CHANGED
@@ -5,9 +5,9 @@ require 'win/gui/input'
|
|
5
5
|
module WinWindowTest
|
6
6
|
|
7
7
|
include WinTestApp
|
8
|
-
include Win::
|
8
|
+
include Win::GUI::Input
|
9
9
|
|
10
|
-
describe Win::
|
10
|
+
describe Win::GUI::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) }}
|
@@ -38,7 +38,7 @@ module WinWindowTest
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
describe Win::
|
41
|
+
describe Win::GUI::Input, ' defines convenience/service methods on top of Windows API' do
|
42
42
|
describe '#keystroke' do
|
43
43
|
spec{ use{ keystroke( vkey = 30, vkey = 30) }}
|
44
44
|
|
@@ -2,12 +2,12 @@ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
|
2
2
|
require 'win/gui/input'
|
3
3
|
#require 'win/gui/window'
|
4
4
|
|
5
|
-
module
|
5
|
+
module WinGUIMessageTest
|
6
6
|
|
7
7
|
include WinTestApp
|
8
|
-
include Win::
|
8
|
+
include Win::GUI::Message
|
9
9
|
|
10
|
-
describe Win::
|
10
|
+
describe Win::GUI::Message do
|
11
11
|
|
12
12
|
describe '#post_message' do
|
13
13
|
spec{ use{ success = PostMessage(handle = 0, msg = 0, w_param = 0, l_param = 0) }}
|
@@ -2,12 +2,12 @@ require File.expand_path(File.dirname(__FILE__) + '/../../../spec_helper')
|
|
2
2
|
require 'win/gui/window'
|
3
3
|
require 'win/gui/window/window'
|
4
4
|
|
5
|
-
module
|
5
|
+
module WinGUITest
|
6
6
|
include WinTestApp
|
7
|
-
include Win::
|
8
|
-
include Win::
|
7
|
+
include Win::GUI::Window
|
8
|
+
include Win::GUI::Input
|
9
9
|
|
10
|
-
describe Win::
|
10
|
+
describe Win::GUI::Window::Window, ' thin wrapper class around window handle' do
|
11
11
|
before(:each) { @app = launch_test_app }
|
12
12
|
after(:each){ close_test_app }
|
13
13
|
|
@@ -44,7 +44,7 @@ module WinGuiTest
|
|
44
44
|
start = Time.now
|
45
45
|
@app.close
|
46
46
|
@app.wait_for_close
|
47
|
-
(Time.now - start).should be <= Win::
|
47
|
+
(Time.now - start).should be <= Win::GUI::Window::Window::CLOSE_TIMEOUT
|
48
48
|
window_visible?(@app.handle).should be false
|
49
49
|
end
|
50
50
|
end
|
data/spec/win/gui/window_spec.rb
CHANGED
@@ -4,7 +4,7 @@ require 'win/gui/window'
|
|
4
4
|
module WinWindowTest
|
5
5
|
|
6
6
|
include WinTestApp
|
7
|
-
include Win::
|
7
|
+
include Win::GUI::Window
|
8
8
|
|
9
9
|
def commands_should_show_window *cmds, tests
|
10
10
|
cmds.each do |cmd|
|
@@ -27,7 +27,7 @@ module WinWindowTest
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
describe Win::
|
30
|
+
describe Win::GUI::Window, ' defines a set user32 API functions related to Window manipulation' do
|
31
31
|
describe '#window?' do
|
32
32
|
spec{ use{ IsWindow(any_handle) }}
|
33
33
|
spec{ use{ is_window(any_handle) }}
|
@@ -311,13 +311,11 @@ module WinWindowTest
|
|
311
311
|
describe '#show_window ', 'LI', 'I' do
|
312
312
|
spec{ use{ was_visible = show_window(handle = any_handle, cmd = SW_SHOWNA) }}
|
313
313
|
|
314
|
-
it '
|
314
|
+
it 'defaults to SW_SHOW if no command given' do
|
315
315
|
test_app do |app|
|
316
|
-
|
317
|
-
|
318
|
-
visible?(app.handle).should ==
|
319
|
-
hide_window(app.handle).should == false
|
320
|
-
visible?(app.handle).should == false
|
316
|
+
hide_window(app.handle)
|
317
|
+
use{show_window(app.handle)}
|
318
|
+
visible?(app.handle).should == true
|
321
319
|
end
|
322
320
|
end
|
323
321
|
|
@@ -354,7 +352,7 @@ module WinWindowTest
|
|
354
352
|
end
|
355
353
|
|
356
354
|
it 'SW_SHOWMINNOACTIVE, SW_SHOWMINIMIZED displays the window as a minimized foreground window' do
|
357
|
-
commands_should_show_window SW_SHOWMINNOACTIVE, SW_SHOWMINIMIZED,
|
355
|
+
commands_should_show_window SW_SHOWMINNOACTIVE, SW_SHOWMINIMIZED, #!
|
358
356
|
:minimized? => true, :maximized? => false, :visible? => true, :foreground? => true
|
359
357
|
end
|
360
358
|
|
@@ -418,7 +416,7 @@ module WinWindowTest
|
|
418
416
|
|
419
417
|
it 'iterates through all the top-level windows for a given desktop'
|
420
418
|
end
|
421
|
-
|
419
|
+
|
422
420
|
describe '#enum_child_windows' do
|
423
421
|
before(:all){@app = launch_test_app}
|
424
422
|
after(:all){close_test_app}
|
@@ -461,20 +459,24 @@ module WinWindowTest
|
|
461
459
|
end
|
462
460
|
end
|
463
461
|
|
464
|
-
describe Win::
|
462
|
+
describe Win::GUI::Window, ' defines convenience/service methods on top of Windows API' do
|
465
463
|
describe '#foreground' do
|
466
464
|
spec{ use{ foreground?( any_handle) }}
|
467
465
|
end
|
466
|
+
|
468
467
|
describe '#hide_window' do
|
469
|
-
spec{ use{ hide_window(any_handle) }}
|
468
|
+
spec{ use{ was_visible = hide_window(any_handle) }}
|
470
469
|
|
471
|
-
end
|
472
470
|
it 'hides window: same as show_window(handle, SW_HIDE)' do
|
473
471
|
test_app do |app|
|
474
|
-
hide_window(app.handle)
|
472
|
+
was_visible = hide_window(app.handle)
|
473
|
+
was_visible.should == true
|
474
|
+
visible?(app.handle).should == false
|
475
|
+
hide_window(app.handle).should == false
|
475
476
|
visible?(app.handle).should == false
|
476
477
|
end
|
477
478
|
end
|
478
479
|
end
|
480
|
+
end
|
479
481
|
end
|
480
482
|
end
|
data/win.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{win}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.11"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["arvicco"]
|
12
|
-
s.date = %q{2010-02-
|
12
|
+
s.date = %q{2010-02-20}
|
13
13
|
s.description = %q{Rubyesque interfaces and wrappers for Windows API functions pre-defined using FFI }
|
14
14
|
s.email = %q{arvitallian@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
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.
|
4
|
+
version: 0.1.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- arvicco
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-02-
|
12
|
+
date: 2010-02-20 00:00:00 +03:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|