1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 """
32 Window instrumentation.
33
34 @group Instrumentation:
35 Window
36 """
37
38 __revision__ = "$Id: window.py 1299 2013-12-20 09:30:55Z qvasimodo $"
39
40 __all__ = ['Window']
41
42 import win32
43
44
45 Process = None
46 Thread = None
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 -class Window (object):
69 """
70 Interface to an open window in the current desktop.
71
72 @group Properties:
73 get_handle, get_pid, get_tid,
74 get_process, get_thread,
75 set_process, set_thread,
76 get_classname, get_style, get_extended_style,
77 get_text, set_text,
78 get_placement, set_placement,
79 get_screen_rect, get_client_rect,
80 screen_to_client, client_to_screen
81
82 @group State:
83 is_valid, is_visible, is_enabled, is_maximized, is_minimized, is_child,
84 is_zoomed, is_iconic
85
86 @group Navigation:
87 get_parent, get_children, get_root, get_tree,
88 get_child_at
89
90 @group Instrumentation:
91 enable, disable, show, hide, maximize, minimize, restore, move, kill
92
93 @group Low-level access:
94 send, post
95
96 @type hWnd: int
97 @ivar hWnd: Window handle.
98
99 @type dwProcessId: int
100 @ivar dwProcessId: Global ID of the process that owns this window.
101
102 @type dwThreadId: int
103 @ivar dwThreadId: Global ID of the thread that owns this window.
104
105 @type process: L{Process}
106 @ivar process: Process that owns this window.
107 Use the L{get_process} method instead.
108
109 @type thread: L{Thread}
110 @ivar thread: Thread that owns this window.
111 Use the L{get_thread} method instead.
112
113 @type classname: str
114 @ivar classname: Window class name.
115
116 @type text: str
117 @ivar text: Window text (caption).
118
119 @type placement: L{win32.WindowPlacement}
120 @ivar placement: Window placement in the desktop.
121 """
122
123 - def __init__(self, hWnd = None, process = None, thread = None):
124 """
125 @type hWnd: int or L{win32.HWND}
126 @param hWnd: Window handle.
127
128 @type process: L{Process}
129 @param process: (Optional) Process that owns this window.
130
131 @type thread: L{Thread}
132 @param thread: (Optional) Thread that owns this window.
133 """
134 self.hWnd = hWnd
135 self.dwProcessId = None
136 self.dwThreadId = None
137 self.set_process(process)
138 self.set_thread(thread)
139
140 @property
142 """
143 Compatibility with ctypes.
144 Allows passing transparently a Window object to an API call.
145 """
146 return self.get_handle()
147
149 """
150 @rtype: int
151 @return: Window handle.
152 @raise ValueError: No window handle set.
153 """
154 if self.hWnd is None:
155 raise ValueError("No window handle set!")
156 return self.hWnd
157
167
177
182
187
192
194 """
195 @rtype: L{Process}
196 @return: Parent Process object.
197 """
198 if self.__process is not None:
199 return self.__process
200 self.__load_Process_class()
201 self.__process = Process(self.get_pid())
202 return self.__process
203
205 """
206 Manually set the parent process. Use with care!
207
208 @type process: L{Process}
209 @param process: (Optional) Process object. Use C{None} to autodetect.
210 """
211 if process is None:
212 self.__process = None
213 else:
214 self.__load_Process_class()
215 if not isinstance(process, Process):
216 msg = "Parent process must be a Process instance, "
217 msg += "got %s instead" % type(process)
218 raise TypeError(msg)
219 self.dwProcessId = process.get_pid()
220 self.__process = process
221
223 """
224 @rtype: L{Thread}
225 @return: Parent Thread object.
226 """
227 if self.__thread is not None:
228 return self.__thread
229 self.__load_Thread_class()
230 self.__thread = Thread(self.get_tid())
231 return self.__thread
232
234 """
235 Manually set the thread process. Use with care!
236
237 @type thread: L{Thread}
238 @param thread: (Optional) Thread object. Use C{None} to autodetect.
239 """
240 if thread is None:
241 self.__thread = None
242 else:
243 self.__load_Thread_class()
244 if not isinstance(thread, Thread):
245 msg = "Parent thread must be a Thread instance, "
246 msg += "got %s instead" % type(thread)
247 raise TypeError(msg)
248 self.dwThreadId = thread.get_tid()
249 self.__thread = thread
250
262
263
264
266 """
267 @rtype: str
268 @return: Window class name.
269
270 @raise WindowsError: An error occured while processing this request.
271 """
272 return win32.GetClassName( self.get_handle() )
273
282
291
292 - def get_text(self):
293 """
294 @see: L{set_text}
295 @rtype: str
296 @return: Window text (caption) on success, C{None} on error.
297 """
298 try:
299 return win32.GetWindowText( self.get_handle() )
300 except WindowsError:
301 return None
302
303 - def set_text(self, text):
304 """
305 Set the window text (caption).
306
307 @see: L{get_text}
308
309 @type text: str
310 @param text: New window text.
311
312 @raise WindowsError: An error occured while processing this request.
313 """
314 win32.SetWindowText( self.get_handle(), text )
315
317 """
318 Retrieve the window placement in the desktop.
319
320 @see: L{set_placement}
321
322 @rtype: L{win32.WindowPlacement}
323 @return: Window placement in the desktop.
324
325 @raise WindowsError: An error occured while processing this request.
326 """
327 return win32.GetWindowPlacement( self.get_handle() )
328
330 """
331 Set the window placement in the desktop.
332
333 @see: L{get_placement}
334
335 @type placement: L{win32.WindowPlacement}
336 @param placement: Window placement in the desktop.
337
338 @raise WindowsError: An error occured while processing this request.
339 """
340 win32.SetWindowPlacement( self.get_handle(), placement )
341
343 """
344 Get the window coordinates in the desktop.
345
346 @rtype: L{win32.Rect}
347 @return: Rectangle occupied by the window in the desktop.
348
349 @raise WindowsError: An error occured while processing this request.
350 """
351 return win32.GetWindowRect( self.get_handle() )
352
366
367
368
369
370
371 process = property(get_process, set_process, doc="")
372 thread = property(get_thread, set_thread, doc="")
373 classname = property(get_classname, doc="")
374 style = property(get_style, doc="")
375 exstyle = property(get_extended_style, doc="")
376 text = property(get_text, set_text, doc="")
377 placement = property(get_placement, set_placement, doc="")
378
379
380
382 """
383 Translates window client coordinates to screen coordinates.
384
385 @note: This is a simplified interface to some of the functionality of
386 the L{win32.Point} class.
387
388 @see: {win32.Point.client_to_screen}
389
390 @type x: int
391 @param x: Horizontal coordinate.
392 @type y: int
393 @param y: Vertical coordinate.
394
395 @rtype: tuple( int, int )
396 @return: Translated coordinates in a tuple (x, y).
397
398 @raise WindowsError: An error occured while processing this request.
399 """
400 return tuple( win32.ClientToScreen( self.get_handle(), (x, y) ) )
401
403 """
404 Translates window screen coordinates to client coordinates.
405
406 @note: This is a simplified interface to some of the functionality of
407 the L{win32.Point} class.
408
409 @see: {win32.Point.screen_to_client}
410
411 @type x: int
412 @param x: Horizontal coordinate.
413 @type y: int
414 @param y: Vertical coordinate.
415
416 @rtype: tuple( int, int )
417 @return: Translated coordinates in a tuple (x, y).
418
419 @raise WindowsError: An error occured while processing this request.
420 """
421 return tuple( win32.ScreenToClient( self.get_handle(), (x, y) ) )
422
423
424
426 """
427 @see: L{get_children}
428 @rtype: L{Window} or None
429 @return: Parent window. Returns C{None} if the window has no parent.
430 @raise WindowsError: An error occured while processing this request.
431 """
432 hWnd = win32.GetParent( self.get_handle() )
433 if hWnd:
434 return self.__get_window(hWnd)
435
437 """
438 @see: L{get_parent}
439 @rtype: list( L{Window} )
440 @return: List of child windows.
441 @raise WindowsError: An error occured while processing this request.
442 """
443 return [
444 self.__get_window(hWnd) \
445 for hWnd in win32.EnumChildWindows( self.get_handle() )
446 ]
447
449 """
450 @see: L{get_root}
451 @rtype: dict( L{Window} S{->} dict( ... ) )
452 @return: Dictionary of dictionaries forming a tree of child windows.
453 @raise WindowsError: An error occured while processing this request.
454 """
455 subtree = dict()
456 for aWindow in self.get_children():
457 subtree[ aWindow ] = aWindow.get_tree()
458 return subtree
459
461 """
462 @see: L{get_tree}
463 @rtype: L{Window}
464 @return: If this is a child window, return the top-level window it
465 belongs to.
466 If this window is already a top-level window, returns itself.
467 @raise WindowsError: An error occured while processing this request.
468 """
469 hWnd = self.get_handle()
470 history = set()
471 hPrevWnd = hWnd
472 while hWnd and hWnd not in history:
473 history.add(hWnd)
474 hPrevWnd = hWnd
475 hWnd = win32.GetParent(hWnd)
476 if hWnd in history:
477
478 return self
479 if hPrevWnd != self.get_handle():
480 return self.__get_window(hPrevWnd)
481 return self
482
484 """
485 Get the child window located at the given coordinates. If no such
486 window exists an exception is raised.
487
488 @see: L{get_children}
489
490 @type x: int
491 @param x: Horizontal coordinate.
492
493 @type y: int
494 @param y: Vertical coordinate.
495
496 @type bAllowTransparency: bool
497 @param bAllowTransparency: If C{True} transparent areas in windows are
498 ignored, returning the window behind them. If C{False} transparent
499 areas are treated just like any other area.
500
501 @rtype: L{Window}
502 @return: Child window at the requested position, or C{None} if there
503 is no window at those coordinates.
504 """
505 try:
506 if bAllowTransparency:
507 hWnd = win32.RealChildWindowFromPoint( self.get_handle(), (x, y) )
508 else:
509 hWnd = win32.ChildWindowFromPoint( self.get_handle(), (x, y) )
510 if hWnd:
511 return self.__get_window(hWnd)
512 except WindowsError:
513 pass
514 return None
515
516
517
519 """
520 @rtype: bool
521 @return: C{True} if the window handle is still valid.
522 """
523 return win32.IsWindow( self.get_handle() )
524
526 """
527 @see: {show}, {hide}
528 @rtype: bool
529 @return: C{True} if the window is in a visible state.
530 """
531 return win32.IsWindowVisible( self.get_handle() )
532
534 """
535 @see: {enable}, {disable}
536 @rtype: bool
537 @return: C{True} if the window is in an enabled state.
538 """
539 return win32.IsWindowEnabled( self.get_handle() )
540
542 """
543 @see: L{maximize}
544 @rtype: bool
545 @return: C{True} if the window is maximized.
546 """
547 return win32.IsZoomed( self.get_handle() )
548
550 """
551 @see: L{minimize}
552 @rtype: bool
553 @return: C{True} if the window is minimized.
554 """
555 return win32.IsIconic( self.get_handle() )
556
558 """
559 @see: L{get_parent}
560 @rtype: bool
561 @return: C{True} if the window is a child window.
562 """
563 return win32.IsChild( self.get_handle() )
564
565 is_zoomed = is_maximized
566 is_iconic = is_minimized
567
568
569
571 """
572 Enable the user input for the window.
573
574 @see: L{disable}
575
576 @raise WindowsError: An error occured while processing this request.
577 """
578 win32.EnableWindow( self.get_handle(), True )
579
581 """
582 Disable the user input for the window.
583
584 @see: L{enable}
585
586 @raise WindowsError: An error occured while processing this request.
587 """
588 win32.EnableWindow( self.get_handle(), False )
589
590 - def show(self, bAsync = True):
605
606 - def hide(self, bAsync = True):
621
637
653
669
670 - def move(self, x = None, y = None, width = None, height = None,
671 bRepaint = True):
672 """
673 Moves and/or resizes the window.
674
675 @note: This is request is performed syncronously.
676
677 @type x: int
678 @param x: (Optional) New horizontal coordinate.
679
680 @type y: int
681 @param y: (Optional) New vertical coordinate.
682
683 @type width: int
684 @param width: (Optional) Desired window width.
685
686 @type height: int
687 @param height: (Optional) Desired window height.
688
689 @type bRepaint: bool
690 @param bRepaint:
691 (Optional) C{True} if the window should be redrawn afterwards.
692
693 @raise WindowsError: An error occured while processing this request.
694 """
695 if None in (x, y, width, height):
696 rect = self.get_screen_rect()
697 if x is None:
698 x = rect.left
699 if y is None:
700 y = rect.top
701 if width is None:
702 width = rect.right - rect.left
703 if height is None:
704 height = rect.bottom - rect.top
705 win32.MoveWindow(self.get_handle(), x, y, width, height, bRepaint)
706
708 """
709 Signals the program to quit.
710
711 @note: This is an asyncronous request.
712
713 @raise WindowsError: An error occured while processing this request.
714 """
715 self.post(win32.WM_QUIT)
716
717 - def send(self, uMsg, wParam = None, lParam = None, dwTimeout = None):
718 """
719 Send a low-level window message syncronically.
720
721 @type uMsg: int
722 @param uMsg: Message code.
723
724 @param wParam:
725 The type and meaning of this parameter depends on the message.
726
727 @param lParam:
728 The type and meaning of this parameter depends on the message.
729
730 @param dwTimeout: Optional timeout for the operation.
731 Use C{None} to wait indefinitely.
732
733 @rtype: int
734 @return: The meaning of the return value depends on the window message.
735 Typically a value of C{0} means an error occured. You can get the
736 error code by calling L{win32.GetLastError}.
737 """
738 if dwTimeout is None:
739 return win32.SendMessage(self.get_handle(), uMsg, wParam, lParam)
740 return win32.SendMessageTimeout(
741 self.get_handle(), uMsg, wParam, lParam,
742 win32.SMTO_ABORTIFHUNG | win32.SMTO_ERRORONEXIT, dwTimeout)
743
744 - def post(self, uMsg, wParam = None, lParam = None):
745 """
746 Post a low-level window message asyncronically.
747
748 @type uMsg: int
749 @param uMsg: Message code.
750
751 @param wParam:
752 The type and meaning of this parameter depends on the message.
753
754 @param lParam:
755 The type and meaning of this parameter depends on the message.
756
757 @raise WindowsError: An error occured while sending the message.
758 """
759 win32.PostMessage(self.get_handle(), uMsg, wParam, lParam)
760