win 0.1.0 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +18 -19
- data/VERSION +1 -1
- data/lib/win/dde.rb +147 -88
- data/lib/win/gui/dialog.rb +35 -1
- data/lib/win/gui/input.rb +128 -93
- data/lib/win/gui/message.rb +365 -5
- data/lib/win/gui/{convenience.rb → window/window.rb} +12 -67
- data/lib/win/gui/window.rb +338 -219
- data/lib/win/gui.rb +1 -2
- data/lib/win/library.rb +0 -2
- data/spec/spec_helper.rb +4 -4
- data/spec/win/gui/dialog_spec.rb +22 -7
- data/spec/win/gui/input_spec.rb +30 -0
- data/spec/win/gui/message_spec.rb +0 -7
- data/spec/win/gui/{convenience_spec.rb → window/window_spec.rb} +13 -61
- data/spec/win/gui/window_spec.rb +30 -4
- data/spec/win/library_spec.rb +0 -27
- data/win.gemspec +5 -5
- metadata +5 -5
data/README.rdoc
CHANGED
@@ -116,41 +116,40 @@ Contributors always welcome!
|
|
116
116
|
== SYNOPSIS
|
117
117
|
=== Using pre-defined Windows API functions:
|
118
118
|
|
119
|
-
|
119
|
+
require 'win/gui'
|
120
120
|
|
121
|
-
|
121
|
+
class MyClass
|
122
122
|
include Win::Gui::Window
|
123
123
|
|
124
124
|
fg_window = foreground_window
|
125
125
|
puts window_text(fg_window)
|
126
126
|
show_window(fg_window) unless minimized?(fg_window)
|
127
127
|
...
|
128
|
-
|
128
|
+
end
|
129
129
|
|
130
130
|
=== Defining your own Windows API functions:
|
131
131
|
|
132
|
-
|
132
|
+
require 'win/library'
|
133
133
|
|
134
|
-
|
135
|
-
|
134
|
+
module YourLibModule
|
135
|
+
include Win::Library
|
136
136
|
|
137
|
-
|
138
|
-
|
137
|
+
# Customizing even further: your own method extension in attached block
|
138
|
+
function :GetWindowText, [ :ulong, :pointer, :int ], :int do |api, handle|
|
139
|
+
buffer = FFI::MemoryPointer.new :char, 512
|
140
|
+
buffer.put_string(0, "\x00" * 511)
|
141
|
+
num_chars = api.call(handle, buffer, 512)
|
142
|
+
num_chars == 0 ? nil : buffer.get_bytes(0, num_chars)
|
143
|
+
end
|
139
144
|
|
140
|
-
|
141
|
-
|
142
|
-
buffer = FFI::MemoryPointer.new :char, 512
|
143
|
-
buffer.put_string(0, "\x00" * 511)
|
144
|
-
num_chars = api.call(handle, buffer, 512)
|
145
|
-
return nil if num_chars == 0
|
146
|
-
string = buffer.get_bytes(0, num_chars)
|
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
147
|
end
|
148
|
-
end
|
149
148
|
|
150
|
-
|
149
|
+
include YourLibModule
|
151
150
|
|
152
|
-
|
153
|
-
|
151
|
+
handle = my_find(nil, 'cmd') # find any shell window
|
152
|
+
puts handle, window_text(handle) # print shell window handle and title
|
154
153
|
|
155
154
|
== PRIOR ART:
|
156
155
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.2
|
data/lib/win/dde.rb
CHANGED
@@ -100,84 +100,141 @@ module Win
|
|
100
100
|
# The RegisterClipboardFormat function registers a new clipboard format.
|
101
101
|
# This format can then be used as a valid clipboard format.
|
102
102
|
#
|
103
|
-
# Syntax
|
103
|
+
# [*Syntax*] UINT RegisterClipboardFormat( LPCTSTR lpszFormat )
|
104
104
|
#
|
105
|
-
#
|
106
|
-
# format_name (P) - [in] Pointer to a null-terminated string that names the new format.
|
105
|
+
# lpszFormat:: [in] Pointer to a null-terminated string that names the new format.
|
107
106
|
#
|
108
|
-
# Returns:
|
109
|
-
#
|
110
|
-
#
|
111
|
-
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
# form of an HGLOBAL value.
|
107
|
+
# *Returns*:: :uint or nil. If the function succeeds, the return value identifies the registered clipboard format.
|
108
|
+
# If the function fails, the return value is *nil*(not zero). For error info, call GetLastError.
|
109
|
+
# ---
|
110
|
+
# *Remarks*:
|
111
|
+
# If a registered format with the specified name already exists, a new format is not registered and the
|
112
|
+
# return value identifies the existing format. This enables more than one application to copy and paste
|
113
|
+
# data using the same registered clipboard format. Note that the comparison is case-insensitive.
|
114
|
+
# Registered clipboard formats are identified by values in the range 0xC000 through 0xFFFF.
|
115
|
+
# When registered clipboard formats are placed on or retrieved from the clipboard, they must be in the
|
116
|
+
# form of an HGLOBAL value.
|
119
117
|
#
|
120
118
|
# :call-seq:
|
121
|
-
#
|
119
|
+
# register_clipboard_format( format_name )
|
122
120
|
#
|
123
|
-
function
|
121
|
+
function :RegisterClipboardFormat, [:pointer], :uint, zeronil: true
|
124
122
|
|
125
|
-
|
126
|
-
#
|
127
|
-
#
|
128
|
-
|
123
|
+
##
|
124
|
+
# The DdeCallback function is an application-defined callback function used with the Dynamic Data Exchange
|
125
|
+
# Management Library (DDEML) functions. It processes Dynamic Data Exchange (DDE) transactions. The PFNCALLBACK
|
126
|
+
# type defines a pointer to this callback function. DdeCallback is a placeholder for the application-defined
|
127
|
+
# function name.
|
128
|
+
#
|
129
|
+
# [*Syntax*] HDDEDATA CALLBACK DdeCallback( UINT uType, UINT uFmt, HCONV hconv, HDDEDATA hsz1, HDDEDATA hsz2,
|
130
|
+
# HDDEDATA hdata, HDDEDATA dwData1, HDDEDATA dwData2);
|
131
|
+
# uType:: [in] Specifies the type of the current transaction. This parameter consists of a combination of
|
132
|
+
# transaction class flags and transaction type flags. The following table describes each of the
|
133
|
+
# transaction classes and provides a list of the transaction types in each class. For information
|
134
|
+
# about a specific transaction type, see the individual description of that type.
|
135
|
+
# - XCLASS_BOOL - A DDE callback function should return TRUE or FALSE when it finishes processing a
|
136
|
+
# transaction that belongs to this class. The XCLASS_BOOL class consists of the following types:
|
137
|
+
# - XTYP_ADVSTART
|
138
|
+
# - XTYP_CONNECT
|
139
|
+
# - XCLASS_DATA - A DDE callback function should return a DDE handle, the CBR_BLOCK return code, or
|
140
|
+
# NULL when it finishes processing a transaction that belongs to this class. The XCLASS_DATA
|
141
|
+
# transaction class consists of the following types:
|
142
|
+
# - XTYP_ADVREQ
|
143
|
+
# - XTYP_REQUEST
|
144
|
+
# - XTYP_WILDCONNECT
|
145
|
+
# - XCLASS_FLAGS - A DDE callback function should return DDE_FACK, DDE_FBUSY, or DDE_FNOTPROCESSED
|
146
|
+
# when it finishes processing a transaction that belongs to this class. The XCLASS_FLAGS transaction
|
147
|
+
# class consists of the following types:
|
148
|
+
# - XTYP_ADVDATA
|
149
|
+
# - XTYP_EXECUTE
|
150
|
+
# - XTYP_POKE
|
151
|
+
# - XCLASS_NOTIFICATION - The transaction types that belong to this class are for notification purposes
|
152
|
+
# only. The return value from the callback function is ignored. The XCLASS_NOTIFICATION transaction
|
153
|
+
# class consists of the following types:
|
154
|
+
# - XTYP_ADVSTOP
|
155
|
+
# - XTYP_CONNECT_CONFIRM
|
156
|
+
# - XTYP_DISCONNECT
|
157
|
+
# - XTYP_ERROR
|
158
|
+
# - XTYP_MONITOR
|
159
|
+
# - XTYP_REGISTER
|
160
|
+
# - XTYP_XACT_COMPLETE
|
161
|
+
# - XTYP_UNREGISTER
|
162
|
+
# uFmt:: [in] Specifies the format in which data is sent or received.
|
163
|
+
# hconv:: [in] Handle to the conversation associated with the current transaction.
|
164
|
+
# hsz1:: [in] Handle to a string. The meaning of this parameter depends on the type of the current transaction.
|
165
|
+
# For the meaning of this parameter, see the description of the transaction type.
|
166
|
+
# hsz2:: [in] Handle to a string. The meaning of this parameter depends on the type of the current transaction.
|
167
|
+
# For the meaning of this parameter, see the description of the transaction type.
|
168
|
+
# hdata:: [in] Handle to DDE data. The meaning of this parameter depends on the type of the current transaction.
|
169
|
+
# For the meaning of this parameter, see the description of the transaction type.
|
170
|
+
# dwData1:: [in] Specifies transaction-specific data. For the meaning, see the description of the transaction type.
|
171
|
+
# dwData2:: [in] Specifies transaction-specific data. For the meaning, see the description of the transaction type.
|
172
|
+
# *Returns*:: The return value depends on the transaction class. For more information about the return values,
|
173
|
+
# see descriptions of the individual transaction types.
|
174
|
+
# ---
|
175
|
+
# *Remarks*:
|
176
|
+
# - The callback function is called asynchronously for transactions that do not involve the creation or termination
|
177
|
+
# of conversations. An application that does not frequently accept incoming messages will have reduced DDE
|
178
|
+
# performance because the Dynamic Data Exchange Management Library (DDEML) uses messages to initiate transactions.
|
179
|
+
# - An application must register the callback function by specifying a pointer to the function in a call to the
|
180
|
+
# DdeInitialize function.
|
181
|
+
#
|
182
|
+
# :call-seq:
|
183
|
+
# DdeCallback block: {|type, format, hconv, hsz1, hsz2, hdata, data1, data2| your code }
|
184
|
+
#
|
185
|
+
callback :DdeCallback, [:uint, :uint, :HCONV, :HDDEDATA, :HDDEDATA, :HDDEDATA, :HDDEDATA, :HDDEDATA], :HDDEDATA
|
129
186
|
|
130
187
|
##
|
131
188
|
# The DdeInitialize function registers an application with the Dynamic Data Exchange Management Library (DDEML).
|
132
189
|
# An application must call this function before calling any other DDEML function.
|
133
190
|
#
|
134
|
-
# Syntax
|
135
|
-
#
|
136
|
-
#
|
137
|
-
#
|
138
|
-
#
|
139
|
-
#
|
140
|
-
#
|
141
|
-
#
|
142
|
-
#
|
143
|
-
#
|
144
|
-
#
|
145
|
-
#
|
146
|
-
#
|
147
|
-
#
|
148
|
-
#
|
149
|
-
#
|
150
|
-
#
|
151
|
-
#
|
152
|
-
#
|
153
|
-
#
|
154
|
-
#
|
155
|
-
#
|
156
|
-
#
|
157
|
-
#
|
158
|
-
#
|
159
|
-
#
|
160
|
-
#
|
161
|
-
#
|
162
|
-
#
|
163
|
-
#
|
164
|
-
#
|
165
|
-
#
|
166
|
-
#
|
167
|
-
#
|
168
|
-
#
|
169
|
-
#
|
170
|
-
#
|
171
|
-
#
|
172
|
-
#
|
173
|
-
#
|
174
|
-
#
|
175
|
-
# and the default value for the iCodePage member of the CONVCONTEXT structure (CP_WINANSI or CP_WINUNICODE).
|
191
|
+
# [*Syntax*] UINT DdeInitialize( LPDWORD pidInst, PFNCALLBACK pfnCallback, DWORD afCmd, DWORD ulRes );
|
192
|
+
#
|
193
|
+
# pidInst:: [in, out] Pointer to the application instance identifier.
|
194
|
+
# At initialization, this parameter should point to 0. If the function succeeds, this parameter points
|
195
|
+
# to the instance identifier for the application. This value should be passed as the idInst parameter
|
196
|
+
# in all other DDEML functions that require it. If an application uses multiple instances of the DDEML
|
197
|
+
# dynamic-link library (DLL), the application should provide a different callback function for each
|
198
|
+
# instance. If pidInst points to a nonzero value, reinitialization of the DDEML is implied. In this
|
199
|
+
# case, pidInst must point to a valid application-instance identifier.
|
200
|
+
# pfnCallback:: Pointer to the application-defined Dynamic Data Exchange DdeCallback function. This function
|
201
|
+
# processes DDE transactions sent by the system. For more information, see the DdeCallback.
|
202
|
+
# afCmd:: [in] Specifies a set of APPCMD_, CBF_, and MF_ flags. The APPCMD_ flags provide special
|
203
|
+
# instructions to DdeInitialize. The CBF_ flags specify filters that prevent specific types of transactions
|
204
|
+
# from reaching the callback function. The MF_ flags specify the types of DDE activity that a DDE monitoring
|
205
|
+
# application monitors. Using these flags enhances the performance of a DDE application by eliminating
|
206
|
+
# unnecessary calls to the callback function. This parameter can be one or more of the following values:
|
207
|
+
# APPCLASS_MONITOR, APPCLASS_STANDARD, APPCMD_CLIENTONLY, APPCMD_FILTERINITS;
|
208
|
+
# CBF_FAIL_ALLSVRXACTIONS, CBF_FAIL_ADVISES, CBF_FAIL_CONNECTIONS, CBF_FAIL_EXECUTES, CBF_FAIL_POKES
|
209
|
+
# CBF_FAIL_REQUESTS, CBF_FAIL_SELFCONNECTIONS, CBF_SKIP_ALLNOTIFICATIONS, CBF_SKIP_CONNECT_CONFIRMS
|
210
|
+
# CBF_SKIP_DISCONNECTS, CBF_SKIP_REGISTRATIONS, CBF_SKIP_UNREGISTRATIONS;
|
211
|
+
# MF_CALLBACKS, MF_CONV, MF_ERRORS, MF_HSZ_INFO, MF_LINKS, MF_POSTMSGS, MF_SENDMSGS
|
212
|
+
# ulRes:: Reserved; must be set to zero.
|
213
|
+
#
|
214
|
+
# *Returns*:: If the function succeeds, the return value is DMLERR_NO_ERROR. If the function fails, the return
|
215
|
+
# value is one of the following values:
|
216
|
+
# - DMLERR_DLL_USAGE
|
217
|
+
# - DMLERR_INVALIDPARAMETER
|
218
|
+
# - DMLERR_SYS_ERROR
|
219
|
+
# ---
|
220
|
+
# *Remarks*:
|
221
|
+
# - An application that uses multiple instances of the DDEML must not pass DDEML objects between instances.
|
222
|
+
# - A DDE monitoring application should not attempt to perform DDE operations (establish conversations,
|
223
|
+
# issue transactions, and so on) within the context of the same application instance.
|
224
|
+
# - A synchronous transaction fails with a DMLERR_REENTRANCY error if any instance of the same task has
|
225
|
+
# a synchronous transaction already in progress.
|
226
|
+
# - The CBF_FAIL_ALLSVRXACTIONS flag causes the DDEML to filter all server transactions and can be changed
|
227
|
+
# by a subsequent call to DdeInitialize. The APPCMD_CLIENTONLY flag prevents the DDEML from creating key
|
228
|
+
# resources for the server and cannot be changed by a subsequent call to DdeInitialize.
|
229
|
+
# - There is an ANSI version and a Unicode version of DdeInitialize. The version called determines the
|
230
|
+
# type of the window procedures used to control DDE conversations (ANSI or Unicode), and the default
|
231
|
+
# value for the iCodePage member of the CONVCONTEXT structure (CP_WINANSI or CP_WINUNICODE).
|
176
232
|
#
|
177
233
|
# :call-seq:
|
178
|
-
#
|
234
|
+
# instance_id, status = dde_initialize( instance_id = 0, cmd )
|
235
|
+
# {|type, format, hconv, hsz1, hsz2, hdata, data1, data2| your dde_callback block}
|
179
236
|
#
|
180
|
-
function
|
237
|
+
function :DdeInitialize, [:pointer, :DdeCallback, :DWORD, :DWORD], :uint,
|
181
238
|
&->(api, old_id=0, cmd, &block){
|
182
239
|
raise ArgumentError, 'No callback block' unless block
|
183
240
|
id = FFI::MemoryPointer.new(:long)
|
@@ -192,30 +249,32 @@ module Win
|
|
192
249
|
# A Dynamic Data Exchange (DDE) client or server application can pass the string handle as a
|
193
250
|
# parameter to other Dynamic Data Exchange Management Library (DDEML) functions.
|
194
251
|
#
|
195
|
-
# Syntax
|
196
|
-
#
|
197
|
-
#
|
198
|
-
#
|
199
|
-
#
|
200
|
-
#
|
201
|
-
#
|
202
|
-
#
|
203
|
-
#
|
204
|
-
#
|
205
|
-
#
|
206
|
-
#
|
207
|
-
#
|
208
|
-
#
|
209
|
-
#
|
210
|
-
#
|
211
|
-
#
|
212
|
-
#
|
213
|
-
#
|
214
|
-
#
|
215
|
-
#
|
216
|
-
#
|
217
|
-
#
|
218
|
-
|
252
|
+
# [*Syntax*] HSZ DdeCreateStringHandle( DWORD idInst, LPTSTR psz, int iCodePage );
|
253
|
+
#
|
254
|
+
# idInst:: [in] Specifies the application instance identifier obtained by a previous call to the
|
255
|
+
# DdeInitialize function.
|
256
|
+
# psz:: [in] Pointer to a buffer that contains the null-terminated string for which a handle
|
257
|
+
# is to be created. This string can be up to 255 characters. The reason for this limit is that
|
258
|
+
# DDEML string management functions are implemented using global atoms.
|
259
|
+
# iCodePage:: [in] Specifies the code page used to render the string. This value should be either
|
260
|
+
# CP_WINANSI (the default code page) or CP_WINUNICODE, depending on whether the ANSI or Unicode
|
261
|
+
# version of DdeInitialize was called by the client application.
|
262
|
+
#
|
263
|
+
# *Returns*:: (L) or nil: If the function succeeds, the return value is a string handle.
|
264
|
+
# If the function fails, the return value is 0(changed to nil in enhanced version).
|
265
|
+
# The DdeGetLastError function can be used to get the error code, which can be one of the
|
266
|
+
# following values: DMLERR_NO_ERROR, DMLERR_INVALIDPARAMETER, DMLERR_SYS_ERROR
|
267
|
+
# ---
|
268
|
+
# *Remarks*: The value of a string handle is not related to the case of the string it identifies.
|
269
|
+
# When an application either creates a string handle or receives one in the callback function
|
270
|
+
# and then uses the DdeKeepStringHandle function to keep it, the application must free that string
|
271
|
+
# handle when it is no longer needed. An instance-specific string handle cannot be mapped from string
|
272
|
+
# handle to string and back to string handle.
|
273
|
+
#
|
274
|
+
# :call-seq:
|
275
|
+
# string_handle = dde_create_string_handle( instance_id, string, code_page_id )
|
276
|
+
#
|
277
|
+
function :DdeCreateStringHandle, [:DWORD, :pointer, :int], :HSZ, zeronil: true
|
219
278
|
|
220
279
|
end
|
221
280
|
end
|
data/lib/win/gui/dialog.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'win/library'
|
2
|
+
require 'win/gui/window'
|
2
3
|
|
3
4
|
module Win
|
4
5
|
module Gui
|
@@ -6,8 +7,41 @@ module Win
|
|
6
7
|
#
|
7
8
|
module Dialog
|
8
9
|
include Win::Library
|
10
|
+
include Win::Gui::Window
|
9
11
|
|
10
|
-
|
12
|
+
# The GetDlgItem function retrieves a handle to a control in the specified dialog box.
|
13
|
+
#
|
14
|
+
# [*Syntax*] HWND GetDlgItem( HWND hDlg, int nIDDlgItem );
|
15
|
+
#
|
16
|
+
# hDlg:: [in] Handle to the dialog box that contains the control.
|
17
|
+
# nIDDlgItem:: [in] Specifies the identifier of the control to be retrieved.
|
18
|
+
# *Returns*:: If the function succeeds, the return value is the window handle of the specified control.
|
19
|
+
# If the function fails, the return value is NULL, indicating an invalid dialog box handle
|
20
|
+
# or a nonexistent control. To get extended error information, call GetLastError.
|
21
|
+
# ---
|
22
|
+
# *Remarks*:
|
23
|
+
# You can use the GetDlgItem function with any parent-child window pair, not just with dialog boxes.
|
24
|
+
# As long as the hDlg parameter specifies a parent window and the child window has a unique identifier
|
25
|
+
# (as specified by the hMenu parameter in the CreateWindow or CreateWindowEx function that created the
|
26
|
+
# child window), GetDlgItem returns a valid handle to the child window.
|
27
|
+
#
|
28
|
+
# :call-seq:
|
29
|
+
# control_handle = [get_]dlg_item( dialog_handle, id )
|
30
|
+
#
|
31
|
+
function :GetDlgItem, [:ulong, :int], :ulong
|
32
|
+
|
33
|
+
# Convenience methods:
|
34
|
+
|
35
|
+
# finds top-level dialog window by title and yields found dialog window to block if given
|
36
|
+
def dialog(title, seconds=3)
|
37
|
+
d = begin
|
38
|
+
win = Window::Window.top_level(title, seconds)
|
39
|
+
yield(win) ? win : nil
|
40
|
+
rescue TimeoutError
|
41
|
+
end
|
42
|
+
d.wait_for_close if d
|
43
|
+
return d
|
44
|
+
end
|
11
45
|
end
|
12
46
|
end
|
13
47
|
end
|