win32-window 0.1.0.pre → 0.2.0.pre

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.
@@ -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.