win-user32-ruby 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,194 @@
1
+ # Author:: Jerry Fernholz
2
+ # Date:: 21 May 2009
3
+ #
4
+ # Functions for simulating window interactions.
5
+
6
+ require 'winapisys'
7
+ require 'timeout'
8
+
9
+ module WinUser32Ruby
10
+ include WinAPISys
11
+
12
+ class Window
13
+ TIMEOUT = 10
14
+ @handle = nil
15
+ attr_reader :handle
16
+
17
+ def initialize(hwnd)
18
+ @handle = hwnd
19
+ end
20
+
21
+ def text
22
+
23
+ end
24
+ # Wrapper for +FindWindow+.
25
+ # +title+:: is the title of the window we are trying to find
26
+ # +class_name+: is the predefined registered control-class name, generally not used
27
+ # *Return*:: window handle
28
+ def self.find_window(title, class_name = nil)
29
+ fw= user32 'FindWindow', 'PP', 'L'
30
+
31
+ begin
32
+ wnd = timeout(TIMEOUT) {sleep 0.2 while (h = fw.call class_name, title) <= 0; h}
33
+ rescue TimeoutError
34
+ return nil
35
+ end
36
+
37
+ Window.new wnd
38
+ end
39
+
40
+ # Wrapper for +FindWindowEx+.
41
+ # +title+:: is the title of the window we are trying to find
42
+ # +class_name+: is the predefined registered control-class name, generally not used
43
+ # *Return*:: window handle
44
+ def find_window_ex(title, child = 0, class_name = nil)
45
+ parent = @handle
46
+
47
+ fw= user32 'FindWindowEx', 'LLPP', 'L'
48
+
49
+ begin
50
+ wnd = timeout(TIMEOUT) {sleep 0.2 while (h = fw.call parent, child, class_name, title) <= 0; h}
51
+ rescue TimeoutError
52
+ return nil
53
+ end
54
+
55
+ Window.new wnd
56
+ end
57
+
58
+ # Wrapper for +GetTopWindow+.
59
+ # +title+:: is the title of the window we are trying to find
60
+ # +class_name+: is the predefined registered control-class name, generally not used
61
+ # *Return*:: window handle
62
+ def get_top_window
63
+ parent = @handle
64
+ fw= user32 'GetTopWindow', 'L', 'L'
65
+
66
+ wnd = timeout(TIMEOUT) {sleep 0.2 while (h = fw.call parent) <= 0; h}
67
+
68
+ Window.new wnd
69
+ end
70
+
71
+ # Wrapper for +GetTopWindow+.
72
+ # +title+:: is the title of the window we are trying to find
73
+ # +class_name+: is the predefined registered control-class name, generally not used
74
+ # *Return*:: window handle
75
+ def self.get_top_window
76
+ parent = 0
77
+ fw= user32 'GetTopWindow', 'L', 'L'
78
+
79
+ wnd = timeout(TIMEOUT) {sleep 0.2 while (h = fw.call parent) <= 0; h}
80
+
81
+ Window.new wnd
82
+ end
83
+
84
+ # Wrapper for +GetWindow+.
85
+ # +hwnd+:: handle to window on which +cmd+ will be called
86
+ # +cmd+: command to issue to +hwnd+
87
+ # *Return*:: handle to window according to +cmd+
88
+ def get_next_child
89
+ hwnd, cmd = @handle, GW_CHILD
90
+ fw = user32 'GetWindow', 'LI', 'L'
91
+
92
+ Window.new fw.call(hwnd, cmd)
93
+ end
94
+
95
+ # Wrapper for +WM_GETTEXT+.
96
+ # +hwnd+:: handle to the window whose text we want
97
+ # *Return*:: window text
98
+ def get_window_text
99
+ hwnd = @handle
100
+ buffer = ' ' * 2048
101
+
102
+ length = send_message hwnd, WM_GETTEXT, buffer.length, buffer
103
+
104
+ length == 0 ? '' : buffer[0..length - 1]
105
+ end
106
+
107
+
108
+ # Wrapper for +GetWindowRect+.
109
+ # +hwnd+:: handle the window whose rectangle we are trying to get
110
+ # *Return*:: [left, top, right, bottom]
111
+ def get_window_rect
112
+ hwnd = @handle
113
+ rect = [0, 0, 0, 0].pack("L*")
114
+
115
+ gr = user32 'GetWindowRect', 'LP', 'I'
116
+
117
+ gr.call hwnd, rect
118
+
119
+ left, top, right, bottom = rect.unpack("L*")
120
+
121
+ [left, top, right, bottom]
122
+ end
123
+
124
+ def get_center
125
+ r = get_window_rect
126
+ [(r[0] + r[2]) / 2, (r[1] + r[3]) / 2]
127
+ end
128
+
129
+ def cursor_center
130
+ set_cursor_pos(*get_center)
131
+ end
132
+
133
+ def click
134
+ cursor_center
135
+ mouse_click
136
+ end
137
+
138
+ # Wrapper for +BringWindowToTop+.
139
+ # +hwnd+:: handle to window
140
+ def bring_window_to_top
141
+ hwnd = @handle
142
+ b = user32 'BringWindowToTop', 'L', 'I'
143
+ b.call hwnd
144
+ end
145
+
146
+ # Wrapper for +SetFocus+.
147
+ # +hwnd+:: handle to window
148
+ # *Return*:: window handle
149
+ def set_focus
150
+ hwnd = @handle
151
+ b = user32 'SetFocus', 'L', 'L'
152
+ b.call hwnd
153
+ end
154
+
155
+ # Wrapper for +SetForegroundWindow+.
156
+ # +hwnd+:: handle to window
157
+ # *Return*:: true if successful
158
+ def set_foreground_window
159
+ hwnd = @handle
160
+ b = user32 'SetForegroundWindow', 'L', 'I'
161
+
162
+ r = b.call hwnd
163
+
164
+ sleep 0.5
165
+ r
166
+ end
167
+
168
+ def self.get_foreground_window
169
+ b = user32 'GetForegroundWindow', 'V', 'L'
170
+
171
+ r = b.call
172
+
173
+ sleep 0.5
174
+ r
175
+ end
176
+
177
+ # Wrapper for +ShowWindow+.
178
+ # +hwnd+:: handle to window
179
+ # *Return*:: true if successful
180
+ def show_window
181
+ hwnd = @handle
182
+ b = user32 'ShowWindow', 'LI', 'I'
183
+ b.call hwnd, SW_RESTORE
184
+ end
185
+
186
+ # Helper to Post Message to close window
187
+ # +hwnd+:: handle to the window to close
188
+ def exit!
189
+ hwnd = @handle
190
+ send_message hwnd, WM_CLOSE, 0, 0
191
+ end
192
+
193
+ end
194
+ end
data/lib/winapisys.rb ADDED
@@ -0,0 +1,117 @@
1
+ # Author:: Jerry Fernholz
2
+ # Date:: 21 May 2009
3
+ #
4
+ # System level function for wrapping the Win32API
5
+
6
+ module WinAPISys
7
+ require 'win32/api'
8
+ include Win32
9
+ # IMPORTANT: Using Win32 requires some special considerations. Native C
10
+ # is strongly typed whereas Ruby is not. Therefore we need to give Ruby hints
11
+ # as to the correct types for any parameters or return_values.
12
+ #
13
+ # Win32 type hints:
14
+ # 'L':: = long
15
+ # 'I':: = int
16
+ # 'P':: = Pointer
17
+ # 'V':: = void
18
+ # 'K':: = callback
19
+ # 'S':: = string
20
+ #
21
+ # See rdoc for win32-api
22
+
23
+ require 'system_const'
24
+ # Defines a bunch of constants from windows.h and winuser.h
25
+
26
+ # Wrap the API call to functions in 'user32.dll' so we don't have to call
27
+ # <tt>API.new 'user32' ...</tt> repeatedly
28
+ # +name+:: Name of the Win32 function to be called
29
+ # +param_type+:: Array of parameter type hints
30
+ # +return_value+:: Type hint for the return value
31
+ # Example: <tt>user32 'FindWindow', ['P', 'P'], 'L'</tt>
32
+ # => calls the <i>FindWindow</i> function
33
+ def user32(name, param_type, return_value)
34
+ API.new name, param_type, return_value, 'user32'
35
+ end
36
+
37
+ # Wrapper for +PostMessage+.
38
+ # +hwnd+:: Handle to the window we're sending the message to
39
+ # +message+:: message to send
40
+ # +w_param+:: message specific information
41
+ # +l_param+:: more message specific information
42
+ def post_message(hwnd, message, w_param, l_param)
43
+ pm = user32 'PostMessage', 'LLLL', 'L'
44
+ pm.call hwnd, message, w_param, l_param
45
+ end
46
+
47
+ # Wrapper for +SendMessage+.
48
+ # +hwnd+:: Handle to the window we're sending the message to
49
+ # +message+:: message to send
50
+ # +w_param+:: message specific information
51
+ # +l_param+:: more message specific information
52
+ def send_message(hwnd, message, w_param, l_param)
53
+ pm = user32 'SendMessage', 'LLLP', 'L'
54
+ pm.call hwnd, message, w_param, l_param
55
+ end
56
+
57
+ # Wrapper for +SetCursorPos+.
58
+ # +x+:: x position
59
+ # +y+:: y position
60
+ # *Return*:: nonzero if successful or zero otherwise
61
+ def set_cursor_pos(x, y)
62
+ s = user32 'SetCursorPos', 'LL', 'I'
63
+
64
+ s.call x, y
65
+ end
66
+
67
+ # Simulates a mouse click by pressing and releasing the _left_ mouse button
68
+ def mouse_click
69
+ me = user32 'mouse_event', 'LLLLL', 'V'
70
+
71
+ me.call MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
72
+ me.call MOUSEEVENTF_LEFTUP, 0, 0, 0, 0
73
+ end
74
+
75
+ # Keyboard Event constants
76
+ KEYEVENTF_KEYDOWN = 0
77
+
78
+ # Wrapper for +keydb_event+.
79
+ # +v_key+:: virtual key code from \http://msdn.microsoft.com/en-us/library/ms645540(VS.85).aspx
80
+ # +event+:: type of event: KEYEVENTF_KEYDOWN or KEYEVENTF_KEYUP
81
+ # +hw_scan_code+:: not used
82
+ # +extra_info+:: not used
83
+ # *Return*:: none
84
+ def kb_event(v_key, event, hw_scan_code = 0x0, extra_info = 0)
85
+ kbe = user32 'keybd_event', %w{I I L L}, 'V'
86
+ kbe.call v_key, hw_scan_code, event, extra_info
87
+ sleep 0.05
88
+ end
89
+
90
+ # Simulates key down event
91
+ def key_up(v_key, scan_code = 0x0)
92
+ kb_event v_key, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, scan_code
93
+ end
94
+
95
+ # Simulates key down event
96
+ def key_down(v_key, scan_code = 0x0)
97
+ kb_event v_key, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYDOWN, scan_code
98
+ end
99
+
100
+ # Simulates key press and release
101
+ def key_press(v_key, scan_code = 0x0)
102
+ kb_event v_key, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYDOWN, scan_code
103
+ kb_event v_key, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, scan_code
104
+ end
105
+
106
+ # Simulates a sequence of keys being pressed, but not released
107
+ def keys_down(v_keys)
108
+ raise if !v_keys.is_a?(Array)
109
+ v_keys.each{|k| key_down k}
110
+ end
111
+
112
+ # Simulates a sequence of keys being released
113
+ def keys_up(v_keys)
114
+ raise if !v_keys.is_a?(Array)
115
+ v_keys.each{|k| key_up k}
116
+ end
117
+ end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: win-user32-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jerry Fernholz
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-06-04 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: win32-api
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.4.2
24
+ version:
25
+ description: Ruby wrapper for the user32.dll on Windows.
26
+ email: jerry.fernholz@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README
33
+ - LICENSE
34
+ files:
35
+ - LICENSE
36
+ - README
37
+ - Rakefile
38
+ - lib/helpers.rb
39
+ - lib/system_const.rb
40
+ - lib/win-user32-ruby.rb
41
+ - lib/winapisys.rb
42
+ has_rdoc: true
43
+ homepage:
44
+ post_install_message:
45
+ rdoc_options: []
46
+
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: "0"
60
+ version:
61
+ requirements: []
62
+
63
+ rubyforge_project:
64
+ rubygems_version: 1.3.1
65
+ signing_key:
66
+ specification_version: 2
67
+ summary: Ruby wrapper for the user32.dll on Windows.
68
+ test_files: []
69
+