win 0.0.4 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|