win-user32-ruby 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+