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 CHANGED
@@ -18,3 +18,7 @@
18
18
  == 0.3.6 / 2010-05-31
19
19
 
20
20
  * Complex convenience methods (dialog
21
+
22
+ == 0.3.7 / 2010-06-01
23
+
24
+ * SetForegroudWindow added
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.6
1
+ 0.3.7
@@ -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
@@ -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
- # control_handle = [get_]dlg_item( dialog_handle, id )
295
+ # selected_item = message_box(owner_handle, text, caption, type)
42
296
  #
43
- function :GetDlgItem, [:ulong, :int], :ulong
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
@@ -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
@@ -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
@@ -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.
@@ -1,5 +1,5 @@
1
1
  require 'ffi'
2
- require 'win/extensions'
2
+ require 'extension'
3
3
 
4
4
  # Related Windows API functions are grouped by topic and defined in separate namespaces (modules),
5
5
  # that also contain related constants and convenience methods. For example, Win::Dde module
@@ -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
@@ -120,10 +120,11 @@ module WinTestApp
120
120
  @launched_test_app = app
121
121
  end
122
122
 
123
- def close_test_app(app = @launched_test_app)
124
- while app && app.respond_to?( :handle) && find_window(nil, WIN_TITLE)
125
- shut_window app.handle
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 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
@@ -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 WinWindowTest
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 correctly specified control'
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
@@ -1,8 +1,7 @@
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 WinWindowTest
4
+ module WinGuiInputTest
6
5
 
7
6
  include WinTestApp
8
7
  include Win::Gui::Input
@@ -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 WinWindowTest
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 = foreground_window
223
+ fg1 = get_foreground_window
205
224
  @app_handle.should == fg1
206
225
  end
207
- fg2 = foreground_window
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
- - 6
9
- version: 0.3.6
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-05-31 00:00:00 +04:00
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
@@ -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
@@ -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