win 0.1.27 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,41 +1,41 @@
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
+ 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/lib/win/gui.rb CHANGED
@@ -1,16 +1,16 @@
1
- require 'win/gui/window'
2
- require 'win/gui/input'
3
- require 'win/gui/message'
4
- require 'win/gui/dialog'
5
-
6
- module Win
7
-
8
- # Contains several modules defining Win32 API functions and constants related to Windows GUI (Graphical User Interface)
9
- #
10
- module GUI
11
- include Win::GUI::Window
12
- include Win::GUI::Input
13
- include Win::GUI::Message
14
- include Win::GUI::Dialog
15
- end
16
- end
1
+ require 'win/gui/window'
2
+ require 'win/gui/input'
3
+ require 'win/gui/message'
4
+ require 'win/gui/dialog'
5
+
6
+ module Win
7
+
8
+ # Contains several modules defining Win32 API functions and constants related to Windows GUI (Graphical User Interface)
9
+ #
10
+ module Gui
11
+ include Win::Gui::Window
12
+ include Win::Gui::Input
13
+ include Win::Gui::Message
14
+ include Win::Gui::Dialog
15
+ end
16
+ end
@@ -1,50 +1,50 @@
1
- require 'win/library'
2
- require 'win/gui/window'
3
-
4
- module Win
5
- module GUI
6
- # Contains constants and Win32API functions related to dialog manipulation
7
- #
8
- module Dialog
9
- include Win::Library
10
- include Win::GUI::Window
11
-
12
- ##
13
- # The GetDlgItem function retrieves a handle to a control in the specified dialog box.
14
- #
15
- # [*Syntax*] HWND GetDlgItem( HWND hDlg, int nIDDlgItem );
16
- #
17
- # hDlg:: [in] Handle to the dialog box that contains the control.
18
- # nIDDlgItem:: [in] Specifies the identifier of the control to be retrieved.
19
- # *Returns*:: If the function succeeds, the return value is the window handle of the specified control.
20
- # If the function fails, the return value is NULL, indicating an invalid dialog box handle
21
- # or a nonexistent control. To get extended error information, call GetLastError.
22
- # ---
23
- # *Remarks*:
24
- # You can use the GetDlgItem function with any parent-child window pair, not just with dialog boxes.
25
- # As long as the hDlg parameter specifies a parent window and the child window has a unique identifier
26
- # (as specified by the hMenu parameter in the CreateWindow or CreateWindowEx function that created the
27
- # child window), GetDlgItem returns a valid handle to the child window.
28
- #
29
- # :call-seq:
30
- # control_handle = [get_]dlg_item( dialog_handle, id )
31
- #
32
- function :GetDlgItem, [:ulong, :int], :ulong
33
-
34
- # Convenience methods:
35
-
36
- # finds top-level dialog window by title and yields found dialog window to block if given
37
- # def dialog(title, seconds=3)
38
- # d = begin
39
- # win = Window::Window.top_level(title, seconds)
40
- # yield(win) ? win : nil
41
- # rescue TimeoutError
42
- # end
43
- # d.wait_for_close if d
44
- # return d
45
- # end
46
- end
47
- end
48
- end
49
-
50
-
1
+ require 'win/library'
2
+ require 'win/gui/window'
3
+
4
+ module Win
5
+ module Gui
6
+ # Contains constants and Win32API functions related to dialog manipulation
7
+ #
8
+ module Dialog
9
+ include Win::Library
10
+ include Win::Gui::Window
11
+
12
+ ##
13
+ # The GetDlgItem function retrieves a handle to a control in the specified dialog box.
14
+ #
15
+ # [*Syntax*] HWND GetDlgItem( HWND hDlg, int nIDDlgItem );
16
+ #
17
+ # hDlg:: [in] Handle to the dialog box that contains the control.
18
+ # nIDDlgItem:: [in] Specifies the identifier of the control to be retrieved.
19
+ # *Returns*:: If the function succeeds, the return value is the window handle of the specified control.
20
+ # If the function fails, the return value is NULL, indicating an invalid dialog box handle
21
+ # or a nonexistent control. To get extended error information, call GetLastError.
22
+ # ---
23
+ # *Remarks*:
24
+ # You can use the GetDlgItem function with any parent-child window pair, not just with dialog boxes.
25
+ # As long as the hDlg parameter specifies a parent window and the child window has a unique identifier
26
+ # (as specified by the hMenu parameter in the CreateWindow or CreateWindowEx function that created the
27
+ # child window), GetDlgItem returns a valid handle to the child window.
28
+ #
29
+ # :call-seq:
30
+ # control_handle = [get_]dlg_item( dialog_handle, id )
31
+ #
32
+ function :GetDlgItem, [:ulong, :int], :ulong
33
+
34
+ # Convenience methods:
35
+
36
+ # finds top-level dialog window by title and yields found dialog window to block if given
37
+ # def dialog(title, seconds=3)
38
+ # d = begin
39
+ # win = Window::Window.top_level(title, seconds)
40
+ # yield(win) ? win : nil
41
+ # rescue TimeoutError
42
+ # end
43
+ # d.wait_for_close if d
44
+ # return d
45
+ # end
46
+ end
47
+ end
48
+ end
49
+
50
+
data/lib/win/gui/input.rb CHANGED
@@ -1,320 +1,320 @@
1
- require 'win/library'
2
-
3
- module Win
4
- module GUI
5
- # Contains constants and Win32API functions related to end user input
6
- #
7
- module Input
8
- include Win::Library
9
-
10
- # Internal constants:
11
-
12
- # Key event delay
13
- KEY_DELAY = 0.00001
14
-
15
- # Windows keyboard-related Constants:
16
-
17
- # Key down keyboard event (the key is being depressed)
18
- KEYEVENTF_KEYDOWN = 0
19
- # Key up keyboard event (the key is being released)
20
- KEYEVENTF_KEYUP = 2
21
- # Extended kb event. If specified, the scan code was preceded by a prefix byte having the value 0xE0 (224).
22
- KEYEVENTF_EXTENDEDKEY = 1
23
-
24
- # Virtual key codes:
25
-
26
- # Control-break processing
27
- VK_CANCEL = 0x03
28
- # Backspace? key
29
- VK_BACK = 0x08
30
- # Tab key
31
- VK_TAB = 0x09
32
- # Shift key
33
- VK_SHIFT = 0x10
34
- # Ctrl key
35
- VK_CONTROL = 0x11
36
- # ENTER key
37
- VK_RETURN = 0x0D
38
- # ALT key
39
- VK_ALT = 0x12
40
- # ALT key alias
41
- VK_MENU = 0x12
42
- # PAUSE key
43
- VK_PAUSE = 0x13
44
- # CAPS LOCK key
45
- VK_CAPITAL = 0x14
46
- # ESC key
47
- VK_ESCAPE = 0x1B
48
- # SPACEBAR
49
- VK_SPACE = 0x20
50
- # PAGE UP key
51
- VK_PRIOR = 0x21
52
- # PAGE DOWN key
53
- VK_NEXT = 0x22
54
- # END key
55
- VK_END = 0x23
56
- # HOME key
57
- VK_HOME = 0x24
58
- # LEFT ARROW key
59
- VK_LEFT = 0x25
60
- # UP ARROW key
61
- VK_UP = 0x26
62
- # RIGHT ARROW key
63
- VK_RIGHT = 0x27
64
- # DOWN ARROW key
65
- VK_DOWN = 0x28
66
- # SELECT key
67
- VK_SELECT = 0x29
68
- # PRINT key
69
- VK_PRINT = 0x2A
70
- # EXECUTE key
71
- VK_EXECUTE = 0x2B
72
- # PRINT SCREEN key
73
- VK_SNAPSHOT = 0x2C
74
- # INS key
75
- VK_INSERT = 0x2D
76
- # DEL key
77
- VK_DELETE = 0x2E
78
- # HELP key
79
- VK_HELP = 0x2F
80
-
81
- # Public Type MOUSEINPUT
82
- # dx As Long
83
- # dy As Long
84
- # mouseData As Long
85
- # dwFlags As Long
86
- # time As Long
87
- # dwExtraInfo As Long
88
- # End Type
89
- #
90
- # Public Type INPUT_TYPE
91
- # dwType As Long
92
- # xi(0 To 23) As Byte
93
- # End Type
94
-
95
- # dwFlags:
96
- # Specifies that the dx and dy parameters contain normalized absolute coordinates. If not set, those parameters
97
- # contain relative data: the change in position since the last reported position. This flag can be set, or not
98
- # set, regardless of what kind of mouse or mouse-like device, if any, is connected to the system. For further
99
- # information about relative mouse motion, see mouse_event Remarks section.
100
- MOUSEEVENTF_ABSOLUTE = 0x8000
101
- #Specifies that movement occurred.
102
- MOUSEEVENTF_MOVE = 0x01
103
- #Specifies that the left button is down.
104
- MOUSEEVENTF_LEFTDOWN = 0x02
105
- #Specifies that the left button is up.
106
- MOUSEEVENTF_LEFTUP = 0x04
107
- #Specifies that the right button is down.
108
- MOUSEEVENTF_RIGHTDOWN = 0x08
109
- #Specifies that the right button is up.
110
- MOUSEEVENTF_RIGHTUP = 0x010
111
- #Specifies that the middle button is down.
112
- MOUSEEVENTF_MIDDLEDOWN = 0x20
113
- #Specifies that the middle button is up.
114
- MOUSEEVENTF_MIDDLEUP = 0x040
115
- #Windows NT/2000/XP: Specifies that the wheel has been moved, if the mouse has a wheel. The amount of movement
116
- #is specified in dwData
117
- MOUSEEVENTF_WHEEL = 0x80
118
- #Windows 2000/XP: Specifies that an X button was pressed.
119
- MOUSEEVENTF_XDOWN = 0x100
120
- #Windows 2000/XP: Specifies that an X button was released.
121
- MOUSEEVENTF_XUP = 0x200
122
-
123
- # dwData:
124
- # One wheel click is defined as WHEEL_DELTA, which is 120.
125
- WHEEL_DELTA = 120
126
- # Set if the first X button was pressed or released.
127
- XBUTTON1 = 1
128
- # Set if the second X button was pressed or released.
129
- XBUTTON2 = 2
130
- # Indicates NO data if dwFlags are NOT any of MOUSEEVENTF_WHEEL, MOUSEEVENTF_XDOWN, or MOUSEEVENTF_XUP
131
- INPUT_MOUSE = 0
132
-
133
-
134
- ##
135
- # The keybd_event function synthesizes a keystroke. The system can use such a synthesized keystroke to generate
136
- # a WM_KEYUP or WM_KEYDOWN message. The keyboard driver's interrupt handler calls the keybd_event function.
137
- #
138
- # <b> !! Windows NT/2000/XP/Vista:This function has been superseded. Use SendInput instead. </b>
139
- #
140
- # [*Syntax*] VOID keybd_event( BYTE bVk, BYTE bScan, DWORD dwFlags, PTR dwExtraInfo);
141
- #
142
- # bVk:: [in] Specifies a virtual-key code. The code must be a value in the range 1 to 254.
143
- # For a complete list, see Virtual-Key Codes.
144
- # bScan:: [in] Specifies a hardware scan code for the key.
145
- # dwFlags:: [in] Specifies various aspects of function operation. This parameter can be
146
- # one or more of the following values:
147
- # KEYEVENTF_EXTENDEDKEY, KEYEVENTF_KEYUP, KEYEVENTF_KEYDOWN
148
- # dwExtraInfo:: [in] Specifies an additional value associated with the key stroke.
149
- #
150
- # <b>NO Return Value</b>
151
- # ---
152
- # *Remarks*:
153
- # - An application can simulate a press of the PRINTSCRN key in order to obtain a screen snapshot
154
- # and save it to the clipboard. To do this, call keybd_event with the bVk parameter set to VK_SNAPSHOT.
155
- #
156
- # - Windows NT/2000/XP: The keybd_event function can toggle the NUM LOCK, CAPS LOCK, and SCROLL LOCK keys.
157
- # - Windows 95/98/Me: The keybd_event function can toggle only the CAPS LOCK and SCROLL LOCK keys.
158
- #
159
- # :call-seq:
160
- # keybd_event( virtual_key, scan_code, flags, extra_info )
161
- #
162
- function :keybd_event, [:char, :char, :ulong, :ulong], :void
163
-
164
- ##
165
- # The mouse_event function synthesizes mouse motion and button clicks.
166
- #
167
- # <b> !! Windows NT/2000/XP/Vista:This function has been superseded. Use SendInput instead. </b>
168
- #
169
- # [*Syntax*] VOID mouse_event( DWORD dwFlags, DWORD dx, DWORD dy, DWORD dwData, ULONG_PTR dwExtraInfo );
170
- #
171
- # dwFlags:: [in] Specifies various aspects of mouse motion and button clicking. This parameter can be certain
172
- # combinations of the following values. The values that specify mouse button status are set to indicate
173
- # changes in status, not ongoing conditions. For example, if the left mouse button is pressed and
174
- # held down, MOUSEEVENTF_LEFTDOWN is set when the left button is first pressed, but not for subsequent
175
- # motions. Similarly, MOUSEEVENTF_LEFTUP is set only when the button is first released. You cannot
176
- # specify both MOUSEEVENTF_WHEEL and either MOUSEEVENTF_XDOWN or MOUSEEVENTF_XUP simultaneously,
177
- # because they both require use of the dwData field:
178
- # MOUSEEVENTF_ABSOLUTE, MOUSEEVENTF_MOVE, MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_LEFTUP,
179
- # MOUSEEVENTF_RIGHTDOWN, MOUSEEVENTF_RIGHTUP, MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_MIDDLEUP,
180
- # MOUSEEVENTF_WHEEL, MOUSEEVENTF_XDOWN, MOUSEEVENTF_XUP
181
- # dx:: [in] Specifies the mouse's absolute position along the x-axis or its amount of motion since the
182
- # last mouse event was generated, depending on the setting of MOUSEEVENTF_ABSOLUTE. Absolute data is
183
- # specified as the mouse's actual x-coordinate; relative data is specified as the number of mickeys moved.
184
- # A mickey is the amount that a mouse has to move for it to report that it has moved.
185
- # dy:: [in] Specifies the mouse's absolute position along the y-axis or its amount of motion since the
186
- # last mouse event was generated, depending on the setting of MOUSEEVENTF_ABSOLUTE. Absolute data is
187
- # specified as the mouse's actual y-coordinate; relative data is specified as the number of mickeys moved.
188
- # dwData:: [in]
189
- # - If dwFlags contains MOUSEEVENTF_WHEEL, then data specifies the amount of wheel movement.
190
- # A positive value indicates that the wheel was rotated forward, away from the user; a negative value
191
- # indicates that the wheel was rotated backward, toward the user. One wheel click is defined as
192
- # WHEEL_DELTA, which is 120.
193
- # - If dwFlags contains MOUSEEVENTF_WHHEEL, then data specifies the amount of
194
- # wheel movement. A positive value indicates that the wheel was rotated to the right; a negative value
195
- # indicates that the wheel was rotated to the left. One wheel click is defined as WHEEL_DELTA (= 120).
196
- # - Windows 2000/XP: If flags contains MOUSEEVENTF_XDOWN or MOUSEEVENTF_XUP, then data specifies which
197
- # X buttons were pressed or released. This value may be any combination of the following flags.
198
- # - If flags is not MOUSEEVENTF_WHEEL, MOUSEEVENTF_XDOWN, or MOUSEEVENTF_XUP, then data should be zero.
199
- # XBUTTON1 - Set if the first X button was pressed or released.
200
- # XBUTTON2 - Set if the second X button was pressed or released.
201
- # dwExtraInfo:: [in] Specifies an additional value associated with the mouse event. An application
202
- # calls GetMessageExtraInfo to obtain this extra information.
203
- # <b>NO Return Value</b>
204
- # ---
205
- # *Remarks*:
206
- # - If the mouse has moved, indicated by MOUSEEVENTF_MOVE being set, dx and dy hold information about
207
- # that motion. The information is specified as absolute or relative integer values.
208
- # - If MOUSEEVENTF_ABSOLUTE value is specified, dx and dy contain normalized absolute coordinates between
209
- # 0 and 65,535. The event procedure maps these coordinates onto the display surface. Coordinate (0,0) maps
210
- # onto the upper-left corner of the display surface, (65535,65535) maps onto the lower-right corner.
211
- # - If the MOUSEEVENTF_ABSOLUTE value is not specified, dx and dy specify relative motions from when the
212
- # last mouse event was generated (the last reported position). Positive values mean the mouse moved right
213
- # (or down); negative values mean the mouse moved left (or up). Relative mouse motion is subject to the
214
- # settings for mouse speed and acceleration level. An end user sets these values using the Mouse application
215
- # in Control Panel. An application obtains and sets these values with the SystemParametersInfo function.
216
- # - The system applies two tests to the specified relative mouse motion when applying acceleration. If the
217
- # specified distance along either the x or y axis is greater than the first mouse threshold value, and the
218
- # mouse acceleration level is not zero, the operating system doubles the distance. If the specified distance
219
- # along either the x- or y-axis is greater than the second mouse threshold value, and the mouse acceleration
220
- # level is equal to two, the operating system doubles the distance that resulted from applying the first
221
- # threshold test. It is thus possible for the operating system to multiply relatively-specified mouse motion
222
- # along the x- or y-axis by up to four times.
223
- # - Once acceleration has been applied, the system scales the resultant value by the desired mouse speed.
224
- # Mouse speed can range from 1 (slowest) to 20 (fastest) and represents how much the pointer moves based
225
- # on the distance the mouse moves. The default value is 10, which results in no additional modification
226
- # to the mouse motion.
227
- # - The mouse_event function is used to synthesize mouse events by applications that need to do so. It is also
228
- # used by applications that need to obtain more information from the mouse than its position and button state.
229
- # For example, if a tablet manufacturer wants to pass pen-based information to its own applications, it can
230
- # write a DLL that communicates directly to the tablet hardware, obtains the extra information, and saves it
231
- # in a queue. The DLL then calls mouse_event with the standard button and x/y position data, along with,
232
- # in the dwExtraInfo parameter, some pointer or index to the queued extra information. When the application
233
- # needs the extra information, it calls the DLL with the pointer or index stored in dwExtraInfo, and the DLL
234
- # returns the extra information.
235
- #
236
- # :call-seq:
237
- # mouse_event( flags, dx, dy, data, extra_info )
238
- #
239
- function :mouse_event, [:ulong, :ulong, :ulong, :ulong, :ulong, ], :void
240
-
241
- ##
242
- # SetCursorPos Function moves the cursor to the specified screen coordinates. If the new coordinates are not
243
- # within the screen rectangle set by the most recent ClipCursor function call, the system automatically adjusts
244
- # the coordinates so that the cursor stays within the rectangle.
245
- #
246
- # [*Syntax*] BOOL SetCursorPos( int X, int Y );
247
- #
248
- # X:: [in] Specifies the new x-coordinate of the cursor, in screen coordinates.
249
- # Y:: [in] Specifies the new y-coordinate of the cursor, in screen coordinates.
250
- #
251
- # *Returns*:: Nonzero(*true*) if successful or zero(*false*) otherwise. To get extended error information,
252
- # call GetLastError. Enhanced to return true/false instead of nonzero/zero
253
- # ---
254
- # *Remarks*: The cursor is a shared resource. A window should move the cursor only when the cursor is in the
255
- # window's client area. The calling process must have WINSTA_WRITEATTRIBUTES access to the window station.
256
- # The input desktop must be the current desktop when you call SetCursorPos. Call OpenInputDesktop to determine
257
- # whether the current desktop is the input desktop. If it is not, call SetThreadDesktop with the HDESK returned
258
- # by OpenInputDesktop to switch to that desktop.
259
- #
260
- # :call-seq:
261
- # success = set_cursor_pos(x,y)
262
- #
263
- function :SetCursorPos, [:int, :int], :int, boolean: true
264
-
265
- ##
266
- # GetCursorPos Function retrieves the cursor's position, in screen coordinates.
267
- #
268
- # [*Syntax*] BOOL GetCursorPos( LPPOINT lpPoint );
269
- #
270
- # lpPoint:: [out] Pointer to a POINT structure that receives the screen coordinates of the cursor.
271
- #
272
- # *Returns*:: Returns nonzero if successful or zero otherwise. To get extended error information, call
273
- # GetLastError.
274
- # ---
275
- # *Remarks*:
276
- # The cursor position is always specified in screen coordinates and is not affected by the mapping mode
277
- # of the window that contains the cursor.
278
- # The calling process must have WINSTA_READATTRIBUTES access to the window station.
279
- # The input desktop must be the current desktop when you call GetCursorPos. Call OpenInputDesktop to
280
- # determine whether the current desktop is the input desktop. If it is not, call SetThreadDesktop with
281
- # the HDESK returned by OpenInputDesktop to switch to that desktop.
282
- # ---
283
- # <b>Enhanced (snake_case) API: accepts no args, returns a pair (x, y) of cursor coordinates</b>
284
- #
285
- # :call-seq:
286
- # x, y = get_cursor_pos()
287
- #
288
- function :GetCursorPos, [:pointer], :int8,
289
- &->(api) {
290
- point = FFI::MemoryPointer.new(:long, 2)
291
- res = api.call point
292
- res == 0 ? [nil, nil] : point.read_array_of_long(2) }
293
- # weird lambda literal instead of normal block is needed because current version of RDoc
294
- # goes crazy if block is attached to meta-definition
295
-
296
-
297
- # Convenience methods
298
-
299
- ##
300
- # Emulates combinations of (any amount of) keys pressed one after another (Ctrl+Alt+P) and then released
301
- # *keys should be a sequence of a virtual-key codes. The codes must be a value in the range 1 to 254.
302
- # For a complete list, see msdn:Virtual Key Codes.
303
- def keystroke(*keys)
304
- return if keys.empty?
305
- keybd_event keys.first, 0, KEYEVENTF_KEYDOWN, 0
306
- sleep KEY_DELAY
307
- keystroke *keys[1..-1]
308
- sleep KEY_DELAY
309
- keybd_event keys.first, 0, KEYEVENTF_KEYUP, 0
310
- end
311
-
312
- # types text message into window holding the focus
313
- def type_in(message)
314
- message.scan(/./m) do |char|
315
- keystroke(*char.to_vkeys)
316
- end
317
- end
318
- end
319
- end
1
+ require 'win/library'
2
+
3
+ module Win
4
+ module Gui
5
+ # Contains constants and Win32API functions related to end user input
6
+ #
7
+ module Input
8
+ include Win::Library
9
+
10
+ # Internal constants:
11
+
12
+ # Key event delay
13
+ KEY_DELAY = 0.00001
14
+
15
+ # Windows keyboard-related Constants:
16
+
17
+ # Key down keyboard event (the key is being depressed)
18
+ KEYEVENTF_KEYDOWN = 0
19
+ # Key up keyboard event (the key is being released)
20
+ KEYEVENTF_KEYUP = 2
21
+ # Extended kb event. If specified, the scan code was preceded by a prefix byte having the value 0xE0 (224).
22
+ KEYEVENTF_EXTENDEDKEY = 1
23
+
24
+ # Virtual key codes:
25
+
26
+ # Control-break processing
27
+ VK_CANCEL = 0x03
28
+ # Backspace? key
29
+ VK_BACK = 0x08
30
+ # Tab key
31
+ VK_TAB = 0x09
32
+ # Shift key
33
+ VK_SHIFT = 0x10
34
+ # Ctrl key
35
+ VK_CONTROL = 0x11
36
+ # ENTER key
37
+ VK_RETURN = 0x0D
38
+ # ALT key
39
+ VK_ALT = 0x12
40
+ # ALT key alias
41
+ VK_MENU = 0x12
42
+ # PAUSE key
43
+ VK_PAUSE = 0x13
44
+ # CAPS LOCK key
45
+ VK_CAPITAL = 0x14
46
+ # ESC key
47
+ VK_ESCAPE = 0x1B
48
+ # SPACEBAR
49
+ VK_SPACE = 0x20
50
+ # PAGE UP key
51
+ VK_PRIOR = 0x21
52
+ # PAGE DOWN key
53
+ VK_NEXT = 0x22
54
+ # END key
55
+ VK_END = 0x23
56
+ # HOME key
57
+ VK_HOME = 0x24
58
+ # LEFT ARROW key
59
+ VK_LEFT = 0x25
60
+ # UP ARROW key
61
+ VK_UP = 0x26
62
+ # RIGHT ARROW key
63
+ VK_RIGHT = 0x27
64
+ # DOWN ARROW key
65
+ VK_DOWN = 0x28
66
+ # SELECT key
67
+ VK_SELECT = 0x29
68
+ # PRINT key
69
+ VK_PRINT = 0x2A
70
+ # EXECUTE key
71
+ VK_EXECUTE = 0x2B
72
+ # PRINT SCREEN key
73
+ VK_SNAPSHOT = 0x2C
74
+ # INS key
75
+ VK_INSERT = 0x2D
76
+ # DEL key
77
+ VK_DELETE = 0x2E
78
+ # HELP key
79
+ VK_HELP = 0x2F
80
+
81
+ # Public Type MOUSEINPUT
82
+ # dx As Long
83
+ # dy As Long
84
+ # mouseData As Long
85
+ # dwFlags As Long
86
+ # time As Long
87
+ # dwExtraInfo As Long
88
+ # End Type
89
+ #
90
+ # Public Type INPUT_TYPE
91
+ # dwType As Long
92
+ # xi(0 To 23) As Byte
93
+ # End Type
94
+
95
+ # dwFlags:
96
+ # Specifies that the dx and dy parameters contain normalized absolute coordinates. If not set, those parameters
97
+ # contain relative data: the change in position since the last reported position. This flag can be set, or not
98
+ # set, regardless of what kind of mouse or mouse-like device, if any, is connected to the system. For further
99
+ # information about relative mouse motion, see mouse_event Remarks section.
100
+ MOUSEEVENTF_ABSOLUTE = 0x8000
101
+ #Specifies that movement occurred.
102
+ MOUSEEVENTF_MOVE = 0x01
103
+ #Specifies that the left button is down.
104
+ MOUSEEVENTF_LEFTDOWN = 0x02
105
+ #Specifies that the left button is up.
106
+ MOUSEEVENTF_LEFTUP = 0x04
107
+ #Specifies that the right button is down.
108
+ MOUSEEVENTF_RIGHTDOWN = 0x08
109
+ #Specifies that the right button is up.
110
+ MOUSEEVENTF_RIGHTUP = 0x010
111
+ #Specifies that the middle button is down.
112
+ MOUSEEVENTF_MIDDLEDOWN = 0x20
113
+ #Specifies that the middle button is up.
114
+ MOUSEEVENTF_MIDDLEUP = 0x040
115
+ #Windows NT/2000/XP: Specifies that the wheel has been moved, if the mouse has a wheel. The amount of movement
116
+ #is specified in dwData
117
+ MOUSEEVENTF_WHEEL = 0x80
118
+ #Windows 2000/XP: Specifies that an X button was pressed.
119
+ MOUSEEVENTF_XDOWN = 0x100
120
+ #Windows 2000/XP: Specifies that an X button was released.
121
+ MOUSEEVENTF_XUP = 0x200
122
+
123
+ # dwData:
124
+ # One wheel click is defined as WHEEL_DELTA, which is 120.
125
+ WHEEL_DELTA = 120
126
+ # Set if the first X button was pressed or released.
127
+ XBUTTON1 = 1
128
+ # Set if the second X button was pressed or released.
129
+ XBUTTON2 = 2
130
+ # Indicates NO data if dwFlags are NOT any of MOUSEEVENTF_WHEEL, MOUSEEVENTF_XDOWN, or MOUSEEVENTF_XUP
131
+ INPUT_MOUSE = 0
132
+
133
+
134
+ ##
135
+ # The keybd_event function synthesizes a keystroke. The system can use such a synthesized keystroke to generate
136
+ # a WM_KEYUP or WM_KEYDOWN message. The keyboard driver's interrupt handler calls the keybd_event function.
137
+ #
138
+ # <b> !! Windows NT/2000/XP/Vista:This function has been superseded. Use SendInput instead. </b>
139
+ #
140
+ # [*Syntax*] VOID keybd_event( BYTE bVk, BYTE bScan, DWORD dwFlags, PTR dwExtraInfo);
141
+ #
142
+ # bVk:: [in] Specifies a virtual-key code. The code must be a value in the range 1 to 254.
143
+ # For a complete list, see Virtual-Key Codes.
144
+ # bScan:: [in] Specifies a hardware scan code for the key.
145
+ # dwFlags:: [in] Specifies various aspects of function operation. This parameter can be
146
+ # one or more of the following values:
147
+ # KEYEVENTF_EXTENDEDKEY, KEYEVENTF_KEYUP, KEYEVENTF_KEYDOWN
148
+ # dwExtraInfo:: [in] Specifies an additional value associated with the key stroke.
149
+ #
150
+ # <b>NO Return Value</b>
151
+ # ---
152
+ # *Remarks*:
153
+ # - An application can simulate a press of the PRINTSCRN key in order to obtain a screen snapshot
154
+ # and save it to the clipboard. To do this, call keybd_event with the bVk parameter set to VK_SNAPSHOT.
155
+ #
156
+ # - Windows NT/2000/XP: The keybd_event function can toggle the NUM LOCK, CAPS LOCK, and SCROLL LOCK keys.
157
+ # - Windows 95/98/Me: The keybd_event function can toggle only the CAPS LOCK and SCROLL LOCK keys.
158
+ #
159
+ # :call-seq:
160
+ # keybd_event( virtual_key, scan_code, flags, extra_info )
161
+ #
162
+ function :keybd_event, [:char, :char, :ulong, :ulong], :void
163
+
164
+ ##
165
+ # The mouse_event function synthesizes mouse motion and button clicks.
166
+ #
167
+ # <b> !! Windows NT/2000/XP/Vista:This function has been superseded. Use SendInput instead. </b>
168
+ #
169
+ # [*Syntax*] VOID mouse_event( DWORD dwFlags, DWORD dx, DWORD dy, DWORD dwData, ULONG_PTR dwExtraInfo );
170
+ #
171
+ # dwFlags:: [in] Specifies various aspects of mouse motion and button clicking. This parameter can be certain
172
+ # combinations of the following values. The values that specify mouse button status are set to indicate
173
+ # changes in status, not ongoing conditions. For example, if the left mouse button is pressed and
174
+ # held down, MOUSEEVENTF_LEFTDOWN is set when the left button is first pressed, but not for subsequent
175
+ # motions. Similarly, MOUSEEVENTF_LEFTUP is set only when the button is first released. You cannot
176
+ # specify both MOUSEEVENTF_WHEEL and either MOUSEEVENTF_XDOWN or MOUSEEVENTF_XUP simultaneously,
177
+ # because they both require use of the dwData field:
178
+ # MOUSEEVENTF_ABSOLUTE, MOUSEEVENTF_MOVE, MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_LEFTUP,
179
+ # MOUSEEVENTF_RIGHTDOWN, MOUSEEVENTF_RIGHTUP, MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_MIDDLEUP,
180
+ # MOUSEEVENTF_WHEEL, MOUSEEVENTF_XDOWN, MOUSEEVENTF_XUP
181
+ # dx:: [in] Specifies the mouse's absolute position along the x-axis or its amount of motion since the
182
+ # last mouse event was generated, depending on the setting of MOUSEEVENTF_ABSOLUTE. Absolute data is
183
+ # specified as the mouse's actual x-coordinate; relative data is specified as the number of mickeys moved.
184
+ # A mickey is the amount that a mouse has to move for it to report that it has moved.
185
+ # dy:: [in] Specifies the mouse's absolute position along the y-axis or its amount of motion since the
186
+ # last mouse event was generated, depending on the setting of MOUSEEVENTF_ABSOLUTE. Absolute data is
187
+ # specified as the mouse's actual y-coordinate; relative data is specified as the number of mickeys moved.
188
+ # dwData:: [in]
189
+ # - If dwFlags contains MOUSEEVENTF_WHEEL, then data specifies the amount of wheel movement.
190
+ # A positive value indicates that the wheel was rotated forward, away from the user; a negative value
191
+ # indicates that the wheel was rotated backward, toward the user. One wheel click is defined as
192
+ # WHEEL_DELTA, which is 120.
193
+ # - If dwFlags contains MOUSEEVENTF_WHHEEL, then data specifies the amount of
194
+ # wheel movement. A positive value indicates that the wheel was rotated to the right; a negative value
195
+ # indicates that the wheel was rotated to the left. One wheel click is defined as WHEEL_DELTA (= 120).
196
+ # - Windows 2000/XP: If flags contains MOUSEEVENTF_XDOWN or MOUSEEVENTF_XUP, then data specifies which
197
+ # X buttons were pressed or released. This value may be any combination of the following flags.
198
+ # - If flags is not MOUSEEVENTF_WHEEL, MOUSEEVENTF_XDOWN, or MOUSEEVENTF_XUP, then data should be zero.
199
+ # XBUTTON1 - Set if the first X button was pressed or released.
200
+ # XBUTTON2 - Set if the second X button was pressed or released.
201
+ # dwExtraInfo:: [in] Specifies an additional value associated with the mouse event. An application
202
+ # calls GetMessageExtraInfo to obtain this extra information.
203
+ # <b>NO Return Value</b>
204
+ # ---
205
+ # *Remarks*:
206
+ # - If the mouse has moved, indicated by MOUSEEVENTF_MOVE being set, dx and dy hold information about
207
+ # that motion. The information is specified as absolute or relative integer values.
208
+ # - If MOUSEEVENTF_ABSOLUTE value is specified, dx and dy contain normalized absolute coordinates between
209
+ # 0 and 65,535. The event procedure maps these coordinates onto the display surface. Coordinate (0,0) maps
210
+ # onto the upper-left corner of the display surface, (65535,65535) maps onto the lower-right corner.
211
+ # - If the MOUSEEVENTF_ABSOLUTE value is not specified, dx and dy specify relative motions from when the
212
+ # last mouse event was generated (the last reported position). Positive values mean the mouse moved right
213
+ # (or down); negative values mean the mouse moved left (or up). Relative mouse motion is subject to the
214
+ # settings for mouse speed and acceleration level. An end user sets these values using the Mouse application
215
+ # in Control Panel. An application obtains and sets these values with the SystemParametersInfo function.
216
+ # - The system applies two tests to the specified relative mouse motion when applying acceleration. If the
217
+ # specified distance along either the x or y axis is greater than the first mouse threshold value, and the
218
+ # mouse acceleration level is not zero, the operating system doubles the distance. If the specified distance
219
+ # along either the x- or y-axis is greater than the second mouse threshold value, and the mouse acceleration
220
+ # level is equal to two, the operating system doubles the distance that resulted from applying the first
221
+ # threshold test. It is thus possible for the operating system to multiply relatively-specified mouse motion
222
+ # along the x- or y-axis by up to four times.
223
+ # - Once acceleration has been applied, the system scales the resultant value by the desired mouse speed.
224
+ # Mouse speed can range from 1 (slowest) to 20 (fastest) and represents how much the pointer moves based
225
+ # on the distance the mouse moves. The default value is 10, which results in no additional modification
226
+ # to the mouse motion.
227
+ # - The mouse_event function is used to synthesize mouse events by applications that need to do so. It is also
228
+ # used by applications that need to obtain more information from the mouse than its position and button state.
229
+ # For example, if a tablet manufacturer wants to pass pen-based information to its own applications, it can
230
+ # write a DLL that communicates directly to the tablet hardware, obtains the extra information, and saves it
231
+ # in a queue. The DLL then calls mouse_event with the standard button and x/y position data, along with,
232
+ # in the dwExtraInfo parameter, some pointer or index to the queued extra information. When the application
233
+ # needs the extra information, it calls the DLL with the pointer or index stored in dwExtraInfo, and the DLL
234
+ # returns the extra information.
235
+ #
236
+ # :call-seq:
237
+ # mouse_event( flags, dx, dy, data, extra_info )
238
+ #
239
+ function :mouse_event, [:ulong, :ulong, :ulong, :ulong, :ulong, ], :void
240
+
241
+ ##
242
+ # SetCursorPos Function moves the cursor to the specified screen coordinates. If the new coordinates are not
243
+ # within the screen rectangle set by the most recent ClipCursor function call, the system automatically adjusts
244
+ # the coordinates so that the cursor stays within the rectangle.
245
+ #
246
+ # [*Syntax*] BOOL SetCursorPos( int X, int Y );
247
+ #
248
+ # X:: [in] Specifies the new x-coordinate of the cursor, in screen coordinates.
249
+ # Y:: [in] Specifies the new y-coordinate of the cursor, in screen coordinates.
250
+ #
251
+ # *Returns*:: Nonzero(*true*) if successful or zero(*false*) otherwise. To get extended error information,
252
+ # call GetLastError. Enhanced to return true/false instead of nonzero/zero
253
+ # ---
254
+ # *Remarks*: The cursor is a shared resource. A window should move the cursor only when the cursor is in the
255
+ # window's client area. The calling process must have WINSTA_WRITEATTRIBUTES access to the window station.
256
+ # The input desktop must be the current desktop when you call SetCursorPos. Call OpenInputDesktop to determine
257
+ # whether the current desktop is the input desktop. If it is not, call SetThreadDesktop with the HDESK returned
258
+ # by OpenInputDesktop to switch to that desktop.
259
+ #
260
+ # :call-seq:
261
+ # success = set_cursor_pos(x,y)
262
+ #
263
+ function :SetCursorPos, [:int, :int], :int, boolean: true
264
+
265
+ ##
266
+ # GetCursorPos Function retrieves the cursor's position, in screen coordinates.
267
+ #
268
+ # [*Syntax*] BOOL GetCursorPos( LPPOINT lpPoint );
269
+ #
270
+ # lpPoint:: [out] Pointer to a POINT structure that receives the screen coordinates of the cursor.
271
+ #
272
+ # *Returns*:: Returns nonzero if successful or zero otherwise. To get extended error information, call
273
+ # GetLastError.
274
+ # ---
275
+ # *Remarks*:
276
+ # The cursor position is always specified in screen coordinates and is not affected by the mapping mode
277
+ # of the window that contains the cursor.
278
+ # The calling process must have WINSTA_READATTRIBUTES access to the window station.
279
+ # The input desktop must be the current desktop when you call GetCursorPos. Call OpenInputDesktop to
280
+ # determine whether the current desktop is the input desktop. If it is not, call SetThreadDesktop with
281
+ # the HDESK returned by OpenInputDesktop to switch to that desktop.
282
+ # ---
283
+ # <b>Enhanced (snake_case) API: accepts no args, returns a pair (x, y) of cursor coordinates</b>
284
+ #
285
+ # :call-seq:
286
+ # x, y = get_cursor_pos()
287
+ #
288
+ function :GetCursorPos, [:pointer], :int8,
289
+ &->(api) {
290
+ point = FFI::MemoryPointer.new(:long, 2)
291
+ res = api.call point
292
+ res == 0 ? [nil, nil] : point.read_array_of_long(2) }
293
+ # weird lambda literal instead of normal block is needed because current version of RDoc
294
+ # goes crazy if block is attached to meta-definition
295
+
296
+
297
+ # Convenience methods
298
+
299
+ ##
300
+ # Emulates combinations of (any amount of) keys pressed one after another (Ctrl+Alt+P) and then released
301
+ # *keys should be a sequence of a virtual-key codes. The codes must be a value in the range 1 to 254.
302
+ # For a complete list, see msdn:Virtual Key Codes.
303
+ def keystroke(*keys)
304
+ return if keys.empty?
305
+ keybd_event keys.first, 0, KEYEVENTF_KEYDOWN, 0
306
+ sleep KEY_DELAY
307
+ keystroke *keys[1..-1]
308
+ sleep KEY_DELAY
309
+ keybd_event keys.first, 0, KEYEVENTF_KEYUP, 0
310
+ end
311
+
312
+ # types text message into window holding the focus
313
+ def type_in(message)
314
+ message.scan(/./m) do |char|
315
+ keystroke(*char.to_vkeys)
316
+ end
317
+ end
318
+ end
319
+ end
320
320
  end