pyWinAuto: c:\.projects\py_pywinauto\pywinauto\controls\win32_controls.py
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021"Wraps various standard windows controls"
0022
0023__revision__ = "$Revision: 492 $"
0024
0025import time
0026
0027import ctypes
0028
0029import HwndWrapper
0030
0031from pywinauto import win32functions
0032from pywinauto import win32defines
0033from pywinauto import win32structures
0034
0035
0036from pywinauto import tests
0037from pywinauto.timings import Timings
0038
0039
0040class ButtonWrapper(HwndWrapper.HwndWrapper):
0041 "Wrap a windows Button control"
0042
0043 friendlyclassname = "Button"
0044 windowclasses = [
0045 "Button",
0046 r"WindowsForms\d*\.BUTTON\..*",
0047 "TButton" ]
0048
0049
0050
0051 def __init__(self, hwnd):
0052 "Initialize the control"
0053 super(ButtonWrapper, self).__init__(hwnd)
0054
0055
0056
0057
0058 def _set_if_needs_image(self, value):
0059 "Does nothing see _get_if_needs_image"
0060 pass
0061
0062 def _get_if_needs_image(self):
0063 "Set the _NeedsImageProp attribute if it is an image button"
0064
0065
0066
0067 style = self.Style()
0068
0069 if self.IsVisible() and ( style & win32defines.BS_BITMAP == style or style & win32defines.BS_ICON == style or style & win32defines.BS_OWNERDRAW == style):
0073
0074
0075 return True
0076 else:
0077 return False
0078 _NeedsImageProp = property(_get_if_needs_image, _set_if_needs_image)
0079
0080
0081 def FriendlyClassName(self):
0082 """Return the friendly class name of the button
0083
0084 Windows controls with the class "Button" can look like different
0085 controls based on their style. They can look like the following
0086 controls:
0087
0088 - Buttons, this method returns "Button"
0089 - CheckBoxes, this method returns "CheckBox"
0090 - RadioButtons, this method returns "RadioButton"
0091 - GroupBoxes, this method returns "GroupBox"
0092
0093 """
0094
0095 style_lsb = self.Style() & 0xF
0096
0097 f_class_name = 'Button'
0098
0099 if style_lsb == win32defines.BS_3STATE or style_lsb == win32defines.BS_AUTO3STATE or style_lsb == win32defines.BS_AUTOCHECKBOX or style_lsb == win32defines.BS_CHECKBOX:
0103 f_class_name = "CheckBox"
0104
0105 elif style_lsb == win32defines.BS_RADIOBUTTON or style_lsb == win32defines.BS_AUTORADIOBUTTON:
0107 f_class_name = "RadioButton"
0108
0109 elif style_lsb == win32defines.BS_GROUPBOX:
0110 f_class_name = "GroupBox"
0111
0112 if self.Style() & win32defines.BS_PUSHLIKE:
0113 f_class_name = "Button"
0114
0115 return f_class_name
0116
0117
0118
0119 def GetCheckState(self):
0120 """Return the check state of the checkbox
0121
0122 The check state is represented by an integer
0123 0 - unchecked
0124 1 - checked
0125 2 - indeterminate
0126
0127 The following constants are defined in the win32defines module
0128 BST_UNCHECKED = 0
0129 BST_CHECKED = 1
0130 BST_INDETERMINATE = 2
0131 """
0132 return self.SendMessage(win32defines.BM_GETCHECK)
0133
0134
0135 def Check(self):
0136 "Check a checkbox"
0137 self.SendMessageTimeout(win32defines.BM_SETCHECK,
0138 win32defines.BST_CHECKED)
0139
0140 win32functions.WaitGuiThreadIdle(self)
0141 time.sleep(Timings.after_buttoncheck_wait)
0142
0143
0144 return self
0145
0146
0147
0148 def UnCheck(self):
0149 "Uncheck a checkbox"
0150 self.SendMessageTimeout(win32defines.BM_SETCHECK,
0151 win32defines.BST_UNCHECKED)
0152
0153 win32functions.WaitGuiThreadIdle(self)
0154 time.sleep(Timings.after_buttoncheck_wait)
0155
0156
0157 return self
0158
0159
0160 def SetCheckIndeterminate(self):
0161 "Set the checkbox to indeterminate"
0162 self.SendMessageTimeout(win32defines.BM_SETCHECK,
0163 win32defines.BST_INDETERMINATE)
0164
0165 win32functions.WaitGuiThreadIdle(self)
0166 time.sleep(Timings.after_buttoncheck_wait)
0167
0168
0169 return self
0170
0171
0172 def IsDialog(self):
0173 "Buttons are never dialogs so return False"
0174 return False
0175
0176
0177 def Click(self, *args, **kwargs):
0178 "Click the Button control"
0179
0180
0181
0182 HwndWrapper.HwndWrapper.Click(self, *args, **kwargs)
0183
0184 time.sleep(Timings.after_button_click_wait)
0185
0186
0187
0188
0189
0190
0191
0192
0193def _get_multiple_text_items(wrapper, count_msg, item_len_msg, item_get_msg):
0194 "Helper function to get multiple text items from a control"
0195
0196 texts = []
0197
0198
0199 num_items = wrapper.SendMessage(count_msg)
0200
0201
0202 for i in range(0, num_items):
0203 text_len = wrapper.SendMessage (item_len_msg, i, 0)
0204
0205 text = ctypes.create_unicode_buffer(text_len + 1)
0206
0207 wrapper.SendMessage(item_get_msg, i, ctypes.byref(text))
0208
0209 texts.append(text.value)
0210
0211 return texts
0212
0213
0214
0215class ComboBoxWrapper(HwndWrapper.HwndWrapper):
0216 "Wrap a windows ComboBox control"
0217
0218 friendlyclassname = "ComboBox"
0219 windowclasses = [
0220 "ComboBox",
0221 "WindowsForms\d*\.COMBOBOX\..*",
0222 "TComboBox"]
0223
0224
0225 def __init__(self, hwnd):
0226 "Initialize the control"
0227 super(ComboBoxWrapper, self).__init__(hwnd)
0228
0229 self.writable_props.extend([
0230 "SelectedIndex",
0231 "DroppedRect",
0232 ])
0233
0234
0235 def DroppedRect(self):
0236 "Get the dropped rectangle of the combobox"
0237 dropped_rect = win32structures.RECT()
0238
0239 self.SendMessage(
0240 win32defines.CB_GETDROPPEDCONTROLRECT,
0241 0,
0242 ctypes.byref(dropped_rect))
0243
0244
0245 dropped_rect -= self.Rectangle()
0246
0247 return dropped_rect
0248
0249
0250 def ItemCount(self):
0251 "Return the number of items in the combobox"
0252 return self.SendMessage(win32defines.CB_GETCOUNT)
0253
0254
0255 def SelectedIndex(self):
0256 "Return the selected index"
0257 return self.SendMessage(win32defines.CB_GETCURSEL)
0258
0259
0260 def _get_item_index(self, ident):
0261 "Get the index for the item with this 'ident'"
0262 if isinstance(ident, (int, long)):
0263
0264 if ident >= self.ItemCount():
0265 raise IndexError(
0266 "Combobox has %d items, you requested item %d"%
0267 (self.ItemCount(),
0268 ident))
0269
0270
0271 if ident < 0:
0272
0273 ident = (self.ItemCount() + ident)
0274
0275 elif isinstance(ident, basestring):
0276
0277
0278 ident = self.ItemTexts().index(ident)
0279
0280 return ident
0281
0282
0283
0284 def ItemData(self, item):
0285 "Return the item data associted with this item"
0286 index = self._get_item_index(item)
0287 "Returns the item data associated with the item if any"
0288 return self.SendMessage(win32defines.CB_GETITEMDATA, index)
0289
0290
0291 def ItemTexts(self):
0292 "Return the text of the items of the combobox"
0293 return _get_multiple_text_items(
0294 self,
0295 win32defines.CB_GETCOUNT,
0296 win32defines.CB_GETLBTEXTLEN,
0297 win32defines.CB_GETLBTEXT)
0298
0299
0300 def Texts(self):
0301 "Return the text of the items in the combobox"
0302 texts = [self.WindowText()]
0303 texts.extend(self.ItemTexts())
0304 return texts
0305
0306
0307 def GetProperties(self):
0308 "Return the properties of the control as a dictionary"
0309 props = HwndWrapper.HwndWrapper.GetProperties(self)
0310
0311
0312
0313
0314
0315 return props
0316
0317
0318 def Select(self, item):
0319 """Select the ComboBox item
0320
0321 item can be either a 0 based index of the item to select
0322 or it can be the string that you want to select
0323 """
0324 self.VerifyActionable()
0325
0326 index = self._get_item_index(item)
0327
0328
0329 self.SendMessageTimeout(win32defines.CB_SETCURSEL, index)
0330
0331
0332 self.NotifyParent(win32defines.CBN_SELENDOK)
0333
0334
0335 self.NotifyParent(win32defines.CBN_SELCHANGE)
0336
0337
0338
0339 if self.HasStyle(win32defines.CBS_DROPDOWN):
0340
0341 self.NotifyParent(win32defines.CBN_CLOSEUP)
0342
0343
0344 win32functions.WaitGuiThreadIdle(self)
0345 time.sleep(Timings.after_comboboxselect_wait)
0346
0347
0348 return self
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364class ListBoxWrapper(HwndWrapper.HwndWrapper):
0365 "Wrap a windows ListBox control"
0366
0367 friendlyclassname = "ListBox"
0368 windowclasses = [
0369 "ListBox",
0370 r"WindowsForms\d*\.LISTBOX\..*",
0371 "TListBox",]
0372
0373
0374 def __init__(self, hwnd):
0375 "Initialize the control"
0376 super(ListBoxWrapper, self).__init__(hwnd)
0377
0378 self.writable_props.extend([
0379 "SelectedIndices"])
0380
0381
0382 def SelectedIndices(self):
0383 "The currently selected indices of the listbox"
0384 num_selected = self.SendMessage(win32defines.LB_GETSELCOUNT)
0385
0386
0387 if num_selected == win32defines.LB_ERR:
0388 items = [self.SendMessage(win32defines.LB_GETCURSEL)]
0389
0390
0391 else:
0392 items = (ctypes.c_int * num_selected)()
0393
0394 self.SendMessage(
0395 win32defines.LB_GETSELITEMS, num_selected, ctypes.byref(items))
0396
0397 return items
0398
0399
0400 def _get_item_index(self, ident):
0401 "Return the index of the item 'ident'"
0402 if isinstance(ident, (int, long)):
0403
0404 if ident >= self.ItemCount():
0405 raise IndexError(
0406 "ListBox has %d items, you requested item %d"%
0407 (self.ItemCount(),
0408 ident))
0409
0410
0411 if ident < 0:
0412 ident = (self.ItemCount() + ident)
0413
0414 elif isinstance(ident, basestring):
0415
0416
0417 ident = self.ItemTexts().index(ident)
0418
0419 return ident
0420
0421
0422 def ItemCount(self):
0423 "Return the number of items in the ListBox"
0424 return self.SendMessage(win32defines.LB_GETCOUNT)
0425
0426
0427 def ItemData(self, i):
0428 "Return the ItemData if any associted with the item"
0429
0430 index = self._get_item_index(i)
0431
0432 return self.SendMessage(win32defines.LB_GETITEMDATA, index)
0433
0434
0435 def ItemTexts(self):
0436 "Return the text of the items of the listbox"
0437 return _get_multiple_text_items(
0438 self,
0439 win32defines.LB_GETCOUNT,
0440 win32defines.LB_GETTEXTLEN,
0441 win32defines.LB_GETTEXT)
0442
0443
0444 def Texts(self):
0445 "Return the texts of the control"
0446 texts = [self.WindowText()]
0447 texts.extend(self.ItemTexts())
0448 return texts
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462 def Select(self, item):
0463 """Select the ListBox item
0464
0465 item can be either a 0 based index of the item to select
0466 or it can be the string that you want to select
0467 """
0468 self.VerifyActionable()
0469
0470
0471
0472 index = self._get_item_index(item)
0473
0474
0475 self.SendMessageTimeout(win32defines.LB_SETCURSEL, index)
0476
0477
0478 self.NotifyParent(win32defines.LBN_SELCHANGE)
0479
0480 win32functions.WaitGuiThreadIdle(self)
0481 time.sleep(Timings.after_listboxselect_wait)
0482
0483 return self
0484
0485
0486 def SetItemFocus(self, item):
0487 "Set the ListBox focus to the item at index"
0488
0489 index = self._get_item_index(item)
0490
0491
0492 if self.HasStyle(win32defines.LBS_EXTENDEDSEL) or self.HasStyle(win32defines.LBS_MULTIPLESEL):
0494 self.SendMessageTimeout(win32defines.LB_SETCARETINDEX, index)
0495 else:
0496 self.SendMessageTimeout(win32defines.LB_SETCURSEL, index)
0497
0498 win32functions.WaitGuiThreadIdle(self)
0499 time.sleep(Timings.after_listboxfocuschange_wait)
0500
0501
0502 return self
0503
0504
0505
0506 def GetItemFocus(self):
0507 "Retrun the index of current selection in a ListBox"
0508
0509
0510 if self.HasStyle(win32defines.LBS_EXTENDEDSEL) or self.HasStyle(win32defines.LBS_MULTIPLESEL):
0512 return self.SendMessage(win32defines.LB_GETCARETINDEX)
0513 else:
0514 return self.SendMessage(win32defines.LB_GETCURSEL)
0515
0516
0517
0518class EditWrapper(HwndWrapper.HwndWrapper):
0519 "Wrap a windows Edit control"
0520
0521 friendlyclassname = "Edit"
0522 windowclasses = [
0523 "Edit",
0524 "TEdit",
0525 "TMemo",
0526 r"WindowsForms\d*\.EDIT\..*",
0527 ]
0528
0529
0530 def __init__(self, hwnd):
0531 "Initialize the control"
0532 super(EditWrapper, self).__init__(hwnd)
0533
0534 self.writable_props.extend([
0535 'SelectionIndices'])
0536
0537
0538 def LineCount(self):
0539 "Return how many lines there are in the Edit"
0540 return self.SendMessage(win32defines.EM_GETLINECOUNT)-1
0541
0542
0543 def LineLength(self, line_index):
0544 "Return how many characters there are in the line"
0545
0546
0547 char_index = self.SendMessage(win32defines.EM_LINEINDEX, line_index)
0548
0549
0550 return self.SendMessage (
0551 win32defines.EM_LINELENGTH, char_index, 0)
0552
0553
0554
0555 def GetLine(self, line_index):
0556 "Return the line specified"
0557
0558 text_len = self.LineLength(line_index)
0559
0560 text = ctypes.create_unicode_buffer(text_len+3)
0561 text[0] = unichr(text_len)
0562
0563
0564 self.SendMessage(
0565 win32defines.EM_GETLINE, line_index, ctypes.byref(text))
0566
0567 return text.value
0568
0569
0570 def Texts(self):
0571 "Get the text of the edit control"
0572
0573 texts = [self.WindowText(), ]
0574
0575 for i in range(0, self.LineCount()+1):
0576 texts.append(self.GetLine(i))
0577
0578 return texts
0579
0580
0581 def TextBlock(self):
0582 "Get the text of the edit control"
0583
0584 length = self.SendMessage(win32defines.WM_GETTEXTLENGTH)
0585 text = ctypes.create_unicode_buffer(length + 1)
0586 self.SendMessage(win32defines.WM_GETTEXT, length+1, ctypes.byref(text))
0587
0588
0589 return text.value
0590
0591
0592 def SelectionIndices(self):
0593 "The start and end indices of the current selection"
0594 start = ctypes.c_int()
0595 end = ctypes.c_int()
0596 self.