ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/ns_dev/Python/NinoCode/Active_prgs/winGuiAuto.py
Revision: 8
Committed: Sat May 5 04:21:19 2012 UTC (13 years, 10 months ago) by ninoborges
Content type: text/x-python
File size: 30593 byte(s)
Log Message:
Initial Import

File Contents

# Content
1 # Module : winGuiAuto.py
2 # Synopsis : Windows GUI automation utilities
3 # Programmer : Simon Brunning - simon@brunningonline.net
4 # Date : 25 June 2003
5 # Version : 1.0 pre-alpha 2
6 # Copyright : Released to the public domain. Provided as-is, with no warranty.
7 # Notes : Requires Python 2.3, win32all and ctypes
8 '''Windows GUI automation utilities.
9
10 Until I get around to writing some docs and examples, the tests at the foot of
11 this module should serve to get you started.
12 '''
13
14 import array
15 import ctypes
16 import os
17 import struct
18 import sys
19 import win32api
20 import win32con
21 import win32gui
22
23 def findTopWindow(wantedText=None, wantedClass=None, selectionFunction=None):
24 '''Find the hwnd of a top level window.
25 You can identify windows using captions, classes, a custom selection
26 function, or any combination of these. (Multiple selection criteria are
27 ANDed. If this isn't what's wanted, use a selection function.)
28
29 Arguments:
30 wantedText Text which the required window's captions must contain.
31 wantedClass Class to which the required window must belong.
32 selectionFunction Window selection function. Reference to a function
33 should be passed here. The function should take hwnd as
34 an argument, and should return True when passed the
35 hwnd of a desired window.
36
37 Raises:
38 WinGuiAutoError When no window found.
39
40 Usage example: optDialog = findTopWindow(wantedText="Options")
41 '''
42 topWindows = findTopWindows(wantedText, wantedClass, selectionFunction)
43 if topWindows:
44 return topWindows[0]
45 else:
46 raise WinGuiAutoError("No top level window found for wantedText=" +
47 repr(wantedText) +
48 ", wantedClass=" +
49 repr(wantedClass) +
50 ", selectionFunction=" +
51 repr(selectionFunction))
52
53 def findTopWindows(wantedText=None, wantedClass=None, selectionFunction=None):
54 '''Find the hwnd of top level windows.
55 You can identify windows using captions, classes, a custom selection
56 function, or any combination of these. (Multiple selection criteria are
57 ANDed. If this isn't what's wanted, use a selection function.)
58
59 Arguments:
60 wantedText Text which required windows' captions must contain.
61 wantedClass Class to which required windows must belong.
62 selectionFunction Window selection function. Reference to a function
63 should be passed here. The function should take hwnd as
64 an argument, and should return True when passed the
65 hwnd of a desired window.
66
67 Returns: A list containing the window handles of all top level
68 windows matching the supplied selection criteria.
69
70 Usage example: optDialogs = findTopWindows(wantedText="Options")
71 '''
72 results = []
73 topWindows = []
74 win32gui.EnumWindows(_windowEnumerationHandler, topWindows)
75 for hwnd, windowText, windowClass in topWindows:
76 if wantedText and not _normaliseText(wantedText) in _normaliseText(windowText):
77 continue
78 if wantedClass and not windowClass == wantedClass:
79 continue
80 if selectionFunction and not selectionFunction(hwnd):
81 continue
82 results.append(hwnd)
83 return results
84
85 def dumpWindow(hwnd):
86 '''Dump all controls from a window into a nested list
87 Useful during development, allowing to you discover the structure of the
88 contents of a window, showing the text and class of all contained controls.
89
90 Arguments: The window handle of the top level window to dump.
91
92 Returns A nested list of controls. Each entry consists of the
93 control's hwnd, its text, its class, and its sub-controls,
94 if any.
95
96 Usage example: replaceDialog = findTopWindow(wantedText='Replace')
97 pprint.pprint(dumpWindow(replaceDialog))
98 '''
99 windows = []
100 try:
101 win32gui.EnumChildWindows(hwnd, _windowEnumerationHandler, windows)
102 except win32gui.error:
103 # No child windows
104 return
105 windows = [list(window) for window in windows]
106 for window in windows:
107 childHwnd, windowText, windowClass = window
108 window_content = dumpWindow(childHwnd)
109 if window_content:
110 window.append(window_content)
111 return windows
112
113 def findControl(topHwnd,
114 wantedText=None,
115 wantedClass=None,
116 selectionFunction=None):
117 '''Find a control.
118 You can identify a control using caption, classe, a custom selection
119 function, or any combination of these. (Multiple selection criteria are
120 ANDed. If this isn't what's wanted, use a selection function.)
121
122 Arguments:
123 topHwnd The window handle of the top level window in which the
124 required controls reside.
125 wantedText Text which the required control's captions must contain.
126 wantedClass Class to which the required control must belong.
127 selectionFunction Control selection function. Reference to a function
128 should be passed here. The function should take hwnd as
129 an argument, and should return True when passed the
130 hwnd of the desired control.
131
132 Returns: The window handle of the first control matching the
133 supplied selection criteria.
134
135 Raises:
136 WinGuiAutoError When no control found.
137
138 Usage example: optDialog = findTopWindow(wantedText="Options")
139 okButton = findControl(optDialog,
140 wantedClass="Button",
141 wantedText="OK")
142 '''
143 controls = findControls(topHwnd,
144 wantedText=wantedText,
145 wantedClass=wantedClass,
146 selectionFunction=selectionFunction)
147 if controls:
148 return controls[0]
149 else:
150 raise WinGuiAutoError("No control found for topHwnd=" +
151 repr(topHwnd) +
152 ", wantedText=" +
153 repr(wantedText) +
154 ", wantedClass=" +
155 repr(wantedClass) +
156 ", selectionFunction=" +
157 repr(selectionFunction))
158
159 def findControls(topHwnd,
160 wantedText=None,
161 wantedClass=None,
162 selectionFunction=None):
163 '''Find controls.
164 You can identify controls using captions, classes, a custom selection
165 function, or any combination of these. (Multiple selection criteria are
166 ANDed. If this isn't what's wanted, use a selection function.)
167
168 Arguments:
169 topHwnd The window handle of the top level window in which the
170 required controls reside.
171 wantedText Text which the required controls' captions must contain.
172 wantedClass Class to which the required controls must belong.
173 selectionFunction Control selection function. Reference to a function
174 should be passed here. The function should take hwnd as
175 an argument, and should return True when passed the
176 hwnd of a desired control.
177
178 Returns: The window handles of the controls matching the
179 supplied selection criteria.
180
181 Usage example: optDialog = findTopWindow(wantedText="Options")
182 def findButtons(hwnd, windowText, windowClass):
183 return windowClass == "Button"
184 buttons = findControl(optDialog, wantedText="Button")
185 '''
186 def searchChildWindows(currentHwnd):
187 results = []
188 childWindows = []
189 try:
190 win32gui.EnumChildWindows(currentHwnd,
191 _windowEnumerationHandler,
192 childWindows)
193 except win32gui.error:
194 # This seems to mean that the control *cannot* have child windows,
195 # i.e. not a container.
196 return
197 for childHwnd, windowText, windowClass in childWindows:
198 descendentMatchingHwnds = searchChildWindows(childHwnd)
199 if descendentMatchingHwnds:
200 results += descendentMatchingHwnds
201
202 if wantedText and \
203 not _normaliseText(wantedText) in _normaliseText(windowText):
204 continue
205 if wantedClass and \
206 not windowClass == wantedClass:
207 continue
208 if selectionFunction and \
209 not selectionFunction(childHwnd):
210 continue
211 results.append(childHwnd)
212 return results
213
214 return searchChildWindows(topHwnd)
215
216 def getTopMenu(hWnd):
217 '''Get a window's main, top level menu.
218
219 Arguments:
220 hWnd The window handle of the top level window for which the top
221 level menu is required.
222
223 Returns: The menu handle of the window's main, top level menu.
224
225 Usage example: hMenu = getTopMenu(hWnd)'''
226 return ctypes.windll.user32.GetMenu(ctypes.c_long(hWnd))
227
228 def activateMenuItem(hWnd, menuItemPath):
229 '''Activate a menu item
230
231 Arguments:
232 hWnd The window handle of the top level window whose menu you
233 wish to activate.
234 menuItemPath The path to the required menu item. This should be a
235 sequence specifying the path through the menu to the
236 required item. Each item in this path can be specified
237 either as an index, or as a menu name.
238
239 Raises:
240 WinGuiAutoError When the requested menu option isn't found.
241
242 Usage example: activateMenuItem(notepadWindow, ('file', 'open'))
243
244 Which is exactly equivalent to...
245
246 activateMenuItem(notepadWindow, (0, 1))'''
247 # By Axel Kowald (kowald@molgen.mpg.de)
248 # Modified by S Brunning to accept strings in addition to indicies.
249
250 # Top level menu
251 hMenu = getTopMenu(hWnd)
252
253 # Get top level menu's item count. Is there a better way to do this?
254 for hMenuItemCount in xrange(256):
255 try:
256 getMenuInfo(hMenu, hMenuItemCount)
257 except WinGuiAutoError:
258 break
259 hMenuItemCount -= 1
260
261 # Walk down submenus
262 for submenu in menuItemPath[:-1]:
263 try: # submenu is an index
264 0 + submenu
265 submenuInfo = getMenuInfo(hMenu, submenu)
266 hMenu, hMenuItemCount = submenuInfo.submenu, submenuInfo.itemCount
267 except TypeError: # Hopefully, submenu is a menu name
268 try:
269 dump, hMenu, hMenuItemCount = _findNamedSubmenu(hMenu,
270 hMenuItemCount,
271 submenu)
272 except WinGuiAutoError:
273 raise WinGuiAutoError("Menu path " +
274 repr(menuItemPath) +
275 " cannot be found.")
276
277 # Get required menu item's ID. (the one at the end).
278 menuItem = menuItemPath[-1]
279 try: # menuItem is an index
280 0 + menuItem
281 menuItemID = ctypes.windll.user32.GetMenuItemID(hMenu,
282 menuItem)
283 except TypeError: # Hopefully, menuItem is a menu name
284 try:
285 subMenuIndex, dump, dump = _findNamedSubmenu(hMenu,
286 hMenuItemCount,
287 menuItem)
288 except WinGuiAutoError:
289 raise WinGuiAutoError("Menu path " +
290 repr(menuItemPath) +
291 " cannot be found.")
292 # TODO - catch WinGuiAutoError. and pass on with better info.
293 menuItemID = ctypes.windll.user32.GetMenuItemID(hMenu, subMenuIndex)
294
295 # Activate
296 win32gui.PostMessage(hWnd, win32con.WM_COMMAND, menuItemID, 0)
297
298 def getMenuInfo(hMenu, uIDItem):
299 '''Get various info about a menu item.
300
301 Arguments:
302 hMenu The menu in which the item is to be found.
303 uIDItem The item's index
304
305 Returns: Menu item information object. This object is basically
306 a 'bunch'
307 (see http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52308).
308 It will have useful attributes: name, itemCount,
309 submenu, isChecked, isDisabled, isGreyed, and
310 isSeperator
311
312 Raises:
313 WinGuiAutoError When the requested menu option isn't found.
314
315 Usage example: submenuInfo = getMenuInfo(hMenu, submenu)
316 hMenu, hMenuItemCount = submenuInfo.submenu, submenuInfo.itemCount'''
317 # An object to hold the menu info
318 class MenuInfo(Bunch):
319 pass
320 menuInfo = MenuInfo()
321
322 # Menu state
323 menuState = ctypes.windll.user32.GetMenuState(hMenu,
324 uIDItem,
325 win32con.MF_BYPOSITION)
326 if menuState == -1:
327 raise WinGuiAutoError("No such menu item, hMenu=" +
328 str(hMenu) +
329 " uIDItem=" +
330 str(uIDItem))
331 menuInfo.isChecked = bool(menuState & win32con.MF_CHECKED)
332 menuInfo.isDisabled = bool(menuState & win32con.MF_DISABLED)
333 menuInfo.isGreyed = bool(menuState & win32con.MF_GRAYED)
334 menuInfo.isSeperator = bool(menuState & win32con.MF_SEPARATOR)
335 # ... there are more, but these are the ones I'm interested in
336
337 # Menu name
338 menuName = ctypes.c_buffer("\000" * 32)
339 ctypes.windll.user32.GetMenuStringA(ctypes.c_int(hMenu),
340 ctypes.c_int(uIDItem),
341 menuName, ctypes.c_int(len(menuName)),
342 win32con.MF_BYPOSITION)
343 menuInfo.name = menuName.value
344
345 # Sub menu info
346 menuInfo.itemCount = menuState >> 8
347 if bool(menuState & win32con.MF_POPUP):
348 menuInfo.submenu = ctypes.windll.user32.GetSubMenu(hMenu, uIDItem)
349 else:
350 menuInfo.submenu = None
351
352 return menuInfo
353
354 def clickButton(hwnd):
355 '''Simulates a single mouse click on a button
356
357 Arguments:
358 hwnd Window handle of the required button.
359
360 Usage example: okButton = findControl(fontDialog,
361 wantedClass="Button",
362 wantedText="OK")
363 clickButton(okButton)
364 '''
365 _sendNotifyMessage(hwnd, win32con.BN_CLICKED)
366
367 def clickStatic(hwnd):
368 '''Simulates a single mouse click on a static
369
370 Arguments:
371 hwnd Window handle of the required static.
372
373 Usage example: TODO
374 '''
375 _sendNotifyMessage(hwnd, win32con.STN_CLICKED)
376
377 def doubleClickStatic(hwnd):
378 '''Simulates a double mouse click on a static
379
380 Arguments:
381 hwnd Window handle of the required static.
382
383 Usage example: TODO
384 '''
385 _sendNotifyMessage(hwnd, win32con.STN_DBLCLK)
386
387 def getComboboxItems(hwnd):
388 '''Returns the items in a combo box control.
389
390 Arguments:
391 hwnd Window handle for the combo box.
392
393 Returns: Combo box items.
394
395 Usage example: fontCombo = findControl(fontDialog, wantedClass="ComboBox")
396 fontComboItems = getComboboxItems(fontCombo)
397 '''
398
399 return _getMultipleWindowValues(hwnd,
400 getCountMessage=win32con.CB_GETCOUNT,
401 getValueMessage=win32con.CB_GETLBTEXT)
402
403 def selectComboboxItem(hwnd, item):
404 '''Selects a specified item in a Combo box control.
405
406 Arguments:
407 hwnd Window handle of the required combo box.
408 item The reqired item. Either an index, of the text of the
409 required item.
410
411 Usage example: fontComboItems = getComboboxItems(fontCombo)
412 selectComboboxItem(fontCombo,
413 random.choice(fontComboItems))
414 '''
415 try: # item is an index Use this to select
416 0 + item
417 win32gui.SendMessage(hwnd, win32con.CB_SETCURSEL, item, 0)
418 _sendNotifyMessage(hwnd, win32con.CBN_SELCHANGE)
419 except TypeError: # Item is a string - find the index, and use that
420 items = getComboboxItems(hwnd)
421 itemIndex = items.index(item)
422 selectComboboxItem(hwnd, itemIndex)
423
424 def getListboxItems(hwnd):
425 '''Returns the items in a list box control.
426
427 Arguments:
428 hwnd Window handle for the list box.
429
430 Returns: List box items.
431
432 Usage example: TODO
433 '''
434
435 return _getMultipleWindowValues(hwnd,
436 getCountMessage=win32con.LB_GETCOUNT,
437 getValueMessage=win32con.LB_GETTEXT)
438
439 def selectListboxItem(hwnd, item):
440 '''Selects a specified item in a list box control.
441
442 Arguments:
443 hwnd Window handle of the required list box.
444 item The reqired item. Either an index, of the text of the
445 required item.
446
447 Usage example: TODO
448 '''
449 try: # item is an index Use this to select
450 0 + item
451 win32gui.SendMessage(hwnd, win32con.LB_SETCURSEL, item, 0)
452 _sendNotifyMessage(hwnd, win32con.LBN_SELCHANGE)
453 except TypeError: # Item is a string - find the index, and use that
454 items = getListboxItems(hwnd)
455 itemIndex = items.index(item)
456 selectListboxItem(hwnd, itemIndex)
457
458 def getEditText(hwnd):
459 '''Returns the text in an edit control.
460
461 Arguments:
462 hwnd Window handle for the edit control.
463
464 Returns Edit control text lines.
465
466 Usage example: pprint.pprint(getEditText(editArea))
467 '''
468 return _getMultipleWindowValues(hwnd,
469 getCountMessage=win32con.EM_GETLINECOUNT,
470 getValueMessage=win32con.EM_GETLINE)
471
472 def setEditText(hwnd, text, append=False):
473 '''Set an edit control's text.
474
475 Arguments:
476 hwnd The edit control's hwnd.
477 text The text to send to the control. This can be a single
478 string, or a sequence of strings. If the latter, each will
479 be become a a seperate line in the control.
480 append Should the new text be appended to the existing text?
481 Defaults to False, meaning that any existing text will be
482 replaced. If True, the new text will be appended to the end
483 of the existing text.
484 Note that the first line of the new text will be directly
485 appended to the end of the last line of the existing text.
486 If appending lines of text, you may wish to pass in an
487 empty string as the 1st element of the 'text' argument.
488
489 Usage example: print "Enter various bits of text."
490 setEditText(editArea, "Hello, again!")
491 time.sleep(.5)
492 setEditText(editArea, "You still there?")
493 time.sleep(.5)
494 setEditText(editArea, ["Here come", "two lines!"])
495 time.sleep(.5)
496
497 print "Add some..."
498 setEditText(editArea, ["", "And a 3rd one!"], append=True)
499 time.sleep(.5)'''
500
501 # Ensure that text is a list
502 try:
503 text + ''
504 text = [text]
505 except TypeError:
506 pass
507
508 # Set the current selection range, depending on append flag
509 if append:
510 win32gui.SendMessage(hwnd,
511 win32con.EM_SETSEL,
512 -1,
513 0)
514 else:
515 win32gui.SendMessage(hwnd,
516 win32con.EM_SETSEL,
517 0,
518 -1)
519
520 # Send the text
521 win32gui.SendMessage(hwnd,
522 win32con.EM_REPLACESEL,
523 True,
524 os.linesep.join(text))
525
526 def _getMultipleWindowValues(hwnd, getCountMessage, getValueMessage):
527 '''A common pattern in the Win32 API is that in order to retrieve a
528 series of values, you use one message to get a count of available
529 items, and another to retrieve them. This internal utility function
530 performs the common processing for this pattern.
531
532 Arguments:
533 hwnd Window handle for the window for which items should be
534 retrieved.
535 getCountMessage Item count message.
536 getValueMessage Value retrieval message.
537
538 Returns: Retrieved items.'''
539 result = []
540
541 VALUE_LENGTH = 256
542 bufferlength_int = struct.pack('i', VALUE_LENGTH) # This is a C style int.
543
544 valuecount = win32gui.SendMessage(hwnd, getCountMessage, 0, 0)
545 for itemIndex in range(valuecount):
546 valuebuffer = array.array('c',
547 bufferlength_int +
548 " " * (VALUE_LENGTH - len(bufferlength_int)))
549 valueLength = win32gui.SendMessage(hwnd,
550 getValueMessage,
551 itemIndex,
552 valuebuffer)
553 result.append(valuebuffer.tostring()[:valueLength])
554 return result
555
556 def _windowEnumerationHandler(hwnd, resultList):
557 '''Pass to win32gui.EnumWindows() to generate list of window handle,
558 window text, window class tuples.'''
559 resultList.append((hwnd,
560 win32gui.GetWindowText(hwnd),
561 win32gui.GetClassName(hwnd)))
562
563 def _buildWinLong(high, low):
564 '''Build a windows long parameter from high and low words.
565 See http://support.microsoft.com/support/kb/articles/q189/1/70.asp
566 '''
567 # return ((high << 16) | low)
568 return int(struct.unpack('>L',
569 struct.pack('>2H',
570 high,
571 low)) [0])
572
573 def _sendNotifyMessage(hwnd, nofifyMessage):
574 '''Send a notify message to a control.'''
575 win32gui.SendMessage(win32gui.GetParent(hwnd),
576 win32con.WM_COMMAND,
577 _buildWinLong(nofifyMessage,
578 win32api.GetWindowLong(hwnd,
579 win32con.GWL_ID)),
580 hwnd)
581
582 def _normaliseText(controlText):
583 '''Remove '&' characters, and lower case.
584 Useful for matching control text.'''
585 return controlText.lower().replace('&', '')
586
587 def _findNamedSubmenu(hMenu, hMenuItemCount, submenuName):
588 '''Find the index number of a menu's submenu with a specific name.'''
589 for submenuIndex in range(hMenuItemCount):
590 submenuInfo = getMenuInfo(hMenu, submenuIndex)
591 if _normaliseText(submenuInfo.name).startswith(_normaliseText(submenuName)):
592 return submenuIndex, submenuInfo.submenu, submenuInfo.itemCount
593 raise WinGuiAutoError("No submenu found for hMenu=" +
594 repr(hMenu) +
595 ", hMenuItemCount=" +
596 repr(hMenuItemCount) +
597 ", submenuName=" +
598 repr(submenuName))
599
600
601 class Bunch(object):
602 '''See http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52308'''
603
604 def __init__(self, **kwds):
605 self.__dict__.update(kwds)
606
607 def __str__(self):
608 state = ["%s=%r" % (attribute, value)
609 for (attribute, value)
610 in self.__dict__.items()]
611 return '\n'.join(state)
612
613 class WinGuiAutoError(Exception):
614 pass
615
616 if __name__ == '__main__':
617 # Test - drives notepad.
618 # I't like to use unittest here, but I've no idea how to automate these
619 # tests.
620
621 # NT/2K/XP notepads have a different menu stuctures.
622 win_version = {4: "NT", 5: "2K", 6: "XP"}[os.sys.getwindowsversion()[0]]
623 print "win_version=", win_version
624
625 import pprint
626 import random
627 import time
628
629 print "Open and locate Notepad"
630 os.startfile('notepad')
631 time.sleep(.5)
632 notepadWindow = findTopWindow(wantedClass='Notepad')
633
634 print "Open and locate the 'replace' dialogue"
635 if win_version in ["NT"]:
636 activateMenuItem(notepadWindow, ['search', 'replace'])
637 elif win_version in ["2K", "XP"]:
638 activateMenuItem(notepadWindow, ['edit', 'replace'])
639 time.sleep(.5)
640 replaceDialog = findTopWindow(wantedText='Replace')
641
642 print "Locate the 'find' edit box"
643 findValue = findControl(replaceDialog, wantedClass="Edit")
644
645 print "Enter some text - and wait long enough for it to be seen"
646 setEditText(findValue, "Hello, mate!")
647 time.sleep(.5)
648
649 print "Locate the 'cancel' button, and click it."
650 cancelButton = findControl(replaceDialog,
651 wantedClass="Button",
652 wantedText="Cancel")
653 clickButton(cancelButton)
654
655 print "Open and locate the 'font' dialogue"
656 if win_version in ["NT"]:
657 activateMenuItem(notepadWindow, ['edit', 'set font'])
658 elif win_version in ["2K", "XP"]:
659 activateMenuItem(notepadWindow, ['format', 'font'])
660 time.sleep(.5)
661 fontDialog = findTopWindow(wantedText='Font')
662
663 print "Let's see if dumping works. Dump the 'font' dialogue contents:"
664 pprint.pprint(dumpWindow(fontDialog))
665
666 print "Change the font"
667 fontCombos = findControls(fontDialog, wantedClass="ComboBox")
668 print "Find the font selection combo"
669 for fontCombo in fontCombos:
670 fontComboItems = getComboboxItems(fontCombo)
671 if 'Arial' in fontComboItems:
672 break
673
674 print "Select at random"
675 selectComboboxItem(fontCombo, random.choice(fontComboItems))
676 time.sleep(.5)
677
678 okButton = findControl(fontDialog, wantedClass="Button", wantedText="OK")
679 clickButton(okButton)
680
681 print "Locate notpads edit area, and enter various bits of text."
682 editArea = findControl(notepadWindow,wantedClass="Edit")
683 setEditText(editArea, "Hello, again!")
684 time.sleep(.5)
685 setEditText(editArea, "You still there?")
686 time.sleep(.5)
687 setEditText(editArea, ["Here come", "two lines!"])
688 time.sleep(.5)
689
690 print "Add some..."
691 setEditText(editArea, ["", "And a 3rd one!"], append=True)
692 time.sleep(.5)
693
694 print "See what's there now:"
695 pprint.pprint(getEditText(editArea))
696
697 print "Exit notepad"
698 activateMenuItem(notepadWindow, ('file', 'exit'))
699 time.sleep(.5)
700
701 print "Don't save."
702 saveDialog = findTopWindow(wantedText='Notepad')
703 time.sleep(.5)
704 noButton = findControl(saveDialog,wantedClass="Button", wantedText="no")
705 clickButton(noButton)
706
707 print "OK, now we'll have a go with WordPad."
708 os.startfile('wordpad')
709 time.sleep(1)
710 wordpadWindow = findTopWindow(wantedText='WordPad')
711
712 print "Open and locate the 'new document' dialog."
713 activateMenuItem(wordpadWindow, [0, 0])
714 time.sleep(.5)
715 newDialog = findTopWindow(wantedText='New')
716
717 print "Check you get an exception for non-existent control"
718 try:
719 findControl(newDialog, wantedClass="Banana")
720 raise Exception("Test failed")
721 except WinGuiAutoError, winGuiAutoError:
722 print "Yup, got: ", str(winGuiAutoError)
723
724 print "Locate the 'document type' list box"
725 docType = findControl(newDialog, wantedClass="ListBox")
726 typeListBox = getListboxItems(docType)
727 print "getListboxItems(docType)=", typeListBox
728
729 print "Select a type at random"
730 selectListboxItem(docType, random.randint(0, len(typeListBox)-1))
731 time.sleep(.5)
732 clickButton(findControl(newDialog, wantedClass="Button", wantedText="OK"))
733
734 print "Check you get an exception for non-existent menu path"
735 try:
736 activateMenuItem(wordpadWindow, ('not', 'there'))
737 raise Exception("Test failed")
738 except WinGuiAutoError, winGuiAutoError:
739 print "Yup, got: ", str(winGuiAutoError)
740
741 print "Check you get an exception for non-existent menu item"
742 try:
743 activateMenuItem(wordpadWindow, ('file', 'missing'))
744 raise Exception("Test failed")
745 except WinGuiAutoError, winGuiAutoError:
746 print "Yup, got: ", str(winGuiAutoError)
747
748 print "Exit wordpad"
749 activateMenuItem(wordpadWindow, ('file', 'exit'))
750
751 print "Check you get an exception for non-existent top window"
752 try:
753 findTopWindow(wantedText="Banana")
754 raise Exception("Test failed")
755 except WinGuiAutoError, winGuiAutoError:
756 print "Yup, got: ", str(winGuiAutoError)
757
758 print "Err, that's it."