win32-window 0.1.0.pre → 0.2.0.pre

Sign up to get free protection for your applications and to get access to all the features.
@@ -1 +1 @@
1
- $version = '0.1.0.pre'
1
+ $version = '0.2.0.pre'
@@ -11,31 +11,109 @@ module Win32
11
11
  class Size < Struct.new(:width, :height)
12
12
  end
13
13
 
14
+ module Geometry
15
+ def location
16
+ g = geometry()
17
+ Point.new(g.left, g.top)
18
+ end
19
+
20
+ def x
21
+ location.x
22
+ end
23
+
24
+ def y
25
+ location.y
26
+ end
27
+
28
+ def left
29
+ geometry.left
30
+ end
31
+
32
+ def right
33
+ geometry.right
34
+ end
35
+
36
+ def top
37
+ geometry.top
38
+ end
39
+
40
+ def bottom
41
+ geometry.bottom
42
+ end
43
+
44
+ def size
45
+ g = geometry()
46
+ Size.new(g.right - g.left + 1, g.bottom - g.top + 1)
47
+ end
48
+
49
+ def width
50
+ size.width
51
+ end
52
+
53
+ def height
54
+ size.height
55
+ end
56
+ end
57
+
14
58
  class Window
15
59
  def initialize(handle)
60
+ # TODO: Validate handle parameter?
61
+
16
62
  @handle = handle
63
+ @client = Client.new(@handle)
17
64
  end
18
65
 
19
66
  def self.find(opts = {})
20
- matches = []
67
+ Thread.current[:matches] = []
68
+ Thread.current[:opts] = opts
69
+
70
+ @@callback ||= API::Callback.new('LP', 'I') { |handle|
71
+ opts = Thread.current[:opts]
21
72
 
22
- callback = API::Callback.new('LP', 'I') { |handle|
23
73
  match = true
24
74
  match &&= opts[:title].nil? || (get_title(handle) =~ opts[:title])
25
75
  match &&= opts[:pid].nil? || (get_pid(handle) == opts[:pid])
26
76
 
27
77
  if match
28
- matches << Window.new(handle)
78
+ Thread.current[:matches] << Window.new(handle)
29
79
  end
30
80
 
31
81
  1
32
82
  }
33
83
 
34
- EnumWindows.call(callback, nil)
84
+ EnumWindows.call(@@callback, nil)
85
+
86
+ return Thread.current[:matches]
87
+ end
88
+
89
+ def self.from_point(*args)
90
+ if (args.length == 1) && (args[0].is_a? Point)
91
+ x = args[0].x
92
+ y = args[0].y
93
+ elsif args.length == 2
94
+ x, y = args
95
+ else
96
+ raise ArgumentError
97
+ end
98
+
99
+ handle = WindowFromPoint.call(x,y)
100
+ if handle == 0
101
+ nil
102
+ else
103
+ Window.new(handle)
104
+ end
105
+ end
35
106
 
36
- return matches
107
+ def self.from_handle(handle)
108
+ if IsWindow.call(handle) != 0
109
+ Window.new(handle)
110
+ else
111
+ nil
112
+ end
37
113
  end
38
114
 
115
+ # See also GetShellWindow
116
+ # http://msdn.microsoft.com/en-us/library/windows/desktop/ms633512(v=vs.85).aspx
39
117
  def self.desktop
40
118
  Window.new(GetDesktopWindow.call())
41
119
  end
@@ -48,22 +126,90 @@ module Win32
48
126
  Window.get_title(@handle)
49
127
  end
50
128
 
129
+ def handle
130
+ @handle
131
+ end
132
+
133
+ def eql?(other)
134
+ self == other
135
+ end
136
+
137
+ def ==(other)
138
+ handle == other.handle
139
+ end
140
+
141
+ def topmost?
142
+ end
143
+
51
144
  def topmost=(topmost)
52
145
  SetWindowPos.call(@handle, topmost ? HWND_TOPMOST : HWND_NOTTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE)
53
146
  end
54
147
 
148
+ # Use also SetForegroundWindow?
149
+ # http://msdn.microsoft.com/en-us/library/windows/desktop/ms633539(v=vs.85).aspx
150
+ # def bring_to_top
151
+ # BringWindowToTop.call(@handle)
152
+ # end
153
+
154
+ def focus
155
+ # ...?
156
+ end
157
+
158
+ def focused?
159
+ end
160
+
161
+ # window.children.from_point(...)
162
+ # http://msdn.microsoft.com/en-us/library/windows/desktop/ms632677(v=vs.85).aspx
163
+ # ChildWindowFromPointEx
164
+
165
+ # window.children.each/window.each_child
166
+ # http://msdn.microsoft.com/en-us/library/windows/desktop/ms633494(v=vs.85).aspx
167
+ # EnumChildWindows
168
+
169
+ # window.children.topmost
170
+ # http://msdn.microsoft.com/en-us/library/windows/desktop/ms633514(v=vs.85).aspx
171
+ # GetTopWindow
172
+
173
+ # window.child_of?
174
+ # http://msdn.microsoft.com/en-us/library/windows/desktop/ms633524(v=vs.85).aspx
175
+ # IsChild
176
+
55
177
  def minimize
56
- CloseWindow.call(@handle)
178
+ ShowWindow.call(@handle, SW_MINIMIZE)
57
179
  end
58
180
 
59
181
  def minimized?
60
182
  IsIconic.call(@handle) != 0
61
183
  end
62
184
 
185
+ def maximize
186
+ ShowWindow.call(@handle, SW_MAXIMIZE)
187
+ end
188
+
189
+ # TODO: max -> min -> restore does not show the window restored,
190
+ # you have to do max -> min -> restore -> restore.
191
+ def restore
192
+ ShowWindow.call(@handle, SW_RESTORE)
193
+ end
194
+
195
+ def maximized?
196
+ IsZoomed.call(@handle) != 0
197
+ end
198
+
63
199
  def visible?
64
200
  IsWindowVisible.call(@handle) != 0
65
201
  end
66
202
 
203
+ # TODO: hide -> maximize/minimize/restore forces the window
204
+ # to be shown again, use SetWindowPlacement?
205
+ def hide
206
+ ShowWindow.call(@handle, SW_HIDE)
207
+ end
208
+
209
+ def show
210
+ ShowWindow.call(@handle, SW_SHOW)
211
+ end
212
+
67
213
  def parent
68
214
  parent = GetParent.call(@handle)
69
215
  if parent == 0
@@ -73,6 +219,17 @@ module Win32
73
219
  end
74
220
  end
75
221
 
222
+ # See GetAncestor
223
+ # http://msdn.microsoft.com/en-us/library/windows/desktop/ms633502(v=vs.85).aspx
224
+ def root
225
+ end
226
+
227
+ # See GetAncestor
228
+ # http://msdn.microsoft.com/en-us/library/windows/desktop/ms633502(v=vs.85).aspx
229
+ def owner
230
+ # ...
231
+ end
232
+
76
233
  def pid
77
234
  Window.get_pid(@handle)
78
235
  end
@@ -85,16 +242,10 @@ module Win32
85
242
  SetWindowPos.call(@handle, 0, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER)
86
243
  end
87
244
 
88
- def location
89
- g = geometry()
90
- Point.new(g.left, g.top)
91
- end
92
-
93
- def size
94
- g = geometry()
95
- Size.new(g.right - g.left, g.bottom - g.top)
96
- end
245
+ include Geometry
97
246
 
247
+ # TODO: geometry should return special values when
248
+ # the window is minimized.
98
249
  def geometry
99
250
  rect = Window.buffer(4 * 4)
100
251
  GetWindowRect.call(@handle, rect)
@@ -102,22 +253,50 @@ module Win32
102
253
  return Rect.new(left, top, right, bottom)
103
254
  end
104
255
 
105
- def client_geometry
106
- rect = Window.buffer(4 * 4)
107
- GetClientRect.call(@handle, rect)
108
- left, top, right, bottom = rect.unpack('LLLL')
256
+ def client
257
+ @client
258
+ end
259
+
260
+ # See GetWindowModuleFileName
261
+ # http://msdn.microsoft.com/en-us/library/windows/desktop/ms633517(v=vs.85).aspx
262
+ def module_name
263
+ end
109
264
 
110
- width = right - left
111
- height = bottom - top
265
+ private
266
+ class Client
267
+ def initialize(handle)
268
+ @handle = handle
269
+ end
270
+
271
+ include Geometry
272
+
273
+ def geometry
274
+ rect = Window.buffer(4 * 4)
275
+ GetClientRect.call(@handle, rect)
276
+ left, top, right, bottom = rect.unpack('LLLL')
277
+
278
+ # From GetClientRect documentation: "In conformance with conventions for
279
+ # the RECT structure, the bottom-right coordinates of the returned rectangle
280
+ # are exclusive. In other words, the pixel at (right, bottom) lies immediately
281
+ # outside the rectangle."
282
+ # Because of this, we decrement to determine the inclusive coordinate.
283
+ right -= 1
284
+ bottom -= 1
285
+
286
+ width = right - left + 1
287
+ height = bottom - top + 1
112
288
 
113
- point = point(left, top)
114
- ClientToScreen.call(@handle, point)
115
- screen_left, screen_top = point.unpack('LL')
289
+ top_left = Window.point(left, top)
290
+ ClientToScreen.call(@handle, top_left)
291
+ screen_left, screen_top = top_left.unpack('LL')
116
292
 
117
- return Rect.new(screen_left, screen_top, screen_left + width, screen_top + height)
293
+ screen_right = screen_left + width - 1
294
+ screen_bottom = screen_top + height - 1
295
+
296
+ return Rect.new(screen_left, screen_top, screen_right, screen_bottom)
297
+ end
118
298
  end
119
299
 
120
- private
121
300
  def self.get_title(handle)
122
301
  if GetWindowTextW.call(handle, buffer = "\0" * 1024, buffer.length) == 0
123
302
  nil
@@ -133,10 +312,10 @@ module Win32
133
312
  end
134
313
 
135
314
  def self.buffer(bytes)
136
- ' ' * bytes
315
+ "\0" * bytes
137
316
  end
138
317
 
139
- def point(x, y)
318
+ def self.point(x, y)
140
319
  [x, y].pack('LL')
141
320
  end
142
321
  end
@@ -159,9 +338,6 @@ module Win32
159
338
  # http://msdn.microsoft.com/en-us/library/windows/desktop/ms633522(v=vs.85).aspx
160
339
  GetWindowThreadProcessId = API.new('GetWindowThreadProcessId', 'IP', 'L', 'user32')
161
340
 
162
- # http://msdn.microsoft.com/en-us/library/windows/desktop/ms632678(v=vs.85).aspx
163
- CloseWindow = API.new('CloseWindow', 'I', 'L', 'user32')
164
-
165
341
  # http://msdn.microsoft.com/en-us/library/windows/desktop/ms633504(v=vs.85).aspx
166
342
  GetDesktopWindow = API.new('GetDesktopWindow', '', 'I', 'user32')
167
343
 
@@ -174,9 +350,38 @@ module Win32
174
350
  # http://msdn.microsoft.com/en-us/library/windows/desktop/ms633527(v=vs.85).aspx
175
351
  IsIconic = API.new('IsIconic', 'I', 'I', 'user32')
176
352
 
353
+ # http://msdn.microsoft.com/en-us/library/windows/desktop/ms633531(v=vs.85).aspx
354
+ IsZoomed = API.new('IsZoomed', 'I', 'I', 'user32')
355
+
177
356
  # http://msdn.microsoft.com/en-us/library/windows/desktop/ms633530(v=vs.85).aspx
178
357
  IsWindowVisible = API.new('IsWindowVisible', 'I', 'I', 'user32')
179
358
 
359
+ # http://msdn.microsoft.com/en-us/library/windows/desktop/ms633548(v=vs.85).aspx
360
+ ShowWindow = API.new('ShowWindow', 'II', 'I', 'user32')
361
+
362
+ # http://msdn.microsoft.com/en-us/library/windows/desktop/ms633558(v=vs.85).aspx
363
+ WindowFromPoint = API.new('WindowFromPoint', 'LL', 'I', 'user32')
364
+
365
+ # http://msdn.microsoft.com/en-us/library/windows/desktop/ms632673(v=vs.85).aspx
366
+ BringWindowToTop = API.new('BringWindowToTop', 'I', 'I', 'user32')
367
+
368
+ # http://msdn.microsoft.com/en-us/library/windows/desktop/ms633528(v=vs.85).aspx
369
+ IsWindow = API.new('IsWindow', 'I', 'I', 'user32')
370
+
371
+ SW_FORCEMINIMIZE = 11
372
+ SW_HIDE = 0
373
+ SW_MAXIMIZE = 3
374
+ SW_MINIMIZE = 6
375
+ SW_RESTORE = 9
376
+ SW_SHOW = 5
377
+ SW_SHOWDEFAULT = 10
378
+ SW_SHOWMAXIMIZED = 3
379
+ SW_SHOWMINIMIZED = 2
380
+ SW_SHOWMINNOACTIVE = 7
381
+ SW_SHOWNA = 8
382
+ SW_SHOWNOACTIVATE = 4
383
+ SW_SHOWNORMAL = 1
384
+
180
385
  HWND_BOTTOM = 1
181
386
  HWND_NOTTOPMOST = -2
182
387
  HWND_TOP = 0
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: win32-window
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre
4
+ version: 0.2.0.pre
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,24 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-03 00:00:00.000000000 Z
12
+ date: 2012-07-19 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: win32-api
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.4.8
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.4.8
14
30
  - !ruby/object:Gem::Dependency
15
31
  name: rake
16
32
  requirement: !ruby/object:Gem::Requirement
@@ -18,7 +34,39 @@ dependencies:
18
34
  requirements:
19
35
  - - ! '>='
20
36
  - !ruby/object:Gem::Version
21
- version: 0.9.2.2
37
+ version: '0.9'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0.9'
46
+ - !ruby/object:Gem::Dependency
47
+ name: qtbindings
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '4.6'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '4.6'
62
+ - !ruby/object:Gem::Dependency
63
+ name: win32-semaphore
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0.4'
22
70
  type: :development
23
71
  prerelease: false
24
72
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,7 +74,7 @@ dependencies:
26
74
  requirements:
27
75
  - - ! '>='
28
76
  - !ruby/object:Gem::Version
29
- version: 0.9.2.2
77
+ version: '0.4'
30
78
  description: ! " A Ruby library to work with Microsoft Windows' Win32 window management
31
79
  APIs,\n including search, enumeration, and window manipulation.\n"
32
80
  email: schmch@gmail.com
@@ -58,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
58
106
  version: 1.3.1
59
107
  requirements: []
60
108
  rubyforge_project:
61
- rubygems_version: 1.8.23
109
+ rubygems_version: 1.8.24
62
110
  signing_key:
63
111
  specification_version: 3
64
112
  summary: Ruby interface to the Win32 window management APIs.