pyWinAuto: c:\.projects\py_pywinauto\pywinauto\tests\truncation.py
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023"""Truncation Test
0024
0025**What is checked**
0026Checks for controls where the text does not fit in the space provided by the
0027control.
0028
0029**How is it checked**
0030There is a function in windows (DrawText) that allows us to find the size that
0031certain text will need. We use this function with correct fonts and other
0032relevant information for the control to be as accurate as possible.
0033
0034**When is a bug reported**
0035When the calculated required size for the text is greater than the size of the
0036space available for displaying the text.
0037
0038**Bug Extra Information**
0039The bug contains the following extra information
0040Name Description
0041Strings The list of the truncated strings as explained above
0042StringIndices The list of indices (0 based) that are truncated. This
0043will often just be 0 but if there are many strings in the control untranslated
0044it will report ALL the strings e.g. 0,2,5,19,23
0045
0046
0047**Is Reference dialog needed**
0048The reference dialog does not need to be available. If it is available then
0049for each bug discovered it is checked to see if it is a problem in the
0050reference dialog.
0051
0052**False positive bug reports**
0053Certain controls do not display the text that is the title of the control, if
0054this is not handled in a standard manner by the software then DLGCheck will
0055report that the string is truncated.
0056
0057**Test Identifier**
0058The identifier for this test/bug is "Truncation"
0059"""
0060
0061__revision__ = "$Revision: 286 $"
0062
0063testname = "Truncation"
0064
0065import ctypes
0066
0067from pywinauto import win32defines
0068from pywinauto import win32functions
0069from pywinauto.win32structures import RECT
0070
0071
0072
0073def TruncationTest(windows):
0074 "Actually do the test"
0075
0076 truncations = []
0077
0078
0079 for win in windows:
0080
0081 truncIdxs, truncStrings = _FindTruncations(win)
0082
0083 isInRef = -1
0084
0085
0086 if truncIdxs:
0087
0088
0089
0090 if win.ref:
0091 isInRef = 0
0092 refTruncIdxs, refTruncStrings = _FindTruncations(win.ref)
0093
0094 if refTruncIdxs:
0095 isInRef = 1
0096
0097 truncIdxs = ",".join([unicode(index) for index in truncIdxs])
0098 truncStrings = '"%s"' % ",".join(
0099 [unicode(string) for string in truncStrings])
0100 truncations.append((
0101 [win,],
0102 {
0103 "StringIndices": truncIdxs,
0104 "Strings": truncStrings,
0105 },
0106 testname,
0107 isInRef)
0108 )
0109
0110
0111 return truncations
0112
0113
0114def _FindTruncations(ctrl):
0115 "Return the index of the texts that are truncated for this control"
0116 truncIdxs = []
0117 truncStrings = []
0118
0119
0120 for idx, (text, rect, font, flags) in enumerate(_GetTruncationInfo(ctrl)):
0121
0122
0123 if not text:
0124 continue
0125
0126
0127 minRect = _GetMinimumRect(text, font, rect, flags)
0128
0129
0130
0131 if minRect.right > rect.right or minRect.bottom > rect.bottom:
0133
0134
0135 truncIdxs.append(idx)
0136 truncStrings.append(text)
0137
0138 return truncIdxs, truncStrings
0139
0140
0141
0142
0143def _GetMinimumRect(text, font, usableRect, drawFlags):
0144 """Return the minimum rectangle that the text will fit into
0145
0146 Uses font, usableRect and drawFlags information to find how
0147 how to do it accurately
0148 """
0149
0150
0151
0152 txtDC = win32functions.CreateDC(u"DISPLAY", None, None, None )
0153
0154 hFontGUI = win32functions.CreateFontIndirect(ctypes.byref(font))
0155
0156
0157 if not hFontGUI:
0158
0159
0160 hFontGUI = win32functions.GetStockObject(win32defines.DEFAULT_GUI_FONT)
0161
0162
0163
0164 if not hFontGUI:
0165
0166
0167 if win32functions.GetSystemMetrics(win32defines.SM_DBCSENABLED):
0168
0169 hFontGUI = win32functions.GetStockObject(
0170 win32defines.SYSTEM_FONT)
0171 else:
0172
0173 hFontGUI = win32functions.GetStockObject(
0174 win32defines.ANSI_VAR_FONT)
0175
0176
0177
0178 win32functions.SelectObject (txtDC, hFontGUI)
0179
0180
0181 modifiedRect = RECT(usableRect)
0182
0183
0184 win32functions.DrawText (txtDC,
0185 unicode(text),
0186 -1,
0187 ctypes.byref(modifiedRect),
0188
0189 win32defines.DT_CALCRECT | drawFlags)
0190
0191
0192
0193
0194
0195
0196
0197 win32functions.DeleteObject(hFontGUI)
0198
0199
0200 win32functions.DeleteDC(txtDC)
0201
0202 return modifiedRect
0203
0204
0205
0206
0207
0208def _ButtonTruncInfo(win):
0209 "Return truncation information specific to Button controls"
0210 lineFormat = win32defines.DT_SINGLELINE
0211
0212 widthAdj = 0
0213 heightAdj = 0
0214
0215
0216 buttonStyle = win.Style() & 0xF
0217
0218 if win.HasStyle(win32defines.BS_MULTILINE):
0219 lineFormat = win32defines.DT_WORDBREAK
0220
0221 if buttonStyle == win32defines.BS_PUSHBUTTON:
0222 heightAdj = 4
0223 widthAdj = 5
0224
0225 elif win.HasStyle(win32defines.BS_PUSHLIKE):
0226 widthAdj = 3
0227 heightAdj = 3
0228 if win.HasStyle(win32defines.BS_MULTILINE):
0229 widthAdj = 9
0230 heightAdj = 2
0231
0232 elif buttonStyle == win32defines.BS_CHECKBOX or buttonStyle == win32defines.BS_AUTOCHECKBOX:
0234 widthAdj = 18
0235
0236 elif buttonStyle == win32defines.BS_RADIOBUTTON or buttonStyle == win32defines.BS_AUTORADIOBUTTON:
0238 widthAdj = 19
0239
0240 elif buttonStyle == win32defines.BS_GROUPBOX:
0241 heightAdj = 4
0242 widthAdj = 9
0243 lineFormat = win32defines.DT_SINGLELINE
0244
0245
0246
0247
0248
0249 if win.HasStyle(win32defines.BS_BITMAP) or win.HasStyle(win32defines.BS_ICON):
0251 heightAdj = -9000
0252 widthAdj = -9000
0253 lineFormat = win32defines.DT_WORDBREAK
0254
0255 newRect = win.ClientRects()[0]
0256 newRect.right -= widthAdj
0257 newRect.bottom -= heightAdj
0258
0259 return [(win.WindowText(), newRect, win.Font(), lineFormat), ]
0260
0261
0262def _ComboBoxTruncInfo(win):
0263 "Return truncation information specific to ComboBox controls"
0264
0265 lineFormat = win32defines.DT_SINGLELINE | win32defines.DT_NOPREFIX
0266
0267 if win.HasStyle(win32defines.CBS_DROPDOWN) or win.HasStyle(win32defines.CBS_DROPDOWNLIST):
0269 widthAdj = 2
0270 else:
0271 widthAdj = 3
0272
0273 truncData = []
0274 for title in win.Texts():
0275 newRect = win.ClientRects()[0]
0276 newRect.right -= widthAdj
0277 truncData.append((title, newRect, win.Font(), lineFormat))
0278
0279 return truncData
0280
0281
0282def _ComboLBoxTruncInfo(win):
0283 "Return truncation information specific to ComboLBox controls"
0284
0285 lineFormat = win32defines.DT_SINGLELINE | win32defines.DT_NOPREFIX
0286
0287 truncData = []
0288 for title in win.Texts():
0289 newRect = win.ClientRects()[0]
0290 newRect.right -= 5
0291 truncData.append((title, newRect, win.Font(), lineFormat))
0292
0293 return truncData
0294
0295
0296
0297def _ListBoxTruncInfo(win):
0298 "Return truncation information specific to ListBox controls"
0299
0300 lineFormat = win32defines.DT_SINGLELINE | win32defines.DT_NOPREFIX
0301
0302 truncData = []
0303 for title in win.Texts():
0304 newRect = win.ClientRects()[0]
0305 newRect.right -= 2
0306 newRect.bottom -= 1
0307 truncData.append((title, newRect, win.Font(), lineFormat))
0308
0309 return truncData
0310
0311
0312
0313def _StaticTruncInfo(win):
0314 "Return truncation information specific to Static controls"
0315 lineFormat = win32defines.DT_WORDBREAK
0316
0317 if win.HasStyle(win32defines.SS_CENTERIMAGE) or win.HasStyle(win32defines.SS_SIMPLE) or win.HasStyle(win32defines.SS_LEFTNOWORDWRAP):
0320
0321 lineFormat = win32defines.DT_SINGLELINE
0322
0323 if win.HasStyle(win32defines.SS_NOPREFIX):
0324 lineFormat |= win32defines.DT_NOPREFIX
0325
0326 return [(win.WindowText(), win.ClientRects()[0], win.Font(), lineFormat), ]
0327
0328
0329def _EditTruncInfo(win):
0330 "Return truncation information specific to Edit controls"
0331 lineFormat = win32defines.DT_WORDBREAK | win32defines.DT_NOPREFIX
0332
0333 if not win.HasStyle(win32defines.ES_MULTILINE):
0334 lineFormat |= win32defines.DT_SINGLELINE
0335
0336 return [(win.WindowText(), win.ClientRects()[0], win.Font(), lineFormat), ]
0337
0338
0339
0340def _DialogTruncInfo(win):
0341 "Return truncation information specific to Header controls"
0342
0343
0344 newRect = win.ClientRects()[0]
0345
0346 newRect.top += 5
0347 newRect.left += 5
0348 newRect.right -= 5
0349
0350
0351 if win.HasStyle(win32defines.WS_THICKFRAME):
0352 newRect.top += 1
0353 newRect.left += 1
0354 newRect.right -= 1
0355
0356
0357
0358 if win.HasStyle(win32defines.WS_SYSMENU) and (win.HasExStyle(win32defines.WS_EX_PALETTEWINDOW) or
0360 win.HasExStyle(win32defines.WS_EX_TOOLWINDOW)):
0361 newRect.right -= 15
0362
0363
0364
0365 elif win.HasStyle(win32defines.WS_SYSMENU):
0366 buttons = []
0367
0368 newRect.right -= 18
0369 buttons.append('close')
0370
0371
0372 if not win.HasExStyle(win32defines.WS_EX_DLGMODALFRAME):
0373 newRect.left += 19
0374
0375
0376
0377 if win.HasExStyle(win32defines.WS_EX_CONTEXTHELP) and not ( win.HasStyle(win32defines.WS_MAXIMIZEBOX) and win.HasStyle(win32defines.WS_MINIMIZEBOX)):
0380
0381 newRect.right -= 17
0382
0383
0384 if win.HasStyle(win32defines.WS_MINIMIZEBOX) or win.HasStyle(win32defines.WS_MAXIMIZEBOX) or win.HasStyle(win32defines.WS_GROUP):
0387 newRect.right -= 3
0388
0389 buttons.append('help')
0390
0391
0392
0393 if win.HasStyle(win32defines.WS_MINIMIZEBOX) or win.HasStyle(win32defines.WS_MAXIMIZEBOX) or win.HasStyle(win32defines.WS_GROUP):
0396
0397 newRect.right -= 32
0398 buttons.append('min')
0399 buttons.append('max')
0400
0401 if buttons:
0402
0403 diff = 5
0404
0405
0406 diff += len(buttons) * 16
0407
0408
0409 if len(buttons) > 1:
0410 diff += 2
0411
0412
0413 if 'min' in buttons and 'help' in buttons:
0414 diff += 4
0415
0416 return [(win.WindowText(), newRect, win.Font(), win32defines.DT_SINGLELINE), ]
0417
0418
0419
0420def _StatusBarTruncInfo(win):
0421 "Return truncation information specific to StatusBar controls"
0422 truncInfo = _WindowTruncInfo(win)
0423 for i, (title, rect, font, flag) in enumerate(truncInfo):
0424
0425 rect.bottom -= win.VertBorderWidth
0426 if i == 0:
0427 rect.right -= win.HorizBorderWidth
0428 else:
0429 rect.right -= win.InterBorderWidth
0430
0431 return truncInfo
0432
0433
0434def _HeaderTruncInfo(win):
0435 "Return truncation information specific to Header controls"
0436 truncInfo = _WindowTruncInfo(win)
0437
0438 for i, (title, rect, font, flag) in enumerate(truncInfo):
0439
0440 rect.right -= 12
0441
0442 return truncInfo
0443
0444
0445
0446
0447
0448
0449def _WindowTruncInfo(win):
0450 "Return Default truncation information"
0451 matchedItems = []
0452
0453 for i, title in enumerate(win.Texts()):
0454
0455
0456 if i < len(win.ClientRects()):
0457 rect = win.ClientRects()[i]
0458 else:
0459
0460 rect = win.ClientRects()[0]
0461
0462
0463 if len(win.Fonts())-1 < i:
0464 font = win.Font()
0465 else:
0466 font = win.Fonts()[i]
0467
0468
0469 matchedItems.append(
0470 (title, rect, font, win32defines.DT_SINGLELINE))
0471
0472 return matchedItems
0473
0474
0475
0476
0477_TruncInfo = {
0478 "#32770" : _DialogTruncInfo,
0479 "ComboBox" : _ComboBoxTruncInfo,
0480 "ComboLBox" : _ComboLBoxTruncInfo,
0481 "ListBox" : _ListBoxTruncInfo,
0482 "Button" : _ButtonTruncInfo,
0483 "Edit": _EditTruncInfo,
0484 "Static" : _StaticTruncInfo,
0485
0486
0487
0488
0489
0490
0491
0492}
0493
0494
0495def _GetTruncationInfo(win):
0496 "helper function to hide non special windows"
0497 if win.Class() in _TruncInfo:
0498 return _TruncInfo[win.Class()](win)
0499 else:
0500
0501 return _WindowTruncInfo(win)