You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ORPA-pyOpenRPA/3rdParty/pywinauto/controlproperties.py

268 lines
8.7 KiB

6 years ago
# GUI Application automation and testing library
# Copyright (C) 2006-2018 Mark Mc Mahon and Contributors
# https://github.com/pywinauto/pywinauto/graphs/contributors
# http://pywinauto.readthedocs.io/en/latest/credits.html
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# * Neither the name of pywinauto nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Wrap"""
from .win32structures import RECT, LOGFONTW
from . import deprecated
#====================================================================
class FuncWrapper(object):
"""Little class to allow attribute access to return a callable object"""
def __init__(self, value):
self.value = value
def __call__(self, *args, **kwargs):
"""Return the saved value"""
return self.value
#====================================================================
class ControlProps(dict):
"""Wrap controls read from a file to resemble hwnd controls"""
def __init__(self, *args, **kwargs):
dict.__init__(self, *args, **kwargs)
self.ref = None
#self.menu_items = []
def __getattr__(self, attr):
# if the key is not in the dictionary but the plural is
if attr not in self and attr + "s" in self:
# return the first element of the possible list item
return FuncWrapper(self[attr+'s'][0])
return FuncWrapper(self[attr])
#def friendly_class_name(self):
# print "sdafafasdfafasdfasdf",
# try:
# print "---", self['friendly_class_name']
# except Exception as e:
# print "fffffffffffffffffffff"
# print `e`
# return self['friendly_class_name']
def window_text(self):
return self['texts'][0]
# Non PEP-8 alias
WindowText = deprecated(window_text)
def HasStyle(self, style):
return self['style'] & style == style
def HasExStyle(self, exstyle):
return self['exstyle'] & exstyle == exstyle
#====================================================================
def GetMenuBlocks(ctrls):
allMenuBlocks = []
for ctrl in ctrls:
if 'menu_items' in ctrl.keys():
# we need to get all the separate menu blocks!
menuBlocks = MenuBlockAsControls(ctrl.menu_items())
allMenuBlocks.extend(menuBlocks)
return allMenuBlocks
#====================================================================
def MenuBlockAsControls(menuItems, parentage = None):
if parentage is None:
parentage = []
blocks = []
curBlock = []
for item in menuItems:
# do a bit of conversion first :-)
itemAsCtrl = MenuItemAsControl(item)
# update the friendly_class_name to contain the 'path' to
# this particular item
# TODO: CHECK - as itemPath is currently unused!
if parentage:
itemPath = "%s->%s" % ("->".join(parentage), item['text'])
else:
itemPath = item['text']
#append the item to the current menu block
curBlock.append(itemAsCtrl)
# If the item has a sub menu
if 'menu_items' in item.keys():
# add the current item the path
parentage.append(item['text'])
# Get the block for the SubMenu, and add it to the list of
# blocks we have found
blocks.extend(
MenuBlockAsControls(
item['menu_items']['menu_items'], parentage))
# and seeing as we are dong with that sub menu remove the current
# item from the path
del(parentage[-1])
# add the current block to the list of blocks
blocks.append(curBlock)
return blocks
#====================================================================
def MenuItemAsControl(menuItem):
"""Make a menu item look like a control for tests"""
itemAsCtrl = ControlProps()
itemAsCtrl["texts"] = [menuItem['text'], ]
itemAsCtrl["control_id"] = menuItem['id']
itemAsCtrl["type"] = menuItem['type']
itemAsCtrl["state"] = menuItem['state']
itemAsCtrl["class_name"] = "MenuItem"
itemAsCtrl["friendly_class_name"] = "MenuItem"
# as most of these don't matter - just set them up with default stuff
itemAsCtrl["rectangle"] = RECT(0, 0, 999, 999)
itemAsCtrl["fonts"] = [LOGFONTW(), ]
itemAsCtrl["client_rects"] = [RECT(0, 0, 999, 999), ]
itemAsCtrl["context_help_id"] = 0
itemAsCtrl["user_data"] = 0
itemAsCtrl["style"] = 0
itemAsCtrl["exstyle"] = 0
itemAsCtrl["is_visible"] = 1
return itemAsCtrl
#====================================================================
def SetReferenceControls(controls, refControls):
"""Set the reference controls for the controls passed in
This does some minor checking as following:
* test that there are the same number of reference controls as
controls - fails with an exception if there are not
* test if all the ID's are the same or not
"""
# numbers of controls must be the same (though in future I could imagine
# relaxing this constraint)
if len(controls) != len(refControls):
raise RuntimeError(
"Numbers of controls on ref. dialog does not match Loc. dialog")
# set the controls
for i, ctrl in enumerate(controls):
ctrl.ref = refControls[i]
toRet = 1
allIDsSameFlag = 2
allClassesSameFlag = 4
# find if all the control id's match
if [ctrl.control_id() for ctrl in controls] == \
[ctrl.control_id() for ctrl in refControls]:
toRet += allIDsSameFlag
# check if the control classes match
if [ctrl.class_name() for ctrl in controls] == \
[ctrl.class_name() for ctrl in refControls]:
toRet += allClassesSameFlag
return toRet
##====================================================================
#class ControlProps(dict):
# #----------------------------------------------------------------
# def __init__(self, props = {}):
# # default to having menuItems for all things
# self.menu_items = []
#
# self.update(props)
# #for x in props:
# #self[x] = props[x]
#
# if hasattr(props, "handle"):
# self.__dict__['handle'] = props.handle
# else:
# self.__dict__['handle'] = None
#
# self.__dict__['ref'] = None
#
# #----------------------------------------------------------------
# # handles attribute access for dictionary items and
# # for plurals (e.g. if self.fonts = [4, 2] then self.font = 4)
# def __getattr__(self, key):
#
# # if the key is not in the dictionary but the plural is
# if key not in self and key + "s" in self:
#
# # try to get the first element of the possible list item
# try:
# return self[key + "s"][0]
# except TypeError as e:
# pass
#
# if key in self:
# return self[key]
#
# return self.__dict__[key]
#
# #----------------------------------------------------------------
# def __setattr__(self, key, value):
# if key in self.__dict__:
# self.__dict__[key] = value
# else:
# self[key] = value
#
# #----------------------------------------------------------------
# def has_style(self, flag):
# return self.style & flag == flag
#
# #----------------------------------------------------------------
# def has_exstyle(self, flag):
# return self.exstyle & flag == flag
#
#