win 0.3.6 → 0.3.7
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY +4 -0
- data/VERSION +1 -1
- data/lib/extension.rb +26 -0
- data/lib/win/gui/dialog.rb +327 -15
- data/lib/win/gui/input.rb +9 -0
- data/lib/win/gui/message.rb +3 -18
- data/lib/win/gui/window.rb +56 -0
- data/lib/win/library.rb +1 -1
- data/spec/extension_spec.rb +73 -0
- data/spec/spec_helper.rb +19 -9
- data/spec/win/gui/dialog_spec.rb +47 -3
- data/spec/win/gui/input_spec.rb +1 -2
- data/spec/win/gui/window_spec.rb +22 -3
- metadata +6 -6
- data/lib/win/extensions.rb +0 -41
- data/spec/win/extensions_spec.rb +0 -73
data/HISTORY
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.7
|
data/lib/extension.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# This file extends core Ruby classes! Please make sure it doesn't create conflicts
|
2
|
+
|
3
|
+
class String
|
4
|
+
# returns snake_case representation of string
|
5
|
+
def snake_case
|
6
|
+
gsub(/([a-z])([A-Z0-9])/, '\1_\2' ).downcase
|
7
|
+
end
|
8
|
+
|
9
|
+
# returns camel_case representation of string
|
10
|
+
def camel_case
|
11
|
+
if self.include? '_'
|
12
|
+
self.split('_').map{|e| e.capitalize}.join
|
13
|
+
else
|
14
|
+
unless self =~ (/^[A-Z]/)
|
15
|
+
self.capitalize
|
16
|
+
else
|
17
|
+
self
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# converts string to 'wide char' (Windows Unicode) format
|
23
|
+
def to_w
|
24
|
+
(self+"\x00").encode('utf-16LE')
|
25
|
+
end
|
26
|
+
end
|
data/lib/win/gui/dialog.rb
CHANGED
@@ -3,23 +3,196 @@ require 'win/gui/window'
|
|
3
3
|
|
4
4
|
module Win
|
5
5
|
module Gui
|
6
|
-
# Contains constants and Win32API functions related to dialog manipulation
|
7
|
-
#
|
8
|
-
module Dialog
|
9
|
-
|
10
|
-
# IDs of standard dialog controls and items
|
11
|
-
IDOK = 1
|
12
|
-
IDCANCEL = 2
|
13
|
-
IDABORT = 3
|
14
|
-
IDRETRY = 4
|
15
|
-
IDIGNORE = 5
|
16
|
-
IDYES = 6
|
17
|
-
IDNO = 7
|
18
|
-
ErrorIcon = 0x0014
|
19
6
|
|
7
|
+
# Contains constants and Win32 API functions related to dialog manipulation.
|
8
|
+
# Windows dialog basics can be found here:
|
9
|
+
# http://msdn.microsoft.com/en-us/library/ms644996#init_box
|
10
|
+
module Dialog
|
20
11
|
include Win::Library
|
21
12
|
include Win::Gui::Window
|
22
13
|
|
14
|
+
# Message Box flags:
|
15
|
+
|
16
|
+
# To indicate the buttons displayed in the message box, specify one of the following values:
|
17
|
+
|
18
|
+
# The message box contains one push button: OK. This is the default.
|
19
|
+
MB_OK = 0x00000000
|
20
|
+
# The message box contains two push buttons: OK and Cancel.
|
21
|
+
MB_OKCANCEL = 0x00000001
|
22
|
+
# The message box contains three push buttons: Abort, Retry, and Ignore (considered obsolete)
|
23
|
+
MB_ABORTRETRYIGNORE = 0x00000002
|
24
|
+
# The message box contains three push buttons: Yes, No, and Cancel.
|
25
|
+
MB_YESNOCANCEL = 0x00000003
|
26
|
+
# The message box contains two push buttons: Yes and No.
|
27
|
+
MB_YESNO = 0x00000004
|
28
|
+
# The message box contains two push buttons: Retry and Cancel.
|
29
|
+
MB_RETRYCANCEL = 0x00000005
|
30
|
+
# The message box contains three push buttons: Cancel, Try Again, Continue (Win 2000/XP).
|
31
|
+
# Use this message box type instead of MB_ABORTRETRYIGNORE.
|
32
|
+
MB_CANCELTRYCONTINUE = 0x00000006
|
33
|
+
|
34
|
+
# To display an icon in the message box, specify one of the following values:
|
35
|
+
|
36
|
+
# A stop-sign icon appears in the message box.
|
37
|
+
MB_ICONHAND = 0x00000010
|
38
|
+
# A question-mark icon appears in the message box. The question-mark message icon is no longer
|
39
|
+
# recommended because it does not clearly represent a specific type of message and because the phrasing
|
40
|
+
# of a message as a question could apply to any message type. In addition, users can confuse the message
|
41
|
+
# symbol question mark with Help information. Therefore, do not use this question mark message symbol in
|
42
|
+
# your message boxes. The system continues to support its inclusion only for backward compatibility.
|
43
|
+
MB_ICONQUESTION = 0x00000020
|
44
|
+
# An exclamation-point icon appears in the message box.
|
45
|
+
MB_ICONEXCLAMATION = 0x00000030
|
46
|
+
# An icon consisting of a lowercase letter i in a circle appears in the message box.
|
47
|
+
MB_ICONASTERISK = 0x00000040
|
48
|
+
MB_USERICON = 0x00000080
|
49
|
+
# An exclamation-point icon appears in the message box.
|
50
|
+
MB_ICONWARNING = MB_ICONEXCLAMATION
|
51
|
+
# A stop-sign icon appears in the message box.
|
52
|
+
MB_ICONERROR = MB_ICONHAND
|
53
|
+
# An icon consisting of a lowercase letter i in a circle appears in the message box.
|
54
|
+
MB_ICONINFORMATION = MB_ICONASTERISK
|
55
|
+
# A stop-sign icon appears in the message box.
|
56
|
+
MB_ICONSTOP = MB_ICONHAND
|
57
|
+
|
58
|
+
# To indicate the default button, specify one of the following values:
|
59
|
+
|
60
|
+
# The first button is the default button.
|
61
|
+
# MB_DEFBUTTON1 is the default unless MB_DEFBUTTON2, MB_DEFBUTTON3, or MB_DEFBUTTON4 is specified.
|
62
|
+
MB_DEFBUTTON1 = 0x00000000
|
63
|
+
# The second button is the default button.
|
64
|
+
MB_DEFBUTTON2 = 0x00000100
|
65
|
+
# The 3rd button is the default button.
|
66
|
+
MB_DEFBUTTON3 = 0x00000200
|
67
|
+
# The 4th button is the default button.
|
68
|
+
MB_DEFBUTTON4 = 0x00000300
|
69
|
+
|
70
|
+
# To indicate the modality of the dialog box, specify one of the following values:
|
71
|
+
|
72
|
+
# The user must respond to the message box before continuing work in the window identified by the hWnd
|
73
|
+
# parameter. However, the user can move to the windows of other threads and work in those windows.
|
74
|
+
# Depending on the hierarchy of windows in the application, the user may be able to move to other
|
75
|
+
# windows within the thread. All child windows of the parent of the message box are automatically
|
76
|
+
# disabled, but pop-up windows are not.
|
77
|
+
# MB_APPLMODAL is the default if neither MB_SYSTEMMODAL nor MB_TASKMODAL is specified.
|
78
|
+
MB_APPLMODAL = 0x00000000
|
79
|
+
# Same as MB_APPLMODAL except that the message box has the WS_EX_TOPMOST style. Use system-modal message
|
80
|
+
# boxes to notify the user of serious, potentially damaging errors that require immediate attention (for
|
81
|
+
# example, running out of memory). This flag has no effect on the user's ability to interact with
|
82
|
+
# windows other than those associated with hWnd.
|
83
|
+
MB_SYSTEMMODAL = 0x00001000
|
84
|
+
# Same as MB_APPLMODAL except that all the top-level windows belonging to the current thread are
|
85
|
+
# disabled if the hWnd parameter is NULL. Use this flag when the calling application or library does not
|
86
|
+
# have a window handle available but still needs to prevent input to other windows in the calling thread
|
87
|
+
# without suspending other threads.
|
88
|
+
MB_TASKMODAL = 0x00002000
|
89
|
+
|
90
|
+
# To specify other options, use one or more of the following values.
|
91
|
+
|
92
|
+
# Adds a Help button to the message box. When the user clicks the Help button or presses F1,
|
93
|
+
# the system sends a WM_HELP message to the owner.
|
94
|
+
MB_HELP = 0x00004000
|
95
|
+
MB_NOFOCUS = 0x00008000
|
96
|
+
# The message box becomes the foreground window. Internally, the system calls the SetForegroundWindow
|
97
|
+
# function for the message box.
|
98
|
+
MB_SETFOREGROUND = 0x00010000
|
99
|
+
# Windows NT/2000/XP: Same as desktop of the interactive window station. For more information, see
|
100
|
+
# Window Stations.
|
101
|
+
# Windows NT 4.0 and earlier: If the current input desktop is not the default desktop, MessageBox fails.
|
102
|
+
# Windows 2000/XP: If the current input desktop is not the default desktop, MessageBox does not return
|
103
|
+
# until the user switches to the default desktop.
|
104
|
+
# Windows 95/98/Me: This flag has no effect.
|
105
|
+
MB_DEFAULT_DESKTOP_ONLY = 0x00020000
|
106
|
+
# The message box is created with the WS_EX_TOPMOST window style.
|
107
|
+
MB_TOPMOST = 0x00040000
|
108
|
+
# The text is right-justified.
|
109
|
+
MB_RIGHT = 0x00080000
|
110
|
+
# Displays message and caption text using right-to-left reading order on Hebrew and Arabic systems.
|
111
|
+
MB_RTLREADING = 0x00100000
|
112
|
+
# Assume Win2k or later
|
113
|
+
# Windows NT/2000/XP: The caller is a service notifying the user of an event. The function displays a
|
114
|
+
# message box on the current active desktop, even if there is no user logged on to the computer.
|
115
|
+
# Terminal Services: If the calling thread has an impersonation token, the function directs the message
|
116
|
+
# box to the session specified in the impersonation token.
|
117
|
+
# If this flag is set, the hWnd parameter must be NULL. This is so that the message box can appear on a
|
118
|
+
# desktop other than the desktop corresponding to the hWnd.
|
119
|
+
# For more information on the changes between Microsoft Windows NT 3.51 and Windows NT 4.0, see Remarks.
|
120
|
+
# For information on security considerations in regard to using this flag, see Interactive Services.
|
121
|
+
MB_SERVICE_NOTIFICATION = 0x00200000
|
122
|
+
# Windows NT/2000/XP: This value corresponds to the value defined for MB_SERVICE_NOTIFICATION for
|
123
|
+
# Windows NT version 3.51.
|
124
|
+
MB_SERVICE_NOTIFICATION_NT3X = 0x00040000
|
125
|
+
MB_TYPEMASK = 0x0000000F
|
126
|
+
MB_ICONMASK = 0x000000F0
|
127
|
+
MB_DEFMASK = 0x00000F00
|
128
|
+
MB_MODEMASK = 0x00003000
|
129
|
+
MB_MISCMASK = 0x0000C000
|
130
|
+
|
131
|
+
# IDs of standard dialog controls and items:
|
132
|
+
|
133
|
+
# These are returned as user input from modal dialog:
|
134
|
+
IDOK = 0x01 # The OK button was selected.
|
135
|
+
IDCANCEL = 0x02 # The Cancel button was selected.
|
136
|
+
IDABORT = 0x03 # The Abort button was selected.
|
137
|
+
IDRETRY = 0x04 # The Retry button was selected.
|
138
|
+
IDIGNORE = 0x05 # The Ignore button was selected.
|
139
|
+
IDYES = 0x06 # The YES button was selected.
|
140
|
+
IDNO = 0x07 # The NO button was selected.
|
141
|
+
IDTRYAGAIN = 0x10 # The Try Again button was selected.
|
142
|
+
IDCONTINUE = 0x11 # The Continue button was selected.
|
143
|
+
|
144
|
+
# These are not returned, their presence helps to programmatically identify type of present dialog:
|
145
|
+
ErrorIcon = 0x14 # ID of Error Icon (this dialog informs about some Error)
|
146
|
+
|
147
|
+
##
|
148
|
+
# DialogProc is an application-defined callback function used with the CreateDialog and DialogBox
|
149
|
+
# families of functions. It processes messages sent to a modal or modeless dialog box. The DLGPROC
|
150
|
+
# type defines a pointer to this callback function. DialogProc is a placeholder for the
|
151
|
+
# application-defined function name.
|
152
|
+
#
|
153
|
+
# [*Syntax*] INT_PTR CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
154
|
+
#
|
155
|
+
# hwndDlg:: [in] Handle to the dialog box.
|
156
|
+
# uMsg:: [in] Specifies the message.
|
157
|
+
# wParam:: [in] Specifies additional message-specific information.
|
158
|
+
# lParam:: [in] Specifies additional message-specific information.
|
159
|
+
#
|
160
|
+
# *Returns*:: Typically, the dialog box procedure should return TRUE if it processed the message, and
|
161
|
+
# FALSE if it did not. If the dialog box procedure returns FALSE, the dialog manager
|
162
|
+
# performs the default dialog operation in response to the message.
|
163
|
+
# If the dialog box procedure processes a message that requires a specific return value, the dialog box
|
164
|
+
# procedure should set the desired return value by calling SetWindowLong(hwndDlg, DWL_MSGRESULT,
|
165
|
+
# lResult) immediately before returning TRUE. Note that you must call SetWindowLong immediately before
|
166
|
+
# returning TRUE; doing so earlier may result in the DWL_MSGRESULT value being overwritten by a nested
|
167
|
+
# dialog box message.
|
168
|
+
# The following messages are exceptions to the general rules stated above. Consult the documentation for
|
169
|
+
# the specific message for details on the semantics of the return value.
|
170
|
+
# WM_CHARTOITEM
|
171
|
+
# WM_COMPAREITEM
|
172
|
+
# WM_CTLCOLORBTN
|
173
|
+
# WM_CTLCOLORDLG
|
174
|
+
# WM_CTLCOLOREDIT
|
175
|
+
# WM_CTLCOLORLISTBOX
|
176
|
+
# WM_CTLCOLORSCROLLBAR
|
177
|
+
# WM_CTLCOLORSTATIC
|
178
|
+
# WM_INITDIALOG
|
179
|
+
# WM_QUERYDRAGICON
|
180
|
+
# WM_VKEYTOITEM
|
181
|
+
# ---
|
182
|
+
# *Remarks*:
|
183
|
+
# You should use the dialog box procedure only if you use the dialog box class for the dialog box. This
|
184
|
+
# is the default class and is used when no explicit class is specified in the dialog box template.
|
185
|
+
# Although the dialog box procedure is similar to a window procedure, it must not call the DefWindowProc
|
186
|
+
# function to process unwanted messages. Unwanted messages are processed internally by the dialog box
|
187
|
+
# window procedure.
|
188
|
+
# ---
|
189
|
+
# *See* *Also*:
|
190
|
+
# Dialog Boxes Overview, CreateDialog, CreateDialogIndirect, CreateDialogIndirectParam,
|
191
|
+
# CreateDialogParam, DefWindowProc, DialogBox, DialogBoxIndirect, DialogBoxIndirectParam,
|
192
|
+
# DialogBoxParam, SetFocus, WM_INITDIALOG
|
193
|
+
#
|
194
|
+
callback :DialogProc, [:HWND, :UINT, :WPARAM, :LPARAM], :int
|
195
|
+
|
23
196
|
##
|
24
197
|
# The GetDlgItem function retrieves a handle to a control in the specified dialog box.
|
25
198
|
#
|
@@ -36,12 +209,151 @@ module Win
|
|
36
209
|
# As long as the hDlg parameter specifies a parent window and the child window has a unique identifier
|
37
210
|
# (as specified by the hMenu parameter in the CreateWindow or CreateWindowEx function that created the
|
38
211
|
# child window), GetDlgItem returns a valid handle to the child window.
|
212
|
+
# ---
|
213
|
+
# <b>Enhanced (snake_case) API: returns nil if function fails</b>
|
214
|
+
#
|
215
|
+
# :call-seq:
|
216
|
+
# control_handle = [get_]dlg_item( dialog_handle, control_id )
|
217
|
+
#
|
218
|
+
function :GetDlgItem, [:ulong, :int], :ulong, zeronil: true
|
219
|
+
|
220
|
+
##
|
221
|
+
# MessageBox Function
|
222
|
+
# --------------------------------------------------------------------------------
|
223
|
+
# The MessageBox function creates, displays, and operates a message box. The message box contains an
|
224
|
+
# application-defined message and title, along with any combination of predefined icons and push
|
225
|
+
# buttons.
|
226
|
+
#
|
227
|
+
# [*Syntax*] int MessageBox( HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType );
|
228
|
+
#
|
229
|
+
# hWnd:: [in] Handle to the owner window of the message box to be created. If this parameter is NULL,
|
230
|
+
# the message box has no owner window.
|
231
|
+
# lpText:: [in] Pointer to a null-terminated string that contains the message to be displayed.
|
232
|
+
# lpCaption:: [in] Pointer to a null-terminated string that contains the dialog box title. If this
|
233
|
+
# parameter is NULL, the default title Error is used.
|
234
|
+
# uType:: [in] Specifies the contents and behavior of the dialog box. This parameter can be a
|
235
|
+
# combination of flags from the following groups of flags.
|
236
|
+
# To indicate the buttons displayed in the message box, specify one of the following values.
|
237
|
+
# MB_ABORTRETRYIGNORE, MB_CANCELTRYCONTINUE, MB_HELP, MB_OK, MB_OKCANCEL, MB_RETRYCANCEL
|
238
|
+
# MB_YESNO, MB_YESNOCANCEL
|
239
|
+
# To display an icon in the message box, specify one of the following values.
|
240
|
+
# MB_ICONEXCLAMATION, MB_ICONWARNING, MB_ICONINFORMATION, MB_ICONASTERISK, MB_ICONQUESTION
|
241
|
+
# MB_ICONSTOP, MB_ICONERROR, MB_ICONHAND
|
242
|
+
# To indicate the default button, specify one of the following values.
|
243
|
+
# MB_DEFBUTTON1, MB_DEFBUTTON2, MB_DEFBUTTON3, MB_DEFBUTTON4
|
244
|
+
# To indicate the modality of the dialog box, specify one of the following values.
|
245
|
+
# MB_APPLMODAL, MB_SYSTEMMODAL, MB_TASKMODAL
|
246
|
+
# To specify other options, use one or more of the following values.
|
247
|
+
# MB_DEFAULT_DESKTOP_ONLY, MB_RIGHT, MB_RTLREADING, MB_SETFOREGROUND, MB_TOPMOST
|
248
|
+
# MB_SERVICE_NOTIFICATION, MB_SERVICE_NOTIFICATION_NT3X
|
249
|
+
# For more information on the changes between Windows NT 3.51 and Windows NT 4.0, see Remarks.
|
250
|
+
#
|
251
|
+
# *Returns*:: If a message box has a Cancel button, the function returns the IDCANCEL value if either
|
252
|
+
# the ESC key is pressed or the Cancel button is selected. If the message box has no Cancel
|
253
|
+
# button, pressing ESC has no effect.
|
254
|
+
# If the function fails, the return value is zero. To get extended error information, call GetLastError.
|
255
|
+
# If the function succeeds, the return value is one of the following menu-item values.
|
256
|
+
# IDABORT:: Abort button was selected.
|
257
|
+
# IDCANCEL:: Cancel button was selected.
|
258
|
+
# IDCONTINUE:: Continue button was selected.
|
259
|
+
# IDIGNORE:: Ignore button was selected.
|
260
|
+
# IDNO:: No button was selected.
|
261
|
+
# IDOK:: OK button was selected.
|
262
|
+
# IDRETRY:: Retry button was selected.
|
263
|
+
# IDTRYAGAIN:: Try Again button was selected.
|
264
|
+
# IDYES:: Yes button was selected.
|
265
|
+
# ---
|
266
|
+
# *Remarks*:
|
267
|
+
# Adding two right-to-left marks (RLMs), represented by Unicode formatting character U+200F, in the
|
268
|
+
# beginning of a MessageBox display string is interpreted by the Win32 MessageBox rendering engine so as
|
269
|
+
# to cause the reading order of the MessageBox to be rendered as right-to-left (RTL).
|
270
|
+
# When you use a system-modal message box to indicate that the system is low on memory, the strings
|
271
|
+
# pointed to by the lpText and lpCaption parameters should not be taken from a resource file because an
|
272
|
+
# attempt to load the resource may fail.
|
273
|
+
# If you create a message box while a dialog box is present, use a handle to the dialog box as the hWnd
|
274
|
+
# parameter. The hWnd parameter should not identify a child window, such as a control in a dialog box.
|
275
|
+
# Windows 95/98/Me: The system can support a maximum of 16,364 window handles.
|
276
|
+
# Windows NT/2000/XP: The value of MB_SERVICE_NOTIFICATION changed starting with Windows NT 4.0. Windows
|
277
|
+
# NT 4.0 provides backward compatibility for preexisting services by mapping the old value to the new
|
278
|
+
# value in the implementation of MessageBox. This mapping is done only for executables that have a
|
279
|
+
# version number earlier than 4.0, as set by the linker.
|
280
|
+
# To build a service that uses MB_SERVICE_NOTIFICATION and can run on both Microsoft Windows NT 3.x and
|
281
|
+
# Windows NT 4.0, you can do one of the following.
|
282
|
+
# At link-time, specify a version number less than 4.0.
|
283
|
+
# At link-time, specify version 4.0. At run-time, use the GetVersionEx function to check the system
|
284
|
+
# version. Then, when running on Windows NT 3.x, use MB_SERVICE_NOTIFICATION_NT3X; and on Windows NT
|
285
|
+
# 4.0, use MB_SERVICE_NOTIFICATION.
|
286
|
+
# Windows 95/98/Me: Even though MessageBoxW exists, it is supported by the Microsoft Layer for Unicode
|
287
|
+
# on Windows 95/98/Me Systems to give more consistent behavior across all Windows operating systems.
|
288
|
+
# ---
|
289
|
+
# *See* *Also*:
|
290
|
+
# Dialog Boxes Overview, FlashWindow, MessageBeep, MessageBoxEx, MessageBoxIndirect, SetForegroundWindow
|
291
|
+
# ---
|
292
|
+
# <b>Enhanced (snake_case) API: accepts text and caption, uType is optional. Returns nil if function fails</b>
|
39
293
|
#
|
40
294
|
# :call-seq:
|
41
|
-
#
|
295
|
+
# selected_item = message_box(owner_handle, text, caption, type)
|
42
296
|
#
|
43
|
-
function :
|
297
|
+
function :MessageBox, [:HWND, :LPCTSTR, :LPCTSTR, :UINT], :int, zeronil: true,
|
298
|
+
&->(api, handle, text, caption, type=MB_OK) {
|
299
|
+
text_pointer = FFI::MemoryPointer.from_string(text)
|
300
|
+
caption_pointer = FFI::MemoryPointer.from_string(caption)
|
301
|
+
api.call handle, text_pointer, caption_pointer, type }
|
302
|
+
|
303
|
+
# Untested:
|
304
|
+
|
305
|
+
##
|
306
|
+
function :CreateDialogIndirectParam, ['L', 'P', 'L', :DialogProc, 'L'], 'L'
|
307
|
+
##
|
308
|
+
function :CreateDialogParam, ['L', 'P', 'L', :DialogProc, 'L'], 'L'
|
309
|
+
##
|
310
|
+
function :DialogBoxIndirectParam, ['L', 'P', 'L', :DialogProc, 'L'], 'P'
|
311
|
+
##
|
312
|
+
function :DialogBoxParam, ['L', 'P', 'L', :DialogProc, 'L'], 'P'
|
313
|
+
##
|
314
|
+
function :EndDialog, 'LP', 'B'
|
315
|
+
##
|
316
|
+
function :GetDialogBaseUnits, 'V', 'L'
|
317
|
+
##
|
318
|
+
function :GetDlgCtrlID, 'L', 'I'
|
319
|
+
##
|
320
|
+
function :GetDlgItemText, 'LIPI', 'I'
|
321
|
+
##
|
322
|
+
function :GetNextDlgGroupItem, 'LLI', 'L'
|
323
|
+
##
|
324
|
+
function :GetNextDlgTabItem, 'LLI', 'L'
|
325
|
+
##
|
326
|
+
function :IsDialogMessage, 'LP', 'B'
|
327
|
+
##
|
328
|
+
function :MapDialogRect, 'LP', 'B'
|
329
|
+
##
|
330
|
+
function :MessageBoxEx, 'LPPII', 'I'
|
331
|
+
##
|
332
|
+
function :MessageBoxIndirect, 'P', 'I'
|
333
|
+
##
|
334
|
+
function :SendDlgItemMessage, 'LIILL', 'L'
|
335
|
+
##
|
336
|
+
function :SetDlgItemInt, 'LIII', 'L'
|
337
|
+
##
|
338
|
+
function :SetDlgItemText, 'LIP', 'B'
|
339
|
+
|
340
|
+
# Macros from WinUser.h
|
341
|
+
|
342
|
+
def CreateDialog(hInstance, lpName, hParent, lpDialogFunc)
|
343
|
+
CreateDialogParam(hInstance, lpName, hParent, lpDialogFunc, 0)
|
344
|
+
end
|
345
|
+
|
346
|
+
def CreateDialogIndirect(hInst, lpTemp, hPar, lpDialFunc)
|
347
|
+
CreateDialogIndirectParam(hInst, lpTemp, hPar, lpDialFunc, 0)
|
348
|
+
end
|
349
|
+
|
350
|
+
def DialogBox(hInstance, lpTemp, hParent, lpDialogFunc)
|
351
|
+
DialogBoxParam(hInstance, lpTemp, hParent, lpDialogFunc, 0)
|
352
|
+
end
|
44
353
|
|
354
|
+
def DialogBoxIndirect(hInst, lpTemp, hParent, lpDialogFunc)
|
355
|
+
DialogBoxParamIndirect(hInst, lpTemp, hParent, lpDialogFunc, 0)
|
356
|
+
end
|
45
357
|
end
|
46
358
|
end
|
47
359
|
end
|
data/lib/win/gui/input.rb
CHANGED
@@ -73,6 +73,15 @@ module Win
|
|
73
73
|
# HELP key
|
74
74
|
VK_HELP = 0x2F
|
75
75
|
|
76
|
+
# US semicolon
|
77
|
+
VK_OEM_1 = 0xBA
|
78
|
+
# US backslash
|
79
|
+
VK_OEM_102 = 0xE2
|
80
|
+
# US period (point)
|
81
|
+
VK_OEM_PERIOD = 0xBE
|
82
|
+
# US comma
|
83
|
+
VK_OEM_COMMA = 0xBC
|
84
|
+
|
76
85
|
# Public Type MOUSEINPUT
|
77
86
|
# dx As Long
|
78
87
|
# dy As Long
|
data/lib/win/gui/message.rb
CHANGED
@@ -748,57 +748,42 @@ module Win
|
|
748
748
|
#
|
749
749
|
function :DispatchMessage, [:pointer], :long
|
750
750
|
|
751
|
+
# Untested:
|
752
|
+
|
751
753
|
##
|
752
754
|
function :BroadcastSystemMessage, 'LPIIL', 'L'
|
753
|
-
|
754
755
|
##
|
755
|
-
try_function :BroadcastSystemMessageEx, 'LPILLP', 'L' # Windows XP or later
|
756
|
-
|
756
|
+
try_function :BroadcastSystemMessageEx, 'LPILLP', 'L' # Windows XP or later only
|
757
757
|
##
|
758
758
|
function :DefWindowProc, 'LLLL', 'L'
|
759
|
-
|
760
759
|
##
|
761
760
|
function :GetInputState, 'V', 'B'
|
762
|
-
|
763
761
|
##
|
764
762
|
function :GetMessageExtraInfo, 'V', 'L'
|
765
|
-
|
766
763
|
##
|
767
764
|
function :GetMessagePos, 'V', 'L'
|
768
|
-
|
769
765
|
##
|
770
766
|
function :GetMessageTime, 'V', 'L'
|
771
|
-
|
772
767
|
##
|
773
768
|
function :GetQueueStatus, 'I', 'L'
|
774
|
-
|
775
769
|
##
|
776
770
|
function :InSendMessage, 'V', 'B'
|
777
|
-
|
778
771
|
##
|
779
772
|
function :InSendMessageEx, 'L', 'L'
|
780
|
-
|
781
773
|
##
|
782
774
|
function :PostQuitMessage, 'I', 'V'
|
783
|
-
|
784
775
|
##
|
785
776
|
function :PostThreadMessage, 'LILL', 'B'
|
786
|
-
|
787
777
|
##
|
788
778
|
function :RegisterWindowMessage, 'P', 'I'
|
789
|
-
|
790
779
|
##
|
791
780
|
function :ReplyMessage, 'L', 'B'
|
792
|
-
|
793
781
|
##
|
794
782
|
function :SendMessageTimeout, 'LILLIIP', 'L'
|
795
|
-
|
796
783
|
##
|
797
784
|
function :SendNotifyMessage, 'LILLIIP', 'L'
|
798
|
-
|
799
785
|
##
|
800
786
|
function :SetMessageExtraInfo, 'L', 'L'
|
801
|
-
|
802
787
|
##
|
803
788
|
function :WaitMessage, 'V', 'B'
|
804
789
|
end
|
data/lib/win/gui/window.rb
CHANGED
@@ -634,6 +634,62 @@ module Win
|
|
634
634
|
#
|
635
635
|
function :GetForegroundWindow, [], :HWND, zeronil: true
|
636
636
|
|
637
|
+
##
|
638
|
+
# SetForegroundWindow function puts the thread that created the specified window into the foreground
|
639
|
+
# and activates the window. Keyboard input is directed to the window, and various visual cues are
|
640
|
+
# changed for the user. The system assigns a slightly higher priority to the thread that created the
|
641
|
+
# foreground window than it does to other threads.
|
642
|
+
#
|
643
|
+
# [*Syntax*] BOOL SetForegroundWindow( HWND hWnd );
|
644
|
+
#
|
645
|
+
# hWnd:: [in] Handle to the window that should be activated and brought to the foreground.
|
646
|
+
#
|
647
|
+
# *Returns*:: If the window was brought to the foreground, the return value is nonzero.
|
648
|
+
# If the window was not brought to the foreground, the return value is zero.
|
649
|
+
# ---
|
650
|
+
# *Remarks*:
|
651
|
+
# Windows 98/Me: The system restricts which processes can set the foreground window. A process can set
|
652
|
+
# the foreground window only if one of the following conditions is true:
|
653
|
+
# - The process is the foreground process.
|
654
|
+
# - The process was started by the foreground process.
|
655
|
+
# - The process received the last input event.
|
656
|
+
# - There is no foreground process.
|
657
|
+
# - The foreground process is being debugged.
|
658
|
+
# - The foreground is not locked (see LockSetForegroundWindow).
|
659
|
+
# - The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
|
660
|
+
# - Windows 2000/XP: No menus are active.
|
661
|
+
#
|
662
|
+
# With this change, an application cannot force a window to the foreground while the user is working
|
663
|
+
# with another window. Instead, Foreground and Background Windows will activate the window (see
|
664
|
+
# SetActiveWindow) and call the function to notify the user. However, on Microsoft Windows 98 and
|
665
|
+
# Windows Millennium Edition (Windows Me), if a nonforeground thread calls SetForegroundWindow and
|
666
|
+
# passes the handle of a window that was not created by the calling thread, the window is not flashed on
|
667
|
+
# the taskbar. To have SetForegroundWindow behave the same as it did on Windows 95 and Microsoft Windows
|
668
|
+
# NT 4.0, change the foreground lock timeout value when the application is installed. This can be done
|
669
|
+
# from the setup or installation application with the following function call:
|
670
|
+
# SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0, SPIF_SENDWININICHANGE |
|
671
|
+
# SPIF_UPDATEINIFILE);
|
672
|
+
# This method allows SetForegroundWindow on Windows 98/Windows Me and Windows 2000/Windows XP to behave
|
673
|
+
# the same as Windows 95 and Windows NT 4.0, respectively, for all applications. The setup application
|
674
|
+
# should warn the user that this is being done so that the user isn't surprised by the changed behavior.
|
675
|
+
# On Windows Windows 2000 and Windows XP, the call fails unless the calling thread can change the
|
676
|
+
# foreground window, so this must be called from a setup or patch application. For more information, see
|
677
|
+
# Foreground and Background Windows.
|
678
|
+
# A process that can set the foreground window can enable another process to set the foreground window
|
679
|
+
# by calling the AllowSetForegroundWindow function. The process specified by dwProcessId loses the
|
680
|
+
# ability to set the foreground window the next time the user generates input, unless the input is
|
681
|
+
# directed at that process, or the next time a process calls AllowSetForegroundWindow, unless that
|
682
|
+
# process is specified.
|
683
|
+
# The foreground process can disable calls to SetForegroundWindow by calling the LockSetForegroundWindow function.
|
684
|
+
#
|
685
|
+
# ---
|
686
|
+
# <b>Enhanced (snake_case) API: returns true/false</b>
|
687
|
+
#
|
688
|
+
# :call-seq:
|
689
|
+
# success = set_foreground_window(h_wnd)
|
690
|
+
#
|
691
|
+
function :SetForegroundWindow, [:HWND], :int8, boolean: true
|
692
|
+
|
637
693
|
##
|
638
694
|
# The GetActiveWindow function retrieves the window handle to the active window attached to
|
639
695
|
# the calling thread's message queue.
|
data/lib/win/library.rb
CHANGED
@@ -0,0 +1,73 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper" )
|
2
|
+
require 'extension'
|
3
|
+
|
4
|
+
module WinTest
|
5
|
+
|
6
|
+
describe String do
|
7
|
+
describe '#snake_case' do
|
8
|
+
it 'transforms CamelCase strings' do
|
9
|
+
'GetCharWidth32'.snake_case.should == 'get_char_width_32'
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'leaves snake_case strings intact' do
|
13
|
+
'keybd_event'.snake_case.should == 'keybd_event'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#camel_case' do
|
18
|
+
it 'transforms snake_case strings' do
|
19
|
+
'get_char_width_32'.camel_case.should == 'GetCharWidth32'
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'leaves CamelCase strings intact' do
|
23
|
+
'GetCharWidth32'.camel_case.should == 'GetCharWidth32'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#to_w' do
|
28
|
+
it 'transcodes string to utf-16LE' do
|
29
|
+
'GetCharWidth32'.to_w.encoding.name.should == 'UTF-16LE'
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'ensures that encoded string is null-terminated' do
|
33
|
+
'GetCharWidth32'.to_w.bytes.to_a[-2..-1].should == [0, 0]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# context '#to_vkeys' do
|
38
|
+
# it 'transforms number char into [equivalent key code]' do
|
39
|
+
# ('0'..'9').each {|char| char.to_vkeys.should == char.unpack('C')}
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# it 'transforms uppercase letters into [shift, equivalent key code]' do
|
43
|
+
# ('A'..'Z').each {|char| char.to_vkeys.should == [0x10, *char.unpack('C')]}
|
44
|
+
# # Win.const_get(:VK_SHIFT) = 0x10 Bad coupling
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# it 'transforms lowercase letters into [(upcase) key code]' do
|
48
|
+
# ('a'..'z').each {|char| char.to_vkeys.should == char.upcase.unpack('C')}
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# it 'transforms space into [equivalent key code]' do
|
52
|
+
# " ".to_vkeys.should == " ".unpack('C')
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# it 'raises error if char is not implemented punctuation' do
|
56
|
+
# ('!'..'/').each {|char| lambda {char.to_vkeys}.should raise_error CONVERSION_ERROR }
|
57
|
+
# (':'..'@').each {|char| lambda {char.to_vkeys}.should raise_error CONVERSION_ERROR }
|
58
|
+
# ('['..'`').each {|char| lambda {char.to_vkeys}.should raise_error CONVERSION_ERROR }
|
59
|
+
# ('{'..'~').each {|char| lambda {char.to_vkeys}.should raise_error CONVERSION_ERROR }
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# it 'raises error if char is non-printable or non-ascii' do
|
63
|
+
# lambda {1.chr.to_vkeys}.should raise_error CONVERSION_ERROR
|
64
|
+
# lambda {230.chr.to_vkeys}.should raise_error CONVERSION_ERROR
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# it 'raises error if string is multi-char' do
|
68
|
+
# lambda {'hello'.to_vkeys}.should raise_error CONVERSION_ERROR
|
69
|
+
# lambda {'23'.to_vkeys}.should raise_error CONVERSION_ERROR
|
70
|
+
# end
|
71
|
+
# end
|
72
|
+
end
|
73
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -120,10 +120,11 @@ module WinTestApp
|
|
120
120
|
@launched_test_app = app
|
121
121
|
end
|
122
122
|
|
123
|
-
def close_test_app
|
124
|
-
while
|
125
|
-
shut_window
|
123
|
+
def close_test_app
|
124
|
+
while @launched_test_app && find_window(nil, WIN_TITLE)
|
125
|
+
shut_window @launched_test_app.handle
|
126
126
|
sleep SLEEP_DELAY
|
127
|
+
keystroke('N') if find_window(nil, "Steganos Locknote") # Dealing with closing modal dialog
|
127
128
|
end
|
128
129
|
@launched_test_app = nil
|
129
130
|
end
|
@@ -131,12 +132,21 @@ module WinTestApp
|
|
131
132
|
# Creates test app object and yields it back to the block
|
132
133
|
def test_app
|
133
134
|
app = launch_test_app
|
134
|
-
|
135
|
-
# def app.textarea #define singleton method retrieving app's text area
|
136
|
-
# Window::Window.new find_window_ex(self.handle, 0, TEXTAREA_CLASS, nil)
|
137
|
-
# end
|
138
|
-
|
139
135
|
yield app
|
140
|
-
close_test_app
|
136
|
+
close_test_app
|
137
|
+
end
|
138
|
+
|
139
|
+
# Emulates combinations of (any amount of) keys pressed one after another (Ctrl+Alt+P) and then released
|
140
|
+
# *keys should be a sequence of a virtual-key codes. These codes must be a value in the range 1 to 254.
|
141
|
+
# For a complete list, see msdn:Virtual Key Codes.
|
142
|
+
# If alphanumerical char is given instead of virtual key code, only lowercase letters result (no VK_SHIFT!).
|
143
|
+
def keystroke(*keys)
|
144
|
+
return if keys.empty?
|
145
|
+
key = String === keys.first ? keys.first.upcase.ord : keys.first.to_i
|
146
|
+
keybd_event key, 0, KEYEVENTF_KEYDOWN, 0
|
147
|
+
sleep KEY_DELAY
|
148
|
+
keystroke *keys[1..-1]
|
149
|
+
sleep KEY_DELAY
|
150
|
+
keybd_event key, 0, KEYEVENTF_KEYUP, 0
|
141
151
|
end
|
142
152
|
end
|
data/spec/win/gui/dialog_spec.rb
CHANGED
@@ -1,18 +1,62 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
2
|
require 'win/gui/input'
|
3
|
-
#require 'win/gui/window'
|
4
3
|
|
5
|
-
module
|
4
|
+
module WinGuiDialogTest
|
6
5
|
|
7
6
|
include WinTestApp
|
8
7
|
include Win::Gui::Dialog
|
9
8
|
|
9
|
+
def test_app_with_dialog(type=:close)
|
10
|
+
test_app do |app|
|
11
|
+
case type
|
12
|
+
when :close
|
13
|
+
keystroke('A')
|
14
|
+
shut_window app.handle
|
15
|
+
sleep 0.01 until dialog = find_window(nil, "Steganos Locknote")
|
16
|
+
when :save
|
17
|
+
keystroke(VK_ALT, 'F', 'A')
|
18
|
+
sleep 0.01 until dialog = find_window(nil, "Save As")
|
19
|
+
end
|
20
|
+
yield app, dialog
|
21
|
+
keystroke(VK_ESCAPE)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
10
25
|
describe Win::Gui::Dialog do
|
11
26
|
|
27
|
+
describe "#message_box" do
|
28
|
+
spec{ pending; use{ selected_item = message_box(owner_handle=0, text="Text", caption="Caption", type=0) }}
|
29
|
+
|
30
|
+
it "creates, displays, and operates a message box" do
|
31
|
+
pending 'Not possible to test message_box directly, it blocks all related threads :('
|
32
|
+
t = Thread.new do
|
33
|
+
selected_item = message_box(handle=0, text="Text", caption="Caption", type=MB_YESNO | MB_HELP)
|
34
|
+
puts selected_item
|
35
|
+
end
|
36
|
+
t.join
|
37
|
+
end
|
38
|
+
end # describe message_box
|
39
|
+
|
40
|
+
|
12
41
|
describe '#get_dlg_item' do
|
13
42
|
spec{ use{ control_handle = get_dlg_item(handle = 0, item_id = 1) }}
|
14
43
|
|
15
|
-
it 'returns handle to
|
44
|
+
it 'returns handle to an existing controls in a dialog' do
|
45
|
+
test_app_with_dialog(:close) do |app, dialog|
|
46
|
+
get_dlg_item(dialog, item_id=IDYES).should_not == nil
|
47
|
+
get_dlg_item(dialog, item_id=IDNO).should_not == nil
|
48
|
+
get_dlg_item(dialog, item_id=IDCANCEL).should_not == nil
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'returns nil/0 for non-existing controls in a dialog' do
|
53
|
+
test_app_with_dialog(:close) do |app, dialog|
|
54
|
+
get_dlg_item(dialog, item_id=IDOK).should == nil
|
55
|
+
get_dlg_item(dialog, item_id=IDABORT).should == nil
|
56
|
+
GetDlgItem(dialog, item_id=IDRETRY).should == 0
|
57
|
+
GetDlgItem(dialog, item_id=IDCONTINUE).should == 0
|
58
|
+
end
|
59
|
+
end
|
16
60
|
|
17
61
|
end
|
18
62
|
end
|
data/spec/win/gui/input_spec.rb
CHANGED
data/spec/win/gui/window_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
2
|
require 'win/gui/window'
|
3
3
|
|
4
|
-
module
|
4
|
+
module WinGuiWindowTest
|
5
5
|
|
6
6
|
include WinTestApp
|
7
7
|
include Win::Gui::Window
|
@@ -192,6 +192,25 @@ module WinWindowTest
|
|
192
192
|
end
|
193
193
|
end
|
194
194
|
|
195
|
+
describe "#set_foreground_window" do
|
196
|
+
spec{ use{ success = SetForegroundWindow(handle=0) }}
|
197
|
+
spec{ use{ success = set_foreground_window(handle=0) }}
|
198
|
+
|
199
|
+
it "puts the thread that created the specified window into the foreground and activates the window" do
|
200
|
+
test_app do |app|
|
201
|
+
set_foreground_window(any_handle).should be_true
|
202
|
+
foreground?(app.handle).should be_false
|
203
|
+
success = set_foreground_window(app.handle)
|
204
|
+
foreground?(app.handle).should be_true
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
it "returns false/0 if operation failed" do
|
209
|
+
set_foreground_window(not_a_handle).should == false
|
210
|
+
SetForegroundWindow(not_a_handle).should == 0
|
211
|
+
end
|
212
|
+
end # describe set_foreground_window
|
213
|
+
|
195
214
|
describe '#get_foreground_window' do
|
196
215
|
# ! Different from GetActiveWindow !
|
197
216
|
spec{ use{ handle = GetForegroundWindow() }}
|
@@ -201,10 +220,10 @@ module WinWindowTest
|
|
201
220
|
it 'returns handle to window that is currently in foreground' do
|
202
221
|
test_app do |app|
|
203
222
|
@app_handle = app.handle
|
204
|
-
fg1 =
|
223
|
+
fg1 = get_foreground_window
|
205
224
|
@app_handle.should == fg1
|
206
225
|
end
|
207
|
-
fg2 =
|
226
|
+
fg2 = get_foreground_window
|
208
227
|
@app_handle.should_not == fg2
|
209
228
|
end
|
210
229
|
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 3
|
8
|
-
-
|
9
|
-
version: 0.3.
|
8
|
+
- 7
|
9
|
+
version: 0.3.7
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- arvicco
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-06-02 00:00:00 +04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -68,22 +68,22 @@ extra_rdoc_files:
|
|
68
68
|
- HISTORY
|
69
69
|
- README.rdoc
|
70
70
|
files:
|
71
|
+
- lib/extension.rb
|
71
72
|
- lib/version.rb
|
72
73
|
- lib/win/dde.rb
|
73
74
|
- lib/win/error.rb
|
74
|
-
- lib/win/extensions.rb
|
75
75
|
- lib/win/gui/dialog.rb
|
76
76
|
- lib/win/gui/input.rb
|
77
77
|
- lib/win/gui/message.rb
|
78
78
|
- lib/win/gui/window.rb
|
79
79
|
- lib/win/gui.rb
|
80
80
|
- lib/win/library.rb
|
81
|
+
- spec/extension_spec.rb
|
81
82
|
- spec/spec.opts
|
82
83
|
- spec/spec_helper.rb
|
83
84
|
- spec/test_apps/locknote/LockNote.exe
|
84
85
|
- spec/win/dde_spec.rb
|
85
86
|
- spec/win/error_spec.rb
|
86
|
-
- spec/win/extensions_spec.rb
|
87
87
|
- spec/win/gui/dialog_spec.rb
|
88
88
|
- spec/win/gui/input_spec.rb
|
89
89
|
- spec/win/gui/message_spec.rb
|
@@ -140,12 +140,12 @@ signing_key:
|
|
140
140
|
specification_version: 3
|
141
141
|
summary: Rubyesque interfaces and wrappers for Windows API functions pre-defined using FFI
|
142
142
|
test_files:
|
143
|
+
- spec/extension_spec.rb
|
143
144
|
- spec/spec.opts
|
144
145
|
- spec/spec_helper.rb
|
145
146
|
- spec/test_apps/locknote/LockNote.exe
|
146
147
|
- spec/win/dde_spec.rb
|
147
148
|
- spec/win/error_spec.rb
|
148
|
-
- spec/win/extensions_spec.rb
|
149
149
|
- spec/win/gui/dialog_spec.rb
|
150
150
|
- spec/win/gui/input_spec.rb
|
151
151
|
- spec/win/gui/message_spec.rb
|
data/lib/win/extensions.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
class String
|
2
|
-
# returns snake_case representation of string
|
3
|
-
def snake_case
|
4
|
-
gsub(/([a-z])([A-Z0-9])/, '\1_\2' ).downcase
|
5
|
-
end
|
6
|
-
|
7
|
-
# returns camel_case representation of string
|
8
|
-
def camel_case
|
9
|
-
if self.include? '_'
|
10
|
-
self.split('_').map{|e| e.capitalize}.join
|
11
|
-
else
|
12
|
-
unless self =~ (/^[A-Z]/)
|
13
|
-
self.capitalize
|
14
|
-
else
|
15
|
-
self
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
# converts string to 'wide char' (Windows Unicode) format
|
21
|
-
def to_w
|
22
|
-
(self+"\x00").encode('utf-16LE')
|
23
|
-
end
|
24
|
-
|
25
|
-
# converts one-char string into keyboard-scan 'Virtual key' code
|
26
|
-
# only letters and numbers convertable so far, need to be extended
|
27
|
-
def to_vkeys
|
28
|
-
unless size == 1
|
29
|
-
raise "Can't convert but a single character: #{self}"
|
30
|
-
end
|
31
|
-
ascii = upcase.unpack('C')[0]
|
32
|
-
case self
|
33
|
-
when 'a'..'z', '0'..'9', ' '
|
34
|
-
[ascii]
|
35
|
-
when 'A'..'Z'
|
36
|
-
[0x10, ascii] # Win.const_get(:VK_SHIFT) = 0x10 Bad coupling
|
37
|
-
else
|
38
|
-
raise "Can't convert unknown character: #{self}"
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
data/spec/win/extensions_spec.rb
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), ".." , "spec_helper" )
|
2
|
-
require 'win/extensions'
|
3
|
-
|
4
|
-
module WinTest
|
5
|
-
|
6
|
-
describe String do
|
7
|
-
context '#snake_case' do
|
8
|
-
it 'transforms CamelCase strings' do
|
9
|
-
'GetCharWidth32'.snake_case.should == 'get_char_width_32'
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'leaves snake_case strings intact' do
|
13
|
-
'keybd_event'.snake_case.should == 'keybd_event'
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
context '#camel_case' do
|
18
|
-
it 'transforms snake_case strings' do
|
19
|
-
'get_char_width_32'.camel_case.should == 'GetCharWidth32'
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'leaves CamelCase strings intact' do
|
23
|
-
'GetCharWidth32'.camel_case.should == 'GetCharWidth32'
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
context '#to_w' do
|
28
|
-
it 'transcodes string to utf-16LE' do
|
29
|
-
'GetCharWidth32'.to_w.encoding.name.should == 'UTF-16LE'
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'ensures that encoded string is null-terminated' do
|
33
|
-
'GetCharWidth32'.to_w.bytes.to_a[-2..-1].should == [0, 0]
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
context '#to_vkeys' do
|
38
|
-
it 'transforms number char into [equivalent key code]' do
|
39
|
-
('0'..'9').each {|char| char.to_vkeys.should == char.unpack('C')}
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'transforms uppercase letters into [shift, equivalent key code]' do
|
43
|
-
('A'..'Z').each {|char| char.to_vkeys.should == [0x10, *char.unpack('C')]}
|
44
|
-
# Win.const_get(:VK_SHIFT) = 0x10 Bad coupling
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'transforms lowercase letters into [(upcase) key code]' do
|
48
|
-
('a'..'z').each {|char| char.to_vkeys.should == char.upcase.unpack('C')}
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'transforms space into [equivalent key code]' do
|
52
|
-
" ".to_vkeys.should == " ".unpack('C')
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'raises error if char is not implemented punctuation' do
|
56
|
-
('!'..'/').each {|char| lambda {char.to_vkeys}.should raise_error CONVERSION_ERROR }
|
57
|
-
(':'..'@').each {|char| lambda {char.to_vkeys}.should raise_error CONVERSION_ERROR }
|
58
|
-
('['..'`').each {|char| lambda {char.to_vkeys}.should raise_error CONVERSION_ERROR }
|
59
|
-
('{'..'~').each {|char| lambda {char.to_vkeys}.should raise_error CONVERSION_ERROR }
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'raises error if char is non-printable or non-ascii' do
|
63
|
-
lambda {1.chr.to_vkeys}.should raise_error CONVERSION_ERROR
|
64
|
-
lambda {230.chr.to_vkeys}.should raise_error CONVERSION_ERROR
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'raises error if string is multi-char' do
|
68
|
-
lambda {'hello'.to_vkeys}.should raise_error CONVERSION_ERROR
|
69
|
-
lambda {'23'.to_vkeys}.should raise_error CONVERSION_ERROR
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|