win 0.0.4 → 0.0.6
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 +12 -13
- data/Rakefile +3 -2
- data/VERSION +1 -1
- data/lib/win/dde.rb +223 -0
- data/lib/win/library.rb +162 -151
- data/lib/win/window/extra.rb +113 -0
- data/lib/win/window.rb +280 -222
- data/spec/spec_helper.rb +15 -7
- data/spec/win/dde_spec.rb +68 -0
- data/spec/win/window/extra_spec.rb +181 -0
- data/spec/win/window_spec.rb +232 -5
- data/win.gemspec +13 -4
- metadata +20 -4
data/README.rdoc
CHANGED
@@ -22,15 +22,15 @@ preferably not turning your code base into an ugly spaghetty of CamelCase calls,
|
|
22
22
|
String/Array pack/unpack gymnastics, buffer/pointer allocations, extracting return
|
23
23
|
values from [in/out] parameters and checking return codes for 0.
|
24
24
|
|
25
|
-
You have several options at this point. You can use
|
25
|
+
You have several options at this point. You can use 'win32-api' or 'ffi' libraries
|
26
26
|
to connect your ruby code to Windows API and manually define wrapper methods for
|
27
27
|
needed function calls. This is definitely a valid approach, even if it is a bit
|
28
|
-
low-level one: you'll
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
28
|
+
low-level one: you'll have to handle (somewhat) gory details of callback announcement,
|
29
|
+
argument preparation, mimicking pointers with Strings or declaring pointers explicitly
|
30
|
+
with FFI and other stuff (like manually defining about a gazillion obscure Windows
|
31
|
+
constants). As an example, consider the amount of code needed to complete a task as
|
32
|
+
simple as getting unicode title text for the window that you already have handle for
|
33
|
+
(using win32-api):
|
34
34
|
|
35
35
|
api = Win32::API.new( 'GetWindowTextW', ['L', 'P', 'I'], 'L', 'user32' )
|
36
36
|
buffer = "\x00" * 1024 # I just hope it will be enough...
|
@@ -60,22 +60,21 @@ As an alternative, you can use 'windows-pr' (pure ruby) library that gives you l
|
|
60
60
|
Windows functions pre-defined and sectioned into modules, declares Windows constants and
|
61
61
|
adds some other niceties. Unfortunately this library works only with MRI (not JRuby or
|
62
62
|
other Ruby implementations), and still lacks Ruby look-and-feel for declared functions.
|
63
|
-
It helps you to cut some of the declaration slack:
|
63
|
+
It helps you to cut some of the declaration slack though:
|
64
64
|
|
65
|
-
|
66
|
-
title = if num_chars == 0
|
65
|
+
title = if GetWindowTextW(window_handle, buffer ="\x00" * 1024 , buffer.size) == 0
|
67
66
|
nil
|
68
67
|
else
|
69
68
|
buffer.force_encoding('utf-16LE').encode('utf-8').rstrip
|
70
69
|
end
|
71
70
|
|
72
|
-
But still
|
71
|
+
But still it seems like TOO MUCH code for something that should (ideally) look like this:
|
73
72
|
|
74
73
|
title = window_text_w(window_handle)
|
75
74
|
|
76
75
|
This is an idea behind this library - make Windows API functions easier to use and feel more
|
77
76
|
natural inside Ruby code. Following the principle of least surprise, we define wrapper methods that:
|
78
|
-
* Have Rubyesque names (minimized? instead of
|
77
|
+
* Have meaningful Rubyesque names (iconic? and minimized? instead of IsIconic, etc)
|
79
78
|
* Require minimum arguments with sensible defaults
|
80
79
|
* Return appropriate values explicitly (several return values if necessary)
|
81
80
|
* Have sensible returns (false/true instead of 0/nonzero for test functions, nil if find function fails, etc)
|
@@ -103,7 +102,7 @@ and code blocks to give you reusable API wrapper methods with the exact behavior
|
|
103
102
|
== REQUIREMENTS:
|
104
103
|
|
105
104
|
Only works with Ruby 1.9 compatible implementations since it uses some of the most recent features
|
106
|
-
(block arguments given to block, etc...)
|
105
|
+
(block arguments given to block, etc...).
|
107
106
|
|
108
107
|
== FEATURES/PROBLEMS:
|
109
108
|
|
data/Rakefile
CHANGED
@@ -5,11 +5,12 @@ begin
|
|
5
5
|
require 'jeweler'
|
6
6
|
Jeweler::Tasks.new do |gem|
|
7
7
|
gem.name = "win"
|
8
|
-
gem.summary = %Q{A collection of Windows functions
|
9
|
-
gem.description = %Q{A collection of Windows functions
|
8
|
+
gem.summary = %Q{A collection of pre-defined Windows API functions with Rubyesque interfaces}
|
9
|
+
gem.description = %Q{A collection of pre-defined Windows API functions with Rubyesque interfaces}
|
10
10
|
gem.email = "arvitallian@gmail.com"
|
11
11
|
gem.homepage = "http://github.com/arvicco/win"
|
12
12
|
gem.authors = ["arvicco"]
|
13
|
+
gem.add_dependency "ffi", ">= 0.6.0"
|
13
14
|
gem.add_development_dependency "rspec", ">= 1.2.9"
|
14
15
|
gem.add_development_dependency "cucumber", ">= 0"
|
15
16
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.6
|
data/lib/win/dde.rb
ADDED
@@ -0,0 +1,223 @@
|
|
1
|
+
require 'win/library'
|
2
|
+
|
3
|
+
module Win
|
4
|
+
|
5
|
+
# Includes functions related to DDE exchange protocol in Windows
|
6
|
+
#
|
7
|
+
module DDE
|
8
|
+
include Win::Library
|
9
|
+
|
10
|
+
# Windows ANSI codepage:
|
11
|
+
CP_WINANSI = 1004
|
12
|
+
|
13
|
+
#
|
14
|
+
DNS_REGISTER = 1
|
15
|
+
DNS_UNREGISTER = 2
|
16
|
+
|
17
|
+
XTYP_CONNECT = 0x60
|
18
|
+
XTYP_DISCONNECT = 0xC0
|
19
|
+
XTYP_POKE = 0x90
|
20
|
+
XTYP_ERROR = 0x00
|
21
|
+
|
22
|
+
# Registers the application as a standard (nonmonitoring) DDEML application.
|
23
|
+
APPCLASS_STANDARD = 0
|
24
|
+
# Makes it possible for the application to monitor DDE activity in the system.
|
25
|
+
# This flag is for use by DDE monitoring applications. The application specifies the types of DDE
|
26
|
+
# activity to monitor by combining one or more monitor flags with the APPCLASS_MONITOR flag.
|
27
|
+
APPCLASS_MONITOR = 0x00000001
|
28
|
+
# ?
|
29
|
+
APPCLASS_MASK = 0x0000000F
|
30
|
+
# Prevents the application from becoming a server in a DDE conversation. The application can only be a client.
|
31
|
+
# This flag reduces consumption of resources by the DDEML. It includes the CBF_FAIL_ALLSVRXACTIONS flag.
|
32
|
+
APPCMD_CLIENTONLY = 0x00000010
|
33
|
+
# Prevents the DDEML from sending XTYP_CONNECT and XTYP_WILDCONNECT transactions to the application until
|
34
|
+
# the application has created its string handles and registered its service names or has turned off filtering
|
35
|
+
# by a subsequent call to the DdeNameService or DdeInitialize function. This flag is always in effect when an
|
36
|
+
# application calls DdeInitialize for the first time, regardless of whether the application specifies the flag.
|
37
|
+
# On subsequent calls to DdeInitialize, not specifying this flag turns off the application's service-name
|
38
|
+
# filters, but specifying it turns on the application's service name filters.
|
39
|
+
APPCMD_FILTERINITS = 0x00000020
|
40
|
+
# ?
|
41
|
+
APPCMD_MASK = 0x00000FF0
|
42
|
+
# Prevents the callback function from receiving XTYP_CONNECT transactions from the application's own instance.
|
43
|
+
# This flag prevents an application from establishing a DDE conversation with its own instance. An application
|
44
|
+
# should use this flag if it needs to communicate with other instances of itself but not with itself.
|
45
|
+
CBF_FAIL_SELFCONNECTIONS = 0x00001000
|
46
|
+
# Prevents the callback function from receiving XTYP_CONNECT and XTYP_WILDCONNECT.
|
47
|
+
CBF_FAIL_CONNECTIONS = 0x00002000
|
48
|
+
# Prevents the callback function from receiving XTYP_ADVSTART and XTYP_ADVSTOP transactions. The system returns
|
49
|
+
# DDE_FNOTPROCESSED to each client that sends an XTYP_ADVSTART or XTYP_ADVSTOP transaction to the server.
|
50
|
+
CBF_FAIL_ADVISES = 0x00004000
|
51
|
+
# Prevents the callback function from receiving XTYP_EXECUTE transactions. The system returns DDE_FNOTPROCESSED
|
52
|
+
# to a client that sends an XTYP_EXECUTE transaction to the server.
|
53
|
+
CBF_FAIL_EXECUTES = 0x00008000
|
54
|
+
# Prevents the callback function from receiving XTYP_POKE transactions. The system returns DDE_FNOTPROCESSED
|
55
|
+
# to a client that sends an XTYP_POKE transaction to the server.
|
56
|
+
CBF_FAIL_POKES = 0x00010000
|
57
|
+
# Prevents the callback function from receiving XTYP_REQUEST transactions. The system returns DDE_FNOTPROCESSED
|
58
|
+
# to a client that sends an XTYP_REQUEST transaction to the server.
|
59
|
+
CBF_FAIL_REQUESTS = 0x00020000
|
60
|
+
# Prevents the callback function from receiving server transactions. The system returns DDE_FNOTPROCESSED to each
|
61
|
+
# client that sends a transaction to this application. This flag is equivalent to combining all CBF_FAIL_ flags.
|
62
|
+
CBF_FAIL_ALLSVRXACTIONS = 0x0003f000
|
63
|
+
# Prevents the callback function from receiving XTYP_CONNECT_CONFIRM.
|
64
|
+
CBF_SKIP_CONNECT_CONFIRMS = 0x00040000
|
65
|
+
# Prevents the callback function from receiving XTYP_REGISTER notifications.
|
66
|
+
CBF_SKIP_REGISTRATIONS = 0x00080000
|
67
|
+
# Prevents the callback function from receiving XTYP_UNREGISTER notifications.
|
68
|
+
CBF_SKIP_UNREGISTRATIONS = 0x00100000
|
69
|
+
# Prevents the callback function from receiving XTYP_DISCONNECT notifications.
|
70
|
+
CBF_SKIP_DISCONNECTS = 0x00200000
|
71
|
+
# Prevents the callback function from receiving any notifications. Equivalent to combining all CBF_SKIP_ flags.
|
72
|
+
CBF_SKIP_ALLNOTIFICATIONS = 0x003c0000
|
73
|
+
# Notifies the callback function whenever a DDE application creates, frees, or increments the usage count of
|
74
|
+
# a string handle or whenever a string handle is freed as a result of a call to the DdeUninitialize function.
|
75
|
+
MF_HSZ_INFO = 0x01000000
|
76
|
+
# Notifies the callback function whenever the system or an application sends a DDE message.
|
77
|
+
MF_SENDMSGS = 0x02000000
|
78
|
+
# Notifies the callback function whenever the system or an application posts a DDE message.
|
79
|
+
MF_POSTMSGS = 0x04000000
|
80
|
+
# Notifies the callback function whenever a transaction is sent to any DDE callback function in the system.
|
81
|
+
MF_CALLBACKS = 0x08000000
|
82
|
+
# Notifies the callback function whenever a DDE error occurs.
|
83
|
+
MF_ERRORS = 0x10000000
|
84
|
+
# Notifies the callback function whenever an advise loop is started or ended.
|
85
|
+
MF_LINKS = 0x20000000
|
86
|
+
# Notifies the callback function whenever a conversation is established or terminated.
|
87
|
+
MF_CONV = 0x40000000
|
88
|
+
# ?
|
89
|
+
MF_MASK = 0xFF000000
|
90
|
+
# Returned if DDE Init successful
|
91
|
+
DMLERR_NO_ERROR = 0x00
|
92
|
+
# Returned if DDE Init failed due to wrong DLL usage
|
93
|
+
DMLERR_DLL_USAGE = 0x4004
|
94
|
+
# Returned if DDE Init failed due to invalid params
|
95
|
+
DMLERR_INVALIDPARAMETER = 0x4006
|
96
|
+
# Returned if DDE Init failed due to system error
|
97
|
+
DMLERR_SYS_ERROR = 0x400f
|
98
|
+
|
99
|
+
##
|
100
|
+
# The RegisterClipboardFormat function registers a new clipboard format.
|
101
|
+
# This format can then be used as a valid clipboard format.
|
102
|
+
#
|
103
|
+
# Syntax: UINT RegisterClipboardFormat( LPCTSTR lpszFormat )
|
104
|
+
#
|
105
|
+
# Params:
|
106
|
+
# format_name (P) - [in] Pointer to a null-terminated string that names the new format.
|
107
|
+
#
|
108
|
+
# Returns: (I) or nil
|
109
|
+
# If the function succeeds, the return value identifies the registered clipboard format.
|
110
|
+
# If the function fails, the return value is nil(not zero). For error information, call GetLastError.
|
111
|
+
#
|
112
|
+
# Remarks:
|
113
|
+
# If a registered format with the specified name already exists, a new format is not registered and the
|
114
|
+
# return value identifies the existing format. This enables more than one application to copy and paste
|
115
|
+
# data using the same registered clipboard format. Note that the comparison is case-insensitive.
|
116
|
+
# Registered clipboard formats are identified by values in the range 0xC000 through 0xFFFF.
|
117
|
+
# When registered clipboard formats are placed on or retrieved from the clipboard, they must be in the
|
118
|
+
# form of an HGLOBAL value.
|
119
|
+
#
|
120
|
+
# :call-seq:
|
121
|
+
# register_clipboard_format( format_name )
|
122
|
+
#
|
123
|
+
function 'RegisterClipboardFormat', 'P', 'I', zeronil: true
|
124
|
+
|
125
|
+
# Procedure that calls (DdeInitialize) function expecting a DdeCallback. Runtime block is converted
|
126
|
+
# into Dde callback and registered with DdeInitialize. Returns DDE init status and DDE instance id.
|
127
|
+
#
|
128
|
+
return_id_status = ->(api, id=0, cmd, &block){
|
129
|
+
raise ArgumentError, 'No callback block' unless block
|
130
|
+
|
131
|
+
status = api.call(id = [id].pack('L'), block, cmd, 0)
|
132
|
+
id = status == 0 ? id.unpack('L').first : nil
|
133
|
+
[id, status] }
|
134
|
+
|
135
|
+
# DdeCallabck declaration
|
136
|
+
# MSDN syntax: HDDEDATA CALLBACK DdeCallback( UINT uType, UINT uFmt, HCONV hconv, HDDEDATA hsz1, HDDEDATA hsz2,
|
137
|
+
# HDDEDATA hdata, HDDEDATA dwData1, HDDEDATA dwData2);
|
138
|
+
callback :dde_callback, [:uint, :uint, :HCONV, :HDDEDATA, :HDDEDATA, :HDDEDATA, :HDDEDATA, :HDDEDATA], :HDDEDATA
|
139
|
+
|
140
|
+
##
|
141
|
+
# The DdeInitialize function registers an application with the Dynamic Data Exchange Management Library (DDEML).
|
142
|
+
# An application must call this function before calling any other DDEML function.
|
143
|
+
#
|
144
|
+
# Syntax: UINT DdeInitialize( LPDWORD pidInst, PFNCALLBACK pfnCallback, DWORD afCmd, DWORD ulRes );
|
145
|
+
#
|
146
|
+
# Params:
|
147
|
+
# pidInst (P) - [in, out] Pointer to the application instance identifier.
|
148
|
+
# At initialization, this parameter should point to 0. If the function succeeds, this parameter points to
|
149
|
+
# the instance identifier for the application. This value should be passed as the idInst parameter in all
|
150
|
+
# other DDEML functions that require it. If an application uses multiple instances of the DDEML dynamic-link
|
151
|
+
# library (DLL), the application should provide a different callback function for each instance.
|
152
|
+
# If pidInst points to a nonzero value, reinitialization of the DDEML is implied. In this case, pidInst must
|
153
|
+
# point to a valid application-instance identifier.
|
154
|
+
# pfnCallback (K) - [in] Pointer to the application-defined Dynamic Data Exchange (DDE) callback function.
|
155
|
+
# This function processes DDE transactions sent by the system. For more information, see the DdeCallback.
|
156
|
+
# afCmd (L) - [in] Specifies a set of APPCMD_, CBF_, and MF_ flags. The APPCMD_ flags provide special
|
157
|
+
# instructions to DdeInitialize. The CBF_ flags specify filters that prevent specific types of transactions
|
158
|
+
# from reaching the callback function. The MF_ flags specify the types of DDE activity that a DDE monitoring
|
159
|
+
# application monitors. Using these flags enhances the performance of a DDE application by eliminating
|
160
|
+
# unnecessary calls to the callback function. This parameter can be one or more of the following values:
|
161
|
+
# APPCLASS_MONITOR, APPCLASS_STANDARD, APPCMD_CLIENTONLY, APPCMD_FILTERINITS,
|
162
|
+
# CBF_FAIL_ALLSVRXACTIONS, CBF_FAIL_ADVISES, CBF_FAIL_CONNECTIONS, CBF_FAIL_EXECUTES, CBF_FAIL_POKES
|
163
|
+
# CBF_FAIL_REQUESTS, CBF_FAIL_SELFCONNECTIONS, CBF_SKIP_ALLNOTIFICATIONS, CBF_SKIP_CONNECT_CONFIRMS
|
164
|
+
# CBF_SKIP_DISCONNECTS, CBF_SKIP_REGISTRATIONS, CBF_SKIP_UNREGISTRATIONS
|
165
|
+
# MF_CALLBACKS, MF_CONV, MF_ERRORS, MF_HSZ_INFO, MF_LINKS, MF_POSTMSGS, MF_SENDMSGS
|
166
|
+
# ulRes (L) - Reserved; must be set to zero.
|
167
|
+
#
|
168
|
+
# Return Value:
|
169
|
+
# If the function succeeds, the return value is DMLERR_NO_ERROR.
|
170
|
+
# If the function fails, the return value is one of the following values:
|
171
|
+
# DMLERR_DLL_USAGE
|
172
|
+
# DMLERR_INVALIDPARAMETER
|
173
|
+
# DMLERR_SYS_ERROR
|
174
|
+
#
|
175
|
+
# Remarks:
|
176
|
+
# An application that uses multiple instances of the DDEML must not pass DDEML objects between instances.
|
177
|
+
# A DDE monitoring application should not attempt to perform DDE operations (establish conversations,
|
178
|
+
# issue transactions, and so on) within the context of the same application instance. A synchronous
|
179
|
+
# transaction fails with a DMLERR_REENTRANCY error if any instance of the same task has a synchronous
|
180
|
+
# transaction already in progress. The CBF_FAIL_ALLSVRXACTIONS flag causes the DDEML to filter all server
|
181
|
+
# transactions and can be changed by a subsequent call to DdeInitialize. The APPCMD_CLIENTONLY flag prevents
|
182
|
+
# the DDEML from creating key resources for the server and cannot be changed by a subsequent call to
|
183
|
+
# DdeInitialize. There is an ANSI version and a Unicode version of DdeInitialize. The version called
|
184
|
+
# determines the type of the window procedures used to control DDE conversations (ANSI or Unicode),
|
185
|
+
# and the default value for the iCodePage member of the CONVCONTEXT structure (CP_WINANSI or CP_WINUNICODE).
|
186
|
+
#
|
187
|
+
# :call-seq:
|
188
|
+
# id_inst, status = dde_initialize( id_inst = 0, cmd ) {|callback args| callback block}
|
189
|
+
#
|
190
|
+
function 'DdeInitialize', [:pointer, :dde_callback, :DWORD, :DWORD], :uint, &return_id_status
|
191
|
+
|
192
|
+
##
|
193
|
+
# The DdeCreateStringHandle function creates a handle that identifies the specified string.
|
194
|
+
# A Dynamic Data Exchange (DDE) client or server application can pass the string handle as a
|
195
|
+
# parameter to other Dynamic Data Exchange Management Library (DDEML) functions.
|
196
|
+
#
|
197
|
+
# Syntax: HSZ DdeCreateStringHandle( DWORD idInst, LPTSTR psz, int iCodePage );
|
198
|
+
#
|
199
|
+
# Parameters:
|
200
|
+
# idInst (L) - [in] Specifies the application instance identifier obtained by a previous call to the
|
201
|
+
# DdeInitialize function.
|
202
|
+
# psz (P) - [in] Pointer to a buffer that contains the null-terminated string for which a handle
|
203
|
+
# is to be created. This string can be up to 255 characters. The reason for this limit is that
|
204
|
+
# DDEML string management functions are implemented using global atoms.
|
205
|
+
# iCodePage (I) - [in] Specifies the code page used to render the string. This value should be either
|
206
|
+
# CP_WINANSI (the default code page) or CP_WINUNICODE, depending on whether the ANSI or Unicode
|
207
|
+
# version of DdeInitialize was called by the client application.
|
208
|
+
#
|
209
|
+
# Return Value (L) or nil: If the function succeeds, the return value is a string handle.
|
210
|
+
# If the function fails, the return value is 0(changed to nil in enhanced version).
|
211
|
+
# The DdeGetLastError function can be used to get the error code, which can be one of the following values:
|
212
|
+
#DMLERR_NO_ERROR, DMLERR_INVALIDPARAMETER, DMLERR_SYS_ERROR
|
213
|
+
#
|
214
|
+
# Remarks: The value of a string handle is not related to the case of the string it identifies.
|
215
|
+
# When an application either creates a string handle or receives one in the callback function
|
216
|
+
# and then uses the DdeKeepStringHandle function to keep it, the application must free that string
|
217
|
+
# handle when it is no longer needed. An instance-specific string handle cannot be mapped from string
|
218
|
+
# handle to string and back to string handle.
|
219
|
+
#
|
220
|
+
function 'DdeCreateStringHandle', [:DWORD, :pointer, :int], :HSZ
|
221
|
+
|
222
|
+
end
|
223
|
+
end
|