# Upgrade pywinauto to 0.6.8 (Fixed some big bug with int convert to long fails) + Some Docs fixes in Pypi

dev-linux
Ivan Maslov 5 years ago
parent a4aa6136de
commit b578600c09

@ -9,6 +9,7 @@
# } # }
# } # }
# } # }
# USAGE in .py # USAGE in .py
# inRequest. # inRequest.
# inRequest.OpenRPA["DefUserRoleAccessAsk"](["Orchestrator","RDPActive","Controls"]) - return True or False # inRequest.OpenRPA["DefUserRoleAccessAsk"](["Orchestrator","RDPActive","Controls"]) - return True or False

@ -1,18 +1,25 @@
Metadata-Version: 2.1 Metadata-Version: 2.1
Name: pyOpenRPA Name: pyOpenRPA
Version: 1.1.12 Version: 1.1.13
Summary: First open source RPA platform for business Summary: First open source RPA platform for business
Home-page: https://gitlab.com/UnicodeLabs/OpenRPA Home-page: https://gitlab.com/UnicodeLabs/OpenRPA
Author: Ivan Maslov Author: Ivan Maslov
Author-email: Ivan.Maslov@unicodelabs.ru Author-email: Ivan.Maslov@unicodelabs.ru
License: MIT License: MIT
Keywords: OpenRPA RPA Robot Automation Robotization Keywords: OpenRPA RPA Robot Automation Robotization OpenSource
Platform: UNKNOWN Platform: UNKNOWN
Classifier: Development Status :: 3 - Alpha Classifier: Development Status :: 5 - Production/Stable
Classifier: License :: OSI Approved :: MIT License Classifier: License :: OSI Approved :: MIT License
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.7
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Software Development :: Testing
Classifier: Topic :: Software Development :: User Interfaces
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: Home Automation
Description-Content-Type: text/markdown Description-Content-Type: text/markdown
Requires-Dist: pywinauto (>=0.6.6) Requires-Dist: pywinauto (>=0.6.8)
Requires-Dist: WMI (>=1.4.9) Requires-Dist: WMI (>=1.4.9)
Requires-Dist: pillow (>=6.0.0) Requires-Dist: pillow (>=6.0.0)
Requires-Dist: keyboard (>=0.13.3) Requires-Dist: keyboard (>=0.13.3)
@ -50,17 +57,17 @@ Resources\WPy64-3720\python-3.7.2.amd64\python.exe
# Module GUI activity List: # Module GUI activity List:
############################ ############################
Новая версия Новая версия
############################ ############################
Получить СЃРїРёСЃРѕРє элементов, который удовлетворяет условиям через расширенный движок РїРѕРёСЃРєР° Получить список элементов, который удовлетворяет условиям через расширенный движок поиска
[ [
{ {
"index":<Позиция элемента РІ родительском объекте>, "index":<Позиция элемента в родительском объекте>,
"depth_start" - глубина, СЃ которой начинается РїРѕРёСЃРє (РїРѕ умолчанию 1) "depth_start" - глубина, с которой начинается поиск (по умолчанию 1)
"depth_end" - глубина, РґРѕ которой ведется РїРѕРёСЃРє (РїРѕ умолчанию 1) "depth_end" - глубина, до которой ведется поиск (по умолчанию 1)
"class_name" - наименование класса, который требуется искать "class_name" - наименование класса, который требуется искать
"title" - наименование заголовка "title" - наименование заголовка
"rich_text" - наименование rich_text "rich_text" - наименование rich_text
} }
] ]

@ -1,8 +1,8 @@
pyOpenRPA-1.1.12.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 pyOpenRPA-1.1.13.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pyOpenRPA-1.1.12.dist-info/METADATA,sha256=QQ3aid4fLcFpJ0aWDRyYrVf1EMWi3cYocTyqvmHwJ90,3542 pyOpenRPA-1.1.13.dist-info/METADATA,sha256=rjIGRZpHzGWnt9LvY4CqdNByJhS4FqqdMUdzP_2BWmk,3352
pyOpenRPA-1.1.12.dist-info/RECORD,, pyOpenRPA-1.1.13.dist-info/RECORD,,
pyOpenRPA-1.1.12.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97 pyOpenRPA-1.1.13.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97
pyOpenRPA-1.1.12.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10 pyOpenRPA-1.1.13.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10
pyOpenRPA/.idea/inspectionProfiles/profiles_settings.xml,sha256=YXLFmX7rPNGcnKK1uX1uKYPN0fpgskYNe7t0BV7cqkY,174 pyOpenRPA/.idea/inspectionProfiles/profiles_settings.xml,sha256=YXLFmX7rPNGcnKK1uX1uKYPN0fpgskYNe7t0BV7cqkY,174
pyOpenRPA/.idea/misc.xml,sha256=ySjeaQ1DfqxaRTlFGT_3zW5r9mWuwxoAK_AX4QiuAZM,203 pyOpenRPA/.idea/misc.xml,sha256=ySjeaQ1DfqxaRTlFGT_3zW5r9mWuwxoAK_AX4QiuAZM,203
pyOpenRPA/.idea/modules.xml,sha256=Q__U1JIA2cjxbLRXAv-SfYY00fZA0TNlpkkbY4s3ncg,277 pyOpenRPA/.idea/modules.xml,sha256=Q__U1JIA2cjxbLRXAv-SfYY00fZA0TNlpkkbY4s3ncg,277
@ -300,6 +300,6 @@ pyOpenRPA/Tools/Terminator.py,sha256=VcjX3gFXiCGu3MMCidhrTNsmC9wsAqfjRJdTSU9fLnU
pyOpenRPA/Tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pyOpenRPA/Tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Tools/__pycache__/Terminator.cpython-37.pyc,, pyOpenRPA/Tools/__pycache__/Terminator.cpython-37.pyc,,
pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/__init__.py,sha256=4A8Uettbe_avfR459RgVJNkUxs-2hHjTgSVKpVOFjKw,175 pyOpenRPA/__init__.py,sha256=MLl4coStn9rfw3D3uxDlH6uWJFlRPjAXs2Scbs-T3KA,175
pyOpenRPA/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/test.txt,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pyOpenRPA/test.txt,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0

@ -3,7 +3,7 @@ r"""
The OpenRPA package (from UnicodeLabs) The OpenRPA package (from UnicodeLabs)
""" """
__version__ = 'v1.1.12' __version__ = 'v1.1.13'
__all__ = [] __all__ = []
__author__ = 'Ivan Maslov <ivan.maslov@unicodelabs.ru>' __author__ = 'Ivan Maslov <ivan.maslov@unicodelabs.ru>'
#from .Core import Robot #from .Core import Robot

@ -1,13 +0,0 @@
At it's simplest it allows you to send mouse and keyboard
actions to windows dialogs and controls, but It has support for more complex
controls also.
Useful links
-------------
- Home page: http://pywinauto.github.io/
- Docs Intro: https://pywinauto.readthedocs.io/en/latest/
- Getting Started Guide: https://pywinauto.readthedocs.io/en/latest/getting_started.html
- StackOverflow tag: https://stackoverflow.com/questions/tagged/pywinauto

@ -1 +0,0 @@
{"classifiers": ["Development Status :: 5 - Production/Stable", "Environment :: Console", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: Microsoft :: Windows", "Programming Language :: Python", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Software Development :: Testing", "Topic :: Software Development :: User Interfaces", "Topic :: Software Development :: Quality Assurance"], "extensions": {"python.details": {"contacts": [{"email": "pywinauto-users@lists.sourceforge.net", "name": "Mark Mc Mahon and Contributors", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "http://pywinauto.github.io/"}}}, "extras": [], "generator": "bdist_wheel (0.29.0)", "keywords": ["windows", "gui", "automation", "GuiAuto", "testing", "test", "desktop", "mouse", "keyboard"], "license": "BSD 3-clause", "metadata_version": "2.0", "name": "pywinauto", "platform": "win32", "run_requires": [{"requires": ["comtypes", "six"]}], "summary": "A set of Python modules to automate the Microsoft Windows GUI", "version": "0.6.6"}

@ -0,0 +1,27 @@
Copyright (c) 2017, Mark Mc Mahon and Contributors
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.

@ -1,6 +1,6 @@
Metadata-Version: 2.0 Metadata-Version: 2.1
Name: pywinauto Name: pywinauto
Version: 0.6.6 Version: 0.6.8
Summary: A set of Python modules to automate the Microsoft Windows GUI Summary: A set of Python modules to automate the Microsoft Windows GUI
Home-page: http://pywinauto.github.io/ Home-page: http://pywinauto.github.io/
Author: Mark Mc Mahon and Contributors Author: Mark Mc Mahon and Contributors
@ -23,9 +23,9 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Software Development :: Testing Classifier: Topic :: Software Development :: Testing
Classifier: Topic :: Software Development :: User Interfaces Classifier: Topic :: Software Development :: User Interfaces
Classifier: Topic :: Software Development :: Quality Assurance Classifier: Topic :: Software Development :: Quality Assurance
Requires-Dist: comtypes
Requires-Dist: six Requires-Dist: six
Requires-Dist: comtypes
Requires-Dist: pywin32
At it's simplest it allows you to send mouse and keyboard At it's simplest it allows you to send mouse and keyboard
actions to windows dialogs and controls, but It has support for more complex actions to windows dialogs and controls, but It has support for more complex

@ -1,11 +1,10 @@
pywinauto-0.6.6.dist-info/DESCRIPTION.rst,sha256=k2uqeFUEl_g6xxBeVuZEfpJGuEOwcWLWkYAPOCoNkrk,443 pywinauto-0.6.8.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pywinauto-0.6.6.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 pywinauto-0.6.8.dist-info/LICENSE,sha256=GKmZqVt7I9hsQQtFNORNafbYzhPDpTcZsGq4ldii5zo,1504
pywinauto-0.6.6.dist-info/METADATA,sha256=0BOLG3k-RTQbPt5MoG8G7P0yDwqhu2hQddg1D03wNgA,1660 pywinauto-0.6.8.dist-info/METADATA,sha256=7x_-XwBl2UsjPrl_4e5bNgDVwA_FMH83WidT-ii0xb0,1723
pywinauto-0.6.6.dist-info/RECORD,, pywinauto-0.6.8.dist-info/RECORD,,
pywinauto-0.6.6.dist-info/WHEEL,sha256=Ds0ba8WsPJtjBPzEMyPOBG3qfPa6B4mlzB-vhzorIZs,97 pywinauto-0.6.8.dist-info/WHEEL,sha256=53VSps8MltPLN_x9Ib61FU2ZSaJKzgrWQqu9rS-Dkgk,116
pywinauto-0.6.6.dist-info/metadata.json,sha256=0I2fhQRsICsiE-qQSyHVGUikMukbxGqL_67vZLVOkPs,1363 pywinauto-0.6.8.dist-info/top_level.txt,sha256=7E8mqRxGiLpAamWQi4ClxZvTp1jx3P0shUi_Tu0zk44,10
pywinauto-0.6.6.dist-info/top_level.txt,sha256=7E8mqRxGiLpAamWQi4ClxZvTp1jx3P0shUi_Tu0zk44,10 pywinauto/__init__.py,sha256=xY7VLfy-UvPNHKJSlzekAoG9Sue8zdNdFIdjS-_zTFs,7231
pywinauto/__init__.py,sha256=BJ2Pni41MWP3DgzGAFhpNvFajGujGcVUxMnf6n5s1tI,6950
pywinauto/__pycache__/__init__.cpython-37.pyc,, pywinauto/__pycache__/__init__.cpython-37.pyc,,
pywinauto/__pycache__/actionlogger.cpython-37.pyc,, pywinauto/__pycache__/actionlogger.cpython-37.pyc,,
pywinauto/__pycache__/application.cpython-37.pyc,, pywinauto/__pycache__/application.cpython-37.pyc,,
@ -33,9 +32,9 @@ pywinauto/__pycache__/win32functions.cpython-37.pyc,,
pywinauto/__pycache__/win32structures.cpython-37.pyc,, pywinauto/__pycache__/win32structures.cpython-37.pyc,,
pywinauto/__pycache__/xml_helpers.cpython-37.pyc,, pywinauto/__pycache__/xml_helpers.cpython-37.pyc,,
pywinauto/actionlogger.py,sha256=JVny3VSQIzcSH6ESfUPkxPozSJrxMMOvlwzNiUzO-_E,5632 pywinauto/actionlogger.py,sha256=JVny3VSQIzcSH6ESfUPkxPozSJrxMMOvlwzNiUzO-_E,5632
pywinauto/application.py,sha256=r1gE55O91UXteKme9rFqBUP1QmbYyt4tmpXNQAHHt7I,55887 pywinauto/application.py,sha256=_KIIkl_ZZNFDZo_phPhYBX1YuNZh4pFW5A1gdYvTXeo,58047
pywinauto/backend.py,sha256=hLgO3HsnCJUYNoPfU8CwD11yMKjUZiPuXlC080JNufE,4186 pywinauto/backend.py,sha256=hLgO3HsnCJUYNoPfU8CwD11yMKjUZiPuXlC080JNufE,4186
pywinauto/base_wrapper.py,sha256=wx_8TIg_RbXX_zvpxGyL8nUWcvfQHVtVK6tAl8gcC_A,37561 pywinauto/base_wrapper.py,sha256=qAIvH6wKd6okBBDHY21gnK7A2DQj5H43qV4heQqQxc4,37590
pywinauto/clipboard.py,sha256=VpKW7WQ3BF57cmLkWA0Of16RG6BCuLSqGX0sW2nN1ds,4329 pywinauto/clipboard.py,sha256=VpKW7WQ3BF57cmLkWA0Of16RG6BCuLSqGX0sW2nN1ds,4329
pywinauto/controlproperties.py,sha256=YQ1lbHxWvMf38PGB0JYdN8rhh9PYoe8iwaWbtw3EU1w,9329 pywinauto/controlproperties.py,sha256=YQ1lbHxWvMf38PGB0JYdN8rhh9PYoe8iwaWbtw3EU1w,9329
pywinauto/controls/__init__.py,sha256=0cuXVxqppu3vQIJfjgxB_J__3Vtr3EvbDEx7TaRY64A,2241 pywinauto/controls/__init__.py,sha256=0cuXVxqppu3vQIJfjgxB_J__3Vtr3EvbDEx7TaRY64A,2241
@ -46,26 +45,26 @@ pywinauto/controls/__pycache__/menuwrapper.cpython-37.pyc,,
pywinauto/controls/__pycache__/uia_controls.cpython-37.pyc,, pywinauto/controls/__pycache__/uia_controls.cpython-37.pyc,,
pywinauto/controls/__pycache__/uiawrapper.cpython-37.pyc,, pywinauto/controls/__pycache__/uiawrapper.cpython-37.pyc,,
pywinauto/controls/__pycache__/win32_controls.cpython-37.pyc,, pywinauto/controls/__pycache__/win32_controls.cpython-37.pyc,,
pywinauto/controls/common_controls.py,sha256=zyx1EyyoSQ_pvl6snIPOzIp6WZuPXOYNAzYqM4Qh5GA,141066 pywinauto/controls/common_controls.py,sha256=4a_RyQcDl4N2JW8F_9sK-utJWJK-ujwqXF4vEhAaFe0,138614
pywinauto/controls/hwndwrapper.py,sha256=46cKLxKhYL6-BzN33KA8kG7wOy1-JGEJ68qVQLiCYts,68153 pywinauto/controls/hwndwrapper.py,sha256=nDiCY-DnVHrD2o49WTRv7-x_2kB9Xf9nBb3gWJkgl5I,68222
pywinauto/controls/menuwrapper.py,sha256=SS5UoaezIMknz_405021QUV0ixClkqCUfuck_EnsgIA,23477 pywinauto/controls/menuwrapper.py,sha256=TlgHXxMm6pUB75VDW6R-X5octoSpauXM0t7pRIJ8bPE,23497
pywinauto/controls/uia_controls.py,sha256=rmME_GCfDbohEBNnHJE_mLStshBvPX_-r8T_Xa6XuH8,53699 pywinauto/controls/uia_controls.py,sha256=ei-u10dGxMRjR7SQupD3dxrvlbiqHm90ggb9WyracJA,54886
pywinauto/controls/uiawrapper.py,sha256=aEVJYh6aB6VIg9sBrHwyQ3LOKTMnFLruVCMmSxy0dfQ,30770 pywinauto/controls/uiawrapper.py,sha256=w7wsUnbsSStm32H5t2jEI-P9sdbMVOS8OYASHJnmhDk,31386
pywinauto/controls/win32_controls.py,sha256=Iz-28a0b_TPR8XiSTIkr8areRXyxuXQ0gOqshIPcrhU,35099 pywinauto/controls/win32_controls.py,sha256=Iz-28a0b_TPR8XiSTIkr8areRXyxuXQ0gOqshIPcrhU,35099
pywinauto/element_info.py,sha256=L-s3E6xdVAxgfCFZXAQlMbaHl5OEtG_xFM845gFz5zc,6067 pywinauto/element_info.py,sha256=L-s3E6xdVAxgfCFZXAQlMbaHl5OEtG_xFM845gFz5zc,6067
pywinauto/findbestmatch.py,sha256=xAJaaiqAnBmQwCrhiqga-AmI5FxR0gZuXE1v1k1tyRA,20605 pywinauto/findbestmatch.py,sha256=izVEqpMSXgFhdMLd3OxN6Sexfo6MGVHTPEwkFxhDDpU,20748
pywinauto/findwindows.py,sha256=wYQgISnlHOAhuvxA0bG9shLSTwu9pKNg1_ApYJi1pHw,14290 pywinauto/findwindows.py,sha256=OMn7J5i4vk2xiVINPQ4daaMZ5MDCAplgnt4MXHo2dGY,14470
pywinauto/fuzzydict.py,sha256=mNFpET8ckSpMen4LdRRYyGRR4LToMbQw-gqNG3lWCqM,6073 pywinauto/fuzzydict.py,sha256=mNFpET8ckSpMen4LdRRYyGRR4LToMbQw-gqNG3lWCqM,6073
pywinauto/handleprops.py,sha256=WavBoIYV0WTLpq5YUXDQS0-kMv3GChpwk2etbMFZA_k,14748 pywinauto/handleprops.py,sha256=85UJyb6LfUVNim5biyB9Fz-oICo3lq1S_-jPxxgs28c,14685
pywinauto/keyboard.py,sha256=Q_hT07R48cC830HzBZTaM2o2XOMtLsucVG_KalAfgz4,22865 pywinauto/keyboard.py,sha256=tJ4MSH7WVvmPrinMDycRr_uWm7AEtiFrfYjFjVgOwW0,24562
pywinauto/linux/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pywinauto/linux/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pywinauto/linux/__pycache__/__init__.cpython-37.pyc,, pywinauto/linux/__pycache__/__init__.cpython-37.pyc,,
pywinauto/linux/__pycache__/clipboard.cpython-37.pyc,, pywinauto/linux/__pycache__/clipboard.cpython-37.pyc,,
pywinauto/linux/__pycache__/keyboard.cpython-37.pyc,, pywinauto/linux/__pycache__/keyboard.cpython-37.pyc,,
pywinauto/linux/clipboard.py,sha256=X4wR0r1_X8fdLF0KphNskV_vV2c0_toNyyt2m-TY6nQ,3568 pywinauto/linux/clipboard.py,sha256=X4wR0r1_X8fdLF0KphNskV_vV2c0_toNyyt2m-TY6nQ,3568
pywinauto/linux/keyboard.py,sha256=kvc5EZY8lML2WoCwV5er9SyzsF2NjQ4Abpum-YYT5-U,17380 pywinauto/linux/keyboard.py,sha256=z540dSwdCvmoyRSpCaJainPOTawbY76eo8i_UW2qyYQ,17458
pywinauto/mouse.py,sha256=-Rh9zY1KUfzVcKblvQixH0WKxf2lW9__yrsI-pRhpe0,10647 pywinauto/mouse.py,sha256=-Rh9zY1KUfzVcKblvQixH0WKxf2lW9__yrsI-pRhpe0,10647
pywinauto/remote_memory_block.py,sha256=fC0HyKKrsFlwS-1QlwQZif3RFqK4hr1RkIwajkbzGM4,12204 pywinauto/remote_memory_block.py,sha256=eox-bC9ZpliwQw3gZuiPku8_oQ9sGNeKfrSOM2pNyJs,12168
pywinauto/sysinfo.py,sha256=NgLfiQ3XNaRGnapzSfYSafwn5my24FjE1uHTU66P4VM,3052 pywinauto/sysinfo.py,sha256=NgLfiQ3XNaRGnapzSfYSafwn5my24FjE1uHTU66P4VM,3052
pywinauto/taskbar.py,sha256=vjHNAdOaQwyZvqJaLMvMB7teJBMOeCgXeedJpZrZGp4,5232 pywinauto/taskbar.py,sha256=vjHNAdOaQwyZvqJaLMvMB7teJBMOeCgXeedJpZrZGp4,5232
pywinauto/tests/__init__.py,sha256=DZXsho8W7nBWDSw5Qb-qao9CNpfOwTCKOtxG0dJRgos,5452 pywinauto/tests/__init__.py,sha256=DZXsho8W7nBWDSw5Qb-qao9CNpfOwTCKOtxG0dJRgos,5452
@ -97,11 +96,11 @@ pywinauto/tests/repeatedhotkey.py,sha256=6xFNznYzzIebpkX2dLUW6rIkTOBIe5la1qVohi3
pywinauto/tests/translation.py,sha256=0qVEsh42uqu1K5MDZfcQunPngSRanPfSLgL99An1W8g,6070 pywinauto/tests/translation.py,sha256=0qVEsh42uqu1K5MDZfcQunPngSRanPfSLgL99An1W8g,6070
pywinauto/tests/truncation.py,sha256=MD5UTKnVtZPZyfP3Ejx5ZMBDrDYY089xY05a8SMtMjc,20006 pywinauto/tests/truncation.py,sha256=MD5UTKnVtZPZyfP3Ejx5ZMBDrDYY089xY05a8SMtMjc,20006
pywinauto/timings.py,sha256=58c9xNODE5LjQYNhqoLpbLfNeJ9Lu0J8GZLw2d2tkMY,15668 pywinauto/timings.py,sha256=58c9xNODE5LjQYNhqoLpbLfNeJ9Lu0J8GZLw2d2tkMY,15668
pywinauto/uia_defines.py,sha256=-4w4hhRCd4O_748nEp5w5kKl-d0vb17aymVr3rdZTQ0,9819 pywinauto/uia_defines.py,sha256=ynA52N4tmKn8KBlqGP0EJ8etpygvYTyZhQNJ-vdOBRw,9979
pywinauto/uia_element_info.py,sha256=g2E9O4qSyXYmj80MqFD7mOin_nHXowM_-fVJVO0oV88,13762 pywinauto/uia_element_info.py,sha256=g2E9O4qSyXYmj80MqFD7mOin_nHXowM_-fVJVO0oV88,13762
pywinauto/win32_element_info.py,sha256=bJ9CIP4RPdGIZVB_HaZQg2Z_92QG2hWYw1aGkoBtTxI,9369 pywinauto/win32_element_info.py,sha256=bJ9CIP4RPdGIZVB_HaZQg2Z_92QG2hWYw1aGkoBtTxI,9369
pywinauto/win32_hooks.py,sha256=X2Le46OJxmco94b0n830RN6Tpnk2BzMTtRVOYdwllWc,24289 pywinauto/win32_hooks.py,sha256=_oG2uuMswls-9jxaGm_XRAstM6E9S38cQ6ZzBEoiYg0,24238
pywinauto/win32defines.py,sha256=i-uScB7nzZRk0fiDNk6TqlhGraRESmjLx-GkBlgOOp4,499259 pywinauto/win32defines.py,sha256=zltu4uEoY397OBLDKI_Vo0R79719_uqHOjL0QuTO3rc,630639
pywinauto/win32functions.py,sha256=uHpPx61qsWL_awp6Kq0D-ERN5GsAvHjC34pN-rx1xQQ,14987 pywinauto/win32functions.py,sha256=fHHeG9kARY_3a05qXoI9hbIIXua6Kj3IJUu6my0W6Fw,24133
pywinauto/win32structures.py,sha256=G9diB0fpPv95J8DQLt6z5D1033Ajw_FZUCojrS0xliA,42128 pywinauto/win32structures.py,sha256=CGxoTtM-fH_AyxpxGhRl28YsVJfBM1jv3_aLUXDo0ng,41700
pywinauto/xml_helpers.py,sha256=uiairq6vJiduprD6KMIvc72qBuplPC-PQqduJVVVZnc,17263 pywinauto/xml_helpers.py,sha256=uiairq6vJiduprD6KMIvc72qBuplPC-PQqduJVVVZnc,17263

@ -1,5 +1,6 @@
Wheel-Version: 1.0 Wheel-Version: 1.0
Generator: bdist_wheel (0.29.0) Generator: bdist_wheel (0.33.4)
Root-Is-Purelib: true Root-Is-Purelib: true
Tag: py2-none-any
Tag: py3-none-any Tag: py3-none-any

@ -32,7 +32,7 @@
"""Python package for automating GUI manipulation on Windows""" """Python package for automating GUI manipulation on Windows"""
__version__ = "0.6.6" __version__ = "0.6.8"
import sys # noqa: E402 import sys # noqa: E402
import warnings # noqa: E402 import warnings # noqa: E402
@ -89,9 +89,7 @@ if sys.platform == 'win32':
from . import findwindows from . import findwindows
WindowAmbiguousError = findwindows.WindowAmbiguousError WindowAmbiguousError = findwindows.WindowAmbiguousError
ElementNotFoundError = findwindows.ElementNotFoundError WindowNotFoundError = findwindows.WindowNotFoundError
if UIA_support:
ElementNotFoundError = findwindows.ElementNotFoundError ElementNotFoundError = findwindows.ElementNotFoundError
ElementAmbiguousError = findwindows.ElementAmbiguousError ElementAmbiguousError = findwindows.ElementAmbiguousError
@ -106,13 +104,14 @@ if sys.platform == 'win32':
class Desktop(object): class Desktop(object):
"""Simple class to call something like ``Desktop().WindowName.ControlName.method()``""" """Simple class to call something like ``Desktop().WindowName.ControlName.method()``"""
def __init__(self, backend=None): def __init__(self, backend=None, allow_magic_lookup=True):
"""Create desktop element description""" """Create desktop element description"""
if not backend: if not backend:
backend = backends.registry.name backend = backends.registry.name
if backend not in backends.registry.backends: if backend not in backends.registry.backends:
raise ValueError('Backend "{0}" is not registered!'.format(backend)) raise ValueError('Backend "{0}" is not registered!'.format(backend))
self.backend = backends.registry.backends[backend] self.backend = backends.registry.backends[backend]
self.allow_magic_lookup = allow_magic_lookup
def window(self, **kwargs): def window(self, **kwargs):
"""Create WindowSpecification object for top-level window""" """Create WindowSpecification object for top-level window"""
@ -121,7 +120,7 @@ if sys.platform == 'win32':
if 'backend' in kwargs: if 'backend' in kwargs:
raise ValueError('Using another backend than set in Desktop constructor is not allowed!') raise ValueError('Using another backend than set in Desktop constructor is not allowed!')
kwargs['backend'] = self.backend.name kwargs['backend'] = self.backend.name
return WindowSpecification(kwargs) return WindowSpecification(kwargs, allow_magic_lookup=self.allow_magic_lookup)
def windows(self, **kwargs): def windows(self, **kwargs):
"""Return a list of wrapped top level windows""" """Return a list of wrapped top level windows"""
@ -145,9 +144,12 @@ if sys.platform == 'win32':
def __getattribute__(self, attr_name): def __getattribute__(self, attr_name):
"""Attribute access for this class""" """Attribute access for this class"""
allow_magic_lookup = object.__getattribute__(self, "allow_magic_lookup") # Beware of recursions here!
try: try:
return object.__getattribute__(self, attr_name) return object.__getattribute__(self, attr_name)
except AttributeError: except AttributeError:
if not allow_magic_lookup:
raise
return self[attr_name] # delegate it to __get_item__ return self[attr_name] # delegate it to __get_item__
def from_point(self, x, y): def from_point(self, x, y):

@ -141,11 +141,12 @@ class WindowSpecification(object):
'active': ('is_active',), 'active': ('is_active',),
} }
def __init__(self, search_criteria): def __init__(self, search_criteria, allow_magic_lookup=True):
""" """
Initialize the class Initialize the class
:param search_criteria: the criteria to match a dialog :param search_criteria: the criteria to match a dialog
:param allow_magic_lookup: whether attribute access must turn into child_window(best_match=...) search as fallback
""" """
# kwargs will contain however to find this window # kwargs will contain however to find this window
if 'backend' not in search_criteria: if 'backend' not in search_criteria:
@ -158,6 +159,7 @@ class WindowSpecification(object):
self.criteria = [search_criteria, ] self.criteria = [search_criteria, ]
self.actions = ActionLogger() self.actions = ActionLogger()
self.backend = registry.backends[search_criteria['backend']] self.backend = registry.backends[search_criteria['backend']]
self.allow_magic_lookup = allow_magic_lookup
if self.backend.name == 'win32': if self.backend.name == 'win32':
# Non PEP-8 aliases for partial backward compatibility # Non PEP-8 aliases for partial backward compatibility
@ -173,7 +175,7 @@ class WindowSpecification(object):
self.window_ = deprecated(self.child_window, deprecated_name='window_') self.window_ = deprecated(self.child_window, deprecated_name='window_')
def __call__(self, *args, **kwargs): def __call__(self, *args, **kwargs):
"""No __call__ so return a usefull error""" """No __call__ so return a useful error"""
if "best_match" in self.criteria[-1]: if "best_match" in self.criteria[-1]:
raise AttributeError("Neither GUI element (wrapper) " \ raise AttributeError("Neither GUI element (wrapper) " \
"nor wrapper method '{0}' were found (typo?)". "nor wrapper method '{0}' were found (typo?)".
@ -182,8 +184,8 @@ class WindowSpecification(object):
message = ( message = (
"You tried to execute a function call on a WindowSpecification " "You tried to execute a function call on a WindowSpecification "
"instance. You probably have a typo for one of the methods of " "instance. You probably have a typo for one of the methods of "
"this class.\n" "this class or of the targeted wrapper object.\n"
"The criteria leading up to this is: " + str(self.criteria)) "The criteria leading up to this are: " + str(self.criteria))
raise AttributeError(message) raise AttributeError(message)
@ -277,7 +279,7 @@ class WindowSpecification(object):
if 'top_level_only' not in criteria: if 'top_level_only' not in criteria:
criteria['top_level_only'] = False criteria['top_level_only'] = False
new_item = WindowSpecification(self.criteria[0]) new_item = WindowSpecification(self.criteria[0], allow_magic_lookup=self.allow_magic_lookup)
new_item.criteria.extend(self.criteria[1:]) new_item.criteria.extend(self.criteria[1:])
new_item.criteria.append(criteria) new_item.criteria.append(criteria)
@ -307,7 +309,7 @@ class WindowSpecification(object):
""" """
# if we already have 2 levels of criteria (dlg, control) # if we already have 2 levels of criteria (dlg, control)
# then resolve the control and do a getitem on it for the # then resolve the control and do a getitem on it for the
if len(self.criteria) >= 2: if len(self.criteria) >= 2: # FIXME - this is surprising
ctrls = self.__resolve_control(self.criteria) ctrls = self.__resolve_control(self.criteria)
@ -324,7 +326,7 @@ class WindowSpecification(object):
# if we get here then we must have only had one criteria so far # if we get here then we must have only had one criteria so far
# so create a new :class:`WindowSpecification` for this control # so create a new :class:`WindowSpecification` for this control
new_item = WindowSpecification(self.criteria[0]) new_item = WindowSpecification(self.criteria[0], allow_magic_lookup=self.allow_magic_lookup)
# add our new criteria # add our new criteria
new_item.criteria.append({"best_match": key}) new_item.criteria.append({"best_match": key})
@ -345,6 +347,21 @@ class WindowSpecification(object):
Otherwise delegate functionality to :func:`__getitem__` - which Otherwise delegate functionality to :func:`__getitem__` - which
sets the appropriate criteria for the control. sets the appropriate criteria for the control.
""" """
allow_magic_lookup = object.__getattribute__(self, "allow_magic_lookup") # Beware of recursions here!
if not allow_magic_lookup:
try:
return object.__getattribute__(self, attr_name)
except AttributeError:
wrapper_object = self.wrapper_object()
try:
return getattr(wrapper_object, attr_name)
except AttributeError:
message = (
'Attribute "%s" exists neither on %s object nor on'
'targeted %s element wrapper (typo? or set allow_magic_lookup to True?)' %
(attr_name, self.__class__, wrapper_object.__class__))
raise AttributeError(message)
if attr_name in ['__dict__', '__members__', '__methods__', '__class__', '__name__']: if attr_name in ['__dict__', '__members__', '__methods__', '__class__', '__name__']:
return object.__getattribute__(self, attr_name) return object.__getattribute__(self, attr_name)
@ -354,10 +371,10 @@ class WindowSpecification(object):
if attr_name in self.__dict__: if attr_name in self.__dict__:
return self.__dict__[attr_name] return self.__dict__[attr_name]
# if we already have 2 levels of criteria (dlg, conrol) # if we already have 2 levels of criteria (dlg, control)
# this third must be an attribute so resolve and get the # this third must be an attribute so resolve and get the
# attribute and return it # attribute and return it
if len(self.criteria) >= 2: if len(self.criteria) >= 2: # FIXME - this is surprising
ctrls = self.__resolve_control(self.criteria) ctrls = self.__resolve_control(self.criteria)
@ -366,6 +383,7 @@ class WindowSpecification(object):
except AttributeError: except AttributeError:
return self.child_window(best_match=attr_name) return self.child_window(best_match=attr_name)
else: else:
# FIXME - I don't get this part at all, why is it win32-specific and why not keep the same logic as above?
# if we have been asked for an attribute of the dialog # if we have been asked for an attribute of the dialog
# then resolve the window and return the attribute # then resolve the window and return the attribute
desktop_wrapper = self.backend.generic_wrapper_class(self.backend.element_info_class()) desktop_wrapper = self.backend.generic_wrapper_class(self.backend.element_info_class())
@ -870,7 +888,7 @@ class Application(object):
.. automethod:: __getitem__ .. automethod:: __getitem__
""" """
def __init__(self, backend="win32", datafilename=None): def __init__(self, backend="win32", datafilename=None, allow_magic_lookup=True):
""" """
Initialize the Application object Initialize the Application object
@ -886,6 +904,7 @@ class Application(object):
if backend not in registry.backends: if backend not in registry.backends:
raise ValueError('Backend "{0}" is not registered!'.format(backend)) raise ValueError('Backend "{0}" is not registered!'.format(backend))
self.backend = registry.backends[backend] self.backend = registry.backends[backend]
self.allow_magic_lookup = allow_magic_lookup
if self.backend.name == 'win32': if self.backend.name == 'win32':
# Non PEP-8 aliases for partial backward compatibility # Non PEP-8 aliases for partial backward compatibility
self.Start = deprecated(self.start) self.Start = deprecated(self.start)
@ -906,6 +925,10 @@ class Application(object):
self.match_history = pickle.load(datafile) self.match_history = pickle.load(datafile)
self.use_history = True self.use_history = True
def __iter__(self):
"""Raise to avoid infinite loops"""
raise NotImplementedError("Object is not iterable, try to use .windows()")
def connect(self, **kwargs): def connect(self, **kwargs):
"""Connect to an already running process """Connect to an already running process
@ -1139,7 +1162,7 @@ class Application(object):
else: else:
criteria['title'] = windows[0].name criteria['title'] = windows[0].name
return WindowSpecification(criteria) return WindowSpecification(criteria, allow_magic_lookup=self.allow_magic_lookup)
def active(self): def active(self):
"""Return WindowSpecification for an active window of the application""" """Return WindowSpecification for an active window of the application"""
@ -1163,7 +1186,7 @@ class Application(object):
else: else:
criteria['title'] = windows[0].name criteria['title'] = windows[0].name
return WindowSpecification(criteria) return WindowSpecification(criteria, allow_magic_lookup=self.allow_magic_lookup)
def windows(self, **kwargs): def windows(self, **kwargs):
"""Return a list of wrapped top level windows of the application""" """Return a list of wrapped top level windows of the application"""
@ -1205,7 +1228,7 @@ class Application(object):
else: else:
# add the restriction for this particular application # add the restriction for this particular application
kwargs['app'] = self kwargs['app'] = self
win_spec = WindowSpecification(kwargs) win_spec = WindowSpecification(kwargs, allow_magic_lookup=self.allow_magic_lookup)
return win_spec return win_spec
Window_ = window_ = window Window_ = window_ = window
@ -1216,6 +1239,17 @@ class Application(object):
return self.window(best_match=key) return self.window(best_match=key)
def __getattribute__(self, attr_name): def __getattribute__(self, attr_name):
allow_magic_lookup = object.__getattribute__(self, "allow_magic_lookup") # Beware of recursions here!
if not allow_magic_lookup:
try:
return object.__getattribute__(self, attr_name)
except AttributeError:
message = (
'Attribute "%s" doesn\'t exist on %s object'
' (typo? or set allow_magic_lookup to True?)' %
(attr_name, self.__class__))
raise AttributeError(message)
"""Find the specified dialog of the application""" """Find the specified dialog of the application"""
if attr_name in ['__dict__', '__members__', '__methods__', '__class__']: if attr_name in ['__dict__', '__members__', '__methods__', '__class__']:
return object.__getattribute__(self, attr_name) return object.__getattribute__(self, attr_name)

@ -38,7 +38,6 @@ import ctypes
import locale import locale
import re import re
import time import time
import win32process
import win32gui import win32gui
import win32con import win32con
import win32api import win32api
@ -925,7 +924,8 @@ class BaseWrapper(object):
with_tabs = False, with_tabs = False,
with_newlines = False, with_newlines = False,
turn_off_numlock = True, turn_off_numlock = True,
set_foreground = True): set_foreground = True,
vk_packet = True):
""" """
Type keys to the element using keyboard.send_keys Type keys to the element using keyboard.send_keys
@ -945,7 +945,7 @@ class BaseWrapper(object):
# attach the Python process with the process that self is in # attach the Python process with the process that self is in
if self.element_info.handle: if self.element_info.handle:
window_thread_id, _ = win32process.GetWindowThreadProcessId(int(self.handle)) window_thread_id = win32functions.GetWindowThreadProcessId(self.handle, None)
win32functions.AttachThreadInput(win32functions.GetCurrentThreadId(), window_thread_id, win32defines.TRUE) win32functions.AttachThreadInput(win32functions.GetCurrentThreadId(), window_thread_id, win32defines.TRUE)
# TODO: check return value of AttachThreadInput properly # TODO: check return value of AttachThreadInput properly
else: else:
@ -967,7 +967,8 @@ class BaseWrapper(object):
with_spaces, with_spaces,
with_tabs, with_tabs,
with_newlines, with_newlines,
turn_off_numlock) turn_off_numlock,
vk_packet)
# detach the python process from the window's process # detach the python process from the window's process
if self.element_info.handle: if self.element_info.handle:

@ -53,7 +53,6 @@ import warnings
import locale import locale
import six import six
from .. import sysinfo
from .. import win32functions from .. import win32functions
from .. import win32defines from .. import win32defines
from .. import win32structures from .. import win32structures
@ -68,9 +67,6 @@ from ..handleprops import is64bitprocess
from ..sysinfo import is_x64_Python from ..sysinfo import is_x64_Python
from .. import deprecated from .. import deprecated
if sysinfo.UIA_support:
from ..uia_defines import IUIA
# Todo: I should return iterators from things like items() and texts() # Todo: I should return iterators from things like items() and texts()
# to save building full lists all the time # to save building full lists all the time
@ -135,7 +131,7 @@ class _listview_item(object):
item.iItem = self.item_index item.iItem = self.item_index
item.iSubItem = self.subitem_index item.iSubItem = self.subitem_index
item.stateMask = win32structures.UINT(-1) item.stateMask = wintypes.UINT(-1)
item.cchTextMax = 2000 item.cchTextMax = 2000
item.pszText = remote_mem.Address() + \ item.pszText = remote_mem.Address() + \
@ -501,9 +497,9 @@ class _listview_item(object):
lvitem = self.listview_ctrl.LVITEM() lvitem = self.listview_ctrl.LVITEM()
lvitem.mask = win32structures.UINT(win32defines.LVIF_STATE) lvitem.mask = wintypes.UINT(win32defines.LVIF_STATE)
lvitem.state = win32structures.UINT(index_to_state_image_mask(1)) # win32structures.UINT(0x1000) lvitem.state = wintypes.UINT(index_to_state_image_mask(1)) # wintypes.UINT(0x1000)
lvitem.stateMask = win32structures.UINT(win32defines.LVIS_STATEIMAGEMASK) lvitem.stateMask = wintypes.UINT(win32defines.LVIS_STATEIMAGEMASK)
remote_mem = RemoteMemoryBlock(self.listview_ctrl) remote_mem = RemoteMemoryBlock(self.listview_ctrl)
remote_mem.Write(lvitem) remote_mem.Write(lvitem)
@ -530,9 +526,9 @@ class _listview_item(object):
lvitem = self.listview_ctrl.LVITEM() lvitem = self.listview_ctrl.LVITEM()
lvitem.mask = win32structures.UINT(win32defines.LVIF_STATE) lvitem.mask = wintypes.UINT(win32defines.LVIF_STATE)
lvitem.state = win32structures.UINT(index_to_state_image_mask(2)) # win32structures.UINT(0x2000) lvitem.state = wintypes.UINT(index_to_state_image_mask(2)) # wintypes.UINT(0x2000)
lvitem.stateMask = win32structures.UINT(win32defines.LVIS_STATEIMAGEMASK) lvitem.stateMask = wintypes.UINT(win32defines.LVIS_STATEIMAGEMASK)
remote_mem = RemoteMemoryBlock(self.listview_ctrl) remote_mem = RemoteMemoryBlock(self.listview_ctrl)
remote_mem.Write(lvitem) remote_mem.Write(lvitem)
@ -591,12 +587,12 @@ class _listview_item(object):
# first we need to change the state of the item # first we need to change the state of the item
lvitem = self.listview_ctrl.LVITEM() lvitem = self.listview_ctrl.LVITEM()
lvitem.mask = win32structures.UINT(win32defines.LVIF_STATE) lvitem.mask = wintypes.UINT(win32defines.LVIF_STATE)
if to_select: if to_select:
lvitem.state = win32structures.UINT(win32defines.LVIS_FOCUSED | win32defines.LVIS_SELECTED) lvitem.state = wintypes.UINT(win32defines.LVIS_FOCUSED | win32defines.LVIS_SELECTED)
lvitem.stateMask = win32structures.UINT(win32defines.LVIS_FOCUSED | win32defines.LVIS_SELECTED) lvitem.stateMask = wintypes.UINT(win32defines.LVIS_FOCUSED | win32defines.LVIS_SELECTED)
remote_mem = RemoteMemoryBlock(self.listview_ctrl) remote_mem = RemoteMemoryBlock(self.listview_ctrl)
remote_mem.Write(lvitem, size=ctypes.sizeof(lvitem)) remote_mem.Write(lvitem, size=ctypes.sizeof(lvitem))
@ -721,10 +717,6 @@ class ListViewWrapper(hwndwrapper.HwndWrapper):
"TSysListView", "TSysListView",
"ListView.*WndClass", "ListView.*WndClass",
] ]
if sysinfo.UIA_support:
#controltypes is empty to make wrapper search result unique
#possible control types: IUIA().UIA_dll.UIA_ListControlTypeId
controltypes = []
#---------------------------------------------------------------- #----------------------------------------------------------------
def __init__(self, hwnd): def __init__(self, hwnd):
@ -1424,7 +1416,7 @@ class _treeview_element(object):
item.pszText = remote_mem.Address() + ctypes.sizeof(item) + 16 item.pszText = remote_mem.Address() + ctypes.sizeof(item) + 16
item.cchTextMax = 2000 item.cchTextMax = 2000
item.hItem = self.elem item.hItem = self.elem
item.stateMask = win32structures.UINT(-1) item.stateMask = wintypes.UINT(-1)
# Write the local TVITEM structure to the remote memory block # Write the local TVITEM structure to the remote memory block
remote_mem.Write(item) remote_mem.Write(item)
@ -1460,8 +1452,6 @@ class TreeViewWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "TreeView" friendlyclassname = "TreeView"
windowclasses = [ windowclasses = [
"SysTreeView32", r"WindowsForms\d*\.SysTreeView32\..*", "TTreeView", "TreeList.TreeListCtrl"] "SysTreeView32", r"WindowsForms\d*\.SysTreeView32\..*", "TTreeView", "TreeList.TreeListCtrl"]
if sysinfo.UIA_support:
controltypes = [IUIA().UIA_dll.UIA_TreeControlTypeId]
#---------------------------------------------------------------- #----------------------------------------------------------------
def __init__(self, hwnd): def __init__(self, hwnd):
@ -1751,8 +1741,6 @@ class HeaderWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "Header" friendlyclassname = "Header"
windowclasses = ["SysHeader32", "msvb_lib_header"] windowclasses = ["SysHeader32", "msvb_lib_header"]
if sysinfo.UIA_support:
controltypes = [IUIA().UIA_dll.UIA_HeaderControlTypeId]
#---------------------------------------------------------------- #----------------------------------------------------------------
def __init__(self, hwnd): def __init__(self, hwnd):
@ -1894,8 +1882,6 @@ class StatusBarWrapper(hwndwrapper.HwndWrapper):
"msctls_statusbar32", "msctls_statusbar32",
".*StatusBar", ".*StatusBar",
r"WindowsForms\d*\.msctls_statusbar32\..*"] r"WindowsForms\d*\.msctls_statusbar32\..*"]
if sysinfo.UIA_support:
controltypes = [IUIA().UIA_dll.UIA_StatusBarControlTypeId]
#---------------------------------------------------------------- #----------------------------------------------------------------
def __init__(self, hwnd): def __init__(self, hwnd):
@ -2065,8 +2051,6 @@ class TabControlWrapper(hwndwrapper.HwndWrapper):
windowclasses = [ windowclasses = [
"SysTabControl32", "SysTabControl32",
r"WindowsForms\d*\.SysTabControl32\..*"] r"WindowsForms\d*\.SysTabControl32\..*"]
if sysinfo.UIA_support:
controltypes = [IUIA().UIA_dll.UIA_TabControlTypeId]
#---------------------------------------------------------------- #----------------------------------------------------------------
def __init__(self, hwnd): def __init__(self, hwnd):
@ -2878,10 +2862,6 @@ class ReBarWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "ReBar" friendlyclassname = "ReBar"
windowclasses = ["ReBarWindow32", ] windowclasses = ["ReBarWindow32", ]
if sysinfo.UIA_support:
#controltypes is empty to make wrapper search result unique
#possible control types: IUIA().UIA_dll.UIA_PaneControlTypeId
controltypes = []
#---------------------------------------------------------------- #----------------------------------------------------------------
def __init__(self, hwnd): def __init__(self, hwnd):
@ -3086,8 +3066,6 @@ class UpDownWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "UpDown" friendlyclassname = "UpDown"
windowclasses = ["msctls_updown32", "msctls_updown", ] windowclasses = ["msctls_updown32", "msctls_updown", ]
if sysinfo.UIA_support:
controltypes = [IUIA().UIA_dll.UIA_SpinnerControlTypeId]
#---------------------------------------------------------------- #----------------------------------------------------------------
def __init__(self, hwnd): def __init__(self, hwnd):
@ -3195,8 +3173,6 @@ class TrackbarWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "Trackbar" friendlyclassname = "Trackbar"
windowclasses = ["msctls_trackbar", ] windowclasses = ["msctls_trackbar", ]
if sysinfo.UIA_support:
controltypes = [IUIA().UIA_dll.UIA_SliderControlTypeId]
def get_range_min(self): def get_range_min(self):
"""Get min available trackbar value""" """Get min available trackbar value"""
@ -3293,10 +3269,6 @@ class AnimationWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "Animation" friendlyclassname = "Animation"
windowclasses = ["SysAnimate32", ] windowclasses = ["SysAnimate32", ]
if sysinfo.UIA_support:
#controltypes is empty to make wrapper search result unique
#possible control types: IUIA().UIA_dll.UIA_PaneControlTypeId
controltypes = []
#==================================================================== #====================================================================
@ -3306,10 +3278,6 @@ class ComboBoxExWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "ComboBoxEx" friendlyclassname = "ComboBoxEx"
windowclasses = ["ComboBoxEx32", ] windowclasses = ["ComboBoxEx32", ]
if sysinfo.UIA_support:
#controltypes is empty to make wrapper search result unique
#possible control types: IUIA().UIA_dll.UIA_PaneControlTypeId
controltypes = []
has_title = False has_title = False
@ -3321,10 +3289,6 @@ class DateTimePickerWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "DateTimePicker" friendlyclassname = "DateTimePicker"
windowclasses = ["SysDateTimePick32", windowclasses = ["SysDateTimePick32",
r"WindowsForms\d*\.SysDateTimePick32\..*", ] r"WindowsForms\d*\.SysDateTimePick32\..*", ]
if sysinfo.UIA_support:
#controltypes is empty to make wrapper search result unique
#possible control types: IUIA().UIA_dll.UIA_PaneControlTypeId
controltypes = []
has_title = False has_title = False
#---------------------------------------------------------------- #----------------------------------------------------------------
@ -3387,10 +3351,6 @@ class HotkeyWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "Hotkey" friendlyclassname = "Hotkey"
windowclasses = ["msctls_hotkey32", ] windowclasses = ["msctls_hotkey32", ]
if sysinfo.UIA_support:
#controltypes is empty to make wrapper search result unique
#possible control types: IUIA().UIA_dll.UIA_PaneControlTypeId
controltypes = []
has_title = False has_title = False
@ -3401,10 +3361,6 @@ class IPAddressWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "IPAddress" friendlyclassname = "IPAddress"
windowclasses = ["SysIPAddress32", ] windowclasses = ["SysIPAddress32", ]
if sysinfo.UIA_support:
#controltypes is empty to make wrapper search result unique
#possible control types: IUIA().UIA_dll.UIA_PaneControlTypeId
controltypes = []
has_title = False has_title = False
@ -3415,8 +3371,6 @@ class CalendarWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "Calendar" friendlyclassname = "Calendar"
windowclasses = ["SysMonthCal32", ] windowclasses = ["SysMonthCal32", ]
if sysinfo.UIA_support:
controltypes = [IUIA().UIA_dll.UIA_CalendarControlTypeId]
has_title = False has_title = False
place_in_calendar = { place_in_calendar = {
@ -3719,10 +3673,6 @@ class PagerWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "Pager" friendlyclassname = "Pager"
windowclasses = ["SysPager", ] windowclasses = ["SysPager", ]
if sysinfo.UIA_support:
#controltypes is empty to make wrapper search result unique
#possible control types: IUIA().UIA_dll.UIA_PaneControlTypeId
controltypes = []
#---------------------------------------------------------------- #----------------------------------------------------------------
def get_position(self): def get_position(self):
@ -3748,8 +3698,6 @@ class ProgressWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "Progress" friendlyclassname = "Progress"
windowclasses = ["msctls_progress", "msctls_progress32", ] windowclasses = ["msctls_progress", "msctls_progress32", ]
if sysinfo.UIA_support:
controltypes = [IUIA().UIA_dll.UIA_ProgressBarControlTypeId]
has_title = False has_title = False
#---------------------------------------------------------------- #----------------------------------------------------------------

@ -493,7 +493,7 @@ class HwndWrapper(BaseWrapper):
(e.g. VK_LEFT, VK_DELETE), a KeySequenceError is raised. Consider using (e.g. VK_LEFT, VK_DELETE), a KeySequenceError is raised. Consider using
the method send_keystrokes for such input. the method send_keystrokes for such input.
""" """
input_locale_id = ctypes.windll.User32.GetKeyboardLayout(0) input_locale_id = win32functions.GetKeyboardLayout(0)
keys = keyboard.parse_keys(chars, with_spaces, with_tabs, with_newlines) keys = keyboard.parse_keys(chars, with_spaces, with_tabs, with_newlines)
for key in keys: for key in keys:
@ -506,11 +506,11 @@ class HwndWrapper(BaseWrapper):
if unicode_char: if unicode_char:
_, char = key_info[:2] _, char = key_info[:2]
vk = ctypes.windll.User32.VkKeyScanExW(char, input_locale_id) & 0xFF vk = win32functions.VkKeyScanExW(chr(char), input_locale_id) & 0xFF
scan = keyboard.MapVirtualKey(vk, 0) scan = win32functions.MapVirtualKeyW(vk, 0)
else: else:
vk, scan = key_info[:2] vk, scan = key_info[:2]
char = keyboard.MapVirtualKey(vk, 2) char = win32functions.MapVirtualKeyW(vk, 2)
if char > 0: if char > 0:
lparam = 1 << 0 | scan << 16 | (flags & 1) << 24 lparam = 1 << 0 | scan << 16 | (flags & 1) << 24
@ -541,22 +541,21 @@ class HwndWrapper(BaseWrapper):
.. _`type_keys`: pywinauto.base_wrapper.html#pywinauto.base_wrapper.BaseWrapper.type_keys .. _`type_keys`: pywinauto.base_wrapper.html#pywinauto.base_wrapper.BaseWrapper.type_keys
""" """
user32 = ctypes.windll.User32
PBYTE256 = ctypes.c_ubyte * 256 PBYTE256 = ctypes.c_ubyte * 256
win32gui.SendMessage(self.handle, win32con.WM_ACTIVATE, win32gui.SendMessage(self.handle, win32con.WM_ACTIVATE,
win32con.WA_ACTIVE, 0) win32con.WA_ACTIVE, 0)
target_thread_id = user32.GetWindowThreadProcessId(self.handle, None) target_thread_id = win32functions.GetWindowThreadProcessId(self.handle, None)
current_thread_id = win32api.GetCurrentThreadId() current_thread_id = win32functions.GetCurrentThreadId()
attach_success = user32.AttachThreadInput(target_thread_id, current_thread_id, True) != 0 attach_success = win32functions.AttachThreadInput(target_thread_id, current_thread_id, True) != 0
if not attach_success: if not attach_success:
warnings.warn('Failed to attach app\'s thread to the current thread\'s message queue', warnings.warn('Failed to attach app\'s thread to the current thread\'s message queue',
UserWarning, stacklevel=2) UserWarning, stacklevel=2)
keyboard_state_stack = [PBYTE256()] keyboard_state_stack = [PBYTE256()]
user32.GetKeyboardState(ctypes.byref(keyboard_state_stack[-1])) win32functions.GetKeyboardState(keyboard_state_stack[-1])
input_locale_id = ctypes.windll.User32.GetKeyboardLayout(0) input_locale_id = win32functions.GetKeyboardLayout(0)
context_code = 0 context_code = 0
keys = keyboard.parse_keys(keystrokes, with_spaces, with_tabs, with_newlines) keys = keyboard.parse_keys(keystrokes, with_spaces, with_tabs, with_newlines)
@ -578,11 +577,11 @@ class HwndWrapper(BaseWrapper):
shift_state = 0 shift_state = 0
unicode_codepoint = flags & keyboard.KEYEVENTF_UNICODE != 0 unicode_codepoint = flags & keyboard.KEYEVENTF_UNICODE != 0
if unicode_codepoint: if unicode_codepoint:
char = scan char = chr(scan)
vk_with_flags = user32.VkKeyScanExW(char, input_locale_id) vk_with_flags = win32functions.VkKeyScanExW(char, input_locale_id)
vk = vk_with_flags & 0xFF vk = vk_with_flags & 0xFF
shift_state = (vk_with_flags & 0xFF00) >> 8 shift_state = (vk_with_flags & 0xFF00) >> 8
scan = keyboard.MapVirtualKey(vk, 0) scan = win32functions.MapVirtualKeyW(vk, 0)
if key.down and vk > 0: if key.down and vk > 0:
new_keyboard_state = copy.deepcopy(keyboard_state_stack[-1]) new_keyboard_state = copy.deepcopy(keyboard_state_stack[-1])
@ -602,8 +601,8 @@ class HwndWrapper(BaseWrapper):
context_code << 29 | context_code << 29 |
0 << 31) 0 << 31)
user32.SetKeyboardState(ctypes.byref(keyboard_state_stack[-1])) win32functions.SetKeyboardState(keyboard_state_stack[-1])
win32api.PostMessage(self.handle, down_msg, vk, lparam) win32functions.PostMessage(self.handle, down_msg, vk, lparam)
if vk == keyboard.VK_MENU: if vk == keyboard.VK_MENU:
context_code = 1 context_code = 1
@ -621,8 +620,8 @@ class HwndWrapper(BaseWrapper):
1 << 30 | 1 << 30 |
1 << 31) 1 << 31)
win32api.PostMessage(self.handle, up_msg, vk, lparam) win32functions.PostMessage(self.handle, up_msg, vk, lparam)
user32.SetKeyboardState(ctypes.byref(keyboard_state_stack[-1])) win32functions.SetKeyboardState(keyboard_state_stack[-1])
if vk == keyboard.VK_MENU: if vk == keyboard.VK_MENU:
context_code = 0 context_code = 0
@ -636,10 +635,10 @@ class HwndWrapper(BaseWrapper):
UserWarning, stacklevel=2) UserWarning, stacklevel=2)
else: else:
warnings.warn(e.strerror, UserWarning, stacklevel=2) warnings.warn(e.strerror, UserWarning, stacklevel=2)
user32.SetKeyboardState(ctypes.byref(keyboard_state_stack[0])) win32functions.SetKeyboardState(keyboard_state_stack[0])
if attach_success: if attach_success:
user32.AttachThreadInput(target_thread_id, current_thread_id, False) win32functions.AttachThreadInput(target_thread_id, current_thread_id, False)
# ----------------------------------------------------------- # -----------------------------------------------------------
def send_message_timeout( def send_message_timeout(
@ -1256,7 +1255,7 @@ class HwndWrapper(BaseWrapper):
"""Return a handle to the active window within the process""" """Return a handle to the active window within the process"""
gui_info = win32structures.GUITHREADINFO() gui_info = win32structures.GUITHREADINFO()
gui_info.cbSize = ctypes.sizeof(gui_info) gui_info.cbSize = ctypes.sizeof(gui_info)
window_thread_id, _ = win32process.GetWindowThreadProcessId(int(self.handle)) window_thread_id = win32functions.GetWindowThreadProcessId(self.handle, None)
ret = win32functions.GetGUIThreadInfo( ret = win32functions.GetGUIThreadInfo(
window_thread_id, window_thread_id,
ctypes.byref(gui_info)) ctypes.byref(gui_info))
@ -1278,7 +1277,7 @@ class HwndWrapper(BaseWrapper):
""" """
gui_info = win32structures.GUITHREADINFO() gui_info = win32structures.GUITHREADINFO()
gui_info.cbSize = ctypes.sizeof(gui_info) gui_info.cbSize = ctypes.sizeof(gui_info)
window_thread_id, _ = win32process.GetWindowThreadProcessId(self.handle) window_thread_id = win32functions.GetWindowThreadProcessId(self.handle, None)
ret = win32functions.GetGUIThreadInfo( ret = win32functions.GetGUIThreadInfo(
window_thread_id, window_thread_id,
ctypes.byref(gui_info)) ctypes.byref(gui_info))
@ -1335,7 +1334,7 @@ class HwndWrapper(BaseWrapper):
def has_keyboard_focus(self): def has_keyboard_focus(self):
"""Check the keyboard focus on this control.""" """Check the keyboard focus on this control."""
control_thread = win32process.GetWindowThreadProcessId(self.handle)[0] control_thread = win32functions.GetWindowThreadProcessId(self.handle, None)
win32process.AttachThreadInput(control_thread, win32api.GetCurrentThreadId(), 1) win32process.AttachThreadInput(control_thread, win32api.GetCurrentThreadId(), 1)
focused = win32gui.GetFocus() focused = win32gui.GetFocus()
win32process.AttachThreadInput(control_thread, win32api.GetCurrentThreadId(), 0) win32process.AttachThreadInput(control_thread, win32api.GetCurrentThreadId(), 0)
@ -1346,9 +1345,9 @@ class HwndWrapper(BaseWrapper):
def set_keyboard_focus(self): def set_keyboard_focus(self):
"""Set the keyboard focus to this control.""" """Set the keyboard focus to this control."""
control_thread = win32process.GetWindowThreadProcessId(self.handle)[0] control_thread = win32functions.GetWindowThreadProcessId(self.handle, None)
win32process.AttachThreadInput(control_thread, win32api.GetCurrentThreadId(), 1) win32process.AttachThreadInput(control_thread, win32api.GetCurrentThreadId(), 1)
win32gui.SetFocus(self.handle) win32functions.SetFocus(self.handle)
win32process.AttachThreadInput(control_thread, win32api.GetCurrentThreadId(), 0) win32process.AttachThreadInput(control_thread, win32api.GetCurrentThreadId(), 0)
win32functions.WaitGuiThreadIdle(self.handle) win32functions.WaitGuiThreadIdle(self.handle)
@ -1602,12 +1601,13 @@ class DialogWrapper(HwndWrapper):
#win32defines.SMTO_BLOCK) #win32defines.SMTO_BLOCK)
# get a handle we can wait on # get a handle we can wait on
_, pid = win32process.GetWindowThreadProcessId(int(self.handle)) pid = ctypes.c_ulong()
win32functions.GetWindowThreadProcessId(self.handle, ctypes.byref(pid))
try: try:
process_wait_handle = win32api.OpenProcess( process_wait_handle = win32api.OpenProcess(
win32con.SYNCHRONIZE | win32con.PROCESS_TERMINATE, win32con.SYNCHRONIZE | win32con.PROCESS_TERMINATE,
0, 0,
pid) pid.value)
except win32gui.error: except win32gui.error:
return True # already closed return True # already closed
@ -1723,7 +1723,7 @@ def _perform_click(
# figure out the flags and pack coordinates # figure out the flags and pack coordinates
flags, click_point = _calc_flags_and_coords(pressed, coords) flags, click_point = _calc_flags_and_coords(pressed, coords)
#control_thread = win32functions.GetWindowThreadProcessId(ctrl, 0) #control_thread = win32functions.GetWindowThreadProcessId(ctrl, None)
#win32functions.AttachThreadInput(win32functions.GetCurrentThreadId(), control_thread, win32defines.TRUE) #win32functions.AttachThreadInput(win32functions.GetCurrentThreadId(), control_thread, win32defines.TRUE)
# TODO: check return value of AttachThreadInput properly # TODO: check return value of AttachThreadInput properly

@ -283,7 +283,7 @@ class MenuItem(object):
# if the item is not visible - work up along it's parents # if the item is not visible - work up along it's parents
# until we find an item we CAN click on # until we find an item we CAN click on
if rect == (0, 0, 0, 0) and self.menu.owner_item: if rect == win32structures.RECT(0, 0, 0, 0) and self.menu.owner_item:
self.menu.owner_item.click_input() self.menu.owner_item.click_input()
rect = self.rectangle() rect = self.rectangle()

@ -200,7 +200,11 @@ class ComboBoxWrapper(uiawrapper.UIAWrapper):
# ----------------------------------------------------------- # -----------------------------------------------------------
def texts(self): def texts(self):
"""Return the text of the items in the combobox""" """Return the text of the items in the combobox"""
texts = [] texts = self._texts_from_item_container()
if len(texts):
# flatten the list
return [ t for lst in texts for t in lst ]
# ComboBox has to be expanded to populate a list of its children items # ComboBox has to be expanded to populate a list of its children items
try: try:
super(ComboBoxWrapper, self).expand() super(ComboBoxWrapper, self).expand()
@ -370,6 +374,11 @@ class EditWrapper(uiawrapper.UIAWrapper):
"""Return the current value of the element""" """Return the current value of the element"""
return self.iface_value.CurrentValue return self.iface_value.CurrentValue
# -----------------------------------------------------------
def is_editable(self):
"""Return the edit possibility of the element"""
return not self.iface_value.CurrentIsReadOnly
# ----------------------------------------------------------- # -----------------------------------------------------------
def texts(self): def texts(self):
"""Get the text of the edit control""" """Get the text of the edit control"""
@ -846,8 +855,17 @@ class ListViewWrapper(uiawrapper.UIAWrapper):
raise ValueError("Element '{0}' not found".format(row)) raise ValueError("Element '{0}' not found".format(row))
elif isinstance(row, six.integer_types): elif isinstance(row, six.integer_types):
# Get the item by a row index # Get the item by a row index
# TODO: Can't get virtualized items that way try:
# TODO: See TODO section of item_count() method for details com_elem = 0
for _ in range(0, self.__resolve_row_index(row) + 1):
com_elem = self.iface_item_container.FindItemByProperty(com_elem, 0, uia_defs.vt_empty)
# Try to load element using VirtualizedItem pattern
try:
get_elem_interface(com_elem, "VirtualizedItem").Realize()
except NoPatternInterfaceError:
pass
itm = uiawrapper.UIAWrapper(uia_element_info.UIAElementInfo(com_elem))
except (NoPatternInterfaceError, ValueError, AttributeError):
list_items = self.children(content_only=True) list_items = self.children(content_only=True)
itm = list_items[self.__resolve_row_index(row)] itm = list_items[self.__resolve_row_index(row)]
else: else:
@ -960,18 +978,18 @@ class MenuWrapper(uiawrapper.UIAWrapper):
return item return item
# ----------------------------------------------------------- # -----------------------------------------------------------
@staticmethod def _activate(self, item, is_last):
def _activate(item):
"""Activate the specified item""" """Activate the specified item"""
if not item.is_active(): if not item.is_active():
item.set_focus() item.set_focus()
try: try:
item.expand() item.expand()
except(NoPatternInterfaceError): except(NoPatternInterfaceError):
pass if self.element_info.framework_id == 'WinForm' and not is_last:
item.select()
# ----------------------------------------------------------- # -----------------------------------------------------------
def _sub_item_by_text(self, menu, name, exact): def _sub_item_by_text(self, menu, name, exact, is_last):
"""Find a menu sub-item by the specified text""" """Find a menu sub-item by the specified text"""
sub_item = None sub_item = None
items = menu.items() items = menu.items()
@ -987,18 +1005,18 @@ class MenuWrapper(uiawrapper.UIAWrapper):
texts.append(i.window_text()) texts.append(i.window_text())
sub_item = findbestmatch.find_best_match(name, texts, items) sub_item = findbestmatch.find_best_match(name, texts, items)
self._activate(sub_item) self._activate(sub_item, is_last)
return sub_item return sub_item
# ----------------------------------------------------------- # -----------------------------------------------------------
def _sub_item_by_idx(self, menu, idx): def _sub_item_by_idx(self, menu, idx, is_last):
"""Find a menu sub-item by the specified index""" """Find a menu sub-item by the specified index"""
sub_item = None sub_item = None
items = menu.items() items = menu.items()
if items: if items:
sub_item = items[idx] sub_item = items[idx]
self._activate(sub_item) self._activate(sub_item, is_last)
return sub_item return sub_item
# ----------------------------------------------------------- # -----------------------------------------------------------
@ -1011,35 +1029,39 @@ class MenuWrapper(uiawrapper.UIAWrapper):
Note: $ - specifier is not supported Note: $ - specifier is not supported
""" """
# Get the path parts # Get the path parts
part0, parts = path.split("->", 1) menu_items = [p.strip() for p in path.split("->")]
part0 = part0.strip() items_cnt = len(menu_items)
if len(part0) == 0: if items_cnt == 0:
raise IndexError() raise IndexError()
for item in menu_items:
if not item:
raise IndexError("Empty item name between '->' separators")
def next_level_menu(parent_menu, item_name, is_last):
if item_name.startswith("#"):
return self._sub_item_by_idx(parent_menu, int(item_name[1:]), is_last)
else:
return self._sub_item_by_text(parent_menu, item_name, exact, is_last)
# Find a top level menu item and select it. After selecting this item # Find a top level menu item and select it. After selecting this item
# a new Menu control is created and placed on the dialog. It can be # a new Menu control is created and placed on the dialog. It can be
# a direct child or a descendant. # a direct child or a descendant.
# Sometimes we need to re-discover Menu again # Sometimes we need to re-discover Menu again
try: try:
menu = None menu = next_level_menu(self, menu_items[0], items_cnt == 1)
if part0.startswith("#"): if items_cnt == 1:
menu = self._sub_item_by_idx(self, int(part0[1:])) return menu
else:
menu = self._sub_item_by_text(self, part0, exact)
if not menu.items(): if not menu.items():
self._activate(menu) self._activate(menu, False)
timings.wait_until( timings.wait_until(
timings.Timings.window_find_timeout, timings.Timings.window_find_timeout,
timings.Timings.window_find_retry, timings.Timings.window_find_retry,
lambda: len(self.top_level_parent().descendants(control_type="Menu")) > 0) lambda: len(self.top_level_parent().descendants(control_type="Menu")) > 0)
menu = self.top_level_parent().descendants(control_type="Menu")[0] menu = self.top_level_parent().descendants(control_type="Menu")[0]
for cur_part in [p.strip() for p in parts.split("->")]: for i in range(1, items_cnt):
if cur_part.startswith("#"): menu = next_level_menu(menu, menu_items[i], items_cnt == i + 1)
menu = self._sub_item_by_idx(menu, int(cur_part[1:]))
else:
menu = self._sub_item_by_text(menu, cur_part, exact)
except(AttributeError): except(AttributeError):
raise IndexError() raise IndexError()

@ -782,5 +782,19 @@ class UIAWrapper(BaseWrapper):
return self return self
# -----------------------------------------------------------
def _texts_from_item_container(self):
"""Get texts through the ItemContainer interface"""
texts = []
try:
com_elem = self.iface_item_container.FindItemByProperty(0, 0, uia_defs.vt_empty)
while com_elem:
itm = UIAWrapper(UIAElementInfo(com_elem))
texts.append(itm.texts())
com_elem = self.iface_item_container.FindItemByProperty(com_elem, 0, uia_defs.vt_empty)
except (uia_defs.NoPatternInterfaceError):
pass
return texts
backend.register('uia', UIAElementInfo, UIAWrapper) backend.register('uia', UIAElementInfo, UIAWrapper)

@ -331,8 +331,9 @@ def get_control_names(control, allcontrols, textcontrols):
if non_text_names: if non_text_names:
names.extend(non_text_names) names.extend(non_text_names)
# return the names - and make sure there are no duplicates # return the names - and make sure there are no duplicates or empty values
return set(names) cleaned_names = set(names) - set([None, ""])
return cleaned_names
#==================================================================== #====================================================================
@ -493,6 +494,8 @@ def find_best_control_matches(search_text, controls):
""" """
name_control_map = build_unique_dict(controls) name_control_map = build_unique_dict(controls)
#print ">>>>>>>", repr(name_control_map).decode("ascii", "ignore")
# # collect all the possible names for all controls # # collect all the possible names for all controls
# # and build a list of them # # and build a list of them
# for ctrl in controls: # for ctrl in controls:

@ -189,9 +189,10 @@ def find_elements(class_name=None,
if top_level_only: if top_level_only:
# find the top level elements # find the top level elements
element = backend_obj.element_info_class() element = backend_obj.element_info_class()
# vryabov: we don't use title=title below, because it fixes issue 779:
# https://github.com/pywinauto/pywinauto/issues/779
elements = element.children(process=process, elements = element.children(process=process,
class_name=class_name, class_name=class_name,
title=title,
control_type=control_type, control_type=control_type,
cache_enable=True) cache_enable=True)
@ -206,8 +207,9 @@ def find_elements(class_name=None,
parent = backend_obj.element_info_class() parent = backend_obj.element_info_class()
# look for ALL children of that parent # look for ALL children of that parent
# vryabov: we don't use title=title below, because it fixes issue 779:
# https://github.com/pywinauto/pywinauto/issues/779
elements = parent.descendants(class_name=class_name, elements = parent.descendants(class_name=class_name,
title=title,
control_type=control_type, control_type=control_type,
cache_enable=True, cache_enable=True,
depth=depth) depth=depth)

@ -35,14 +35,18 @@ These are implemented in a procedural way so as to to be
useful to other modules with the least conceptual overhead useful to other modules with the least conceptual overhead
""" """
import ctypes
import warnings import warnings
import win32process import win32process
import win32api import win32api
import win32con import win32con
import win32gui import win32gui
import pywintypes
from ctypes import wintypes
from ctypes import WINFUNCTYPE
from ctypes import c_int
from ctypes import byref
from ctypes import sizeof
from ctypes import create_unicode_buffer
from . import win32functions from . import win32functions
from . import win32defines from . import win32defines
from . import win32structures from . import win32structures
@ -58,7 +62,7 @@ def text(handle):
if class_name == 'MSCTFIME UI': if class_name == 'MSCTFIME UI':
return 'M' return 'M'
if class_name is None: if class_name is None:
return None return ''
#length = win32functions.SendMessage(handle, win32defines.WM_GETTEXTLENGTH, 0, 0) #length = win32functions.SendMessage(handle, win32defines.WM_GETTEXTLENGTH, 0, 0)
# XXX: there are some very rare cases when WM_GETTEXTLENGTH hangs! # XXX: there are some very rare cases when WM_GETTEXTLENGTH hangs!
@ -71,11 +75,11 @@ def text(handle):
0, 0,
win32defines.SMTO_ABORTIFHUNG, win32defines.SMTO_ABORTIFHUNG,
500, 500,
ctypes.byref(c_length) byref(c_length)
) )
if result == 0: if result == 0:
ActionLogger().log('WARNING! Cannot retrieve text length for handle = ' + str(handle)) ActionLogger().log('WARNING! Cannot retrieve text length for handle = ' + str(handle))
return None return ''
else: else:
length = c_length.value length = c_length.value
@ -85,10 +89,10 @@ def text(handle):
if length > 0: if length > 0:
length += 1 length += 1
buffer_ = ctypes.create_unicode_buffer(length) buffer_ = create_unicode_buffer(length)
ret = win32functions.SendMessage( ret = win32functions.SendMessage(
handle, win32defines.WM_GETTEXT, length, ctypes.byref(buffer_)) handle, win32defines.WM_GETTEXT, length, byref(buffer_))
if ret: if ret:
textval = buffer_.value textval = buffer_.value
@ -101,7 +105,7 @@ def classname(handle):
"""Return the class name of the window""" """Return the class name of the window"""
if handle is None: if handle is None:
return None return None
class_name = ctypes.create_unicode_buffer(u"", 257) class_name = create_unicode_buffer(u"", 257)
win32functions.GetClassName(handle, class_name, 256) win32functions.GetClassName(handle, class_name, 256)
return class_name.value return class_name.value
@ -192,8 +196,8 @@ def is64bitbinary(filename):
binary_type = win32file.GetBinaryType(filename) binary_type = win32file.GetBinaryType(filename)
return binary_type != win32file.SCS_32BIT_BINARY return binary_type != win32file.SCS_32BIT_BINARY
except Exception as exc: except Exception as exc:
warnings.warn('Cannot get binary type for file "{}". Error: {}' \ warnings.warn('Cannot get binary type for file "{}". Error: {}'
''.format(filename, exc), RuntimeWarning, stacklevel=2) .format(filename, exc), RuntimeWarning, stacklevel=2)
return None return None
@ -201,24 +205,24 @@ def is64bitbinary(filename):
def clientrect(handle): def clientrect(handle):
"""Return the client rectangle of the control""" """Return the client rectangle of the control"""
client_rect = win32structures.RECT() client_rect = win32structures.RECT()
win32functions.GetClientRect(handle, ctypes.byref(client_rect)) win32functions.GetClientRect(handle, byref(client_rect))
return client_rect return client_rect
#========================================================================= #=========================================================================
def rectangle(handle): def rectangle(handle):
"""Return the rectangle of the window""" """Return the rectangle of the window"""
# GetWindowRect returns 4-tuple rect = win32structures.RECT()
try: win32functions.GetWindowRect(handle, byref(rect))
return win32structures.RECT(*win32gui.GetWindowRect(handle)) return rect
except pywintypes.error:
return win32structures.RECT()
#========================================================================= #=========================================================================
def font(handle): def font(handle):
"""Return the font as a LOGFONTW of the window""" """Return the font as a LOGFONTW of the window"""
# get the font handle # get the font handle
if handle is None:
handle = 0 # make sure we don't pass window handle down as None
font_handle = win32functions.SendMessage( font_handle = win32functions.SendMessage(
handle, win32defines.WM_GETFONT, 0, 0) handle, win32defines.WM_GETFONT, 0, 0)
@ -244,15 +248,10 @@ def font(handle):
font_handle = win32functions.GetStockObject( font_handle = win32functions.GetStockObject(
win32defines.ANSI_VAR_FONT) win32defines.ANSI_VAR_FONT)
else:
fontval = win32structures.LOGFONTW()
ret = win32functions.GetObject(
font_handle, ctypes.sizeof(fontval), ctypes.byref(fontval))
# Get the Logfont structure of the font of the control # Get the Logfont structure of the font of the control
fontval = win32structures.LOGFONTW() fontval = win32structures.LOGFONTW()
ret = win32functions.GetObject( ret = win32functions.GetObject(
font_handle, ctypes.sizeof(fontval), ctypes.byref(fontval)) font_handle, sizeof(fontval), byref(fontval))
# The function could not get the font - this is probably # The function could not get the font - this is probably
# because the control does not have associated Font/Text # because the control does not have associated Font/Text
@ -271,11 +270,11 @@ def font(handle):
# get the title font based on the system metrics rather # get the title font based on the system metrics rather
# than the font of the control itself # than the font of the control itself
ncms = win32structures.NONCLIENTMETRICSW() ncms = win32structures.NONCLIENTMETRICSW()
ncms.cbSize = ctypes.sizeof(ncms) ncms.cbSize = sizeof(ncms)
win32functions.SystemParametersInfo( win32functions.SystemParametersInfo(
win32defines.SPI_GETNONCLIENTMETRICS, win32defines.SPI_GETNONCLIENTMETRICS,
ctypes.sizeof(ncms), sizeof(ncms),
ctypes.byref(ncms), byref(ncms),
0) 0)
# with either of the following 2 flags set the font of the # with either of the following 2 flags set the font of the
@ -293,8 +292,9 @@ def font(handle):
#========================================================================= #=========================================================================
def processid(handle): def processid(handle):
"""Return the ID of process that controls this window""" """Return the ID of process that controls this window"""
_, process_id = win32process.GetWindowThreadProcessId(int(handle)) pid = wintypes.DWORD()
return process_id win32functions.GetWindowThreadProcessId(handle, byref(pid))
return pid.value
#========================================================================= #=========================================================================
@ -327,10 +327,10 @@ def children(handle):
return True return True
# define the child proc type # define the child proc type
enum_child_proc_t = ctypes.WINFUNCTYPE( enum_child_proc_t = WINFUNCTYPE(
ctypes.c_int, # return type c_int, # return type
win32structures.HWND, # the window handle wintypes.HWND, # the window handle
win32structures.LPARAM) # extra information wintypes.LPARAM) # extra information
# update the proc to the correct type # update the proc to the correct type
proc = enum_child_proc_t(enum_child_proc) proc = enum_child_proc_t(enum_child_proc)

@ -64,6 +64,8 @@ below. The module is also available on Linux.
{VK_F19}, {VK_EXECUTE}, {VK_PLAY}, {VK_RMENU}, {VK_F13}, {VK_F12}, {LWIN}, {VK_F19}, {VK_EXECUTE}, {VK_PLAY}, {VK_RMENU}, {VK_F13}, {VK_F12}, {LWIN},
{VK_DOWN}, {VK_F17}, {VK_F16}, {VK_F15}, {VK_F14} {VK_DOWN}, {VK_F17}, {VK_F16}, {VK_F15}, {VK_F14}
~ is a shorter alias for {ENTER}
**Modifiers:** **Modifiers:**
- ``'+': {VK_SHIFT}`` - ``'+': {VK_SHIFT}``
@ -96,10 +98,19 @@ Use curly brackers to escape modifiers and type reserved symbols as single keys:
send_keys('{^}a{^}c{%}') # type string "^a^c%" (Ctrl will not be pressed) send_keys('{^}a{^}c{%}') # type string "^a^c%" (Ctrl will not be pressed)
send_keys('{{}ENTER{}}') # type string "{ENTER}" without pressing Enter key send_keys('{{}ENTER{}}') # type string "{ENTER}" without pressing Enter key
For Windows only, pywinauto defaults to sending a virtual key packet
(VK_PACKET) for textual input. For applications that do not handle VK_PACKET
appropriately, the ``vk_packet`` option may be set to ``False``. In this case
pywinauto will attempt to send the virtual key code of the requested key. This
option only affects the behavior of keys matching [-=[]\;',./a-zA-Z0-9 ]. Note
that upper and lower case are included for a-z. Both reference the same
virtual key for convenience.
""" """
from __future__ import unicode_literals from __future__ import unicode_literals
import sys import sys
import string
from . import deprecated from . import deprecated
@ -113,6 +124,7 @@ else:
import six import six
from . import win32structures from . import win32structures
from . import win32functions
__all__ = ['KeySequenceError', 'send_keys'] __all__ = ['KeySequenceError', 'send_keys']
@ -120,17 +132,6 @@ else:
DEBUG = 0 DEBUG = 0
GetMessageExtraInfo = ctypes.windll.user32.GetMessageExtraInfo
MapVirtualKey = ctypes.windll.user32.MapVirtualKeyW
SendInput = ctypes.windll.user32.SendInput
UINT = ctypes.c_uint
SendInput.restype = UINT
SendInput.argtypes = [UINT, ctypes.c_void_p, ctypes.c_int]
VkKeyScan = ctypes.windll.user32.VkKeyScanW
VkKeyScan.restype = ctypes.c_short
VkKeyScan.argtypes = [ctypes.c_wchar]
INPUT_KEYBOARD = 1 INPUT_KEYBOARD = 1
KEYEVENTF_EXTENDEDKEY = 1 KEYEVENTF_EXTENDEDKEY = 1
KEYEVENTF_KEYUP = 2 KEYEVENTF_KEYUP = 2
@ -310,6 +311,29 @@ else:
'%': VK_MENU, '%': VK_MENU,
} }
# Virtual keys that map to an ASCII character
# See https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
ascii_vk = {
' ': 0x20,
'=': 0xbb,
',': 0xbc,
'-': 0xbd,
'.': 0xbe,
# According to the above reference, the following characters vary per region.
# This mapping applies to US keyboards
';': 0xba,
'/': 0xbf,
'`': 0xc0,
'[': 0xdb,
'\\': 0xdc,
']': 0xdd,
'\'': 0xde,
}
# [0-9A-Z] map exactly to their ASCII counterparts
ascii_vk.update(dict((c, ord(c)) for c in string.ascii_uppercase + string.digits))
# map [a-z] to their uppercase ASCII counterparts
ascii_vk.update(dict((c, ord(c.upper())) for c in string.ascii_lowercase))
class KeySequenceError(Exception): class KeySequenceError(Exception):
@ -368,7 +392,7 @@ else:
# it seems to return 0 every time but it's required by MSDN specification # it seems to return 0 every time but it's required by MSDN specification
# so call it just in case # so call it just in case
inp.ki.dwExtraInfo = GetMessageExtraInfo() inp.ki.dwExtraInfo = win32functions.GetMessageExtraInfo()
# if we are releasing - then let it up # if we are releasing - then let it up
if self.up: if self.up:
@ -381,7 +405,7 @@ else:
inputs = self.GetInput() inputs = self.GetInput()
# SendInput() supports all Unicode symbols # SendInput() supports all Unicode symbols
num_inserted_events = SendInput(len(inputs), ctypes.byref(inputs), num_inserted_events = win32functions.SendInput(len(inputs), ctypes.byref(inputs),
ctypes.sizeof(win32structures.INPUT)) ctypes.sizeof(win32structures.INPUT))
if num_inserted_events != len(inputs): if num_inserted_events != len(inputs):
raise RuntimeError('SendInput() inserted only ' + str(num_inserted_events) + raise RuntimeError('SendInput() inserted only ' + str(num_inserted_events) +
@ -447,7 +471,7 @@ else:
# return self.key, 0, 0 # return self.key, 0, 0
# this works for Tic Tac Toe i.e. +{RIGHT} SHIFT + RIGHT # this works for Tic Tac Toe i.e. +{RIGHT} SHIFT + RIGHT
return self.key, MapVirtualKey(self.key, 0), flags return self.key, win32functions.MapVirtualKeyW(self.key, 0), flags
def run(self): def run(self):
"""Execute the action""" """Execute the action"""
@ -468,9 +492,9 @@ else:
The vk and scan code are generated differently. The vk and scan code are generated differently.
""" """
vkey_scan = LoByte(VkKeyScan(self.key)) vkey_scan = LoByte(win32functions.VkKeyScanW(self.key))
return (vkey_scan, MapVirtualKey(vkey_scan, 0), 0) return (vkey_scan, win32functions.MapVirtualKeyW(vkey_scan, 0), 0)
def key_description(self): def key_description(self):
"""Return a description of the key""" """Return a description of the key"""
@ -500,7 +524,7 @@ else:
__repr__ = __str__ __repr__ = __str__
def handle_code(code): def handle_code(code, vk_packet):
"""Handle a key or sequence of keys in braces""" """Handle a key or sequence of keys in braces"""
code_keys = [] code_keys = []
# it is a known code (e.g. {DOWN}, {ENTER}, etc) # it is a known code (e.g. {DOWN}, {ENTER}, etc)
@ -509,6 +533,9 @@ else:
# it is an escaped modifier e.g. {%}, {^}, {+} # it is an escaped modifier e.g. {%}, {^}, {+}
elif len(code) == 1: elif len(code) == 1:
if not vk_packet and code in ascii_vk:
code_keys.append(VirtualKeyAction(ascii_vk[code]))
else:
code_keys.append(KeyAction(code)) code_keys.append(KeyAction(code))
# it is a repetition or a pause {DOWN 5}, {PAUSE 1.3} # it is a repetition or a pause {DOWN 5}, {PAUSE 1.3}
@ -535,7 +562,7 @@ else:
[VirtualKeyAction(CODES[to_repeat])] * count) [VirtualKeyAction(CODES[to_repeat])] * count)
# otherwise parse the keys and we get back a KeyAction # otherwise parse the keys and we get back a KeyAction
else: else:
to_repeat = parse_keys(to_repeat) to_repeat = parse_keys(to_repeat, vk_packet=vk_packet)
if isinstance(to_repeat, list): if isinstance(to_repeat, list):
keys = to_repeat * count keys = to_repeat * count
else: else:
@ -550,7 +577,8 @@ else:
with_spaces=False, with_spaces=False,
with_tabs=False, with_tabs=False,
with_newlines=False, with_newlines=False,
modifiers=None): modifiers=None,
vk_packet=True):
"""Return the parsed keys""" """Return the parsed keys"""
keys = [] keys = []
if not modifiers: if not modifiers:
@ -579,8 +607,10 @@ else:
end_pos = string.find(")", index) end_pos = string.find(")", index)
if end_pos == -1: if end_pos == -1:
raise KeySequenceError('`)` not found') raise KeySequenceError('`)` not found')
keys.extend( keys.extend(parse_keys(
parse_keys(string[index:end_pos], modifiers=modifiers)) string[index:end_pos],
modifiers=modifiers,
vk_packet=vk_packet))
index = end_pos + 1 index = end_pos + 1
# Escape or named key # Escape or named key
@ -597,7 +627,7 @@ else:
if any(key_event in code.lower() for key_event in key_events): if any(key_event in code.lower() for key_event in key_events):
code, current_key_event = code.split(' ') code, current_key_event = code.split(' ')
should_escape_next_keys = True should_escape_next_keys = True
current_keys = handle_code(code) current_keys = handle_code(code, vk_packet)
if current_key_event is not None: if current_key_event is not None:
if isinstance(current_keys[0].key, six.string_types): if isinstance(current_keys[0].key, six.string_types):
current_keys[0] = EscapedKeyAction(current_keys[0].key) current_keys[0] = EscapedKeyAction(current_keys[0].key)
@ -636,6 +666,11 @@ else:
elif modifiers or should_escape_next_keys: elif modifiers or should_escape_next_keys:
keys.append(EscapedKeyAction(c)) keys.append(EscapedKeyAction(c))
# if user disables the vk_packet option, always try to send a
# virtual key of the actual keystroke
elif not vk_packet and c in ascii_vk:
keys.append(VirtualKeyAction(ascii_vk[c]))
else: else:
keys.append(KeyAction(c)) keys.append(KeyAction(c))
@ -667,9 +702,12 @@ else:
with_spaces=False, with_spaces=False,
with_tabs=False, with_tabs=False,
with_newlines=False, with_newlines=False,
turn_off_numlock=True): turn_off_numlock=True,
vk_packet=True):
"""Parse the keys and type them""" """Parse the keys and type them"""
keys = parse_keys(keys, with_spaces, with_tabs, with_newlines) keys = parse_keys(
keys, with_spaces, with_tabs, with_newlines,
vk_packet=vk_packet)
for k in keys: for k in keys:
k.run() k.run()

@ -382,7 +382,7 @@ class PauseAction(KeyAction):
__repr__ = __str__ __repr__ = __str__
def handle_code(code): def handle_code(code, vk_packet=True):
"""Handle a key or sequence of keys in braces""" """Handle a key or sequence of keys in braces"""
code_keys = [] code_keys = []
# it is a known code (e.g. {DOWN}, {ENTER}, etc) # it is a known code (e.g. {DOWN}, {ENTER}, etc)
@ -433,7 +433,8 @@ def parse_keys(string,
with_spaces = False, with_spaces = False,
with_tabs = False, with_tabs = False,
with_newlines = False, with_newlines = False,
modifiers = None): modifiers = None,
vk_packet=True):
"""Return the parsed keys""" """Return the parsed keys"""
keys = [] keys = []
if not modifiers: if not modifiers:
@ -523,7 +524,8 @@ def send_keys(keys,
with_spaces=False, with_spaces=False,
with_tabs=False, with_tabs=False,
with_newlines=False, with_newlines=False,
turn_off_numlock=True): turn_off_numlock=True,
vk_packet=True):
"""Parse the keys and type them""" """Parse the keys and type them"""
keys = parse_keys(keys, with_spaces, with_tabs, with_newlines) keys = parse_keys(keys, with_spaces, with_tabs, with_newlines)
for k in keys: for k in keys:

@ -35,10 +35,15 @@ Win32 API functions to perform custom marshalling
from __future__ import print_function from __future__ import print_function
import sys import sys
import ctypes
import win32api import win32api
import win32process
from ctypes import wintypes
from ctypes import c_void_p
from ctypes import pointer
from ctypes import sizeof
from ctypes import byref
from ctypes import c_size_t
from ctypes import WinError
from . import win32functions from . import win32functions
from . import win32defines from . import win32defines
from . import win32structures from . import win32structures
@ -70,10 +75,12 @@ class RemoteMemoryBlock(object):
self._as_parameter_ = self.mem_address self._as_parameter_ = self.mem_address
_, process_id = win32process.GetWindowThreadProcessId(self.handle) pid = wintypes.DWORD()
win32functions.GetWindowThreadProcessId(self.handle, byref(pid))
process_id = pid.value
if not process_id: if not process_id:
raise AccessDenied( raise AccessDenied(
str(ctypes.WinError()) + " Cannot get process ID from handle.") str(WinError()) + " Cannot get process ID from handle.")
self.process = win32functions.OpenProcess( self.process = win32functions.OpenProcess(
win32defines.PROCESS_VM_OPERATION | win32defines.PROCESS_VM_OPERATION |
@ -85,12 +92,12 @@ class RemoteMemoryBlock(object):
if not self.process: if not self.process:
raise AccessDenied( raise AccessDenied(
str(ctypes.WinError()) + "process: %d", str(WinError()) + "process: %d",
process_id) process_id)
self.mem_address = win32functions.VirtualAllocEx( self.mem_address = win32functions.VirtualAllocEx(
ctypes.c_void_p(self.process), # remote process c_void_p(self.process), # remote process
ctypes.c_void_p(0), # let Valloc decide where c_void_p(0), # let Valloc decide where
win32structures.ULONG_PTR(self.size + 4), # how much to allocate win32structures.ULONG_PTR(self.size + 4), # how much to allocate
win32defines.MEM_RESERVE | \ win32defines.MEM_RESERVE | \
win32defines.MEM_COMMIT, # allocation type win32defines.MEM_COMMIT, # allocation type
@ -100,7 +107,7 @@ class RemoteMemoryBlock(object):
self.mem_address = self.mem_address.value self.mem_address = self.mem_address.value
if self.mem_address == 0: if self.mem_address == 0:
raise ctypes.WinError() raise WinError()
if hex(self.mem_address) == '0xffffffff80000000' or hex(self.mem_address).upper() == '0xFFFFFFFF00000000': if hex(self.mem_address) == '0xffffffff80000000' or hex(self.mem_address).upper() == '0xFFFFFFFF00000000':
raise Exception('Incorrect allocation: ' + hex(self.mem_address)) raise Exception('Incorrect allocation: ' + hex(self.mem_address))
@ -108,11 +115,11 @@ class RemoteMemoryBlock(object):
self._as_parameter_ = self.mem_address self._as_parameter_ = self.mem_address
# write guard signature at the end of memory block # write guard signature at the end of memory block
signature = win32structures.LONG(0x66666666) signature = wintypes.LONG(0x66666666)
ret = win32functions.WriteProcessMemory( ret = win32functions.WriteProcessMemory(
ctypes.c_void_p(self.process), c_void_p(self.process),
ctypes.c_void_p(self.mem_address + self.size), c_void_p(self.mem_address + self.size),
ctypes.pointer(signature), pointer(signature),
win32structures.ULONG_PTR(4), win32structures.ULONG_PTR(4),
win32structures.ULONG_PTR(0) win32structures.ULONG_PTR(0)
) )
@ -129,7 +136,7 @@ class RemoteMemoryBlock(object):
if ret == 0: if ret == 0:
ActionLogger().log('Warning: cannot close process handle!') ActionLogger().log('Warning: cannot close process handle!')
#raise ctypes.WinError() #raise WinError()
#---------------------------------------------------------------- #----------------------------------------------------------------
def CleanUp(self): def CleanUp(self):
@ -140,17 +147,17 @@ class RemoteMemoryBlock(object):
self.CheckGuardSignature() self.CheckGuardSignature()
ret = win32functions.VirtualFreeEx( ret = win32functions.VirtualFreeEx(
ctypes.c_void_p(self.process), c_void_p(self.process),
ctypes.c_void_p(self.mem_address), c_void_p(self.mem_address),
win32structures.ULONG_PTR(0), win32structures.ULONG_PTR(0),
win32structures.DWORD(win32defines.MEM_RELEASE)) wintypes.DWORD(win32defines.MEM_RELEASE))
if ret == 0: if ret == 0:
print('Error: CleanUp: VirtualFreeEx() returned zero for address ', hex(self.mem_address)) print('Error: CleanUp: VirtualFreeEx() returned zero for address ', hex(self.mem_address))
last_error = win32api.GetLastError() last_error = win32api.GetLastError()
print('LastError = ', last_error, ': ', win32api.FormatMessage(last_error).rstrip()) print('LastError = ', last_error, ': ', win32api.FormatMessage(last_error).rstrip())
sys.stdout.flush() sys.stdout.flush()
self._CloseHandle() self._CloseHandle()
raise ctypes.WinError() raise WinError()
self.mem_address = 0 self.mem_address = 0
self._CloseHandle() self._CloseHandle()
else: else:
@ -180,7 +187,7 @@ class RemoteMemoryBlock(object):
if size: if size:
nSize = win32structures.ULONG_PTR(size) nSize = win32structures.ULONG_PTR(size)
else: else:
nSize = win32structures.ULONG_PTR(ctypes.sizeof(data)) nSize = win32structures.ULONG_PTR(sizeof(data))
if self.size < nSize.value: if self.size < nSize.value:
raise Exception(('Write: RemoteMemoryBlock is too small ({0} bytes),' + raise Exception(('Write: RemoteMemoryBlock is too small ({0} bytes),' +
@ -190,19 +197,19 @@ class RemoteMemoryBlock(object):
raise Exception('Write: RemoteMemoryBlock has incorrect address = ' + hex(address)) raise Exception('Write: RemoteMemoryBlock has incorrect address = ' + hex(address))
ret = win32functions.WriteProcessMemory( ret = win32functions.WriteProcessMemory(
ctypes.c_void_p(self.process), c_void_p(self.process),
ctypes.c_void_p(address), c_void_p(address),
ctypes.pointer(data), pointer(data),
nSize, nSize,
win32structures.ULONG_PTR(0) win32structures.ULONG_PTR(0)
) )
if ret == 0: if ret == 0:
ActionLogger().log('Error: Write failed: address = ', address) ActionLogger().log('Error: Write failed: address = ' + str(address))
last_error = win32api.GetLastError() last_error = win32api.GetLastError()
ActionLogger().log('Error: LastError = ', last_error, ': ', ActionLogger().log('Error: LastError = ' + str(last_error) + ': ' +
win32api.FormatMessage(last_error).rstrip()) win32api.FormatMessage(last_error).rstrip())
raise ctypes.WinError() raise WinError()
self.CheckGuardSignature() self.CheckGuardSignature()
#---------------------------------------------------------------- #----------------------------------------------------------------
@ -216,7 +223,7 @@ class RemoteMemoryBlock(object):
if size: if size:
nSize = win32structures.ULONG_PTR(size) nSize = win32structures.ULONG_PTR(size)
else: else:
nSize = win32structures.ULONG_PTR(ctypes.sizeof(data)) nSize = win32structures.ULONG_PTR(sizeof(data))
if self.size < nSize.value: if self.size < nSize.value:
raise Exception(('Read: RemoteMemoryBlock is too small ({0} bytes),' + raise Exception(('Read: RemoteMemoryBlock is too small ({0} bytes),' +
@ -225,14 +232,14 @@ class RemoteMemoryBlock(object):
if hex(address).lower().startswith('0xffffff'): if hex(address).lower().startswith('0xffffff'):
raise Exception('Read: RemoteMemoryBlock has incorrect address =' + hex(address)) raise Exception('Read: RemoteMemoryBlock has incorrect address =' + hex(address))
lpNumberOfBytesRead = ctypes.c_size_t(0) lpNumberOfBytesRead = c_size_t(0)
ret = win32functions.ReadProcessMemory( ret = win32functions.ReadProcessMemory(
ctypes.c_void_p(self.process), c_void_p(self.process),
ctypes.c_void_p(address), c_void_p(address),
ctypes.byref(data), byref(data),
nSize, nSize,
ctypes.byref(lpNumberOfBytesRead) byref(lpNumberOfBytesRead)
) )
# disabled as it often returns an error - but # disabled as it often returns an error - but
@ -240,27 +247,27 @@ class RemoteMemoryBlock(object):
if ret == 0: if ret == 0:
# try again # try again
ret = win32functions.ReadProcessMemory( ret = win32functions.ReadProcessMemory(
ctypes.c_void_p(self.process), c_void_p(self.process),
ctypes.c_void_p(address), c_void_p(address),
ctypes.byref(data), byref(data),
nSize, nSize,
ctypes.byref(lpNumberOfBytesRead) byref(lpNumberOfBytesRead)
) )
if ret == 0: if ret == 0:
last_error = win32api.GetLastError() last_error = win32api.GetLastError()
if last_error != win32defines.ERROR_PARTIAL_COPY: if last_error != win32defines.ERROR_PARTIAL_COPY:
ActionLogger().log('Read: WARNING! self.mem_address =' + ActionLogger().log('Read: WARNING! self.mem_address =' +
hex(self.mem_address) + ' data address =' + str(ctypes.byref(data))) hex(self.mem_address) + ' data address =' + str(byref(data)))
ActionLogger().log('LastError = ' + str(last_error) + ActionLogger().log('LastError = ' + str(last_error) +
': ' + win32api.FormatMessage(last_error).rstrip()) ': ' + win32api.FormatMessage(last_error).rstrip())
else: else:
ActionLogger().log('Error: ERROR_PARTIAL_COPY') ActionLogger().log('Error: ERROR_PARTIAL_COPY')
ActionLogger().log('\nRead: WARNING! self.mem_address =' + ActionLogger().log('\nRead: WARNING! self.mem_address =' +
hex(self.mem_address) + ' data address =' + str(ctypes.byref(data))) hex(self.mem_address) + ' data address =' + str(byref(data)))
ActionLogger().log('lpNumberOfBytesRead =' + ActionLogger().log('lpNumberOfBytesRead =' +
str(lpNumberOfBytesRead) + ' nSize =' + str(nSize)) str(lpNumberOfBytesRead) + ' nSize =' + str(nSize))
raise ctypes.WinError() raise WinError()
else: else:
ActionLogger().log('Warning! Read OK: 2nd attempt!') ActionLogger().log('Warning! Read OK: 2nd attempt!')
#else: #else:
@ -273,18 +280,18 @@ class RemoteMemoryBlock(object):
def CheckGuardSignature(self): def CheckGuardSignature(self):
"""read guard signature at the end of memory block""" """read guard signature at the end of memory block"""
signature = win32structures.LONG(0) signature = win32structures.LONG(0)
lpNumberOfBytesRead = ctypes.c_size_t(0) lpNumberOfBytesRead = c_size_t(0)
ret = win32functions.ReadProcessMemory( ret = win32functions.ReadProcessMemory(
ctypes.c_void_p(self.process), c_void_p(self.process),
ctypes.c_void_p(self.mem_address + self.size), c_void_p(self.mem_address + self.size),
ctypes.pointer(signature), # 0x66666666 pointer(signature), # 0x66666666
win32structures.ULONG_PTR(4), win32structures.ULONG_PTR(4),
ctypes.byref(lpNumberOfBytesRead)) byref(lpNumberOfBytesRead))
if ret == 0: if ret == 0:
ActionLogger().log('Error: Failed to read guard signature: address = ' + ActionLogger().log('Error: Failed to read guard signature: address = ' +
hex(self.mem_address) + ', size = ' + str(self.size) + hex(self.mem_address) + ', size = ' + str(self.size) +
', lpNumberOfBytesRead = ' + str(lpNumberOfBytesRead)) ', lpNumberOfBytesRead = ' + str(lpNumberOfBytesRead))
raise ctypes.WinError() raise WinError()
else: else:
if hex(signature.value) != '0x66666666': if hex(signature.value) != '0x66666666':
raise Exception('---------------------------------------- ' + raise Exception('---------------------------------------- ' +

@ -82,8 +82,8 @@ class IUIA(object):
end_len = len('ControlTypeId') end_len = len('ControlTypeId')
self._control_types = [attr[start_len:-end_len] for attr in dir(self.UIA_dll) if attr.endswith('ControlTypeId')] self._control_types = [attr[start_len:-end_len] for attr in dir(self.UIA_dll) if attr.endswith('ControlTypeId')]
self.known_control_types = {} # string id: numeric id self.known_control_types = { 'InvalidControlType': 0 } # string id: numeric id
self.known_control_type_ids = {} # numeric id: string id self.known_control_type_ids = { 0: 'InvalidControlType' } # numeric id: string id
for ctrl_type in self._control_types: for ctrl_type in self._control_types:
type_id_name = 'UIA_' + ctrl_type + 'ControlTypeId' type_id_name = 'UIA_' + ctrl_type + 'ControlTypeId'
@ -218,6 +218,8 @@ scroll_no_amount = IUIA().ui_automation_client.ScrollAmount_NoAmount
scroll_large_increment = IUIA().ui_automation_client.ScrollAmount_LargeIncrement scroll_large_increment = IUIA().ui_automation_client.ScrollAmount_LargeIncrement
scroll_small_increment = IUIA().ui_automation_client.ScrollAmount_SmallIncrement scroll_small_increment = IUIA().ui_automation_client.ScrollAmount_SmallIncrement
vt_empty = IUIA().ui_automation_client.VARIANT.empty.vt
vt_null = IUIA().ui_automation_client.VARIANT.null.vt
def get_elem_interface(element_info, pattern_name): def get_elem_interface(element_info, pattern_name):
"""A helper to retrieve an element interface by the specified pattern name """A helper to retrieve an element interface by the specified pattern name

@ -79,7 +79,6 @@ windll.user32.SetWindowsHookExA.restype = wintypes.HHOOK
windll.user32.SetWindowsHookExA.argtypes = [c_int, HOOKCB, wintypes.HINSTANCE, wintypes.DWORD] windll.user32.SetWindowsHookExA.argtypes = [c_int, HOOKCB, wintypes.HINSTANCE, wintypes.DWORD]
windll.user32.SetWindowsHookExW.restype = wintypes.HHOOK windll.user32.SetWindowsHookExW.restype = wintypes.HHOOK
windll.user32.SetWindowsHookExW.argtypes = [c_int, HOOKCB, wintypes.HINSTANCE, wintypes.DWORD] windll.user32.SetWindowsHookExW.argtypes = [c_int, HOOKCB, wintypes.HINSTANCE, wintypes.DWORD]
windll.user32.GetMessageW.argtypes = [POINTER(wintypes.MSG), wintypes.HWND, c_uint, c_uint]
windll.user32.TranslateMessage.argtypes = [POINTER(wintypes.MSG)] windll.user32.TranslateMessage.argtypes = [POINTER(wintypes.MSG)]
windll.user32.DispatchMessageW.argtypes = [POINTER(wintypes.MSG)] windll.user32.DispatchMessageW.argtypes = [POINTER(wintypes.MSG)]
@ -452,7 +451,7 @@ class Hook(object):
al = ActionLogger() al = ActionLogger()
al.log("_process_kbd_msg_type, bad event_type: {0}".format(event_type)) al.log("_process_kbd_msg_type, bad event_type: {0}".format(event_type))
if event_type == 'key down': if event_type == 'key down' and current_key not in self.pressed_keys:
self.pressed_keys.append(current_key) self.pressed_keys.append(current_key)
elif event_type == 'key up': elif event_type == 'key up':
if current_key in self.pressed_keys: if current_key in self.pressed_keys:

@ -31,192 +31,678 @@
"""Defines Windows(tm) functions""" """Defines Windows(tm) functions"""
import ctypes from ctypes import LibraryLoader
from ctypes import WinDLL
from ctypes import wintypes from ctypes import wintypes
from . import win32defines, win32structures from . import win32defines, win32structures
from .actionlogger import ActionLogger from .actionlogger import ActionLogger
from ctypes import c_uint, c_short, c_long from ctypes import c_short
from ctypes import WINFUNCTYPE
from ctypes import c_void_p
from ctypes import c_int
from ctypes import byref
from ctypes import POINTER
from ctypes import c_ubyte
from ctypes import c_size_t
# Quote: "If you want cached libs without polluting ctypes.cdll or
# ctypes.windll, just create your own instance such as
# windll = ctypes.LibraryLoader(ctypes.WinDLL)."
# see https://bugs.python.org/issue22552
windll = LibraryLoader(WinDLL)
import sys
if sys.platform == "cygwin":
windll = ctypes.cdll
HRESULT = c_long
UINT = c_uint
SHORT = c_short SHORT = c_short
CreateBrushIndirect = ctypes.windll.gdi32.CreateBrushIndirect CreateBrushIndirect = windll.gdi32.CreateBrushIndirect
CreateDC = ctypes.windll.gdi32.CreateDCW CreateBrushIndirect.restype = wintypes.HBRUSH
CreateFontIndirect = ctypes.windll.gdi32.CreateFontIndirectW CreateBrushIndirect.argtypes = [
CreatePen = ctypes.windll.gdi32.CreatePen c_void_p,
DeleteDC = ctypes.windll.gdi32.DeleteDC ]
GetObject = ctypes.windll.gdi32.GetObjectW CreateDC = windll.gdi32.CreateDCW
DeleteObject = ctypes.windll.gdi32.DeleteObject CreateDC.restype = wintypes.HDC
DrawText = ctypes.windll.user32.DrawTextW CreateDC.argtypes = [
TextOut = ctypes.windll.gdi32.TextOutW wintypes.LPCWSTR,
Rectangle = ctypes.windll.gdi32.Rectangle wintypes.LPCWSTR,
SelectObject = ctypes.windll.gdi32.SelectObject wintypes.LPCWSTR,
GetStockObject = ctypes.windll.gdi32.GetStockObject c_void_p,
GetSystemMetrics = ctypes.windll.user32.GetSystemMetrics ]
GetSystemMetrics.restype = ctypes.c_int CreateFontIndirect = windll.gdi32.CreateFontIndirectW
GetSystemMetrics.argtypes = (ctypes.c_int, ) CreateFontIndirect.restype = wintypes.HFONT
GetTextMetrics = ctypes.windll.gdi32.GetTextMetricsW CreateFontIndirect.argtypes = [
POINTER(win32structures.LOGFONTW),
]
EnumChildWindows = ctypes.windll.user32.EnumChildWindows CreatePen = windll.gdi32.CreatePen
EnumDesktopWindows = ctypes.windll.user32.EnumDesktopWindows CreatePen.restype = wintypes.HPEN
EnumWindows = ctypes.windll.user32.EnumWindows CreatePen.argtypes = [
GetDC = ctypes.windll.user32.GetDC c_int,
GetDesktopWindow = ctypes.windll.user32.GetDesktopWindow c_int,
wintypes.COLORREF,
]
SendInput = ctypes.windll.user32.SendInput DeleteDC = windll.gdi32.DeleteDC
SetCursorPos = ctypes.windll.user32.SetCursorPos DeleteDC.restype = wintypes.BOOL
GetCursorPos = ctypes.windll.user32.GetCursorPos DeleteDC.argtypes = [
GetCaretPos = ctypes.windll.user32.GetCaretPos wintypes.HDC,
]
GetObject = windll.gdi32.GetObjectW
GetObject.restype = c_int
GetObject.argtypes = [
wintypes.HANDLE,
c_int,
wintypes.LPVOID,
]
DeleteObject = windll.gdi32.DeleteObject
DeleteObject.restype = wintypes.BOOL
DeleteObject.argtypes = [
wintypes.HGDIOBJ,
]
DrawText = windll.user32.DrawTextW
DrawText.restype = c_int
DrawText.argtypes = [
wintypes.HDC,
wintypes.LPCWSTR,
c_int,
POINTER(wintypes.RECT),
wintypes.UINT,
]
TextOut = windll.gdi32.TextOutW
TextOut.restype = wintypes.BOOL
TextOut.argtypes = [
wintypes.HDC,
c_int,
c_int,
wintypes.LPCWSTR,
c_int,
]
Rectangle = windll.gdi32.Rectangle
Rectangle.restype = wintypes.BOOL
Rectangle.argtypes = [
wintypes.HDC,
c_int,
c_int,
c_int,
c_int,
]
SelectObject = windll.gdi32.SelectObject
SelectObject.restype = wintypes.HGDIOBJ
SelectObject.argtypes = [
wintypes.HDC,
wintypes.HGDIOBJ,
]
GetStockObject = windll.gdi32.GetStockObject
GetStockObject.restype = wintypes.HGDIOBJ
GetStockObject.argtypes = [
c_int,
]
GetSystemMetrics = windll.user32.GetSystemMetrics
GetSystemMetrics.restype = c_int
GetSystemMetrics.argtypes = [
c_int,
]
GetTextMetrics = windll.gdi32.GetTextMetricsW
GetTextMetrics.restype = wintypes.BOOL
GetTextMetrics.argtypes = [
wintypes.HDC,
POINTER(win32structures.TEXTMETRICW),
]
EnumChildWindows = windll.user32.EnumChildWindows
EnumChildWindows.restype = wintypes.BOOL
EnumChildWindows.argtypes = [
wintypes.HWND,
WINFUNCTYPE(wintypes.BOOL, wintypes.HWND, wintypes.LPARAM),
wintypes.LPARAM,
]
EnumDesktopWindows = windll.user32.EnumDesktopWindows
EnumDesktopWindows.restype = wintypes.BOOL
EnumDesktopWindows.argtypes = [
wintypes.LPVOID,
WINFUNCTYPE(wintypes.BOOL, wintypes.HWND, wintypes.LPARAM),
wintypes.LPARAM,
]
EnumWindows = windll.user32.EnumWindows
EnumWindows.restype = wintypes.BOOL
EnumWindows.argtypes = [
WINFUNCTYPE(wintypes.BOOL, wintypes.HWND, wintypes.LPARAM),
wintypes.LPARAM,
]
GetDC = windll.user32.GetDC
GetDC.restype = wintypes.LPVOID
GetDC.argtypes = [
wintypes.HWND,
]
GetDesktopWindow = windll.user32.GetDesktopWindow
GetDesktopWindow.restype = wintypes.HWND
GetDesktopWindow.argtypes = [
]
SendInput = windll.user32.SendInput
SendInput.restype = wintypes.UINT
SendInput.argtypes = [
wintypes.UINT,
c_void_p, # using POINTER(win32structures.INPUT) needs rework in keyboard.py
c_int,
]
SetCursorPos = windll.user32.SetCursorPos
SetCursorPos.restype = wintypes.BOOL
SetCursorPos.argtypes = [
c_int,
c_int,
]
GetCursorPos = windll.user32.GetCursorPos
GetCursorPos.restype = wintypes.BOOL
GetCursorPos.argtypes = [
POINTER(wintypes.POINT),
]
GetCaretPos = windll.user32.GetCaretPos
GetCaretPos.restype = wintypes.BOOL
GetCaretPos.argtypes = [
POINTER(wintypes.POINT),
]
GetKeyboardState = windll.user32.GetKeyboardState
GetKeyboardState.restype = wintypes.BOOL
GetKeyboardState.argtypes = [
POINTER(c_ubyte),
]
SetKeyboardState = windll.user32.SetKeyboardState
SetKeyboardState.restype = wintypes.BOOL
SetKeyboardState.argtypes = [
POINTER(c_ubyte),
]
GetKeyboardLayout = windll.user32.GetKeyboardLayout
GetKeyboardLayout.restype = wintypes.HKL
GetKeyboardLayout.argtypes = [
wintypes.DWORD,
]
VkKeyScanW = windll.user32.VkKeyScanW
VkKeyScanW.restype = SHORT
VkKeyScanW.argtypes = [
wintypes.WCHAR,
]
VkKeyScanExW = windll.user32.VkKeyScanExW
VkKeyScanExW.restype = SHORT
VkKeyScanExW.argtypes = [
wintypes.WCHAR,
wintypes.HKL,
]
GetMessageExtraInfo = windll.user32.GetMessageExtraInfo
MapVirtualKeyW = windll.user32.MapVirtualKeyW
# menu functions # menu functions
DrawMenuBar = ctypes.windll.user32.DrawMenuBar DrawMenuBar = windll.user32.DrawMenuBar
GetMenu = ctypes.windll.user32.GetMenu DrawMenuBar.restype = wintypes.BOOL
GetMenuBarInfo = ctypes.windll.user32.GetMenuBarInfo DrawMenuBar.argstype = [
GetMenuInfo = ctypes.windll.user32.GetMenuInfo wintypes.HWND,
GetMenuItemCount = ctypes.windll.user32.GetMenuItemCount ]
GetMenuItemInfo = ctypes.windll.user32.GetMenuItemInfoW GetMenu = windll.user32.GetMenu
SetMenuItemInfo = ctypes.windll.user32.SetMenuItemInfoW GetMenu.restype = wintypes.HMENU
GetMenuItemRect = ctypes.windll.user32.GetMenuItemRect GetMenu.argtypes = [
CheckMenuItem = ctypes.windll.user32.CheckMenuItem wintypes.HWND,
GetMenuState = ctypes.windll.user32.GetMenuState ]
GetSubMenu = ctypes.windll.user32.GetSubMenu GetMenuBarInfo = windll.user32.GetMenuBarInfo
GetSystemMenu = ctypes.windll.user32.GetSystemMenu GetMenuBarInfo.restype = wintypes.BOOL
HiliteMenuItem = ctypes.windll.user32.HiliteMenuItem GetMenuBarInfo.argtypes = [
IsMenu = ctypes.windll.user32.IsMenu wintypes.HWND,
MenuItemFromPoint = ctypes.windll.user32.MenuItemFromPoint wintypes.LONG,
wintypes.LONG,
BringWindowToTop = ctypes.windll.user32.BringWindowToTop POINTER(win32structures.MENUBARINFO),
]
GetVersion = ctypes.windll.kernel32.GetVersion GetMenuInfo = windll.user32.GetMenuInfo
GetMenuInfo.restype = wintypes.BOOL
GetParent = ctypes.windll.user32.GetParent GetMenuInfo.argtypes = [
GetWindow = ctypes.windll.user32.GetWindow wintypes.HWND,
ShowWindow = ctypes.windll.user32.ShowWindow POINTER(win32structures.MENUINFO),
GetWindowContextHelpId = ctypes.windll.user32.GetWindowContextHelpId ]
GetWindowLong = ctypes.windll.user32.GetWindowLongW GetMenuItemCount = windll.user32.GetMenuItemCount
GetWindowPlacement = ctypes.windll.user32.GetWindowPlacement GetMenuItemCount.restype = c_int
GetWindowRect = ctypes.windll.user32.GetWindowRect GetMenuItemCount.argtypes = [
GetWindowText = ctypes.windll.user32.GetWindowTextW wintypes.HMENU,
GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW ]
GetClassName = ctypes.windll.user32.GetClassNameW GetMenuItemInfo = windll.user32.GetMenuItemInfoW
GetClassName.argtypes = [win32structures.HWND, wintypes.LPWSTR, ctypes.c_int] GetMenuItemInfo.restype = wintypes.BOOL
GetClassName.restrype = ctypes.c_int GetMenuItemInfo.argtypes = [
GetClientRect = ctypes.windll.user32.GetClientRect wintypes.HMENU,
IsChild = ctypes.windll.user32.IsChild wintypes.UINT,
IsWindow = ctypes.windll.user32.IsWindow wintypes.BOOL,
IsWindow.argtypes = [win32structures.HWND] POINTER(win32structures.MENUITEMINFOW),
IsWindow.restype = win32structures.BOOL ]
IsWindowUnicode = ctypes.windll.user32.IsWindowUnicode SetMenuItemInfo = windll.user32.SetMenuItemInfoW
IsWindowUnicode.argtypes = [win32structures.HWND] SetMenuItemInfo.restype = wintypes.BOOL
IsWindowUnicode.restype = win32structures.BOOL SetMenuItemInfo.argtypes = [
IsWindowVisible = ctypes.windll.user32.IsWindowVisible wintypes.HMENU,
IsWindowVisible.argtypes = [win32structures.HWND] wintypes.UINT,
IsWindowVisible.restype = win32structures.BOOL wintypes.BOOL,
IsWindowEnabled = ctypes.windll.user32.IsWindowEnabled POINTER(win32structures.MENUITEMINFOW),
IsWindowEnabled.argtypes = [win32structures.HWND] ]
IsWindowEnabled.restype = win32structures.BOOL GetMenuItemRect = windll.user32.GetMenuItemRect
ClientToScreen = ctypes.windll.user32.ClientToScreen GetMenuItemRect.restype = wintypes.BOOL
ScreenToClient = ctypes.windll.user32.ScreenToClient GetMenuItemRect.argtypes = [
wintypes.HWND,
GetCurrentThreadId = ctypes.windll.Kernel32.GetCurrentThreadId wintypes.HMENU,
GetWindowThreadProcessId = ctypes.windll.user32.GetWindowThreadProcessId wintypes.UINT,
GetGUIThreadInfo = ctypes.windll.user32.GetGUIThreadInfo POINTER(wintypes.RECT),
AttachThreadInput = ctypes.windll.user32.AttachThreadInput ]
AttachThreadInput.restype = win32structures.BOOL CheckMenuItem = windll.user32.CheckMenuItem
AttachThreadInput.argtypes = [win32structures.DWORD, win32structures.DWORD, win32structures.BOOL] CheckMenuItem.restype = wintypes.DWORD
#GetWindowThreadProcessId = ctypes.windll.user32.GetWindowThreadProcessId CheckMenuItem.argtypes = [
GetLastError = ctypes.windll.kernel32.GetLastError wintypes.HMENU,
wintypes.UINT,
OpenProcess = ctypes.windll.kernel32.OpenProcess wintypes.UINT,
CloseHandle = ctypes.windll.kernel32.CloseHandle ]
CreateProcess = ctypes.windll.kernel32.CreateProcessW GetMenuState = windll.user32.GetMenuState
TerminateProcess = ctypes.windll.kernel32.TerminateProcess GetMenuState.restype = wintypes.UINT
ExitProcess = ctypes.windll.kernel32.ExitProcess GetMenuState.argtypes = [
wintypes.HMENU,
ReadProcessMemory = ctypes.windll.kernel32.ReadProcessMemory wintypes.UINT,
GlobalAlloc = ctypes.windll.kernel32.GlobalAlloc wintypes.UINT,
GlobalLock = ctypes.windll.kernel32.GlobalLock ]
GlobalUnlock = ctypes.windll.kernel32.GlobalUnlock GetSubMenu = windll.user32.GetSubMenu
GetSubMenu.restype = wintypes.HMENU
SendMessage = ctypes.windll.user32.SendMessageW GetSubMenu.argtypes = [
SendMessageTimeout = ctypes.windll.user32.SendMessageTimeoutW wintypes.HMENU,
SendMessageTimeout.argtypes = [win32structures.HWND, win32structures.UINT, win32structures.WPARAM, c_int,
win32structures.LPARAM, win32structures.UINT, win32structures.UINT, ]
win32structures.PDWORD_PTR] GetSystemMenu = windll.user32.GetSystemMenu
SendMessageTimeout.restype = win32structures.LRESULT GetSystemMenu.restype = wintypes.HMENU
SendMessageA = ctypes.windll.user32.SendMessageA GetSystemMenu.argtypes = [
PostMessage = ctypes.windll.user32.PostMessageW wintypes.HWND,
GetMessage = ctypes.windll.user32.GetMessageW wintypes.BOOL,
RegisterWindowMessage = ctypes.windll.user32.RegisterWindowMessageW ]
RegisterWindowMessage.restype = UINT HiliteMenuItem = windll.user32.HiliteMenuItem
HiliteMenuItem.restype = wintypes.BOOL
MoveWindow = ctypes.windll.user32.MoveWindow HiliteMenuItem.argtypes = [
EnableWindow = ctypes.windll.user32.EnableWindow wintypes.HWND,
SetActiveWindow = ctypes.windll.user32.SetActiveWindow wintypes.HMENU,
GetFocus = ctypes.windll.user32.GetFocus wintypes.UINT,
SetFocus = ctypes.windll.user32.SetFocus wintypes.UINT,
SetForegroundWindow = ctypes.windll.user32.SetForegroundWindow ]
GetForegroundWindow = ctypes.windll.user32.GetForegroundWindow IsMenu = windll.user32.IsMenu
SetWindowLong = ctypes.windll.user32.SetWindowLongW IsMenu.restype = wintypes.BOOL
IsMenu.argtypes = [
wintypes.HMENU,
]
MenuItemFromPoint = windll.user32.MenuItemFromPoint
MenuItemFromPoint.restype = c_int
MenuItemFromPoint.argtypes = [
wintypes.HWND,
wintypes.HMENU,
POINTER(wintypes.POINT),
]
BringWindowToTop = windll.user32.BringWindowToTop
BringWindowToTop.restype = wintypes.BOOL
BringWindowToTop.argtypes = [
wintypes.HWND,
]
GetParent = windll.user32.GetParent
GetParent.restype = wintypes.HWND
GetParent.argtypes = [
wintypes.HWND,
]
GetWindow = windll.user32.GetWindow
GetWindow.restype = wintypes.HWND
GetWindow.argtypes = [
wintypes.HWND,
wintypes.UINT,
]
ShowWindow = windll.user32.ShowWindow
ShowWindow.restype = wintypes.BOOL
ShowWindow.argtypes = [
wintypes.HWND,
c_int,
]
GetWindowContextHelpId = windll.user32.GetWindowContextHelpId
GetWindowContextHelpId.restype = wintypes.DWORD
GetWindowContextHelpId.argtypes = [
wintypes.HWND,
]
GetWindowLong = windll.user32.GetWindowLongW
GetWindowLong.restype = wintypes.LONG
GetWindowLong.argtypes = [
wintypes.HWND,
c_int,
]
GetWindowPlacement = windll.user32.GetWindowPlacement
GetWindowPlacement.restype = wintypes.BOOL
GetWindowPlacement.argtypes = [
wintypes.HWND,
POINTER(win32structures.WINDOWPLACEMENT),
]
GetWindowRect = windll.user32.GetWindowRect
GetWindowRect.restype = wintypes.BOOL
GetWindowRect.argtypes = [
wintypes.HWND,
POINTER(wintypes.RECT),
]
GetWindowText = windll.user32.GetWindowTextW
GetWindowText.restype = c_int
GetWindowText.argtypes = [
wintypes.HWND,
wintypes.LPWSTR,
c_int,
]
GetWindowTextLength = windll.user32.GetWindowTextLengthW
GetWindowTextLength.restype = c_int
GetWindowTextLength.argtypes = [
wintypes.HWND,
]
GetClassName = windll.user32.GetClassNameW
GetClassName.restype = c_int
GetClassName.argtypes = [
wintypes.HWND,
wintypes.LPWSTR,
c_int,
]
GetClientRect = windll.user32.GetClientRect
GetClientRect.restype = wintypes.BOOL
GetClientRect.argtypes = [
wintypes.HWND,
POINTER(wintypes.RECT),
]
IsChild = windll.user32.IsChild
IsChild.restype = wintypes.BOOL
IsChild.argtypes = [
wintypes.HWND,
wintypes.HWND,
]
IsWindow = windll.user32.IsWindow
IsWindow.restype = wintypes.BOOL
IsWindow.argtypes = [
wintypes.HWND,
]
IsWindowUnicode = windll.user32.IsWindowUnicode
IsWindowUnicode.restype = wintypes.BOOL
IsWindowUnicode.argtypes = [
wintypes.HWND,
]
IsWindowVisible = windll.user32.IsWindowVisible
IsWindowVisible.restype = wintypes.BOOL
IsWindowVisible.argtypes = [
wintypes.HWND,
]
IsWindowEnabled = windll.user32.IsWindowEnabled
IsWindowEnabled.restype = wintypes.BOOL
IsWindowEnabled.argtypes = [
wintypes.HWND,
]
ClientToScreen = windll.user32.ClientToScreen
ClientToScreen.restype = wintypes.BOOL
ClientToScreen.argtypes = [
wintypes.HWND,
POINTER(wintypes.POINT),
]
ScreenToClient = windll.user32.ScreenToClient
ScreenToClient.restype = wintypes.BOOL
ScreenToClient.argtypes = [
wintypes.HWND,
POINTER(wintypes.POINT),
]
GetCurrentThreadId = windll.kernel32.GetCurrentThreadId
GetCurrentThreadId.restype = wintypes.DWORD
GetCurrentThreadId.argtypes = [
]
GetWindowThreadProcessId = windll.user32.GetWindowThreadProcessId
GetWindowThreadProcessId.restype = wintypes.DWORD
GetWindowThreadProcessId.argtypes = [
wintypes.HWND,
POINTER(wintypes.DWORD),
]
GetGUIThreadInfo = windll.user32.GetGUIThreadInfo
GetGUIThreadInfo.restype = wintypes.BOOL
GetGUIThreadInfo.argtypes = [
wintypes.DWORD,
POINTER(win32structures.GUITHREADINFO),
]
AttachThreadInput = windll.user32.AttachThreadInput
AttachThreadInput.restype = wintypes.BOOL
AttachThreadInput.argtypes = [
wintypes.DWORD,
wintypes.DWORD,
wintypes.BOOL
]
OpenProcess = windll.kernel32.OpenProcess
OpenProcess.restype = wintypes.HANDLE
OpenProcess.argtypes = [
wintypes.DWORD,
wintypes.BOOL,
wintypes.DWORD,
]
CloseHandle = windll.kernel32.CloseHandle
CloseHandle.restype = wintypes.BOOL
CloseHandle.argtypes = [
wintypes.HANDLE,
]
CreateProcess = windll.kernel32.CreateProcessW
CreateProcess.restype = wintypes.BOOL
CreateProcess.argtypes = [
wintypes.LPCWSTR,
wintypes.LPWSTR,
POINTER(win32structures.SECURITY_ATTRIBUTES),
POINTER(win32structures.SECURITY_ATTRIBUTES),
wintypes.BOOL,
wintypes.DWORD,
wintypes.LPVOID,
wintypes.LPCWSTR,
POINTER(win32structures.STARTUPINFOW),
POINTER(win32structures.PROCESS_INFORMATION),
]
TerminateProcess = windll.kernel32.TerminateProcess
TerminateProcess.restype = wintypes.BOOL
TerminateProcess.argtypes = [
wintypes.HANDLE,
wintypes.UINT,
]
ExitProcess = windll.kernel32.ExitProcess
ExitProcess.restype = None
ExitProcess.argtypes = [
wintypes.UINT,
]
ReadProcessMemory = windll.kernel32.ReadProcessMemory
ReadProcessMemory.restype = wintypes.BOOL
ReadProcessMemory.argtypes = [
wintypes.HANDLE,
wintypes.LPVOID,
wintypes.LPVOID,
c_size_t,
POINTER(c_size_t),
]
GlobalAlloc = windll.kernel32.GlobalAlloc
GlobalLock = windll.kernel32.GlobalLock
GlobalUnlock = windll.kernel32.GlobalUnlock
SendMessage = windll.user32.SendMessageW
SendMessage.restype = wintypes.LPARAM
SendMessage.argtypes = [
wintypes.HWND,
wintypes.UINT,
wintypes.WPARAM,
wintypes.LPVOID,
]
SendMessageTimeout = windll.user32.SendMessageTimeoutW
SendMessageTimeout.restype = wintypes.LPARAM
SendMessageTimeout.argtypes = [
wintypes.HWND,
wintypes.UINT,
wintypes.WPARAM,
wintypes.LPARAM,
wintypes.UINT,
wintypes.UINT,
win32structures.PDWORD_PTR,
]
PostMessage = windll.user32.PostMessageW
PostMessage.restype = wintypes.BOOL
PostMessage.argtypes = [
wintypes.HWND,
wintypes.UINT,
wintypes.WPARAM,
wintypes.LPARAM,
]
GetMessage = windll.user32.GetMessageW
GetMessage.restype = wintypes.BOOL
GetMessage.argtypes = [
POINTER(wintypes.MSG),
wintypes.HWND,
wintypes.UINT,
wintypes.UINT,
]
RegisterWindowMessage = windll.user32.RegisterWindowMessageW
RegisterWindowMessage.restype = wintypes.UINT
RegisterWindowMessage.argtypes = [
wintypes.LPCWSTR,
]
MoveWindow = windll.user32.MoveWindow
MoveWindow.restype = wintypes.BOOL
MoveWindow.argtypes = [
wintypes.HWND,
c_int,
c_int,
c_int,
c_int,
wintypes.BOOL,
]
EnableWindow = windll.user32.EnableWindow
EnableWindow.restype = wintypes.BOOL
EnableWindow.argtypes = [
wintypes.HWND,
wintypes.BOOL,
]
SetFocus = windll.user32.SetFocus
SetFocus.restype = wintypes.HWND
SetFocus.argtypes = [
wintypes.HWND,
]
SetWindowLong = windll.user32.SetWindowLongW
SetWindowLong.restype = wintypes.LONG
SetWindowLong.argtypes = [
wintypes.HWND,
c_int,
wintypes.LONG,
]
try: try:
SetWindowLongPtr = ctypes.windll.user32.SetWindowLongPtrW SetWindowLongPtr = windll.user32.SetWindowLongPtrW
SetWindowLongPtr.argtypes = [win32structures.HWND, ctypes.c_int, win32structures.LONG_PTR] SetWindowLongPtr.argtypes = [wintypes.HWND, c_int, wintypes.LONG_PTR]
SetWindowLongPtr.restype = win32structures.LONG_PTR SetWindowLongPtr.restype = wintypes.LONG_PTR
except AttributeError: except AttributeError:
SetWindowLongPtr = SetWindowLong SetWindowLongPtr = SetWindowLong
SystemParametersInfo = ctypes.windll.user32.SystemParametersInfoW SystemParametersInfo = windll.user32.SystemParametersInfoW
VirtualAllocEx = ctypes.windll.kernel32.VirtualAllocEx SystemParametersInfo.restype = wintypes.UINT
VirtualAllocEx.restype = ctypes.c_void_p SystemParametersInfo.argtypes = [
VirtualFreeEx = ctypes.windll.kernel32.VirtualFreeEx wintypes.UINT,
DebugBreakProcess = ctypes.windll.kernel32.DebugBreakProcess wintypes.UINT,
wintypes.LPVOID, # should map well to PVOID
VirtualAlloc = ctypes.windll.kernel32.VirtualAlloc wintypes.UINT,
VirtualFree = ctypes.windll.kernel32.VirtualFree ]
WriteProcessMemory = ctypes.windll.kernel32.WriteProcessMemory VirtualAllocEx = windll.kernel32.VirtualAllocEx
GetActiveWindow = ctypes.windll.user32.GetActiveWindow VirtualAllocEx.restype = wintypes.LPVOID
GetLastActivePopup = ctypes.windll.user32.GetLastActivePopup VirtualAllocEx.argtypes = [
FindWindow = ctypes.windll.user32.FindWindowW wintypes.HANDLE,
GetTopWindow = ctypes.windll.user32.GetTopWindow wintypes.LPVOID,
c_size_t,
SetCapture = ctypes.windll.user32.SetCapture wintypes.DWORD,
ReleaseCapture = ctypes.windll.user32.ReleaseCapture wintypes.DWORD,
]
ShowOwnedPopups = ctypes.windll.user32.ShowOwnedPopups VirtualFreeEx = windll.kernel32.VirtualFreeEx
WindowFromPoint = ctypes.windll.user32.WindowFromPoint VirtualFreeEx.restype = wintypes.BOOL
VirtualFreeEx.argtypes = [
WideCharToMultiByte = ctypes.windll.kernel32.WideCharToMultiByte wintypes.HANDLE,
GetACP = ctypes.windll.kernel32.GetACP wintypes.LPVOID,
c_size_t,
WaitForSingleObject = ctypes.windll.kernel32.WaitForSingleObject wintypes.DWORD,
WaitForInputIdle = ctypes.windll.user32.WaitForInputIdle ]
VirtualAlloc = windll.kernel32.VirtualAlloc
IsHungAppWindow = ctypes.windll.user32.IsHungAppWindow VirtualAlloc.restype = wintypes.LPVOID
IsHungAppWindow.restype = win32structures.BOOL VirtualAlloc.argtypes = [
IsHungAppWindow.argtypes = [win32structures.HWND] wintypes.LPVOID,
c_size_t,
GetModuleFileNameEx = ctypes.windll.psapi.GetModuleFileNameExW wintypes.DWORD,
wintypes.DWORD,
GetClipboardData = ctypes.windll.user32.GetClipboardData ]
OpenClipboard = ctypes.windll.user32.OpenClipboard VirtualFree = windll.kernel32.VirtualFree
EmptyClipboard = ctypes.windll.user32.EmptyClipboard VirtualFree.retype = wintypes.BOOL
CloseClipboard = ctypes.windll.user32.CloseClipboard VirtualFree.argtypes = [
CountClipboardFormats = ctypes.windll.user32.CountClipboardFormats wintypes.LPVOID,
EnumClipboardFormats = ctypes.windll.user32.EnumClipboardFormats c_size_t,
GetClipboardFormatName = ctypes.windll.user32.GetClipboardFormatNameW wintypes.DWORD,
]
WriteProcessMemory = windll.kernel32.WriteProcessMemory
WriteProcessMemory.restype = wintypes.BOOL
WriteProcessMemory.argtypes = [
wintypes.HANDLE,
wintypes.LPVOID,
wintypes.LPVOID,
c_size_t,
POINTER(c_size_t),
]
ReleaseCapture = windll.user32.ReleaseCapture
ReleaseCapture.restype = wintypes.BOOL
ReleaseCapture.argtypes = [
]
WindowFromPoint = windll.user32.WindowFromPoint
WindowFromPoint.restype = wintypes.HWND
WindowFromPoint.argtypes = [
wintypes.POINT,
]
WaitForSingleObject = windll.kernel32.WaitForSingleObject
WaitForSingleObject.restype = wintypes.DWORD
WaitForSingleObject.argtypes = [
wintypes.HANDLE,
wintypes.DWORD,
]
WaitForInputIdle = windll.user32.WaitForInputIdle
WaitForInputIdle.restype = wintypes.DWORD
WaitForInputIdle.argtypes = [
wintypes.HANDLE,
wintypes.DWORD,
]
IsHungAppWindow = windll.user32.IsHungAppWindow
IsHungAppWindow.restype = wintypes.BOOL
IsHungAppWindow.argtypes = [
wintypes.HWND,
]
GetModuleFileNameEx = windll.psapi.GetModuleFileNameExW
GetModuleFileNameEx.restype = wintypes.DWORD
GetModuleFileNameEx.argtypes = [
wintypes.HANDLE,
wintypes.HMODULE,
wintypes.LPWSTR,
wintypes.DWORD,
]
GetClipboardData = windll.user32.GetClipboardData
GetClipboardData.restype = wintypes.HANDLE
GetClipboardData.argtypes = [
wintypes.UINT,
]
OpenClipboard = windll.user32.OpenClipboard
OpenClipboard.restype = wintypes.BOOL
OpenClipboard.argtypes = [
wintypes.HWND,
]
EmptyClipboard = windll.user32.EmptyClipboard
EmptyClipboard.restype = wintypes.BOOL
EmptyClipboard.argtypes = [
]
CloseClipboard = windll.user32.CloseClipboard
CloseClipboard.restype = wintypes.BOOL
CloseClipboard.argtypes = [
]
CountClipboardFormats = windll.user32.CountClipboardFormats
CountClipboardFormats.restype = c_int
CountClipboardFormats.argtypes = [
]
EnumClipboardFormats = windll.user32.EnumClipboardFormats
EnumClipboardFormats.restype = wintypes.UINT
EnumClipboardFormats.argtypes = [
wintypes.UINT,
]
GetClipboardFormatName = windll.user32.GetClipboardFormatNameW
GetClipboardFormatName.restype = c_int
GetClipboardFormatName.argtypes = [
wintypes.UINT,
wintypes.LPWSTR,
c_int,
]
# DPIAware API funcs are not available on WinXP # DPIAware API funcs are not available on WinXP
try: try:
IsProcessDPIAware = ctypes.windll.user32.IsProcessDPIAware IsProcessDPIAware = windll.user32.IsProcessDPIAware
SetProcessDPIAware = ctypes.windll.user32.SetProcessDPIAware SetProcessDPIAware = windll.user32.SetProcessDPIAware
except AttributeError: except AttributeError:
IsProcessDPIAware = None IsProcessDPIAware = None
SetProcessDPIAware = None SetProcessDPIAware = None
@ -230,7 +716,7 @@ except AttributeError:
# Process_Per_Monitor_DPI_Aware = 2 # Process_Per_Monitor_DPI_Aware = 2
# } Process_DPI_Awareness; # } Process_DPI_Awareness;
try: try:
shcore = ctypes.windll.LoadLibrary("Shcore.dll") shcore = windll.LoadLibrary("Shcore.dll")
SetProcessDpiAwareness = shcore.SetProcessDpiAwareness SetProcessDpiAwareness = shcore.SetProcessDpiAwareness
GetProcessDpiAwareness = shcore.GetProcessDpiAwareness GetProcessDpiAwareness = shcore.GetProcessDpiAwareness
Process_DPI_Awareness = { Process_DPI_Awareness = {
@ -252,26 +738,17 @@ elif SetProcessDPIAware:
ActionLogger().log("Call SetProcessDPIAware") ActionLogger().log("Call SetProcessDPIAware")
SetProcessDPIAware() SetProcessDPIAware()
GetQueueStatus = ctypes.windll.user32.GetQueueStatus GetQueueStatus = windll.user32.GetQueueStatus
LoadString = ctypes.windll.user32.LoadStringW LoadString = windll.user32.LoadStringW
#def VkKeyScanW(p1):
# # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4225
# return VkKeyScanW._api_(p1)
#VkKeyScan = stdcall(SHORT, 'user32', [c_wchar]) (VkKeyScanW)
#
#def MapVirtualKeyExW(p1, p2, p3): #def MapVirtualKeyExW(p1, p2, p3):
# # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4376 # # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4376
# return MapVirtualKeyExW._api_(p1, p2, p3) # return MapVirtualKeyExW._api_(p1, p2, p3)
#MapVirtualKeyEx = stdcall( #MapVirtualKeyEx = stdcall(
# UINT, 'user32', [c_uint, c_uint, c_long]) (MapVirtualKeyExW) # UINT, 'user32', [c_uint, c_uint, c_long]) (MapVirtualKeyExW)
# #
#def MapVirtualKeyW(p1, p2):
# # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4355
# return MapVirtualKeyW._api_(p1, p2)
#MapVirtualKey = stdcall(UINT, 'user32', [c_uint, c_uint]) (MapVirtualKeyW)
#==================================================================== #====================================================================
@ -297,7 +774,7 @@ def LoWord(value):
def WaitGuiThreadIdle(handle): def WaitGuiThreadIdle(handle):
"""Wait until the thread of the specified handle is ready""" """Wait until the thread of the specified handle is ready"""
process_id = wintypes.DWORD(0) process_id = wintypes.DWORD(0)
GetWindowThreadProcessId(handle, ctypes.POINTER(wintypes.DWORD)(process_id)) GetWindowThreadProcessId(handle, byref(process_id))
# ask the control if it has finished processing the message # ask the control if it has finished processing the message
hprocess = OpenProcess( hprocess = OpenProcess(
@ -327,10 +804,10 @@ def GetDpiAwarenessByPid(pid):
return dpi_awareness return dpi_awareness
try: try:
dpi_awareness = ctypes.c_int() dpi_awareness = c_int()
hRes = GetProcessDpiAwareness( hRes = GetProcessDpiAwareness(
hProcess, hProcess,
ctypes.byref(dpi_awareness)) byref(dpi_awareness))
CloseHandle(hProcess) CloseHandle(hProcess)
if hRes == 0: if hRes == 0:
return dpi_awareness.value return dpi_awareness.value

@ -32,19 +32,18 @@
"""Definition of Windows structures""" """Definition of Windows structures"""
import six import six
import ctypes from ctypes import Structure as Struct
from ctypes import \ from ctypes import \
c_int, c_uint, c_long, c_ulong, c_void_p, c_wchar, c_char, \ c_int, c_long, c_void_p, c_char, memmove, addressof, \
c_ubyte, c_ushort, \
POINTER, sizeof, alignment, Union, c_longlong, c_size_t, wintypes POINTER, sizeof, alignment, Union, c_longlong, c_size_t, wintypes
from .win32defines import LF_FACESIZE from .win32defines import LF_FACESIZE
from . import sysinfo from . import sysinfo
class Structure(ctypes.Structure): class StructureMixIn(object):
"""Override the Structure class from ctypes to add printing and comparison""" """Define printing and comparison behaviors to be used for the Structure class from ctypes"""
#---------------------------------------------------------------- #----------------------------------------------------------------
def __str__(self): def __str__(self):
@ -52,47 +51,59 @@ class Structure(ctypes.Structure):
fields in exceptList will not be printed""" fields in exceptList will not be printed"""
lines = [] lines = []
for f in self._fields_: for field_name, _ in getattr(self, "_fields_", []):
name = f[0] lines.append("%20s\t%s"% (field_name, getattr(self, field_name)))
lines.append("%20s\t%s"% (name, getattr(self, name)))
return "\n".join(lines) return "\n".join(lines)
#---------------------------------------------------------------- #----------------------------------------------------------------
def __eq__(self, other_struct): def __eq__(self, other):
"""Return True if the two structures have the same coordinates""" """Return True if the two instances have the same coordinates"""
if isinstance(other_struct, ctypes.Structure): fields = getattr(self, "_fields_", [])
if isinstance(other, Struct):
try: try:
# pretend they are two structures - check that they both # pretend they are two structures - check that they both
# have the same value for all fields # have the same value for all fields
are_equal = True if len(fields) != len(getattr(other, "_fields_", [])):
for field in self._fields_: return False
name = field[0] for field_name, _ in fields:
if getattr(self, name) != getattr(other_struct, name): if getattr(self, field_name) != getattr(other, field_name):
are_equal = False return False
break return True
return are_equal
except AttributeError: except AttributeError:
return False return False
if isinstance(other_struct, (list, tuple)): elif isinstance(other, (list, tuple)):
# Now try to see if we have been passed in a list or tuple # Now try to see if we have been passed in a list or tuple
if len(fields) != len(other):
return False
try: try:
are_equal = True for i, (field_name, _) in enumerate(fields):
for i, field in enumerate(self._fields_): if getattr(self, field_name) != other[i]:
name = field[0] return False
if getattr(self, name) != other_struct[i]: return True
are_equal = False
break
return are_equal
except Exception: except Exception:
return False return False
return False return False
#----------------------------------------------------------------
def __ne__(self, other):
"""Return False if the two instances have the same coordinates"""
return not self.__eq__(other)
__hash__ = None
class Structure(Struct, StructureMixIn):
"""Override the Structure class from ctypes to add printing and comparison"""
pass
##==================================================================== ##====================================================================
#def PrintCtypesStruct(struct, exceptList = []): #def PrintCtypesStruct(struct, exceptList = []):
# """Print out the fields of the ctypes Structure # """Print out the fields of the ctypes Structure
@ -110,7 +121,7 @@ class Structure(ctypes.Structure):
# e.g. RECT.__reduce__ = _reduce # e.g. RECT.__reduce__ = _reduce
def _construct(typ, buf): def _construct(typ, buf):
obj = typ.__new__(typ) obj = typ.__new__(typ)
ctypes.memmove(ctypes.addressof(obj), buf, len(buf)) memmove(addressof(obj), buf, len(buf))
return obj return obj
def _reduce(self): def _reduce(self):
@ -119,21 +130,21 @@ def _reduce(self):
#LPTTTOOLINFOW = POINTER(tagTOOLINFOW) #LPTTTOOLINFOW = POINTER(tagTOOLINFOW)
#PTOOLINFOW = POINTER(tagTOOLINFOW) #PTOOLINFOW = POINTER(tagTOOLINFOW)
BOOL = c_int BOOL = wintypes.BOOL
BYTE = c_ubyte BYTE = wintypes.BYTE
CHAR = c_char CHAR = c_char
DWORD = c_ulong DWORD = wintypes.DWORD
HANDLE = c_void_p HANDLE = wintypes.HANDLE
HBITMAP = c_long HBITMAP = HANDLE
LONG = c_long LONG = wintypes.LONG
LPVOID = c_void_p LPVOID = wintypes.LPVOID
PVOID = c_void_p PVOID = c_void_p
UINT = c_uint UINT = wintypes.UINT
WCHAR = c_wchar WCHAR = wintypes.WCHAR
WORD = c_ushort WORD = wintypes.WORD
LRESULT = wintypes.LPARAM LRESULT = wintypes.LPARAM
COLORREF = DWORD COLORREF = wintypes.COLORREF
LPBYTE = POINTER(BYTE) LPBYTE = POINTER(BYTE)
LPWSTR = c_size_t #POINTER(WCHAR) LPWSTR = c_size_t #POINTER(WCHAR)
DWORD_PTR = UINT_PTR = ULONG_PTR = c_size_t DWORD_PTR = UINT_PTR = ULONG_PTR = c_size_t
@ -143,26 +154,20 @@ if sysinfo.is_x64_Python():
else: else:
INT_PTR = LONG_PTR = c_long INT_PTR = LONG_PTR = c_long
HBITMAP = LONG_PTR #LONG
HINSTANCE = LONG_PTR #LONG HINSTANCE = LONG_PTR #LONG
HMENU = LONG_PTR #LONG HMENU = LONG_PTR #LONG
HBRUSH = LONG_PTR #LONG HBRUSH = wintypes.HBRUSH # LONG_PTR #LONG
HTREEITEM = LONG_PTR #LONG HTREEITEM = LONG_PTR #LONG
HWND = LONG_PTR #LONG HWND = wintypes.HWND
# TODO: switch to ctypes.wintypes.LPARAM and ctypes.wintypes.WPARAM
# Notice that wintypes definition of LPARAM/WPARAM differs between 32/64 bit # Notice that wintypes definition of LPARAM/WPARAM differs between 32/64 bit
LPARAM = LONG_PTR LPARAM = wintypes.LPARAM
WPARAM = UINT_PTR WPARAM = wintypes.WPARAM
class POINT(Structure): class POINT(wintypes.POINT, StructureMixIn):
_pack_ = 4
_fields_ = [ """Wrap the POINT structure and add extra functionality"""
# C:/PROGRA~1/MIAF9D~1/VC98/Include/windef.h 307
('x', LONG),
('y', LONG),
]
def __iter__(self): def __iter__(self):
"""Allow iteration through coordinates""" """Allow iteration through coordinates"""
@ -178,25 +183,18 @@ class POINT(Structure):
else: else:
raise IndexError("Illegal index") raise IndexError("Illegal index")
assert sizeof(POINT) == 8, sizeof(POINT) assert sizeof(POINT) == 8, sizeof(POINT)
assert alignment(POINT) == 4, alignment(POINT) assert alignment(POINT) == 4, alignment(POINT)
# ==================================================================== # ====================================================================
class RECT(Structure): class RECT(wintypes.RECT, StructureMixIn):
"""Wrap the RECT structure and add extra functionality""" """Wrap the RECT structure and add extra functionality"""
_fields_ = [
# C:/PROGRA~1/MIAF9D~1/VC98/Include/windef.h 287
('left', LONG),
('top', LONG),
('right', LONG),
('bottom', LONG),
]
# ---------------------------------------------------------------- # ----------------------------------------------------------------
def __init__(self, otherRect_or_left = 0, top = 0, right = 0, bottom = 0): def __init__(self, otherRect_or_left=0, top=0, right=0, bottom=0):
"""Provide a constructor for RECT structures """Provide a constructor for RECT structures
A RECT can be constructed by: A RECT can be constructed by:
@ -220,20 +218,6 @@ class RECT(Structure):
self.top = long_int(top) self.top = long_int(top)
self.bottom = long_int(bottom) self.bottom = long_int(bottom)
# # ----------------------------------------------------------------
# def __eq__(self, otherRect):
# "return true if the two rectangles have the same coordinates"
#
# try:
# return \
# self.left == otherRect.left and \
# self.top == otherRect.top and \
# self.right == otherRect.right and \
# self.bottom == otherRect.bottom
# except AttributeError:
# return False
# ---------------------------------------------------------------- # ----------------------------------------------------------------
def __str__(self): def __str__(self):
"""Return a string representation of the RECT""" """Return a string representation of the RECT"""
@ -286,18 +270,17 @@ class RECT(Structure):
def mid_point(self): def mid_point(self):
"""Return a POINT structure representing the mid point""" """Return a POINT structure representing the mid point"""
pt = POINT() pt = POINT()
pt.x = self.left + int(float(self.width())/2.) pt.x = self.left + int(float(self.width()) / 2.)
pt.y = self.top + int(float(self.height())/2.) pt.y = self.top + int(float(self.height()) / 2.)
return pt return pt
#def __hash__(self): __reduce__ = _reduce
# return hash (self.left, self.top, self.right, self.bottom)
RECT.__reduce__ = _reduce
assert sizeof(RECT) == 16, sizeof(RECT) assert sizeof(RECT) == 16, sizeof(RECT)
assert alignment(RECT) == 4, alignment(RECT) assert alignment(RECT) == 4, alignment(RECT)
class SETTEXTEX(Structure): class SETTEXTEX(Structure):
_pack_ = 1 _pack_ = 1
_fields_ = [ _fields_ = [

@ -1,18 +1,25 @@
Metadata-Version: 2.1 Metadata-Version: 2.1
Name: pyOpenRPA Name: pyOpenRPA
Version: 1.1.12 Version: 1.1.13
Summary: First open source RPA platform for business Summary: First open source RPA platform for business
Home-page: https://gitlab.com/UnicodeLabs/OpenRPA Home-page: https://gitlab.com/UnicodeLabs/OpenRPA
Author: Ivan Maslov Author: Ivan Maslov
Author-email: Ivan.Maslov@unicodelabs.ru Author-email: Ivan.Maslov@unicodelabs.ru
License: MIT License: MIT
Keywords: OpenRPA RPA Robot Automation Robotization Keywords: OpenRPA RPA Robot Automation Robotization OpenSource
Platform: UNKNOWN Platform: UNKNOWN
Classifier: Development Status :: 3 - Alpha Classifier: Development Status :: 5 - Production/Stable
Classifier: License :: OSI Approved :: MIT License Classifier: License :: OSI Approved :: MIT License
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.7
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Software Development :: Testing
Classifier: Topic :: Software Development :: User Interfaces
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: Home Automation
Description-Content-Type: text/markdown Description-Content-Type: text/markdown
Requires-Dist: pywinauto (>=0.6.6) Requires-Dist: pywinauto (>=0.6.8)
Requires-Dist: WMI (>=1.4.9) Requires-Dist: WMI (>=1.4.9)
Requires-Dist: pillow (>=6.0.0) Requires-Dist: pillow (>=6.0.0)
Requires-Dist: keyboard (>=0.13.3) Requires-Dist: keyboard (>=0.13.3)
@ -50,17 +57,17 @@ Resources\WPy64-3720\python-3.7.2.amd64\python.exe
# Module GUI activity List: # Module GUI activity List:
############################ ############################
Новая версия Новая версия
############################ ############################
Получить СЃРїРёСЃРѕРє элементов, который удовлетворяет условиям через расширенный движок РїРѕРёСЃРєР° Получить список элементов, который удовлетворяет условиям через расширенный движок поиска
[ [
{ {
"index":<Позиция элемента РІ родительском объекте>, "index":<Позиция элемента в родительском объекте>,
"depth_start" - глубина, СЃ которой начинается РїРѕРёСЃРє (РїРѕ умолчанию 1) "depth_start" - глубина, с которой начинается поиск (по умолчанию 1)
"depth_end" - глубина, РґРѕ которой ведется РїРѕРёСЃРє (РїРѕ умолчанию 1) "depth_end" - глубина, до которой ведется поиск (по умолчанию 1)
"class_name" - наименование класса, который требуется искать "class_name" - наименование класса, который требуется искать
"title" - наименование заголовка "title" - наименование заголовка
"rich_text" - наименование rich_text "rich_text" - наименование rich_text
} }
] ]

@ -1,8 +1,8 @@
pyOpenRPA-1.1.12.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 pyOpenRPA-1.1.13.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pyOpenRPA-1.1.12.dist-info/METADATA,sha256=QQ3aid4fLcFpJ0aWDRyYrVf1EMWi3cYocTyqvmHwJ90,3542 pyOpenRPA-1.1.13.dist-info/METADATA,sha256=rjIGRZpHzGWnt9LvY4CqdNByJhS4FqqdMUdzP_2BWmk,3352
pyOpenRPA-1.1.12.dist-info/RECORD,, pyOpenRPA-1.1.13.dist-info/RECORD,,
pyOpenRPA-1.1.12.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97 pyOpenRPA-1.1.13.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97
pyOpenRPA-1.1.12.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10 pyOpenRPA-1.1.13.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10
pyOpenRPA/.idea/inspectionProfiles/profiles_settings.xml,sha256=YXLFmX7rPNGcnKK1uX1uKYPN0fpgskYNe7t0BV7cqkY,174 pyOpenRPA/.idea/inspectionProfiles/profiles_settings.xml,sha256=YXLFmX7rPNGcnKK1uX1uKYPN0fpgskYNe7t0BV7cqkY,174
pyOpenRPA/.idea/misc.xml,sha256=ySjeaQ1DfqxaRTlFGT_3zW5r9mWuwxoAK_AX4QiuAZM,203 pyOpenRPA/.idea/misc.xml,sha256=ySjeaQ1DfqxaRTlFGT_3zW5r9mWuwxoAK_AX4QiuAZM,203
pyOpenRPA/.idea/modules.xml,sha256=Q__U1JIA2cjxbLRXAv-SfYY00fZA0TNlpkkbY4s3ncg,277 pyOpenRPA/.idea/modules.xml,sha256=Q__U1JIA2cjxbLRXAv-SfYY00fZA0TNlpkkbY4s3ncg,277
@ -300,6 +300,6 @@ pyOpenRPA/Tools/Terminator.py,sha256=VcjX3gFXiCGu3MMCidhrTNsmC9wsAqfjRJdTSU9fLnU
pyOpenRPA/Tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pyOpenRPA/Tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Tools/__pycache__/Terminator.cpython-37.pyc,, pyOpenRPA/Tools/__pycache__/Terminator.cpython-37.pyc,,
pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/__init__.py,sha256=4A8Uettbe_avfR459RgVJNkUxs-2hHjTgSVKpVOFjKw,175 pyOpenRPA/__init__.py,sha256=MLl4coStn9rfw3D3uxDlH6uWJFlRPjAXs2Scbs-T3KA,175
pyOpenRPA/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/test.txt,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pyOpenRPA/test.txt,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0

@ -3,7 +3,7 @@ r"""
The OpenRPA package (from UnicodeLabs) The OpenRPA package (from UnicodeLabs)
""" """
__version__ = 'v1.1.12' __version__ = 'v1.1.13'
__all__ = [] __all__ = []
__author__ = 'Ivan Maslov <ivan.maslov@unicodelabs.ru>' __author__ = 'Ivan Maslov <ivan.maslov@unicodelabs.ru>'
#from .Core import Robot #from .Core import Robot

@ -1,13 +0,0 @@
At it's simplest it allows you to send mouse and keyboard
actions to windows dialogs and controls, but It has support for more complex
controls also.
Useful links
-------------
- Home page: http://pywinauto.github.io/
- Docs Intro: https://pywinauto.readthedocs.io/en/latest/
- Getting Started Guide: https://pywinauto.readthedocs.io/en/latest/getting_started.html
- StackOverflow tag: https://stackoverflow.com/questions/tagged/pywinauto

@ -1 +0,0 @@
{"classifiers": ["Development Status :: 5 - Production/Stable", "Environment :: Console", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: Microsoft :: Windows", "Programming Language :: Python", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Software Development :: Testing", "Topic :: Software Development :: User Interfaces", "Topic :: Software Development :: Quality Assurance"], "extensions": {"python.details": {"contacts": [{"email": "pywinauto-users@lists.sourceforge.net", "name": "Mark Mc Mahon and Contributors", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "http://pywinauto.github.io/"}}}, "extras": [], "generator": "bdist_wheel (0.29.0)", "keywords": ["windows", "gui", "automation", "GuiAuto", "testing", "test", "desktop", "mouse", "keyboard"], "license": "BSD 3-clause", "metadata_version": "2.0", "name": "pywinauto", "platform": "win32", "run_requires": [{"requires": ["comtypes", "six"]}], "summary": "A set of Python modules to automate the Microsoft Windows GUI", "version": "0.6.6"}

@ -0,0 +1,27 @@
Copyright (c) 2017, Mark Mc Mahon and Contributors
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.

@ -1,6 +1,6 @@
Metadata-Version: 2.0 Metadata-Version: 2.1
Name: pywinauto Name: pywinauto
Version: 0.6.6 Version: 0.6.8
Summary: A set of Python modules to automate the Microsoft Windows GUI Summary: A set of Python modules to automate the Microsoft Windows GUI
Home-page: http://pywinauto.github.io/ Home-page: http://pywinauto.github.io/
Author: Mark Mc Mahon and Contributors Author: Mark Mc Mahon and Contributors
@ -23,9 +23,9 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Software Development :: Testing Classifier: Topic :: Software Development :: Testing
Classifier: Topic :: Software Development :: User Interfaces Classifier: Topic :: Software Development :: User Interfaces
Classifier: Topic :: Software Development :: Quality Assurance Classifier: Topic :: Software Development :: Quality Assurance
Requires-Dist: comtypes
Requires-Dist: six Requires-Dist: six
Requires-Dist: comtypes
Requires-Dist: pywin32
At it's simplest it allows you to send mouse and keyboard At it's simplest it allows you to send mouse and keyboard
actions to windows dialogs and controls, but It has support for more complex actions to windows dialogs and controls, but It has support for more complex

@ -1,11 +1,10 @@
pywinauto-0.6.6.dist-info/DESCRIPTION.rst,sha256=k2uqeFUEl_g6xxBeVuZEfpJGuEOwcWLWkYAPOCoNkrk,443 pywinauto-0.6.8.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pywinauto-0.6.6.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 pywinauto-0.6.8.dist-info/LICENSE,sha256=GKmZqVt7I9hsQQtFNORNafbYzhPDpTcZsGq4ldii5zo,1504
pywinauto-0.6.6.dist-info/METADATA,sha256=0BOLG3k-RTQbPt5MoG8G7P0yDwqhu2hQddg1D03wNgA,1660 pywinauto-0.6.8.dist-info/METADATA,sha256=7x_-XwBl2UsjPrl_4e5bNgDVwA_FMH83WidT-ii0xb0,1723
pywinauto-0.6.6.dist-info/RECORD,, pywinauto-0.6.8.dist-info/RECORD,,
pywinauto-0.6.6.dist-info/WHEEL,sha256=Ds0ba8WsPJtjBPzEMyPOBG3qfPa6B4mlzB-vhzorIZs,97 pywinauto-0.6.8.dist-info/WHEEL,sha256=53VSps8MltPLN_x9Ib61FU2ZSaJKzgrWQqu9rS-Dkgk,116
pywinauto-0.6.6.dist-info/metadata.json,sha256=0I2fhQRsICsiE-qQSyHVGUikMukbxGqL_67vZLVOkPs,1363 pywinauto-0.6.8.dist-info/top_level.txt,sha256=7E8mqRxGiLpAamWQi4ClxZvTp1jx3P0shUi_Tu0zk44,10
pywinauto-0.6.6.dist-info/top_level.txt,sha256=7E8mqRxGiLpAamWQi4ClxZvTp1jx3P0shUi_Tu0zk44,10 pywinauto/__init__.py,sha256=xY7VLfy-UvPNHKJSlzekAoG9Sue8zdNdFIdjS-_zTFs,7231
pywinauto/__init__.py,sha256=BJ2Pni41MWP3DgzGAFhpNvFajGujGcVUxMnf6n5s1tI,6950
pywinauto/__pycache__/__init__.cpython-37.pyc,, pywinauto/__pycache__/__init__.cpython-37.pyc,,
pywinauto/__pycache__/actionlogger.cpython-37.pyc,, pywinauto/__pycache__/actionlogger.cpython-37.pyc,,
pywinauto/__pycache__/application.cpython-37.pyc,, pywinauto/__pycache__/application.cpython-37.pyc,,
@ -33,9 +32,9 @@ pywinauto/__pycache__/win32functions.cpython-37.pyc,,
pywinauto/__pycache__/win32structures.cpython-37.pyc,, pywinauto/__pycache__/win32structures.cpython-37.pyc,,
pywinauto/__pycache__/xml_helpers.cpython-37.pyc,, pywinauto/__pycache__/xml_helpers.cpython-37.pyc,,
pywinauto/actionlogger.py,sha256=JVny3VSQIzcSH6ESfUPkxPozSJrxMMOvlwzNiUzO-_E,5632 pywinauto/actionlogger.py,sha256=JVny3VSQIzcSH6ESfUPkxPozSJrxMMOvlwzNiUzO-_E,5632
pywinauto/application.py,sha256=r1gE55O91UXteKme9rFqBUP1QmbYyt4tmpXNQAHHt7I,55887 pywinauto/application.py,sha256=_KIIkl_ZZNFDZo_phPhYBX1YuNZh4pFW5A1gdYvTXeo,58047
pywinauto/backend.py,sha256=hLgO3HsnCJUYNoPfU8CwD11yMKjUZiPuXlC080JNufE,4186 pywinauto/backend.py,sha256=hLgO3HsnCJUYNoPfU8CwD11yMKjUZiPuXlC080JNufE,4186
pywinauto/base_wrapper.py,sha256=wx_8TIg_RbXX_zvpxGyL8nUWcvfQHVtVK6tAl8gcC_A,37561 pywinauto/base_wrapper.py,sha256=qAIvH6wKd6okBBDHY21gnK7A2DQj5H43qV4heQqQxc4,37590
pywinauto/clipboard.py,sha256=VpKW7WQ3BF57cmLkWA0Of16RG6BCuLSqGX0sW2nN1ds,4329 pywinauto/clipboard.py,sha256=VpKW7WQ3BF57cmLkWA0Of16RG6BCuLSqGX0sW2nN1ds,4329
pywinauto/controlproperties.py,sha256=YQ1lbHxWvMf38PGB0JYdN8rhh9PYoe8iwaWbtw3EU1w,9329 pywinauto/controlproperties.py,sha256=YQ1lbHxWvMf38PGB0JYdN8rhh9PYoe8iwaWbtw3EU1w,9329
pywinauto/controls/__init__.py,sha256=0cuXVxqppu3vQIJfjgxB_J__3Vtr3EvbDEx7TaRY64A,2241 pywinauto/controls/__init__.py,sha256=0cuXVxqppu3vQIJfjgxB_J__3Vtr3EvbDEx7TaRY64A,2241
@ -46,26 +45,26 @@ pywinauto/controls/__pycache__/menuwrapper.cpython-37.pyc,,
pywinauto/controls/__pycache__/uia_controls.cpython-37.pyc,, pywinauto/controls/__pycache__/uia_controls.cpython-37.pyc,,
pywinauto/controls/__pycache__/uiawrapper.cpython-37.pyc,, pywinauto/controls/__pycache__/uiawrapper.cpython-37.pyc,,
pywinauto/controls/__pycache__/win32_controls.cpython-37.pyc,, pywinauto/controls/__pycache__/win32_controls.cpython-37.pyc,,
pywinauto/controls/common_controls.py,sha256=zyx1EyyoSQ_pvl6snIPOzIp6WZuPXOYNAzYqM4Qh5GA,141066 pywinauto/controls/common_controls.py,sha256=4a_RyQcDl4N2JW8F_9sK-utJWJK-ujwqXF4vEhAaFe0,138614
pywinauto/controls/hwndwrapper.py,sha256=46cKLxKhYL6-BzN33KA8kG7wOy1-JGEJ68qVQLiCYts,68153 pywinauto/controls/hwndwrapper.py,sha256=nDiCY-DnVHrD2o49WTRv7-x_2kB9Xf9nBb3gWJkgl5I,68222
pywinauto/controls/menuwrapper.py,sha256=SS5UoaezIMknz_405021QUV0ixClkqCUfuck_EnsgIA,23477 pywinauto/controls/menuwrapper.py,sha256=TlgHXxMm6pUB75VDW6R-X5octoSpauXM0t7pRIJ8bPE,23497
pywinauto/controls/uia_controls.py,sha256=rmME_GCfDbohEBNnHJE_mLStshBvPX_-r8T_Xa6XuH8,53699 pywinauto/controls/uia_controls.py,sha256=ei-u10dGxMRjR7SQupD3dxrvlbiqHm90ggb9WyracJA,54886
pywinauto/controls/uiawrapper.py,sha256=aEVJYh6aB6VIg9sBrHwyQ3LOKTMnFLruVCMmSxy0dfQ,30770 pywinauto/controls/uiawrapper.py,sha256=w7wsUnbsSStm32H5t2jEI-P9sdbMVOS8OYASHJnmhDk,31386
pywinauto/controls/win32_controls.py,sha256=Iz-28a0b_TPR8XiSTIkr8areRXyxuXQ0gOqshIPcrhU,35099 pywinauto/controls/win32_controls.py,sha256=Iz-28a0b_TPR8XiSTIkr8areRXyxuXQ0gOqshIPcrhU,35099
pywinauto/element_info.py,sha256=L-s3E6xdVAxgfCFZXAQlMbaHl5OEtG_xFM845gFz5zc,6067 pywinauto/element_info.py,sha256=L-s3E6xdVAxgfCFZXAQlMbaHl5OEtG_xFM845gFz5zc,6067
pywinauto/findbestmatch.py,sha256=xAJaaiqAnBmQwCrhiqga-AmI5FxR0gZuXE1v1k1tyRA,20605 pywinauto/findbestmatch.py,sha256=izVEqpMSXgFhdMLd3OxN6Sexfo6MGVHTPEwkFxhDDpU,20748
pywinauto/findwindows.py,sha256=wYQgISnlHOAhuvxA0bG9shLSTwu9pKNg1_ApYJi1pHw,14290 pywinauto/findwindows.py,sha256=OMn7J5i4vk2xiVINPQ4daaMZ5MDCAplgnt4MXHo2dGY,14470
pywinauto/fuzzydict.py,sha256=mNFpET8ckSpMen4LdRRYyGRR4LToMbQw-gqNG3lWCqM,6073 pywinauto/fuzzydict.py,sha256=mNFpET8ckSpMen4LdRRYyGRR4LToMbQw-gqNG3lWCqM,6073
pywinauto/handleprops.py,sha256=WavBoIYV0WTLpq5YUXDQS0-kMv3GChpwk2etbMFZA_k,14748 pywinauto/handleprops.py,sha256=85UJyb6LfUVNim5biyB9Fz-oICo3lq1S_-jPxxgs28c,14685
pywinauto/keyboard.py,sha256=Q_hT07R48cC830HzBZTaM2o2XOMtLsucVG_KalAfgz4,22865 pywinauto/keyboard.py,sha256=tJ4MSH7WVvmPrinMDycRr_uWm7AEtiFrfYjFjVgOwW0,24562
pywinauto/linux/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pywinauto/linux/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pywinauto/linux/__pycache__/__init__.cpython-37.pyc,, pywinauto/linux/__pycache__/__init__.cpython-37.pyc,,
pywinauto/linux/__pycache__/clipboard.cpython-37.pyc,, pywinauto/linux/__pycache__/clipboard.cpython-37.pyc,,
pywinauto/linux/__pycache__/keyboard.cpython-37.pyc,, pywinauto/linux/__pycache__/keyboard.cpython-37.pyc,,
pywinauto/linux/clipboard.py,sha256=X4wR0r1_X8fdLF0KphNskV_vV2c0_toNyyt2m-TY6nQ,3568 pywinauto/linux/clipboard.py,sha256=X4wR0r1_X8fdLF0KphNskV_vV2c0_toNyyt2m-TY6nQ,3568
pywinauto/linux/keyboard.py,sha256=kvc5EZY8lML2WoCwV5er9SyzsF2NjQ4Abpum-YYT5-U,17380 pywinauto/linux/keyboard.py,sha256=z540dSwdCvmoyRSpCaJainPOTawbY76eo8i_UW2qyYQ,17458
pywinauto/mouse.py,sha256=-Rh9zY1KUfzVcKblvQixH0WKxf2lW9__yrsI-pRhpe0,10647 pywinauto/mouse.py,sha256=-Rh9zY1KUfzVcKblvQixH0WKxf2lW9__yrsI-pRhpe0,10647
pywinauto/remote_memory_block.py,sha256=fC0HyKKrsFlwS-1QlwQZif3RFqK4hr1RkIwajkbzGM4,12204 pywinauto/remote_memory_block.py,sha256=eox-bC9ZpliwQw3gZuiPku8_oQ9sGNeKfrSOM2pNyJs,12168
pywinauto/sysinfo.py,sha256=NgLfiQ3XNaRGnapzSfYSafwn5my24FjE1uHTU66P4VM,3052 pywinauto/sysinfo.py,sha256=NgLfiQ3XNaRGnapzSfYSafwn5my24FjE1uHTU66P4VM,3052
pywinauto/taskbar.py,sha256=vjHNAdOaQwyZvqJaLMvMB7teJBMOeCgXeedJpZrZGp4,5232 pywinauto/taskbar.py,sha256=vjHNAdOaQwyZvqJaLMvMB7teJBMOeCgXeedJpZrZGp4,5232
pywinauto/tests/__init__.py,sha256=DZXsho8W7nBWDSw5Qb-qao9CNpfOwTCKOtxG0dJRgos,5452 pywinauto/tests/__init__.py,sha256=DZXsho8W7nBWDSw5Qb-qao9CNpfOwTCKOtxG0dJRgos,5452
@ -97,11 +96,11 @@ pywinauto/tests/repeatedhotkey.py,sha256=6xFNznYzzIebpkX2dLUW6rIkTOBIe5la1qVohi3
pywinauto/tests/translation.py,sha256=0qVEsh42uqu1K5MDZfcQunPngSRanPfSLgL99An1W8g,6070 pywinauto/tests/translation.py,sha256=0qVEsh42uqu1K5MDZfcQunPngSRanPfSLgL99An1W8g,6070
pywinauto/tests/truncation.py,sha256=MD5UTKnVtZPZyfP3Ejx5ZMBDrDYY089xY05a8SMtMjc,20006 pywinauto/tests/truncation.py,sha256=MD5UTKnVtZPZyfP3Ejx5ZMBDrDYY089xY05a8SMtMjc,20006
pywinauto/timings.py,sha256=58c9xNODE5LjQYNhqoLpbLfNeJ9Lu0J8GZLw2d2tkMY,15668 pywinauto/timings.py,sha256=58c9xNODE5LjQYNhqoLpbLfNeJ9Lu0J8GZLw2d2tkMY,15668
pywinauto/uia_defines.py,sha256=-4w4hhRCd4O_748nEp5w5kKl-d0vb17aymVr3rdZTQ0,9819 pywinauto/uia_defines.py,sha256=ynA52N4tmKn8KBlqGP0EJ8etpygvYTyZhQNJ-vdOBRw,9979
pywinauto/uia_element_info.py,sha256=g2E9O4qSyXYmj80MqFD7mOin_nHXowM_-fVJVO0oV88,13762 pywinauto/uia_element_info.py,sha256=g2E9O4qSyXYmj80MqFD7mOin_nHXowM_-fVJVO0oV88,13762
pywinauto/win32_element_info.py,sha256=bJ9CIP4RPdGIZVB_HaZQg2Z_92QG2hWYw1aGkoBtTxI,9369 pywinauto/win32_element_info.py,sha256=bJ9CIP4RPdGIZVB_HaZQg2Z_92QG2hWYw1aGkoBtTxI,9369
pywinauto/win32_hooks.py,sha256=X2Le46OJxmco94b0n830RN6Tpnk2BzMTtRVOYdwllWc,24289 pywinauto/win32_hooks.py,sha256=_oG2uuMswls-9jxaGm_XRAstM6E9S38cQ6ZzBEoiYg0,24238
pywinauto/win32defines.py,sha256=i-uScB7nzZRk0fiDNk6TqlhGraRESmjLx-GkBlgOOp4,499259 pywinauto/win32defines.py,sha256=zltu4uEoY397OBLDKI_Vo0R79719_uqHOjL0QuTO3rc,630639
pywinauto/win32functions.py,sha256=uHpPx61qsWL_awp6Kq0D-ERN5GsAvHjC34pN-rx1xQQ,14987 pywinauto/win32functions.py,sha256=fHHeG9kARY_3a05qXoI9hbIIXua6Kj3IJUu6my0W6Fw,24133
pywinauto/win32structures.py,sha256=G9diB0fpPv95J8DQLt6z5D1033Ajw_FZUCojrS0xliA,42128 pywinauto/win32structures.py,sha256=CGxoTtM-fH_AyxpxGhRl28YsVJfBM1jv3_aLUXDo0ng,41700
pywinauto/xml_helpers.py,sha256=uiairq6vJiduprD6KMIvc72qBuplPC-PQqduJVVVZnc,17263 pywinauto/xml_helpers.py,sha256=uiairq6vJiduprD6KMIvc72qBuplPC-PQqduJVVVZnc,17263

@ -1,5 +1,6 @@
Wheel-Version: 1.0 Wheel-Version: 1.0
Generator: bdist_wheel (0.29.0) Generator: bdist_wheel (0.33.4)
Root-Is-Purelib: true Root-Is-Purelib: true
Tag: py2-none-any
Tag: py3-none-any Tag: py3-none-any

@ -32,7 +32,7 @@
"""Python package for automating GUI manipulation on Windows""" """Python package for automating GUI manipulation on Windows"""
__version__ = "0.6.6" __version__ = "0.6.8"
import sys # noqa: E402 import sys # noqa: E402
import warnings # noqa: E402 import warnings # noqa: E402
@ -89,9 +89,7 @@ if sys.platform == 'win32':
from . import findwindows from . import findwindows
WindowAmbiguousError = findwindows.WindowAmbiguousError WindowAmbiguousError = findwindows.WindowAmbiguousError
ElementNotFoundError = findwindows.ElementNotFoundError WindowNotFoundError = findwindows.WindowNotFoundError
if UIA_support:
ElementNotFoundError = findwindows.ElementNotFoundError ElementNotFoundError = findwindows.ElementNotFoundError
ElementAmbiguousError = findwindows.ElementAmbiguousError ElementAmbiguousError = findwindows.ElementAmbiguousError
@ -106,13 +104,14 @@ if sys.platform == 'win32':
class Desktop(object): class Desktop(object):
"""Simple class to call something like ``Desktop().WindowName.ControlName.method()``""" """Simple class to call something like ``Desktop().WindowName.ControlName.method()``"""
def __init__(self, backend=None): def __init__(self, backend=None, allow_magic_lookup=True):
"""Create desktop element description""" """Create desktop element description"""
if not backend: if not backend:
backend = backends.registry.name backend = backends.registry.name
if backend not in backends.registry.backends: if backend not in backends.registry.backends:
raise ValueError('Backend "{0}" is not registered!'.format(backend)) raise ValueError('Backend "{0}" is not registered!'.format(backend))
self.backend = backends.registry.backends[backend] self.backend = backends.registry.backends[backend]
self.allow_magic_lookup = allow_magic_lookup
def window(self, **kwargs): def window(self, **kwargs):
"""Create WindowSpecification object for top-level window""" """Create WindowSpecification object for top-level window"""
@ -121,7 +120,7 @@ if sys.platform == 'win32':
if 'backend' in kwargs: if 'backend' in kwargs:
raise ValueError('Using another backend than set in Desktop constructor is not allowed!') raise ValueError('Using another backend than set in Desktop constructor is not allowed!')
kwargs['backend'] = self.backend.name kwargs['backend'] = self.backend.name
return WindowSpecification(kwargs) return WindowSpecification(kwargs, allow_magic_lookup=self.allow_magic_lookup)
def windows(self, **kwargs): def windows(self, **kwargs):
"""Return a list of wrapped top level windows""" """Return a list of wrapped top level windows"""
@ -145,9 +144,12 @@ if sys.platform == 'win32':
def __getattribute__(self, attr_name): def __getattribute__(self, attr_name):
"""Attribute access for this class""" """Attribute access for this class"""
allow_magic_lookup = object.__getattribute__(self, "allow_magic_lookup") # Beware of recursions here!
try: try:
return object.__getattribute__(self, attr_name) return object.__getattribute__(self, attr_name)
except AttributeError: except AttributeError:
if not allow_magic_lookup:
raise
return self[attr_name] # delegate it to __get_item__ return self[attr_name] # delegate it to __get_item__
def from_point(self, x, y): def from_point(self, x, y):

@ -141,11 +141,12 @@ class WindowSpecification(object):
'active': ('is_active',), 'active': ('is_active',),
} }
def __init__(self, search_criteria): def __init__(self, search_criteria, allow_magic_lookup=True):
""" """
Initialize the class Initialize the class
:param search_criteria: the criteria to match a dialog :param search_criteria: the criteria to match a dialog
:param allow_magic_lookup: whether attribute access must turn into child_window(best_match=...) search as fallback
""" """
# kwargs will contain however to find this window # kwargs will contain however to find this window
if 'backend' not in search_criteria: if 'backend' not in search_criteria:
@ -158,6 +159,7 @@ class WindowSpecification(object):
self.criteria = [search_criteria, ] self.criteria = [search_criteria, ]
self.actions = ActionLogger() self.actions = ActionLogger()
self.backend = registry.backends[search_criteria['backend']] self.backend = registry.backends[search_criteria['backend']]
self.allow_magic_lookup = allow_magic_lookup
if self.backend.name == 'win32': if self.backend.name == 'win32':
# Non PEP-8 aliases for partial backward compatibility # Non PEP-8 aliases for partial backward compatibility
@ -173,7 +175,7 @@ class WindowSpecification(object):
self.window_ = deprecated(self.child_window, deprecated_name='window_') self.window_ = deprecated(self.child_window, deprecated_name='window_')
def __call__(self, *args, **kwargs): def __call__(self, *args, **kwargs):
"""No __call__ so return a usefull error""" """No __call__ so return a useful error"""
if "best_match" in self.criteria[-1]: if "best_match" in self.criteria[-1]:
raise AttributeError("Neither GUI element (wrapper) " \ raise AttributeError("Neither GUI element (wrapper) " \
"nor wrapper method '{0}' were found (typo?)". "nor wrapper method '{0}' were found (typo?)".
@ -182,8 +184,8 @@ class WindowSpecification(object):
message = ( message = (
"You tried to execute a function call on a WindowSpecification " "You tried to execute a function call on a WindowSpecification "
"instance. You probably have a typo for one of the methods of " "instance. You probably have a typo for one of the methods of "
"this class.\n" "this class or of the targeted wrapper object.\n"
"The criteria leading up to this is: " + str(self.criteria)) "The criteria leading up to this are: " + str(self.criteria))
raise AttributeError(message) raise AttributeError(message)
@ -277,7 +279,7 @@ class WindowSpecification(object):
if 'top_level_only' not in criteria: if 'top_level_only' not in criteria:
criteria['top_level_only'] = False criteria['top_level_only'] = False
new_item = WindowSpecification(self.criteria[0]) new_item = WindowSpecification(self.criteria[0], allow_magic_lookup=self.allow_magic_lookup)
new_item.criteria.extend(self.criteria[1:]) new_item.criteria.extend(self.criteria[1:])
new_item.criteria.append(criteria) new_item.criteria.append(criteria)
@ -307,7 +309,7 @@ class WindowSpecification(object):
""" """
# if we already have 2 levels of criteria (dlg, control) # if we already have 2 levels of criteria (dlg, control)
# then resolve the control and do a getitem on it for the # then resolve the control and do a getitem on it for the
if len(self.criteria) >= 2: if len(self.criteria) >= 2: # FIXME - this is surprising
ctrls = self.__resolve_control(self.criteria) ctrls = self.__resolve_control(self.criteria)
@ -324,7 +326,7 @@ class WindowSpecification(object):
# if we get here then we must have only had one criteria so far # if we get here then we must have only had one criteria so far
# so create a new :class:`WindowSpecification` for this control # so create a new :class:`WindowSpecification` for this control
new_item = WindowSpecification(self.criteria[0]) new_item = WindowSpecification(self.criteria[0], allow_magic_lookup=self.allow_magic_lookup)
# add our new criteria # add our new criteria
new_item.criteria.append({"best_match": key}) new_item.criteria.append({"best_match": key})
@ -345,6 +347,21 @@ class WindowSpecification(object):
Otherwise delegate functionality to :func:`__getitem__` - which Otherwise delegate functionality to :func:`__getitem__` - which
sets the appropriate criteria for the control. sets the appropriate criteria for the control.
""" """
allow_magic_lookup = object.__getattribute__(self, "allow_magic_lookup") # Beware of recursions here!
if not allow_magic_lookup:
try:
return object.__getattribute__(self, attr_name)
except AttributeError:
wrapper_object = self.wrapper_object()
try:
return getattr(wrapper_object, attr_name)
except AttributeError:
message = (
'Attribute "%s" exists neither on %s object nor on'
'targeted %s element wrapper (typo? or set allow_magic_lookup to True?)' %
(attr_name, self.__class__, wrapper_object.__class__))
raise AttributeError(message)
if attr_name in ['__dict__', '__members__', '__methods__', '__class__', '__name__']: if attr_name in ['__dict__', '__members__', '__methods__', '__class__', '__name__']:
return object.__getattribute__(self, attr_name) return object.__getattribute__(self, attr_name)
@ -354,10 +371,10 @@ class WindowSpecification(object):
if attr_name in self.__dict__: if attr_name in self.__dict__:
return self.__dict__[attr_name] return self.__dict__[attr_name]
# if we already have 2 levels of criteria (dlg, conrol) # if we already have 2 levels of criteria (dlg, control)
# this third must be an attribute so resolve and get the # this third must be an attribute so resolve and get the
# attribute and return it # attribute and return it
if len(self.criteria) >= 2: if len(self.criteria) >= 2: # FIXME - this is surprising
ctrls = self.__resolve_control(self.criteria) ctrls = self.__resolve_control(self.criteria)
@ -366,6 +383,7 @@ class WindowSpecification(object):
except AttributeError: except AttributeError:
return self.child_window(best_match=attr_name) return self.child_window(best_match=attr_name)
else: else:
# FIXME - I don't get this part at all, why is it win32-specific and why not keep the same logic as above?
# if we have been asked for an attribute of the dialog # if we have been asked for an attribute of the dialog
# then resolve the window and return the attribute # then resolve the window and return the attribute
desktop_wrapper = self.backend.generic_wrapper_class(self.backend.element_info_class()) desktop_wrapper = self.backend.generic_wrapper_class(self.backend.element_info_class())
@ -870,7 +888,7 @@ class Application(object):
.. automethod:: __getitem__ .. automethod:: __getitem__
""" """
def __init__(self, backend="win32", datafilename=None): def __init__(self, backend="win32", datafilename=None, allow_magic_lookup=True):
""" """
Initialize the Application object Initialize the Application object
@ -886,6 +904,7 @@ class Application(object):
if backend not in registry.backends: if backend not in registry.backends:
raise ValueError('Backend "{0}" is not registered!'.format(backend)) raise ValueError('Backend "{0}" is not registered!'.format(backend))
self.backend = registry.backends[backend] self.backend = registry.backends[backend]
self.allow_magic_lookup = allow_magic_lookup
if self.backend.name == 'win32': if self.backend.name == 'win32':
# Non PEP-8 aliases for partial backward compatibility # Non PEP-8 aliases for partial backward compatibility
self.Start = deprecated(self.start) self.Start = deprecated(self.start)
@ -906,6 +925,10 @@ class Application(object):
self.match_history = pickle.load(datafile) self.match_history = pickle.load(datafile)
self.use_history = True self.use_history = True
def __iter__(self):
"""Raise to avoid infinite loops"""
raise NotImplementedError("Object is not iterable, try to use .windows()")
def connect(self, **kwargs): def connect(self, **kwargs):
"""Connect to an already running process """Connect to an already running process
@ -1139,7 +1162,7 @@ class Application(object):
else: else:
criteria['title'] = windows[0].name criteria['title'] = windows[0].name
return WindowSpecification(criteria) return WindowSpecification(criteria, allow_magic_lookup=self.allow_magic_lookup)
def active(self): def active(self):
"""Return WindowSpecification for an active window of the application""" """Return WindowSpecification for an active window of the application"""
@ -1163,7 +1186,7 @@ class Application(object):
else: else:
criteria['title'] = windows[0].name criteria['title'] = windows[0].name
return WindowSpecification(criteria) return WindowSpecification(criteria, allow_magic_lookup=self.allow_magic_lookup)
def windows(self, **kwargs): def windows(self, **kwargs):
"""Return a list of wrapped top level windows of the application""" """Return a list of wrapped top level windows of the application"""
@ -1205,7 +1228,7 @@ class Application(object):
else: else:
# add the restriction for this particular application # add the restriction for this particular application
kwargs['app'] = self kwargs['app'] = self
win_spec = WindowSpecification(kwargs) win_spec = WindowSpecification(kwargs, allow_magic_lookup=self.allow_magic_lookup)
return win_spec return win_spec
Window_ = window_ = window Window_ = window_ = window
@ -1216,6 +1239,17 @@ class Application(object):
return self.window(best_match=key) return self.window(best_match=key)
def __getattribute__(self, attr_name): def __getattribute__(self, attr_name):
allow_magic_lookup = object.__getattribute__(self, "allow_magic_lookup") # Beware of recursions here!
if not allow_magic_lookup:
try:
return object.__getattribute__(self, attr_name)
except AttributeError:
message = (
'Attribute "%s" doesn\'t exist on %s object'
' (typo? or set allow_magic_lookup to True?)' %
(attr_name, self.__class__))
raise AttributeError(message)
"""Find the specified dialog of the application""" """Find the specified dialog of the application"""
if attr_name in ['__dict__', '__members__', '__methods__', '__class__']: if attr_name in ['__dict__', '__members__', '__methods__', '__class__']:
return object.__getattribute__(self, attr_name) return object.__getattribute__(self, attr_name)

@ -38,7 +38,6 @@ import ctypes
import locale import locale
import re import re
import time import time
import win32process
import win32gui import win32gui
import win32con import win32con
import win32api import win32api
@ -925,7 +924,8 @@ class BaseWrapper(object):
with_tabs = False, with_tabs = False,
with_newlines = False, with_newlines = False,
turn_off_numlock = True, turn_off_numlock = True,
set_foreground = True): set_foreground = True,
vk_packet = True):
""" """
Type keys to the element using keyboard.send_keys Type keys to the element using keyboard.send_keys
@ -945,7 +945,7 @@ class BaseWrapper(object):
# attach the Python process with the process that self is in # attach the Python process with the process that self is in
if self.element_info.handle: if self.element_info.handle:
window_thread_id, _ = win32process.GetWindowThreadProcessId(int(self.handle)) window_thread_id = win32functions.GetWindowThreadProcessId(self.handle, None)
win32functions.AttachThreadInput(win32functions.GetCurrentThreadId(), window_thread_id, win32defines.TRUE) win32functions.AttachThreadInput(win32functions.GetCurrentThreadId(), window_thread_id, win32defines.TRUE)
# TODO: check return value of AttachThreadInput properly # TODO: check return value of AttachThreadInput properly
else: else:
@ -967,7 +967,8 @@ class BaseWrapper(object):
with_spaces, with_spaces,
with_tabs, with_tabs,
with_newlines, with_newlines,
turn_off_numlock) turn_off_numlock,
vk_packet)
# detach the python process from the window's process # detach the python process from the window's process
if self.element_info.handle: if self.element_info.handle:

@ -53,7 +53,6 @@ import warnings
import locale import locale
import six import six
from .. import sysinfo
from .. import win32functions from .. import win32functions
from .. import win32defines from .. import win32defines
from .. import win32structures from .. import win32structures
@ -68,9 +67,6 @@ from ..handleprops import is64bitprocess
from ..sysinfo import is_x64_Python from ..sysinfo import is_x64_Python
from .. import deprecated from .. import deprecated
if sysinfo.UIA_support:
from ..uia_defines import IUIA
# Todo: I should return iterators from things like items() and texts() # Todo: I should return iterators from things like items() and texts()
# to save building full lists all the time # to save building full lists all the time
@ -135,7 +131,7 @@ class _listview_item(object):
item.iItem = self.item_index item.iItem = self.item_index
item.iSubItem = self.subitem_index item.iSubItem = self.subitem_index
item.stateMask = win32structures.UINT(-1) item.stateMask = wintypes.UINT(-1)
item.cchTextMax = 2000 item.cchTextMax = 2000
item.pszText = remote_mem.Address() + \ item.pszText = remote_mem.Address() + \
@ -501,9 +497,9 @@ class _listview_item(object):
lvitem = self.listview_ctrl.LVITEM() lvitem = self.listview_ctrl.LVITEM()
lvitem.mask = win32structures.UINT(win32defines.LVIF_STATE) lvitem.mask = wintypes.UINT(win32defines.LVIF_STATE)
lvitem.state = win32structures.UINT(index_to_state_image_mask(1)) # win32structures.UINT(0x1000) lvitem.state = wintypes.UINT(index_to_state_image_mask(1)) # wintypes.UINT(0x1000)
lvitem.stateMask = win32structures.UINT(win32defines.LVIS_STATEIMAGEMASK) lvitem.stateMask = wintypes.UINT(win32defines.LVIS_STATEIMAGEMASK)
remote_mem = RemoteMemoryBlock(self.listview_ctrl) remote_mem = RemoteMemoryBlock(self.listview_ctrl)
remote_mem.Write(lvitem) remote_mem.Write(lvitem)
@ -530,9 +526,9 @@ class _listview_item(object):
lvitem = self.listview_ctrl.LVITEM() lvitem = self.listview_ctrl.LVITEM()
lvitem.mask = win32structures.UINT(win32defines.LVIF_STATE) lvitem.mask = wintypes.UINT(win32defines.LVIF_STATE)
lvitem.state = win32structures.UINT(index_to_state_image_mask(2)) # win32structures.UINT(0x2000) lvitem.state = wintypes.UINT(index_to_state_image_mask(2)) # wintypes.UINT(0x2000)
lvitem.stateMask = win32structures.UINT(win32defines.LVIS_STATEIMAGEMASK) lvitem.stateMask = wintypes.UINT(win32defines.LVIS_STATEIMAGEMASK)
remote_mem = RemoteMemoryBlock(self.listview_ctrl) remote_mem = RemoteMemoryBlock(self.listview_ctrl)
remote_mem.Write(lvitem) remote_mem.Write(lvitem)
@ -591,12 +587,12 @@ class _listview_item(object):
# first we need to change the state of the item # first we need to change the state of the item
lvitem = self.listview_ctrl.LVITEM() lvitem = self.listview_ctrl.LVITEM()
lvitem.mask = win32structures.UINT(win32defines.LVIF_STATE) lvitem.mask = wintypes.UINT(win32defines.LVIF_STATE)
if to_select: if to_select:
lvitem.state = win32structures.UINT(win32defines.LVIS_FOCUSED | win32defines.LVIS_SELECTED) lvitem.state = wintypes.UINT(win32defines.LVIS_FOCUSED | win32defines.LVIS_SELECTED)
lvitem.stateMask = win32structures.UINT(win32defines.LVIS_FOCUSED | win32defines.LVIS_SELECTED) lvitem.stateMask = wintypes.UINT(win32defines.LVIS_FOCUSED | win32defines.LVIS_SELECTED)
remote_mem = RemoteMemoryBlock(self.listview_ctrl) remote_mem = RemoteMemoryBlock(self.listview_ctrl)
remote_mem.Write(lvitem, size=ctypes.sizeof(lvitem)) remote_mem.Write(lvitem, size=ctypes.sizeof(lvitem))
@ -721,10 +717,6 @@ class ListViewWrapper(hwndwrapper.HwndWrapper):
"TSysListView", "TSysListView",
"ListView.*WndClass", "ListView.*WndClass",
] ]
if sysinfo.UIA_support:
#controltypes is empty to make wrapper search result unique
#possible control types: IUIA().UIA_dll.UIA_ListControlTypeId
controltypes = []
#---------------------------------------------------------------- #----------------------------------------------------------------
def __init__(self, hwnd): def __init__(self, hwnd):
@ -1424,7 +1416,7 @@ class _treeview_element(object):
item.pszText = remote_mem.Address() + ctypes.sizeof(item) + 16 item.pszText = remote_mem.Address() + ctypes.sizeof(item) + 16
item.cchTextMax = 2000 item.cchTextMax = 2000
item.hItem = self.elem item.hItem = self.elem
item.stateMask = win32structures.UINT(-1) item.stateMask = wintypes.UINT(-1)
# Write the local TVITEM structure to the remote memory block # Write the local TVITEM structure to the remote memory block
remote_mem.Write(item) remote_mem.Write(item)
@ -1460,8 +1452,6 @@ class TreeViewWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "TreeView" friendlyclassname = "TreeView"
windowclasses = [ windowclasses = [
"SysTreeView32", r"WindowsForms\d*\.SysTreeView32\..*", "TTreeView", "TreeList.TreeListCtrl"] "SysTreeView32", r"WindowsForms\d*\.SysTreeView32\..*", "TTreeView", "TreeList.TreeListCtrl"]
if sysinfo.UIA_support:
controltypes = [IUIA().UIA_dll.UIA_TreeControlTypeId]
#---------------------------------------------------------------- #----------------------------------------------------------------
def __init__(self, hwnd): def __init__(self, hwnd):
@ -1751,8 +1741,6 @@ class HeaderWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "Header" friendlyclassname = "Header"
windowclasses = ["SysHeader32", "msvb_lib_header"] windowclasses = ["SysHeader32", "msvb_lib_header"]
if sysinfo.UIA_support:
controltypes = [IUIA().UIA_dll.UIA_HeaderControlTypeId]
#---------------------------------------------------------------- #----------------------------------------------------------------
def __init__(self, hwnd): def __init__(self, hwnd):
@ -1894,8 +1882,6 @@ class StatusBarWrapper(hwndwrapper.HwndWrapper):
"msctls_statusbar32", "msctls_statusbar32",
".*StatusBar", ".*StatusBar",
r"WindowsForms\d*\.msctls_statusbar32\..*"] r"WindowsForms\d*\.msctls_statusbar32\..*"]
if sysinfo.UIA_support:
controltypes = [IUIA().UIA_dll.UIA_StatusBarControlTypeId]
#---------------------------------------------------------------- #----------------------------------------------------------------
def __init__(self, hwnd): def __init__(self, hwnd):
@ -2065,8 +2051,6 @@ class TabControlWrapper(hwndwrapper.HwndWrapper):
windowclasses = [ windowclasses = [
"SysTabControl32", "SysTabControl32",
r"WindowsForms\d*\.SysTabControl32\..*"] r"WindowsForms\d*\.SysTabControl32\..*"]
if sysinfo.UIA_support:
controltypes = [IUIA().UIA_dll.UIA_TabControlTypeId]
#---------------------------------------------------------------- #----------------------------------------------------------------
def __init__(self, hwnd): def __init__(self, hwnd):
@ -2878,10 +2862,6 @@ class ReBarWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "ReBar" friendlyclassname = "ReBar"
windowclasses = ["ReBarWindow32", ] windowclasses = ["ReBarWindow32", ]
if sysinfo.UIA_support:
#controltypes is empty to make wrapper search result unique
#possible control types: IUIA().UIA_dll.UIA_PaneControlTypeId
controltypes = []
#---------------------------------------------------------------- #----------------------------------------------------------------
def __init__(self, hwnd): def __init__(self, hwnd):
@ -3086,8 +3066,6 @@ class UpDownWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "UpDown" friendlyclassname = "UpDown"
windowclasses = ["msctls_updown32", "msctls_updown", ] windowclasses = ["msctls_updown32", "msctls_updown", ]
if sysinfo.UIA_support:
controltypes = [IUIA().UIA_dll.UIA_SpinnerControlTypeId]
#---------------------------------------------------------------- #----------------------------------------------------------------
def __init__(self, hwnd): def __init__(self, hwnd):
@ -3195,8 +3173,6 @@ class TrackbarWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "Trackbar" friendlyclassname = "Trackbar"
windowclasses = ["msctls_trackbar", ] windowclasses = ["msctls_trackbar", ]
if sysinfo.UIA_support:
controltypes = [IUIA().UIA_dll.UIA_SliderControlTypeId]
def get_range_min(self): def get_range_min(self):
"""Get min available trackbar value""" """Get min available trackbar value"""
@ -3293,10 +3269,6 @@ class AnimationWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "Animation" friendlyclassname = "Animation"
windowclasses = ["SysAnimate32", ] windowclasses = ["SysAnimate32", ]
if sysinfo.UIA_support:
#controltypes is empty to make wrapper search result unique
#possible control types: IUIA().UIA_dll.UIA_PaneControlTypeId
controltypes = []
#==================================================================== #====================================================================
@ -3306,10 +3278,6 @@ class ComboBoxExWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "ComboBoxEx" friendlyclassname = "ComboBoxEx"
windowclasses = ["ComboBoxEx32", ] windowclasses = ["ComboBoxEx32", ]
if sysinfo.UIA_support:
#controltypes is empty to make wrapper search result unique
#possible control types: IUIA().UIA_dll.UIA_PaneControlTypeId
controltypes = []
has_title = False has_title = False
@ -3321,10 +3289,6 @@ class DateTimePickerWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "DateTimePicker" friendlyclassname = "DateTimePicker"
windowclasses = ["SysDateTimePick32", windowclasses = ["SysDateTimePick32",
r"WindowsForms\d*\.SysDateTimePick32\..*", ] r"WindowsForms\d*\.SysDateTimePick32\..*", ]
if sysinfo.UIA_support:
#controltypes is empty to make wrapper search result unique
#possible control types: IUIA().UIA_dll.UIA_PaneControlTypeId
controltypes = []
has_title = False has_title = False
#---------------------------------------------------------------- #----------------------------------------------------------------
@ -3387,10 +3351,6 @@ class HotkeyWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "Hotkey" friendlyclassname = "Hotkey"
windowclasses = ["msctls_hotkey32", ] windowclasses = ["msctls_hotkey32", ]
if sysinfo.UIA_support:
#controltypes is empty to make wrapper search result unique
#possible control types: IUIA().UIA_dll.UIA_PaneControlTypeId
controltypes = []
has_title = False has_title = False
@ -3401,10 +3361,6 @@ class IPAddressWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "IPAddress" friendlyclassname = "IPAddress"
windowclasses = ["SysIPAddress32", ] windowclasses = ["SysIPAddress32", ]
if sysinfo.UIA_support:
#controltypes is empty to make wrapper search result unique
#possible control types: IUIA().UIA_dll.UIA_PaneControlTypeId
controltypes = []
has_title = False has_title = False
@ -3415,8 +3371,6 @@ class CalendarWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "Calendar" friendlyclassname = "Calendar"
windowclasses = ["SysMonthCal32", ] windowclasses = ["SysMonthCal32", ]
if sysinfo.UIA_support:
controltypes = [IUIA().UIA_dll.UIA_CalendarControlTypeId]
has_title = False has_title = False
place_in_calendar = { place_in_calendar = {
@ -3719,10 +3673,6 @@ class PagerWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "Pager" friendlyclassname = "Pager"
windowclasses = ["SysPager", ] windowclasses = ["SysPager", ]
if sysinfo.UIA_support:
#controltypes is empty to make wrapper search result unique
#possible control types: IUIA().UIA_dll.UIA_PaneControlTypeId
controltypes = []
#---------------------------------------------------------------- #----------------------------------------------------------------
def get_position(self): def get_position(self):
@ -3748,8 +3698,6 @@ class ProgressWrapper(hwndwrapper.HwndWrapper):
friendlyclassname = "Progress" friendlyclassname = "Progress"
windowclasses = ["msctls_progress", "msctls_progress32", ] windowclasses = ["msctls_progress", "msctls_progress32", ]
if sysinfo.UIA_support:
controltypes = [IUIA().UIA_dll.UIA_ProgressBarControlTypeId]
has_title = False has_title = False
#---------------------------------------------------------------- #----------------------------------------------------------------

@ -493,7 +493,7 @@ class HwndWrapper(BaseWrapper):
(e.g. VK_LEFT, VK_DELETE), a KeySequenceError is raised. Consider using (e.g. VK_LEFT, VK_DELETE), a KeySequenceError is raised. Consider using
the method send_keystrokes for such input. the method send_keystrokes for such input.
""" """
input_locale_id = ctypes.windll.User32.GetKeyboardLayout(0) input_locale_id = win32functions.GetKeyboardLayout(0)
keys = keyboard.parse_keys(chars, with_spaces, with_tabs, with_newlines) keys = keyboard.parse_keys(chars, with_spaces, with_tabs, with_newlines)
for key in keys: for key in keys:
@ -506,11 +506,11 @@ class HwndWrapper(BaseWrapper):
if unicode_char: if unicode_char:
_, char = key_info[:2] _, char = key_info[:2]
vk = ctypes.windll.User32.VkKeyScanExW(char, input_locale_id) & 0xFF vk = win32functions.VkKeyScanExW(chr(char), input_locale_id) & 0xFF
scan = keyboard.MapVirtualKey(vk, 0) scan = win32functions.MapVirtualKeyW(vk, 0)
else: else:
vk, scan = key_info[:2] vk, scan = key_info[:2]
char = keyboard.MapVirtualKey(vk, 2) char = win32functions.MapVirtualKeyW(vk, 2)
if char > 0: if char > 0:
lparam = 1 << 0 | scan << 16 | (flags & 1) << 24 lparam = 1 << 0 | scan << 16 | (flags & 1) << 24
@ -541,22 +541,21 @@ class HwndWrapper(BaseWrapper):
.. _`type_keys`: pywinauto.base_wrapper.html#pywinauto.base_wrapper.BaseWrapper.type_keys .. _`type_keys`: pywinauto.base_wrapper.html#pywinauto.base_wrapper.BaseWrapper.type_keys
""" """
user32 = ctypes.windll.User32
PBYTE256 = ctypes.c_ubyte * 256 PBYTE256 = ctypes.c_ubyte * 256
win32gui.SendMessage(self.handle, win32con.WM_ACTIVATE, win32gui.SendMessage(self.handle, win32con.WM_ACTIVATE,
win32con.WA_ACTIVE, 0) win32con.WA_ACTIVE, 0)
target_thread_id = user32.GetWindowThreadProcessId(self.handle, None) target_thread_id = win32functions.GetWindowThreadProcessId(self.handle, None)
current_thread_id = win32api.GetCurrentThreadId() current_thread_id = win32functions.GetCurrentThreadId()
attach_success = user32.AttachThreadInput(target_thread_id, current_thread_id, True) != 0 attach_success = win32functions.AttachThreadInput(target_thread_id, current_thread_id, True) != 0
if not attach_success: if not attach_success:
warnings.warn('Failed to attach app\'s thread to the current thread\'s message queue', warnings.warn('Failed to attach app\'s thread to the current thread\'s message queue',
UserWarning, stacklevel=2) UserWarning, stacklevel=2)
keyboard_state_stack = [PBYTE256()] keyboard_state_stack = [PBYTE256()]
user32.GetKeyboardState(ctypes.byref(keyboard_state_stack[-1])) win32functions.GetKeyboardState(keyboard_state_stack[-1])
input_locale_id = ctypes.windll.User32.GetKeyboardLayout(0) input_locale_id = win32functions.GetKeyboardLayout(0)
context_code = 0 context_code = 0
keys = keyboard.parse_keys(keystrokes, with_spaces, with_tabs, with_newlines) keys = keyboard.parse_keys(keystrokes, with_spaces, with_tabs, with_newlines)
@ -578,11 +577,11 @@ class HwndWrapper(BaseWrapper):
shift_state = 0 shift_state = 0
unicode_codepoint = flags & keyboard.KEYEVENTF_UNICODE != 0 unicode_codepoint = flags & keyboard.KEYEVENTF_UNICODE != 0
if unicode_codepoint: if unicode_codepoint:
char = scan char = chr(scan)
vk_with_flags = user32.VkKeyScanExW(char, input_locale_id) vk_with_flags = win32functions.VkKeyScanExW(char, input_locale_id)
vk = vk_with_flags & 0xFF vk = vk_with_flags & 0xFF
shift_state = (vk_with_flags & 0xFF00) >> 8 shift_state = (vk_with_flags & 0xFF00) >> 8
scan = keyboard.MapVirtualKey(vk, 0) scan = win32functions.MapVirtualKeyW(vk, 0)
if key.down and vk > 0: if key.down and vk > 0:
new_keyboard_state = copy.deepcopy(keyboard_state_stack[-1]) new_keyboard_state = copy.deepcopy(keyboard_state_stack[-1])
@ -602,8 +601,8 @@ class HwndWrapper(BaseWrapper):
context_code << 29 | context_code << 29 |
0 << 31) 0 << 31)
user32.SetKeyboardState(ctypes.byref(keyboard_state_stack[-1])) win32functions.SetKeyboardState(keyboard_state_stack[-1])
win32api.PostMessage(self.handle, down_msg, vk, lparam) win32functions.PostMessage(self.handle, down_msg, vk, lparam)
if vk == keyboard.VK_MENU: if vk == keyboard.VK_MENU:
context_code = 1 context_code = 1
@ -621,8 +620,8 @@ class HwndWrapper(BaseWrapper):
1 << 30 | 1 << 30 |
1 << 31) 1 << 31)
win32api.PostMessage(self.handle, up_msg, vk, lparam) win32functions.PostMessage(self.handle, up_msg, vk, lparam)
user32.SetKeyboardState(ctypes.byref(keyboard_state_stack[-1])) win32functions.SetKeyboardState(keyboard_state_stack[-1])
if vk == keyboard.VK_MENU: if vk == keyboard.VK_MENU:
context_code = 0 context_code = 0
@ -636,10 +635,10 @@ class HwndWrapper(BaseWrapper):
UserWarning, stacklevel=2) UserWarning, stacklevel=2)
else: else:
warnings.warn(e.strerror, UserWarning, stacklevel=2) warnings.warn(e.strerror, UserWarning, stacklevel=2)
user32.SetKeyboardState(ctypes.byref(keyboard_state_stack[0])) win32functions.SetKeyboardState(keyboard_state_stack[0])
if attach_success: if attach_success:
user32.AttachThreadInput(target_thread_id, current_thread_id, False) win32functions.AttachThreadInput(target_thread_id, current_thread_id, False)
# ----------------------------------------------------------- # -----------------------------------------------------------
def send_message_timeout( def send_message_timeout(
@ -1256,7 +1255,7 @@ class HwndWrapper(BaseWrapper):
"""Return a handle to the active window within the process""" """Return a handle to the active window within the process"""
gui_info = win32structures.GUITHREADINFO() gui_info = win32structures.GUITHREADINFO()
gui_info.cbSize = ctypes.sizeof(gui_info) gui_info.cbSize = ctypes.sizeof(gui_info)
window_thread_id, _ = win32process.GetWindowThreadProcessId(int(self.handle)) window_thread_id = win32functions.GetWindowThreadProcessId(self.handle, None)
ret = win32functions.GetGUIThreadInfo( ret = win32functions.GetGUIThreadInfo(
window_thread_id, window_thread_id,
ctypes.byref(gui_info)) ctypes.byref(gui_info))
@ -1278,7 +1277,7 @@ class HwndWrapper(BaseWrapper):
""" """
gui_info = win32structures.GUITHREADINFO() gui_info = win32structures.GUITHREADINFO()
gui_info.cbSize = ctypes.sizeof(gui_info) gui_info.cbSize = ctypes.sizeof(gui_info)
window_thread_id, _ = win32process.GetWindowThreadProcessId(self.handle) window_thread_id = win32functions.GetWindowThreadProcessId(self.handle, None)
ret = win32functions.GetGUIThreadInfo( ret = win32functions.GetGUIThreadInfo(
window_thread_id, window_thread_id,
ctypes.byref(gui_info)) ctypes.byref(gui_info))
@ -1335,7 +1334,7 @@ class HwndWrapper(BaseWrapper):
def has_keyboard_focus(self): def has_keyboard_focus(self):
"""Check the keyboard focus on this control.""" """Check the keyboard focus on this control."""
control_thread = win32process.GetWindowThreadProcessId(self.handle)[0] control_thread = win32functions.GetWindowThreadProcessId(self.handle, None)
win32process.AttachThreadInput(control_thread, win32api.GetCurrentThreadId(), 1) win32process.AttachThreadInput(control_thread, win32api.GetCurrentThreadId(), 1)
focused = win32gui.GetFocus() focused = win32gui.GetFocus()
win32process.AttachThreadInput(control_thread, win32api.GetCurrentThreadId(), 0) win32process.AttachThreadInput(control_thread, win32api.GetCurrentThreadId(), 0)
@ -1346,9 +1345,9 @@ class HwndWrapper(BaseWrapper):
def set_keyboard_focus(self): def set_keyboard_focus(self):
"""Set the keyboard focus to this control.""" """Set the keyboard focus to this control."""
control_thread = win32process.GetWindowThreadProcessId(self.handle)[0] control_thread = win32functions.GetWindowThreadProcessId(self.handle, None)
win32process.AttachThreadInput(control_thread, win32api.GetCurrentThreadId(), 1) win32process.AttachThreadInput(control_thread, win32api.GetCurrentThreadId(), 1)
win32gui.SetFocus(self.handle) win32functions.SetFocus(self.handle)
win32process.AttachThreadInput(control_thread, win32api.GetCurrentThreadId(), 0) win32process.AttachThreadInput(control_thread, win32api.GetCurrentThreadId(), 0)
win32functions.WaitGuiThreadIdle(self.handle) win32functions.WaitGuiThreadIdle(self.handle)
@ -1602,12 +1601,13 @@ class DialogWrapper(HwndWrapper):
#win32defines.SMTO_BLOCK) #win32defines.SMTO_BLOCK)
# get a handle we can wait on # get a handle we can wait on
_, pid = win32process.GetWindowThreadProcessId(int(self.handle)) pid = ctypes.c_ulong()
win32functions.GetWindowThreadProcessId(self.handle, ctypes.byref(pid))
try: try:
process_wait_handle = win32api.OpenProcess( process_wait_handle = win32api.OpenProcess(
win32con.SYNCHRONIZE | win32con.PROCESS_TERMINATE, win32con.SYNCHRONIZE | win32con.PROCESS_TERMINATE,
0, 0,
pid) pid.value)
except win32gui.error: except win32gui.error:
return True # already closed return True # already closed
@ -1723,7 +1723,7 @@ def _perform_click(
# figure out the flags and pack coordinates # figure out the flags and pack coordinates
flags, click_point = _calc_flags_and_coords(pressed, coords) flags, click_point = _calc_flags_and_coords(pressed, coords)
#control_thread = win32functions.GetWindowThreadProcessId(ctrl, 0) #control_thread = win32functions.GetWindowThreadProcessId(ctrl, None)
#win32functions.AttachThreadInput(win32functions.GetCurrentThreadId(), control_thread, win32defines.TRUE) #win32functions.AttachThreadInput(win32functions.GetCurrentThreadId(), control_thread, win32defines.TRUE)
# TODO: check return value of AttachThreadInput properly # TODO: check return value of AttachThreadInput properly

@ -283,7 +283,7 @@ class MenuItem(object):
# if the item is not visible - work up along it's parents # if the item is not visible - work up along it's parents
# until we find an item we CAN click on # until we find an item we CAN click on
if rect == (0, 0, 0, 0) and self.menu.owner_item: if rect == win32structures.RECT(0, 0, 0, 0) and self.menu.owner_item:
self.menu.owner_item.click_input() self.menu.owner_item.click_input()
rect = self.rectangle() rect = self.rectangle()

@ -200,7 +200,11 @@ class ComboBoxWrapper(uiawrapper.UIAWrapper):
# ----------------------------------------------------------- # -----------------------------------------------------------
def texts(self): def texts(self):
"""Return the text of the items in the combobox""" """Return the text of the items in the combobox"""
texts = [] texts = self._texts_from_item_container()
if len(texts):
# flatten the list
return [ t for lst in texts for t in lst ]
# ComboBox has to be expanded to populate a list of its children items # ComboBox has to be expanded to populate a list of its children items
try: try:
super(ComboBoxWrapper, self).expand() super(ComboBoxWrapper, self).expand()
@ -370,6 +374,11 @@ class EditWrapper(uiawrapper.UIAWrapper):
"""Return the current value of the element""" """Return the current value of the element"""
return self.iface_value.CurrentValue return self.iface_value.CurrentValue
# -----------------------------------------------------------
def is_editable(self):
"""Return the edit possibility of the element"""
return not self.iface_value.CurrentIsReadOnly
# ----------------------------------------------------------- # -----------------------------------------------------------
def texts(self): def texts(self):
"""Get the text of the edit control""" """Get the text of the edit control"""
@ -846,8 +855,17 @@ class ListViewWrapper(uiawrapper.UIAWrapper):
raise ValueError("Element '{0}' not found".format(row)) raise ValueError("Element '{0}' not found".format(row))
elif isinstance(row, six.integer_types): elif isinstance(row, six.integer_types):
# Get the item by a row index # Get the item by a row index
# TODO: Can't get virtualized items that way try:
# TODO: See TODO section of item_count() method for details com_elem = 0
for _ in range(0, self.__resolve_row_index(row) + 1):
com_elem = self.iface_item_container.FindItemByProperty(com_elem, 0, uia_defs.vt_empty)
# Try to load element using VirtualizedItem pattern
try:
get_elem_interface(com_elem, "VirtualizedItem").Realize()
except NoPatternInterfaceError:
pass
itm = uiawrapper.UIAWrapper(uia_element_info.UIAElementInfo(com_elem))
except (NoPatternInterfaceError, ValueError, AttributeError):
list_items = self.children(content_only=True) list_items = self.children(content_only=True)
itm = list_items[self.__resolve_row_index(row)] itm = list_items[self.__resolve_row_index(row)]
else: else:
@ -960,18 +978,18 @@ class MenuWrapper(uiawrapper.UIAWrapper):
return item return item
# ----------------------------------------------------------- # -----------------------------------------------------------
@staticmethod def _activate(self, item, is_last):
def _activate(item):
"""Activate the specified item""" """Activate the specified item"""
if not item.is_active(): if not item.is_active():
item.set_focus() item.set_focus()
try: try:
item.expand() item.expand()
except(NoPatternInterfaceError): except(NoPatternInterfaceError):
pass if self.element_info.framework_id == 'WinForm' and not is_last:
item.select()
# ----------------------------------------------------------- # -----------------------------------------------------------
def _sub_item_by_text(self, menu, name, exact): def _sub_item_by_text(self, menu, name, exact, is_last):
"""Find a menu sub-item by the specified text""" """Find a menu sub-item by the specified text"""
sub_item = None sub_item = None
items = menu.items() items = menu.items()
@ -987,18 +1005,18 @@ class MenuWrapper(uiawrapper.UIAWrapper):
texts.append(i.window_text()) texts.append(i.window_text())
sub_item = findbestmatch.find_best_match(name, texts, items) sub_item = findbestmatch.find_best_match(name, texts, items)
self._activate(sub_item) self._activate(sub_item, is_last)
return sub_item return sub_item
# ----------------------------------------------------------- # -----------------------------------------------------------
def _sub_item_by_idx(self, menu, idx): def _sub_item_by_idx(self, menu, idx, is_last):
"""Find a menu sub-item by the specified index""" """Find a menu sub-item by the specified index"""
sub_item = None sub_item = None
items = menu.items() items = menu.items()
if items: if items:
sub_item = items[idx] sub_item = items[idx]
self._activate(sub_item) self._activate(sub_item, is_last)
return sub_item return sub_item
# ----------------------------------------------------------- # -----------------------------------------------------------
@ -1011,35 +1029,39 @@ class MenuWrapper(uiawrapper.UIAWrapper):
Note: $ - specifier is not supported Note: $ - specifier is not supported
""" """
# Get the path parts # Get the path parts
part0, parts = path.split("->", 1) menu_items = [p.strip() for p in path.split("->")]
part0 = part0.strip() items_cnt = len(menu_items)
if len(part0) == 0: if items_cnt == 0:
raise IndexError() raise IndexError()
for item in menu_items:
if not item:
raise IndexError("Empty item name between '->' separators")
def next_level_menu(parent_menu, item_name, is_last):
if item_name.startswith("#"):
return self._sub_item_by_idx(parent_menu, int(item_name[1:]), is_last)
else:
return self._sub_item_by_text(parent_menu, item_name, exact, is_last)
# Find a top level menu item and select it. After selecting this item # Find a top level menu item and select it. After selecting this item
# a new Menu control is created and placed on the dialog. It can be # a new Menu control is created and placed on the dialog. It can be
# a direct child or a descendant. # a direct child or a descendant.
# Sometimes we need to re-discover Menu again # Sometimes we need to re-discover Menu again
try: try:
menu = None menu = next_level_menu(self, menu_items[0], items_cnt == 1)
if part0.startswith("#"): if items_cnt == 1:
menu = self._sub_item_by_idx(self, int(part0[1:])) return menu
else:
menu = self._sub_item_by_text(self, part0, exact)
if not menu.items(): if not menu.items():
self._activate(menu) self._activate(menu, False)
timings.wait_until( timings.wait_until(
timings.Timings.window_find_timeout, timings.Timings.window_find_timeout,
timings.Timings.window_find_retry, timings.Timings.window_find_retry,
lambda: len(self.top_level_parent().descendants(control_type="Menu")) > 0) lambda: len(self.top_level_parent().descendants(control_type="Menu")) > 0)
menu = self.top_level_parent().descendants(control_type="Menu")[0] menu = self.top_level_parent().descendants(control_type="Menu")[0]
for cur_part in [p.strip() for p in parts.split("->")]: for i in range(1, items_cnt):
if cur_part.startswith("#"): menu = next_level_menu(menu, menu_items[i], items_cnt == i + 1)
menu = self._sub_item_by_idx(menu, int(cur_part[1:]))
else:
menu = self._sub_item_by_text(menu, cur_part, exact)
except(AttributeError): except(AttributeError):
raise IndexError() raise IndexError()

@ -782,5 +782,19 @@ class UIAWrapper(BaseWrapper):
return self return self
# -----------------------------------------------------------
def _texts_from_item_container(self):
"""Get texts through the ItemContainer interface"""
texts = []
try:
com_elem = self.iface_item_container.FindItemByProperty(0, 0, uia_defs.vt_empty)
while com_elem:
itm = UIAWrapper(UIAElementInfo(com_elem))
texts.append(itm.texts())
com_elem = self.iface_item_container.FindItemByProperty(com_elem, 0, uia_defs.vt_empty)
except (uia_defs.NoPatternInterfaceError):
pass
return texts
backend.register('uia', UIAElementInfo, UIAWrapper) backend.register('uia', UIAElementInfo, UIAWrapper)

@ -331,8 +331,9 @@ def get_control_names(control, allcontrols, textcontrols):
if non_text_names: if non_text_names:
names.extend(non_text_names) names.extend(non_text_names)
# return the names - and make sure there are no duplicates # return the names - and make sure there are no duplicates or empty values
return set(names) cleaned_names = set(names) - set([None, ""])
return cleaned_names
#==================================================================== #====================================================================
@ -493,6 +494,8 @@ def find_best_control_matches(search_text, controls):
""" """
name_control_map = build_unique_dict(controls) name_control_map = build_unique_dict(controls)
#print ">>>>>>>", repr(name_control_map).decode("ascii", "ignore")
# # collect all the possible names for all controls # # collect all the possible names for all controls
# # and build a list of them # # and build a list of them
# for ctrl in controls: # for ctrl in controls:

@ -189,9 +189,10 @@ def find_elements(class_name=None,
if top_level_only: if top_level_only:
# find the top level elements # find the top level elements
element = backend_obj.element_info_class() element = backend_obj.element_info_class()
# vryabov: we don't use title=title below, because it fixes issue 779:
# https://github.com/pywinauto/pywinauto/issues/779
elements = element.children(process=process, elements = element.children(process=process,
class_name=class_name, class_name=class_name,
title=title,
control_type=control_type, control_type=control_type,
cache_enable=True) cache_enable=True)
@ -206,8 +207,9 @@ def find_elements(class_name=None,
parent = backend_obj.element_info_class() parent = backend_obj.element_info_class()
# look for ALL children of that parent # look for ALL children of that parent
# vryabov: we don't use title=title below, because it fixes issue 779:
# https://github.com/pywinauto/pywinauto/issues/779
elements = parent.descendants(class_name=class_name, elements = parent.descendants(class_name=class_name,
title=title,
control_type=control_type, control_type=control_type,
cache_enable=True, cache_enable=True,
depth=depth) depth=depth)

@ -35,14 +35,18 @@ These are implemented in a procedural way so as to to be
useful to other modules with the least conceptual overhead useful to other modules with the least conceptual overhead
""" """
import ctypes
import warnings import warnings
import win32process import win32process
import win32api import win32api
import win32con import win32con
import win32gui import win32gui
import pywintypes
from ctypes import wintypes
from ctypes import WINFUNCTYPE
from ctypes import c_int
from ctypes import byref
from ctypes import sizeof
from ctypes import create_unicode_buffer
from . import win32functions from . import win32functions
from . import win32defines from . import win32defines
from . import win32structures from . import win32structures
@ -58,7 +62,7 @@ def text(handle):
if class_name == 'MSCTFIME UI': if class_name == 'MSCTFIME UI':
return 'M' return 'M'
if class_name is None: if class_name is None:
return None return ''
#length = win32functions.SendMessage(handle, win32defines.WM_GETTEXTLENGTH, 0, 0) #length = win32functions.SendMessage(handle, win32defines.WM_GETTEXTLENGTH, 0, 0)
# XXX: there are some very rare cases when WM_GETTEXTLENGTH hangs! # XXX: there are some very rare cases when WM_GETTEXTLENGTH hangs!
@ -71,11 +75,11 @@ def text(handle):
0, 0,
win32defines.SMTO_ABORTIFHUNG, win32defines.SMTO_ABORTIFHUNG,
500, 500,
ctypes.byref(c_length) byref(c_length)
) )
if result == 0: if result == 0:
ActionLogger().log('WARNING! Cannot retrieve text length for handle = ' + str(handle)) ActionLogger().log('WARNING! Cannot retrieve text length for handle = ' + str(handle))
return None return ''
else: else:
length = c_length.value length = c_length.value
@ -85,10 +89,10 @@ def text(handle):
if length > 0: if length > 0:
length += 1 length += 1
buffer_ = ctypes.create_unicode_buffer(length) buffer_ = create_unicode_buffer(length)
ret = win32functions.SendMessage( ret = win32functions.SendMessage(
handle, win32defines.WM_GETTEXT, length, ctypes.byref(buffer_)) handle, win32defines.WM_GETTEXT, length, byref(buffer_))
if ret: if ret:
textval = buffer_.value textval = buffer_.value
@ -101,7 +105,7 @@ def classname(handle):
"""Return the class name of the window""" """Return the class name of the window"""
if handle is None: if handle is None:
return None return None
class_name = ctypes.create_unicode_buffer(u"", 257) class_name = create_unicode_buffer(u"", 257)
win32functions.GetClassName(handle, class_name, 256) win32functions.GetClassName(handle, class_name, 256)
return class_name.value return class_name.value
@ -192,8 +196,8 @@ def is64bitbinary(filename):
binary_type = win32file.GetBinaryType(filename) binary_type = win32file.GetBinaryType(filename)
return binary_type != win32file.SCS_32BIT_BINARY return binary_type != win32file.SCS_32BIT_BINARY
except Exception as exc: except Exception as exc:
warnings.warn('Cannot get binary type for file "{}". Error: {}' \ warnings.warn('Cannot get binary type for file "{}". Error: {}'
''.format(filename, exc), RuntimeWarning, stacklevel=2) .format(filename, exc), RuntimeWarning, stacklevel=2)
return None return None
@ -201,24 +205,24 @@ def is64bitbinary(filename):
def clientrect(handle): def clientrect(handle):
"""Return the client rectangle of the control""" """Return the client rectangle of the control"""
client_rect = win32structures.RECT() client_rect = win32structures.RECT()
win32functions.GetClientRect(handle, ctypes.byref(client_rect)) win32functions.GetClientRect(handle, byref(client_rect))
return client_rect return client_rect
#========================================================================= #=========================================================================
def rectangle(handle): def rectangle(handle):
"""Return the rectangle of the window""" """Return the rectangle of the window"""
# GetWindowRect returns 4-tuple rect = win32structures.RECT()
try: win32functions.GetWindowRect(handle, byref(rect))
return win32structures.RECT(*win32gui.GetWindowRect(handle)) return rect
except pywintypes.error:
return win32structures.RECT()
#========================================================================= #=========================================================================
def font(handle): def font(handle):
"""Return the font as a LOGFONTW of the window""" """Return the font as a LOGFONTW of the window"""
# get the font handle # get the font handle
if handle is None:
handle = 0 # make sure we don't pass window handle down as None
font_handle = win32functions.SendMessage( font_handle = win32functions.SendMessage(
handle, win32defines.WM_GETFONT, 0, 0) handle, win32defines.WM_GETFONT, 0, 0)
@ -244,15 +248,10 @@ def font(handle):
font_handle = win32functions.GetStockObject( font_handle = win32functions.GetStockObject(
win32defines.ANSI_VAR_FONT) win32defines.ANSI_VAR_FONT)
else:
fontval = win32structures.LOGFONTW()
ret = win32functions.GetObject(
font_handle, ctypes.sizeof(fontval), ctypes.byref(fontval))
# Get the Logfont structure of the font of the control # Get the Logfont structure of the font of the control
fontval = win32structures.LOGFONTW() fontval = win32structures.LOGFONTW()
ret = win32functions.GetObject( ret = win32functions.GetObject(
font_handle, ctypes.sizeof(fontval), ctypes.byref(fontval)) font_handle, sizeof(fontval), byref(fontval))
# The function could not get the font - this is probably # The function could not get the font - this is probably
# because the control does not have associated Font/Text # because the control does not have associated Font/Text
@ -271,11 +270,11 @@ def font(handle):
# get the title font based on the system metrics rather # get the title font based on the system metrics rather
# than the font of the control itself # than the font of the control itself
ncms = win32structures.NONCLIENTMETRICSW() ncms = win32structures.NONCLIENTMETRICSW()
ncms.cbSize = ctypes.sizeof(ncms) ncms.cbSize = sizeof(ncms)
win32functions.SystemParametersInfo( win32functions.SystemParametersInfo(
win32defines.SPI_GETNONCLIENTMETRICS, win32defines.SPI_GETNONCLIENTMETRICS,
ctypes.sizeof(ncms), sizeof(ncms),
ctypes.byref(ncms), byref(ncms),
0) 0)
# with either of the following 2 flags set the font of the # with either of the following 2 flags set the font of the
@ -293,8 +292,9 @@ def font(handle):
#========================================================================= #=========================================================================
def processid(handle): def processid(handle):
"""Return the ID of process that controls this window""" """Return the ID of process that controls this window"""
_, process_id = win32process.GetWindowThreadProcessId(int(handle)) pid = wintypes.DWORD()
return process_id win32functions.GetWindowThreadProcessId(handle, byref(pid))
return pid.value
#========================================================================= #=========================================================================
@ -327,10 +327,10 @@ def children(handle):
return True return True
# define the child proc type # define the child proc type
enum_child_proc_t = ctypes.WINFUNCTYPE( enum_child_proc_t = WINFUNCTYPE(
ctypes.c_int, # return type c_int, # return type
win32structures.HWND, # the window handle wintypes.HWND, # the window handle
win32structures.LPARAM) # extra information wintypes.LPARAM) # extra information
# update the proc to the correct type # update the proc to the correct type
proc = enum_child_proc_t(enum_child_proc) proc = enum_child_proc_t(enum_child_proc)

@ -64,6 +64,8 @@ below. The module is also available on Linux.
{VK_F19}, {VK_EXECUTE}, {VK_PLAY}, {VK_RMENU}, {VK_F13}, {VK_F12}, {LWIN}, {VK_F19}, {VK_EXECUTE}, {VK_PLAY}, {VK_RMENU}, {VK_F13}, {VK_F12}, {LWIN},
{VK_DOWN}, {VK_F17}, {VK_F16}, {VK_F15}, {VK_F14} {VK_DOWN}, {VK_F17}, {VK_F16}, {VK_F15}, {VK_F14}
~ is a shorter alias for {ENTER}
**Modifiers:** **Modifiers:**
- ``'+': {VK_SHIFT}`` - ``'+': {VK_SHIFT}``
@ -96,10 +98,19 @@ Use curly brackers to escape modifiers and type reserved symbols as single keys:
send_keys('{^}a{^}c{%}') # type string "^a^c%" (Ctrl will not be pressed) send_keys('{^}a{^}c{%}') # type string "^a^c%" (Ctrl will not be pressed)
send_keys('{{}ENTER{}}') # type string "{ENTER}" without pressing Enter key send_keys('{{}ENTER{}}') # type string "{ENTER}" without pressing Enter key
For Windows only, pywinauto defaults to sending a virtual key packet
(VK_PACKET) for textual input. For applications that do not handle VK_PACKET
appropriately, the ``vk_packet`` option may be set to ``False``. In this case
pywinauto will attempt to send the virtual key code of the requested key. This
option only affects the behavior of keys matching [-=[]\;',./a-zA-Z0-9 ]. Note
that upper and lower case are included for a-z. Both reference the same
virtual key for convenience.
""" """
from __future__ import unicode_literals from __future__ import unicode_literals
import sys import sys
import string
from . import deprecated from . import deprecated
@ -113,6 +124,7 @@ else:
import six import six
from . import win32structures from . import win32structures
from . import win32functions
__all__ = ['KeySequenceError', 'send_keys'] __all__ = ['KeySequenceError', 'send_keys']
@ -120,17 +132,6 @@ else:
DEBUG = 0 DEBUG = 0
GetMessageExtraInfo = ctypes.windll.user32.GetMessageExtraInfo
MapVirtualKey = ctypes.windll.user32.MapVirtualKeyW
SendInput = ctypes.windll.user32.SendInput
UINT = ctypes.c_uint
SendInput.restype = UINT
SendInput.argtypes = [UINT, ctypes.c_void_p, ctypes.c_int]
VkKeyScan = ctypes.windll.user32.VkKeyScanW
VkKeyScan.restype = ctypes.c_short
VkKeyScan.argtypes = [ctypes.c_wchar]
INPUT_KEYBOARD = 1 INPUT_KEYBOARD = 1
KEYEVENTF_EXTENDEDKEY = 1 KEYEVENTF_EXTENDEDKEY = 1
KEYEVENTF_KEYUP = 2 KEYEVENTF_KEYUP = 2
@ -310,6 +311,29 @@ else:
'%': VK_MENU, '%': VK_MENU,
} }
# Virtual keys that map to an ASCII character
# See https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
ascii_vk = {
' ': 0x20,
'=': 0xbb,
',': 0xbc,
'-': 0xbd,
'.': 0xbe,
# According to the above reference, the following characters vary per region.
# This mapping applies to US keyboards
';': 0xba,
'/': 0xbf,
'`': 0xc0,
'[': 0xdb,
'\\': 0xdc,
']': 0xdd,
'\'': 0xde,
}
# [0-9A-Z] map exactly to their ASCII counterparts
ascii_vk.update(dict((c, ord(c)) for c in string.ascii_uppercase + string.digits))
# map [a-z] to their uppercase ASCII counterparts
ascii_vk.update(dict((c, ord(c.upper())) for c in string.ascii_lowercase))
class KeySequenceError(Exception): class KeySequenceError(Exception):
@ -368,7 +392,7 @@ else:
# it seems to return 0 every time but it's required by MSDN specification # it seems to return 0 every time but it's required by MSDN specification
# so call it just in case # so call it just in case
inp.ki.dwExtraInfo = GetMessageExtraInfo() inp.ki.dwExtraInfo = win32functions.GetMessageExtraInfo()
# if we are releasing - then let it up # if we are releasing - then let it up
if self.up: if self.up:
@ -381,7 +405,7 @@ else:
inputs = self.GetInput() inputs = self.GetInput()
# SendInput() supports all Unicode symbols # SendInput() supports all Unicode symbols
num_inserted_events = SendInput(len(inputs), ctypes.byref(inputs), num_inserted_events = win32functions.SendInput(len(inputs), ctypes.byref(inputs),
ctypes.sizeof(win32structures.INPUT)) ctypes.sizeof(win32structures.INPUT))
if num_inserted_events != len(inputs): if num_inserted_events != len(inputs):
raise RuntimeError('SendInput() inserted only ' + str(num_inserted_events) + raise RuntimeError('SendInput() inserted only ' + str(num_inserted_events) +
@ -447,7 +471,7 @@ else:
# return self.key, 0, 0 # return self.key, 0, 0
# this works for Tic Tac Toe i.e. +{RIGHT} SHIFT + RIGHT # this works for Tic Tac Toe i.e. +{RIGHT} SHIFT + RIGHT
return self.key, MapVirtualKey(self.key, 0), flags return self.key, win32functions.MapVirtualKeyW(self.key, 0), flags
def run(self): def run(self):
"""Execute the action""" """Execute the action"""
@ -468,9 +492,9 @@ else:
The vk and scan code are generated differently. The vk and scan code are generated differently.
""" """
vkey_scan = LoByte(VkKeyScan(self.key)) vkey_scan = LoByte(win32functions.VkKeyScanW(self.key))
return (vkey_scan, MapVirtualKey(vkey_scan, 0), 0) return (vkey_scan, win32functions.MapVirtualKeyW(vkey_scan, 0), 0)
def key_description(self): def key_description(self):
"""Return a description of the key""" """Return a description of the key"""
@ -500,7 +524,7 @@ else:
__repr__ = __str__ __repr__ = __str__
def handle_code(code): def handle_code(code, vk_packet):
"""Handle a key or sequence of keys in braces""" """Handle a key or sequence of keys in braces"""
code_keys = [] code_keys = []
# it is a known code (e.g. {DOWN}, {ENTER}, etc) # it is a known code (e.g. {DOWN}, {ENTER}, etc)
@ -509,6 +533,9 @@ else:
# it is an escaped modifier e.g. {%}, {^}, {+} # it is an escaped modifier e.g. {%}, {^}, {+}
elif len(code) == 1: elif len(code) == 1:
if not vk_packet and code in ascii_vk:
code_keys.append(VirtualKeyAction(ascii_vk[code]))
else:
code_keys.append(KeyAction(code)) code_keys.append(KeyAction(code))
# it is a repetition or a pause {DOWN 5}, {PAUSE 1.3} # it is a repetition or a pause {DOWN 5}, {PAUSE 1.3}
@ -535,7 +562,7 @@ else:
[VirtualKeyAction(CODES[to_repeat])] * count) [VirtualKeyAction(CODES[to_repeat])] * count)
# otherwise parse the keys and we get back a KeyAction # otherwise parse the keys and we get back a KeyAction
else: else:
to_repeat = parse_keys(to_repeat) to_repeat = parse_keys(to_repeat, vk_packet=vk_packet)
if isinstance(to_repeat, list): if isinstance(to_repeat, list):
keys = to_repeat * count keys = to_repeat * count
else: else:
@ -550,7 +577,8 @@ else:
with_spaces=False, with_spaces=False,
with_tabs=False, with_tabs=False,
with_newlines=False, with_newlines=False,
modifiers=None): modifiers=None,
vk_packet=True):
"""Return the parsed keys""" """Return the parsed keys"""
keys = [] keys = []
if not modifiers: if not modifiers:
@ -579,8 +607,10 @@ else:
end_pos = string.find(")", index) end_pos = string.find(")", index)
if end_pos == -1: if end_pos == -1:
raise KeySequenceError('`)` not found') raise KeySequenceError('`)` not found')
keys.extend( keys.extend(parse_keys(
parse_keys(string[index:end_pos], modifiers=modifiers)) string[index:end_pos],
modifiers=modifiers,
vk_packet=vk_packet))
index = end_pos + 1 index = end_pos + 1
# Escape or named key # Escape or named key
@ -597,7 +627,7 @@ else:
if any(key_event in code.lower() for key_event in key_events): if any(key_event in code.lower() for key_event in key_events):
code, current_key_event = code.split(' ') code, current_key_event = code.split(' ')
should_escape_next_keys = True should_escape_next_keys = True
current_keys = handle_code(code) current_keys = handle_code(code, vk_packet)
if current_key_event is not None: if current_key_event is not None:
if isinstance(current_keys[0].key, six.string_types): if isinstance(current_keys[0].key, six.string_types):
current_keys[0] = EscapedKeyAction(current_keys[0].key) current_keys[0] = EscapedKeyAction(current_keys[0].key)
@ -636,6 +666,11 @@ else:
elif modifiers or should_escape_next_keys: elif modifiers or should_escape_next_keys:
keys.append(EscapedKeyAction(c)) keys.append(EscapedKeyAction(c))
# if user disables the vk_packet option, always try to send a
# virtual key of the actual keystroke
elif not vk_packet and c in ascii_vk:
keys.append(VirtualKeyAction(ascii_vk[c]))
else: else:
keys.append(KeyAction(c)) keys.append(KeyAction(c))
@ -667,9 +702,12 @@ else:
with_spaces=False, with_spaces=False,
with_tabs=False, with_tabs=False,
with_newlines=False, with_newlines=False,
turn_off_numlock=True): turn_off_numlock=True,
vk_packet=True):
"""Parse the keys and type them""" """Parse the keys and type them"""
keys = parse_keys(keys, with_spaces, with_tabs, with_newlines) keys = parse_keys(
keys, with_spaces, with_tabs, with_newlines,
vk_packet=vk_packet)
for k in keys: for k in keys:
k.run() k.run()

@ -382,7 +382,7 @@ class PauseAction(KeyAction):
__repr__ = __str__ __repr__ = __str__
def handle_code(code): def handle_code(code, vk_packet=True):
"""Handle a key or sequence of keys in braces""" """Handle a key or sequence of keys in braces"""
code_keys = [] code_keys = []
# it is a known code (e.g. {DOWN}, {ENTER}, etc) # it is a known code (e.g. {DOWN}, {ENTER}, etc)
@ -433,7 +433,8 @@ def parse_keys(string,
with_spaces = False, with_spaces = False,
with_tabs = False, with_tabs = False,
with_newlines = False, with_newlines = False,
modifiers = None): modifiers = None,
vk_packet=True):
"""Return the parsed keys""" """Return the parsed keys"""
keys = [] keys = []
if not modifiers: if not modifiers:
@ -523,7 +524,8 @@ def send_keys(keys,
with_spaces=False, with_spaces=False,
with_tabs=False, with_tabs=False,
with_newlines=False, with_newlines=False,
turn_off_numlock=True): turn_off_numlock=True,
vk_packet=True):
"""Parse the keys and type them""" """Parse the keys and type them"""
keys = parse_keys(keys, with_spaces, with_tabs, with_newlines) keys = parse_keys(keys, with_spaces, with_tabs, with_newlines)
for k in keys: for k in keys:

@ -35,10 +35,15 @@ Win32 API functions to perform custom marshalling
from __future__ import print_function from __future__ import print_function
import sys import sys
import ctypes
import win32api import win32api
import win32process
from ctypes import wintypes
from ctypes import c_void_p
from ctypes import pointer
from ctypes import sizeof
from ctypes import byref
from ctypes import c_size_t
from ctypes import WinError
from . import win32functions from . import win32functions
from . import win32defines from . import win32defines
from . import win32structures from . import win32structures
@ -70,10 +75,12 @@ class RemoteMemoryBlock(object):
self._as_parameter_ = self.mem_address self._as_parameter_ = self.mem_address
_, process_id = win32process.GetWindowThreadProcessId(self.handle) pid = wintypes.DWORD()
win32functions.GetWindowThreadProcessId(self.handle, byref(pid))
process_id = pid.value
if not process_id: if not process_id:
raise AccessDenied( raise AccessDenied(
str(ctypes.WinError()) + " Cannot get process ID from handle.") str(WinError()) + " Cannot get process ID from handle.")
self.process = win32functions.OpenProcess( self.process = win32functions.OpenProcess(
win32defines.PROCESS_VM_OPERATION | win32defines.PROCESS_VM_OPERATION |
@ -85,12 +92,12 @@ class RemoteMemoryBlock(object):
if not self.process: if not self.process:
raise AccessDenied( raise AccessDenied(
str(ctypes.WinError()) + "process: %d", str(WinError()) + "process: %d",
process_id) process_id)
self.mem_address = win32functions.VirtualAllocEx( self.mem_address = win32functions.VirtualAllocEx(
ctypes.c_void_p(self.process), # remote process c_void_p(self.process), # remote process
ctypes.c_void_p(0), # let Valloc decide where c_void_p(0), # let Valloc decide where
win32structures.ULONG_PTR(self.size + 4), # how much to allocate win32structures.ULONG_PTR(self.size + 4), # how much to allocate
win32defines.MEM_RESERVE | \ win32defines.MEM_RESERVE | \
win32defines.MEM_COMMIT, # allocation type win32defines.MEM_COMMIT, # allocation type
@ -100,7 +107,7 @@ class RemoteMemoryBlock(object):
self.mem_address = self.mem_address.value self.mem_address = self.mem_address.value
if self.mem_address == 0: if self.mem_address == 0:
raise ctypes.WinError() raise WinError()
if hex(self.mem_address) == '0xffffffff80000000' or hex(self.mem_address).upper() == '0xFFFFFFFF00000000': if hex(self.mem_address) == '0xffffffff80000000' or hex(self.mem_address).upper() == '0xFFFFFFFF00000000':
raise Exception('Incorrect allocation: ' + hex(self.mem_address)) raise Exception('Incorrect allocation: ' + hex(self.mem_address))
@ -108,11 +115,11 @@ class RemoteMemoryBlock(object):
self._as_parameter_ = self.mem_address self._as_parameter_ = self.mem_address
# write guard signature at the end of memory block # write guard signature at the end of memory block
signature = win32structures.LONG(0x66666666) signature = wintypes.LONG(0x66666666)
ret = win32functions.WriteProcessMemory( ret = win32functions.WriteProcessMemory(
ctypes.c_void_p(self.process), c_void_p(self.process),
ctypes.c_void_p(self.mem_address + self.size), c_void_p(self.mem_address + self.size),
ctypes.pointer(signature), pointer(signature),
win32structures.ULONG_PTR(4), win32structures.ULONG_PTR(4),
win32structures.ULONG_PTR(0) win32structures.ULONG_PTR(0)
) )
@ -129,7 +136,7 @@ class RemoteMemoryBlock(object):
if ret == 0: if ret == 0:
ActionLogger().log('Warning: cannot close process handle!') ActionLogger().log('Warning: cannot close process handle!')
#raise ctypes.WinError() #raise WinError()
#---------------------------------------------------------------- #----------------------------------------------------------------
def CleanUp(self): def CleanUp(self):
@ -140,17 +147,17 @@ class RemoteMemoryBlock(object):
self.CheckGuardSignature() self.CheckGuardSignature()
ret = win32functions.VirtualFreeEx( ret = win32functions.VirtualFreeEx(
ctypes.c_void_p(self.process), c_void_p(self.process),
ctypes.c_void_p(self.mem_address), c_void_p(self.mem_address),
win32structures.ULONG_PTR(0), win32structures.ULONG_PTR(0),
win32structures.DWORD(win32defines.MEM_RELEASE)) wintypes.DWORD(win32defines.MEM_RELEASE))
if ret == 0: if ret == 0:
print('Error: CleanUp: VirtualFreeEx() returned zero for address ', hex(self.mem_address)) print('Error: CleanUp: VirtualFreeEx() returned zero for address ', hex(self.mem_address))
last_error = win32api.GetLastError() last_error = win32api.GetLastError()
print('LastError = ', last_error, ': ', win32api.FormatMessage(last_error).rstrip()) print('LastError = ', last_error, ': ', win32api.FormatMessage(last_error).rstrip())
sys.stdout.flush() sys.stdout.flush()
self._CloseHandle() self._CloseHandle()
raise ctypes.WinError() raise WinError()
self.mem_address = 0 self.mem_address = 0
self._CloseHandle() self._CloseHandle()
else: else:
@ -180,7 +187,7 @@ class RemoteMemoryBlock(object):
if size: if size:
nSize = win32structures.ULONG_PTR(size) nSize = win32structures.ULONG_PTR(size)
else: else:
nSize = win32structures.ULONG_PTR(ctypes.sizeof(data)) nSize = win32structures.ULONG_PTR(sizeof(data))
if self.size < nSize.value: if self.size < nSize.value:
raise Exception(('Write: RemoteMemoryBlock is too small ({0} bytes),' + raise Exception(('Write: RemoteMemoryBlock is too small ({0} bytes),' +
@ -190,19 +197,19 @@ class RemoteMemoryBlock(object):
raise Exception('Write: RemoteMemoryBlock has incorrect address = ' + hex(address)) raise Exception('Write: RemoteMemoryBlock has incorrect address = ' + hex(address))
ret = win32functions.WriteProcessMemory( ret = win32functions.WriteProcessMemory(
ctypes.c_void_p(self.process), c_void_p(self.process),
ctypes.c_void_p(address), c_void_p(address),
ctypes.pointer(data), pointer(data),
nSize, nSize,
win32structures.ULONG_PTR(0) win32structures.ULONG_PTR(0)
) )
if ret == 0: if ret == 0:
ActionLogger().log('Error: Write failed: address = ', address) ActionLogger().log('Error: Write failed: address = ' + str(address))
last_error = win32api.GetLastError() last_error = win32api.GetLastError()
ActionLogger().log('Error: LastError = ', last_error, ': ', ActionLogger().log('Error: LastError = ' + str(last_error) + ': ' +
win32api.FormatMessage(last_error).rstrip()) win32api.FormatMessage(last_error).rstrip())
raise ctypes.WinError() raise WinError()
self.CheckGuardSignature() self.CheckGuardSignature()
#---------------------------------------------------------------- #----------------------------------------------------------------
@ -216,7 +223,7 @@ class RemoteMemoryBlock(object):
if size: if size:
nSize = win32structures.ULONG_PTR(size) nSize = win32structures.ULONG_PTR(size)
else: else:
nSize = win32structures.ULONG_PTR(ctypes.sizeof(data)) nSize = win32structures.ULONG_PTR(sizeof(data))
if self.size < nSize.value: if self.size < nSize.value:
raise Exception(('Read: RemoteMemoryBlock is too small ({0} bytes),' + raise Exception(('Read: RemoteMemoryBlock is too small ({0} bytes),' +
@ -225,14 +232,14 @@ class RemoteMemoryBlock(object):
if hex(address).lower().startswith('0xffffff'): if hex(address).lower().startswith('0xffffff'):
raise Exception('Read: RemoteMemoryBlock has incorrect address =' + hex(address)) raise Exception('Read: RemoteMemoryBlock has incorrect address =' + hex(address))
lpNumberOfBytesRead = ctypes.c_size_t(0) lpNumberOfBytesRead = c_size_t(0)
ret = win32functions.ReadProcessMemory( ret = win32functions.ReadProcessMemory(
ctypes.c_void_p(self.process), c_void_p(self.process),
ctypes.c_void_p(address), c_void_p(address),
ctypes.byref(data), byref(data),
nSize, nSize,
ctypes.byref(lpNumberOfBytesRead) byref(lpNumberOfBytesRead)
) )
# disabled as it often returns an error - but # disabled as it often returns an error - but
@ -240,27 +247,27 @@ class RemoteMemoryBlock(object):
if ret == 0: if ret == 0:
# try again # try again
ret = win32functions.ReadProcessMemory( ret = win32functions.ReadProcessMemory(
ctypes.c_void_p(self.process), c_void_p(self.process),
ctypes.c_void_p(address), c_void_p(address),
ctypes.byref(data), byref(data),
nSize, nSize,
ctypes.byref(lpNumberOfBytesRead) byref(lpNumberOfBytesRead)
) )
if ret == 0: if ret == 0:
last_error = win32api.GetLastError() last_error = win32api.GetLastError()
if last_error != win32defines.ERROR_PARTIAL_COPY: if last_error != win32defines.ERROR_PARTIAL_COPY:
ActionLogger().log('Read: WARNING! self.mem_address =' + ActionLogger().log('Read: WARNING! self.mem_address =' +
hex(self.mem_address) + ' data address =' + str(ctypes.byref(data))) hex(self.mem_address) + ' data address =' + str(byref(data)))
ActionLogger().log('LastError = ' + str(last_error) + ActionLogger().log('LastError = ' + str(last_error) +
': ' + win32api.FormatMessage(last_error).rstrip()) ': ' + win32api.FormatMessage(last_error).rstrip())
else: else:
ActionLogger().log('Error: ERROR_PARTIAL_COPY') ActionLogger().log('Error: ERROR_PARTIAL_COPY')
ActionLogger().log('\nRead: WARNING! self.mem_address =' + ActionLogger().log('\nRead: WARNING! self.mem_address =' +
hex(self.mem_address) + ' data address =' + str(ctypes.byref(data))) hex(self.mem_address) + ' data address =' + str(byref(data)))
ActionLogger().log('lpNumberOfBytesRead =' + ActionLogger().log('lpNumberOfBytesRead =' +
str(lpNumberOfBytesRead) + ' nSize =' + str(nSize)) str(lpNumberOfBytesRead) + ' nSize =' + str(nSize))
raise ctypes.WinError() raise WinError()
else: else:
ActionLogger().log('Warning! Read OK: 2nd attempt!') ActionLogger().log('Warning! Read OK: 2nd attempt!')
#else: #else:
@ -273,18 +280,18 @@ class RemoteMemoryBlock(object):
def CheckGuardSignature(self): def CheckGuardSignature(self):
"""read guard signature at the end of memory block""" """read guard signature at the end of memory block"""
signature = win32structures.LONG(0) signature = win32structures.LONG(0)
lpNumberOfBytesRead = ctypes.c_size_t(0) lpNumberOfBytesRead = c_size_t(0)
ret = win32functions.ReadProcessMemory( ret = win32functions.ReadProcessMemory(
ctypes.c_void_p(self.process), c_void_p(self.process),
ctypes.c_void_p(self.mem_address + self.size), c_void_p(self.mem_address + self.size),
ctypes.pointer(signature), # 0x66666666 pointer(signature), # 0x66666666
win32structures.ULONG_PTR(4), win32structures.ULONG_PTR(4),
ctypes.byref(lpNumberOfBytesRead)) byref(lpNumberOfBytesRead))
if ret == 0: if ret == 0:
ActionLogger().log('Error: Failed to read guard signature: address = ' + ActionLogger().log('Error: Failed to read guard signature: address = ' +
hex(self.mem_address) + ', size = ' + str(self.size) + hex(self.mem_address) + ', size = ' + str(self.size) +
', lpNumberOfBytesRead = ' + str(lpNumberOfBytesRead)) ', lpNumberOfBytesRead = ' + str(lpNumberOfBytesRead))
raise ctypes.WinError() raise WinError()
else: else:
if hex(signature.value) != '0x66666666': if hex(signature.value) != '0x66666666':
raise Exception('---------------------------------------- ' + raise Exception('---------------------------------------- ' +

@ -82,8 +82,8 @@ class IUIA(object):
end_len = len('ControlTypeId') end_len = len('ControlTypeId')
self._control_types = [attr[start_len:-end_len] for attr in dir(self.UIA_dll) if attr.endswith('ControlTypeId')] self._control_types = [attr[start_len:-end_len] for attr in dir(self.UIA_dll) if attr.endswith('ControlTypeId')]
self.known_control_types = {} # string id: numeric id self.known_control_types = { 'InvalidControlType': 0 } # string id: numeric id
self.known_control_type_ids = {} # numeric id: string id self.known_control_type_ids = { 0: 'InvalidControlType' } # numeric id: string id
for ctrl_type in self._control_types: for ctrl_type in self._control_types:
type_id_name = 'UIA_' + ctrl_type + 'ControlTypeId' type_id_name = 'UIA_' + ctrl_type + 'ControlTypeId'
@ -218,6 +218,8 @@ scroll_no_amount = IUIA().ui_automation_client.ScrollAmount_NoAmount
scroll_large_increment = IUIA().ui_automation_client.ScrollAmount_LargeIncrement scroll_large_increment = IUIA().ui_automation_client.ScrollAmount_LargeIncrement
scroll_small_increment = IUIA().ui_automation_client.ScrollAmount_SmallIncrement scroll_small_increment = IUIA().ui_automation_client.ScrollAmount_SmallIncrement
vt_empty = IUIA().ui_automation_client.VARIANT.empty.vt
vt_null = IUIA().ui_automation_client.VARIANT.null.vt
def get_elem_interface(element_info, pattern_name): def get_elem_interface(element_info, pattern_name):
"""A helper to retrieve an element interface by the specified pattern name """A helper to retrieve an element interface by the specified pattern name

@ -79,7 +79,6 @@ windll.user32.SetWindowsHookExA.restype = wintypes.HHOOK
windll.user32.SetWindowsHookExA.argtypes = [c_int, HOOKCB, wintypes.HINSTANCE, wintypes.DWORD] windll.user32.SetWindowsHookExA.argtypes = [c_int, HOOKCB, wintypes.HINSTANCE, wintypes.DWORD]
windll.user32.SetWindowsHookExW.restype = wintypes.HHOOK windll.user32.SetWindowsHookExW.restype = wintypes.HHOOK
windll.user32.SetWindowsHookExW.argtypes = [c_int, HOOKCB, wintypes.HINSTANCE, wintypes.DWORD] windll.user32.SetWindowsHookExW.argtypes = [c_int, HOOKCB, wintypes.HINSTANCE, wintypes.DWORD]
windll.user32.GetMessageW.argtypes = [POINTER(wintypes.MSG), wintypes.HWND, c_uint, c_uint]
windll.user32.TranslateMessage.argtypes = [POINTER(wintypes.MSG)] windll.user32.TranslateMessage.argtypes = [POINTER(wintypes.MSG)]
windll.user32.DispatchMessageW.argtypes = [POINTER(wintypes.MSG)] windll.user32.DispatchMessageW.argtypes = [POINTER(wintypes.MSG)]
@ -452,7 +451,7 @@ class Hook(object):
al = ActionLogger() al = ActionLogger()
al.log("_process_kbd_msg_type, bad event_type: {0}".format(event_type)) al.log("_process_kbd_msg_type, bad event_type: {0}".format(event_type))
if event_type == 'key down': if event_type == 'key down' and current_key not in self.pressed_keys:
self.pressed_keys.append(current_key) self.pressed_keys.append(current_key)
elif event_type == 'key up': elif event_type == 'key up':
if current_key in self.pressed_keys: if current_key in self.pressed_keys:

@ -31,192 +31,678 @@
"""Defines Windows(tm) functions""" """Defines Windows(tm) functions"""
import ctypes from ctypes import LibraryLoader
from ctypes import WinDLL
from ctypes import wintypes from ctypes import wintypes
from . import win32defines, win32structures from . import win32defines, win32structures
from .actionlogger import ActionLogger from .actionlogger import ActionLogger
from ctypes import c_uint, c_short, c_long from ctypes import c_short
from ctypes import WINFUNCTYPE
from ctypes import c_void_p
from ctypes import c_int
from ctypes import byref
from ctypes import POINTER
from ctypes import c_ubyte
from ctypes import c_size_t
# Quote: "If you want cached libs without polluting ctypes.cdll or
# ctypes.windll, just create your own instance such as
# windll = ctypes.LibraryLoader(ctypes.WinDLL)."
# see https://bugs.python.org/issue22552
windll = LibraryLoader(WinDLL)
import sys
if sys.platform == "cygwin":
windll = ctypes.cdll
HRESULT = c_long
UINT = c_uint
SHORT = c_short SHORT = c_short
CreateBrushIndirect = ctypes.windll.gdi32.CreateBrushIndirect CreateBrushIndirect = windll.gdi32.CreateBrushIndirect
CreateDC = ctypes.windll.gdi32.CreateDCW CreateBrushIndirect.restype = wintypes.HBRUSH
CreateFontIndirect = ctypes.windll.gdi32.CreateFontIndirectW CreateBrushIndirect.argtypes = [
CreatePen = ctypes.windll.gdi32.CreatePen c_void_p,
DeleteDC = ctypes.windll.gdi32.DeleteDC ]
GetObject = ctypes.windll.gdi32.GetObjectW CreateDC = windll.gdi32.CreateDCW
DeleteObject = ctypes.windll.gdi32.DeleteObject CreateDC.restype = wintypes.HDC
DrawText = ctypes.windll.user32.DrawTextW CreateDC.argtypes = [
TextOut = ctypes.windll.gdi32.TextOutW wintypes.LPCWSTR,
Rectangle = ctypes.windll.gdi32.Rectangle wintypes.LPCWSTR,
SelectObject = ctypes.windll.gdi32.SelectObject wintypes.LPCWSTR,
GetStockObject = ctypes.windll.gdi32.GetStockObject c_void_p,
GetSystemMetrics = ctypes.windll.user32.GetSystemMetrics ]
GetSystemMetrics.restype = ctypes.c_int CreateFontIndirect = windll.gdi32.CreateFontIndirectW
GetSystemMetrics.argtypes = (ctypes.c_int, ) CreateFontIndirect.restype = wintypes.HFONT
GetTextMetrics = ctypes.windll.gdi32.GetTextMetricsW CreateFontIndirect.argtypes = [
POINTER(win32structures.LOGFONTW),
]
EnumChildWindows = ctypes.windll.user32.EnumChildWindows CreatePen = windll.gdi32.CreatePen
EnumDesktopWindows = ctypes.windll.user32.EnumDesktopWindows CreatePen.restype = wintypes.HPEN
EnumWindows = ctypes.windll.user32.EnumWindows CreatePen.argtypes = [
GetDC = ctypes.windll.user32.GetDC c_int,
GetDesktopWindow = ctypes.windll.user32.GetDesktopWindow c_int,
wintypes.COLORREF,
]
SendInput = ctypes.windll.user32.SendInput DeleteDC = windll.gdi32.DeleteDC
SetCursorPos = ctypes.windll.user32.SetCursorPos DeleteDC.restype = wintypes.BOOL
GetCursorPos = ctypes.windll.user32.GetCursorPos DeleteDC.argtypes = [
GetCaretPos = ctypes.windll.user32.GetCaretPos wintypes.HDC,
]
GetObject = windll.gdi32.GetObjectW
GetObject.restype = c_int
GetObject.argtypes = [
wintypes.HANDLE,
c_int,
wintypes.LPVOID,
]
DeleteObject = windll.gdi32.DeleteObject
DeleteObject.restype = wintypes.BOOL
DeleteObject.argtypes = [
wintypes.HGDIOBJ,
]
DrawText = windll.user32.DrawTextW
DrawText.restype = c_int
DrawText.argtypes = [
wintypes.HDC,
wintypes.LPCWSTR,
c_int,
POINTER(wintypes.RECT),
wintypes.UINT,
]
TextOut = windll.gdi32.TextOutW
TextOut.restype = wintypes.BOOL
TextOut.argtypes = [
wintypes.HDC,
c_int,
c_int,
wintypes.LPCWSTR,
c_int,
]
Rectangle = windll.gdi32.Rectangle
Rectangle.restype = wintypes.BOOL
Rectangle.argtypes = [
wintypes.HDC,
c_int,
c_int,
c_int,
c_int,
]
SelectObject = windll.gdi32.SelectObject
SelectObject.restype = wintypes.HGDIOBJ
SelectObject.argtypes = [
wintypes.HDC,
wintypes.HGDIOBJ,
]
GetStockObject = windll.gdi32.GetStockObject
GetStockObject.restype = wintypes.HGDIOBJ
GetStockObject.argtypes = [
c_int,
]
GetSystemMetrics = windll.user32.GetSystemMetrics
GetSystemMetrics.restype = c_int
GetSystemMetrics.argtypes = [
c_int,
]
GetTextMetrics = windll.gdi32.GetTextMetricsW
GetTextMetrics.restype = wintypes.BOOL
GetTextMetrics.argtypes = [
wintypes.HDC,
POINTER(win32structures.TEXTMETRICW),
]
EnumChildWindows = windll.user32.EnumChildWindows
EnumChildWindows.restype = wintypes.BOOL
EnumChildWindows.argtypes = [
wintypes.HWND,
WINFUNCTYPE(wintypes.BOOL, wintypes.HWND, wintypes.LPARAM),
wintypes.LPARAM,
]
EnumDesktopWindows = windll.user32.EnumDesktopWindows
EnumDesktopWindows.restype = wintypes.BOOL
EnumDesktopWindows.argtypes = [
wintypes.LPVOID,
WINFUNCTYPE(wintypes.BOOL, wintypes.HWND, wintypes.LPARAM),
wintypes.LPARAM,
]
EnumWindows = windll.user32.EnumWindows
EnumWindows.restype = wintypes.BOOL
EnumWindows.argtypes = [
WINFUNCTYPE(wintypes.BOOL, wintypes.HWND, wintypes.LPARAM),
wintypes.LPARAM,
]
GetDC = windll.user32.GetDC
GetDC.restype = wintypes.LPVOID
GetDC.argtypes = [
wintypes.HWND,
]
GetDesktopWindow = windll.user32.GetDesktopWindow
GetDesktopWindow.restype = wintypes.HWND
GetDesktopWindow.argtypes = [
]
SendInput = windll.user32.SendInput
SendInput.restype = wintypes.UINT
SendInput.argtypes = [
wintypes.UINT,
c_void_p, # using POINTER(win32structures.INPUT) needs rework in keyboard.py
c_int,
]
SetCursorPos = windll.user32.SetCursorPos
SetCursorPos.restype = wintypes.BOOL
SetCursorPos.argtypes = [
c_int,
c_int,
]
GetCursorPos = windll.user32.GetCursorPos
GetCursorPos.restype = wintypes.BOOL
GetCursorPos.argtypes = [
POINTER(wintypes.POINT),
]
GetCaretPos = windll.user32.GetCaretPos
GetCaretPos.restype = wintypes.BOOL
GetCaretPos.argtypes = [
POINTER(wintypes.POINT),
]
GetKeyboardState = windll.user32.GetKeyboardState
GetKeyboardState.restype = wintypes.BOOL
GetKeyboardState.argtypes = [
POINTER(c_ubyte),
]
SetKeyboardState = windll.user32.SetKeyboardState
SetKeyboardState.restype = wintypes.BOOL
SetKeyboardState.argtypes = [
POINTER(c_ubyte),
]
GetKeyboardLayout = windll.user32.GetKeyboardLayout
GetKeyboardLayout.restype = wintypes.HKL
GetKeyboardLayout.argtypes = [
wintypes.DWORD,
]
VkKeyScanW = windll.user32.VkKeyScanW
VkKeyScanW.restype = SHORT
VkKeyScanW.argtypes = [
wintypes.WCHAR,
]
VkKeyScanExW = windll.user32.VkKeyScanExW
VkKeyScanExW.restype = SHORT
VkKeyScanExW.argtypes = [
wintypes.WCHAR,
wintypes.HKL,
]
GetMessageExtraInfo = windll.user32.GetMessageExtraInfo
MapVirtualKeyW = windll.user32.MapVirtualKeyW
# menu functions # menu functions
DrawMenuBar = ctypes.windll.user32.DrawMenuBar DrawMenuBar = windll.user32.DrawMenuBar
GetMenu = ctypes.windll.user32.GetMenu DrawMenuBar.restype = wintypes.BOOL
GetMenuBarInfo = ctypes.windll.user32.GetMenuBarInfo DrawMenuBar.argstype = [
GetMenuInfo = ctypes.windll.user32.GetMenuInfo wintypes.HWND,
GetMenuItemCount = ctypes.windll.user32.GetMenuItemCount ]
GetMenuItemInfo = ctypes.windll.user32.GetMenuItemInfoW GetMenu = windll.user32.GetMenu
SetMenuItemInfo = ctypes.windll.user32.SetMenuItemInfoW GetMenu.restype = wintypes.HMENU
GetMenuItemRect = ctypes.windll.user32.GetMenuItemRect GetMenu.argtypes = [
CheckMenuItem = ctypes.windll.user32.CheckMenuItem wintypes.HWND,
GetMenuState = ctypes.windll.user32.GetMenuState ]
GetSubMenu = ctypes.windll.user32.GetSubMenu GetMenuBarInfo = windll.user32.GetMenuBarInfo
GetSystemMenu = ctypes.windll.user32.GetSystemMenu GetMenuBarInfo.restype = wintypes.BOOL
HiliteMenuItem = ctypes.windll.user32.HiliteMenuItem GetMenuBarInfo.argtypes = [
IsMenu = ctypes.windll.user32.IsMenu wintypes.HWND,
MenuItemFromPoint = ctypes.windll.user32.MenuItemFromPoint wintypes.LONG,
wintypes.LONG,
BringWindowToTop = ctypes.windll.user32.BringWindowToTop POINTER(win32structures.MENUBARINFO),
]
GetVersion = ctypes.windll.kernel32.GetVersion GetMenuInfo = windll.user32.GetMenuInfo
GetMenuInfo.restype = wintypes.BOOL
GetParent = ctypes.windll.user32.GetParent GetMenuInfo.argtypes = [
GetWindow = ctypes.windll.user32.GetWindow wintypes.HWND,
ShowWindow = ctypes.windll.user32.ShowWindow POINTER(win32structures.MENUINFO),
GetWindowContextHelpId = ctypes.windll.user32.GetWindowContextHelpId ]
GetWindowLong = ctypes.windll.user32.GetWindowLongW GetMenuItemCount = windll.user32.GetMenuItemCount
GetWindowPlacement = ctypes.windll.user32.GetWindowPlacement GetMenuItemCount.restype = c_int
GetWindowRect = ctypes.windll.user32.GetWindowRect GetMenuItemCount.argtypes = [
GetWindowText = ctypes.windll.user32.GetWindowTextW wintypes.HMENU,
GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW ]
GetClassName = ctypes.windll.user32.GetClassNameW GetMenuItemInfo = windll.user32.GetMenuItemInfoW
GetClassName.argtypes = [win32structures.HWND, wintypes.LPWSTR, ctypes.c_int] GetMenuItemInfo.restype = wintypes.BOOL
GetClassName.restrype = ctypes.c_int GetMenuItemInfo.argtypes = [
GetClientRect = ctypes.windll.user32.GetClientRect wintypes.HMENU,
IsChild = ctypes.windll.user32.IsChild wintypes.UINT,
IsWindow = ctypes.windll.user32.IsWindow wintypes.BOOL,
IsWindow.argtypes = [win32structures.HWND] POINTER(win32structures.MENUITEMINFOW),
IsWindow.restype = win32structures.BOOL ]
IsWindowUnicode = ctypes.windll.user32.IsWindowUnicode SetMenuItemInfo = windll.user32.SetMenuItemInfoW
IsWindowUnicode.argtypes = [win32structures.HWND] SetMenuItemInfo.restype = wintypes.BOOL
IsWindowUnicode.restype = win32structures.BOOL SetMenuItemInfo.argtypes = [
IsWindowVisible = ctypes.windll.user32.IsWindowVisible wintypes.HMENU,
IsWindowVisible.argtypes = [win32structures.HWND] wintypes.UINT,
IsWindowVisible.restype = win32structures.BOOL wintypes.BOOL,
IsWindowEnabled = ctypes.windll.user32.IsWindowEnabled POINTER(win32structures.MENUITEMINFOW),
IsWindowEnabled.argtypes = [win32structures.HWND] ]
IsWindowEnabled.restype = win32structures.BOOL GetMenuItemRect = windll.user32.GetMenuItemRect
ClientToScreen = ctypes.windll.user32.ClientToScreen GetMenuItemRect.restype = wintypes.BOOL
ScreenToClient = ctypes.windll.user32.ScreenToClient GetMenuItemRect.argtypes = [
wintypes.HWND,
GetCurrentThreadId = ctypes.windll.Kernel32.GetCurrentThreadId wintypes.HMENU,
GetWindowThreadProcessId = ctypes.windll.user32.GetWindowThreadProcessId wintypes.UINT,
GetGUIThreadInfo = ctypes.windll.user32.GetGUIThreadInfo POINTER(wintypes.RECT),
AttachThreadInput = ctypes.windll.user32.AttachThreadInput ]
AttachThreadInput.restype = win32structures.BOOL CheckMenuItem = windll.user32.CheckMenuItem
AttachThreadInput.argtypes = [win32structures.DWORD, win32structures.DWORD, win32structures.BOOL] CheckMenuItem.restype = wintypes.DWORD
#GetWindowThreadProcessId = ctypes.windll.user32.GetWindowThreadProcessId CheckMenuItem.argtypes = [
GetLastError = ctypes.windll.kernel32.GetLastError wintypes.HMENU,
wintypes.UINT,
OpenProcess = ctypes.windll.kernel32.OpenProcess wintypes.UINT,
CloseHandle = ctypes.windll.kernel32.CloseHandle ]
CreateProcess = ctypes.windll.kernel32.CreateProcessW GetMenuState = windll.user32.GetMenuState
TerminateProcess = ctypes.windll.kernel32.TerminateProcess GetMenuState.restype = wintypes.UINT
ExitProcess = ctypes.windll.kernel32.ExitProcess GetMenuState.argtypes = [
wintypes.HMENU,
ReadProcessMemory = ctypes.windll.kernel32.ReadProcessMemory wintypes.UINT,
GlobalAlloc = ctypes.windll.kernel32.GlobalAlloc wintypes.UINT,
GlobalLock = ctypes.windll.kernel32.GlobalLock ]
GlobalUnlock = ctypes.windll.kernel32.GlobalUnlock GetSubMenu = windll.user32.GetSubMenu
GetSubMenu.restype = wintypes.HMENU
SendMessage = ctypes.windll.user32.SendMessageW GetSubMenu.argtypes = [
SendMessageTimeout = ctypes.windll.user32.SendMessageTimeoutW wintypes.HMENU,
SendMessageTimeout.argtypes = [win32structures.HWND, win32structures.UINT, win32structures.WPARAM, c_int,
win32structures.LPARAM, win32structures.UINT, win32structures.UINT, ]
win32structures.PDWORD_PTR] GetSystemMenu = windll.user32.GetSystemMenu
SendMessageTimeout.restype = win32structures.LRESULT GetSystemMenu.restype = wintypes.HMENU
SendMessageA = ctypes.windll.user32.SendMessageA GetSystemMenu.argtypes = [
PostMessage = ctypes.windll.user32.PostMessageW wintypes.HWND,
GetMessage = ctypes.windll.user32.GetMessageW wintypes.BOOL,
RegisterWindowMessage = ctypes.windll.user32.RegisterWindowMessageW ]
RegisterWindowMessage.restype = UINT HiliteMenuItem = windll.user32.HiliteMenuItem
HiliteMenuItem.restype = wintypes.BOOL
MoveWindow = ctypes.windll.user32.MoveWindow HiliteMenuItem.argtypes = [
EnableWindow = ctypes.windll.user32.EnableWindow wintypes.HWND,
SetActiveWindow = ctypes.windll.user32.SetActiveWindow wintypes.HMENU,
GetFocus = ctypes.windll.user32.GetFocus wintypes.UINT,
SetFocus = ctypes.windll.user32.SetFocus wintypes.UINT,
SetForegroundWindow = ctypes.windll.user32.SetForegroundWindow ]
GetForegroundWindow = ctypes.windll.user32.GetForegroundWindow IsMenu = windll.user32.IsMenu
SetWindowLong = ctypes.windll.user32.SetWindowLongW IsMenu.restype = wintypes.BOOL
IsMenu.argtypes = [
wintypes.HMENU,
]
MenuItemFromPoint = windll.user32.MenuItemFromPoint
MenuItemFromPoint.restype = c_int
MenuItemFromPoint.argtypes = [
wintypes.HWND,
wintypes.HMENU,
POINTER(wintypes.POINT),
]
BringWindowToTop = windll.user32.BringWindowToTop
BringWindowToTop.restype = wintypes.BOOL
BringWindowToTop.argtypes = [
wintypes.HWND,
]
GetParent = windll.user32.GetParent
GetParent.restype = wintypes.HWND
GetParent.argtypes = [
wintypes.HWND,
]
GetWindow = windll.user32.GetWindow
GetWindow.restype = wintypes.HWND
GetWindow.argtypes = [
wintypes.HWND,
wintypes.UINT,
]
ShowWindow = windll.user32.ShowWindow
ShowWindow.restype = wintypes.BOOL
ShowWindow.argtypes = [
wintypes.HWND,
c_int,
]
GetWindowContextHelpId = windll.user32.GetWindowContextHelpId
GetWindowContextHelpId.restype = wintypes.DWORD
GetWindowContextHelpId.argtypes = [
wintypes.HWND,
]
GetWindowLong = windll.user32.GetWindowLongW
GetWindowLong.restype = wintypes.LONG
GetWindowLong.argtypes = [
wintypes.HWND,
c_int,
]
GetWindowPlacement = windll.user32.GetWindowPlacement
GetWindowPlacement.restype = wintypes.BOOL
GetWindowPlacement.argtypes = [
wintypes.HWND,
POINTER(win32structures.WINDOWPLACEMENT),
]
GetWindowRect = windll.user32.GetWindowRect
GetWindowRect.restype = wintypes.BOOL
GetWindowRect.argtypes = [
wintypes.HWND,
POINTER(wintypes.RECT),
]
GetWindowText = windll.user32.GetWindowTextW
GetWindowText.restype = c_int
GetWindowText.argtypes = [
wintypes.HWND,
wintypes.LPWSTR,
c_int,
]
GetWindowTextLength = windll.user32.GetWindowTextLengthW
GetWindowTextLength.restype = c_int
GetWindowTextLength.argtypes = [
wintypes.HWND,
]
GetClassName = windll.user32.GetClassNameW
GetClassName.restype = c_int
GetClassName.argtypes = [
wintypes.HWND,
wintypes.LPWSTR,
c_int,
]
GetClientRect = windll.user32.GetClientRect
GetClientRect.restype = wintypes.BOOL
GetClientRect.argtypes = [
wintypes.HWND,
POINTER(wintypes.RECT),
]
IsChild = windll.user32.IsChild
IsChild.restype = wintypes.BOOL
IsChild.argtypes = [
wintypes.HWND,
wintypes.HWND,
]
IsWindow = windll.user32.IsWindow
IsWindow.restype = wintypes.BOOL
IsWindow.argtypes = [
wintypes.HWND,
]
IsWindowUnicode = windll.user32.IsWindowUnicode
IsWindowUnicode.restype = wintypes.BOOL
IsWindowUnicode.argtypes = [
wintypes.HWND,
]
IsWindowVisible = windll.user32.IsWindowVisible
IsWindowVisible.restype = wintypes.BOOL
IsWindowVisible.argtypes = [
wintypes.HWND,
]
IsWindowEnabled = windll.user32.IsWindowEnabled
IsWindowEnabled.restype = wintypes.BOOL
IsWindowEnabled.argtypes = [
wintypes.HWND,
]
ClientToScreen = windll.user32.ClientToScreen
ClientToScreen.restype = wintypes.BOOL
ClientToScreen.argtypes = [
wintypes.HWND,
POINTER(wintypes.POINT),
]
ScreenToClient = windll.user32.ScreenToClient
ScreenToClient.restype = wintypes.BOOL
ScreenToClient.argtypes = [
wintypes.HWND,
POINTER(wintypes.POINT),
]
GetCurrentThreadId = windll.kernel32.GetCurrentThreadId
GetCurrentThreadId.restype = wintypes.DWORD
GetCurrentThreadId.argtypes = [
]
GetWindowThreadProcessId = windll.user32.GetWindowThreadProcessId
GetWindowThreadProcessId.restype = wintypes.DWORD
GetWindowThreadProcessId.argtypes = [
wintypes.HWND,
POINTER(wintypes.DWORD),
]
GetGUIThreadInfo = windll.user32.GetGUIThreadInfo
GetGUIThreadInfo.restype = wintypes.BOOL
GetGUIThreadInfo.argtypes = [
wintypes.DWORD,
POINTER(win32structures.GUITHREADINFO),
]
AttachThreadInput = windll.user32.AttachThreadInput
AttachThreadInput.restype = wintypes.BOOL
AttachThreadInput.argtypes = [
wintypes.DWORD,
wintypes.DWORD,
wintypes.BOOL
]
OpenProcess = windll.kernel32.OpenProcess
OpenProcess.restype = wintypes.HANDLE
OpenProcess.argtypes = [
wintypes.DWORD,
wintypes.BOOL,
wintypes.DWORD,
]
CloseHandle = windll.kernel32.CloseHandle
CloseHandle.restype = wintypes.BOOL
CloseHandle.argtypes = [
wintypes.HANDLE,
]
CreateProcess = windll.kernel32.CreateProcessW
CreateProcess.restype = wintypes.BOOL
CreateProcess.argtypes = [
wintypes.LPCWSTR,
wintypes.LPWSTR,
POINTER(win32structures.SECURITY_ATTRIBUTES),
POINTER(win32structures.SECURITY_ATTRIBUTES),
wintypes.BOOL,
wintypes.DWORD,
wintypes.LPVOID,
wintypes.LPCWSTR,
POINTER(win32structures.STARTUPINFOW),
POINTER(win32structures.PROCESS_INFORMATION),
]
TerminateProcess = windll.kernel32.TerminateProcess
TerminateProcess.restype = wintypes.BOOL
TerminateProcess.argtypes = [
wintypes.HANDLE,
wintypes.UINT,
]
ExitProcess = windll.kernel32.ExitProcess
ExitProcess.restype = None
ExitProcess.argtypes = [
wintypes.UINT,
]
ReadProcessMemory = windll.kernel32.ReadProcessMemory
ReadProcessMemory.restype = wintypes.BOOL
ReadProcessMemory.argtypes = [
wintypes.HANDLE,
wintypes.LPVOID,
wintypes.LPVOID,
c_size_t,
POINTER(c_size_t),
]
GlobalAlloc = windll.kernel32.GlobalAlloc
GlobalLock = windll.kernel32.GlobalLock
GlobalUnlock = windll.kernel32.GlobalUnlock
SendMessage = windll.user32.SendMessageW
SendMessage.restype = wintypes.LPARAM
SendMessage.argtypes = [
wintypes.HWND,
wintypes.UINT,
wintypes.WPARAM,
wintypes.LPVOID,
]
SendMessageTimeout = windll.user32.SendMessageTimeoutW
SendMessageTimeout.restype = wintypes.LPARAM
SendMessageTimeout.argtypes = [
wintypes.HWND,
wintypes.UINT,
wintypes.WPARAM,
wintypes.LPARAM,
wintypes.UINT,
wintypes.UINT,
win32structures.PDWORD_PTR,
]
PostMessage = windll.user32.PostMessageW
PostMessage.restype = wintypes.BOOL
PostMessage.argtypes = [
wintypes.HWND,
wintypes.UINT,
wintypes.WPARAM,
wintypes.LPARAM,
]
GetMessage = windll.user32.GetMessageW
GetMessage.restype = wintypes.BOOL
GetMessage.argtypes = [
POINTER(wintypes.MSG),
wintypes.HWND,
wintypes.UINT,
wintypes.UINT,
]
RegisterWindowMessage = windll.user32.RegisterWindowMessageW
RegisterWindowMessage.restype = wintypes.UINT
RegisterWindowMessage.argtypes = [
wintypes.LPCWSTR,
]
MoveWindow = windll.user32.MoveWindow
MoveWindow.restype = wintypes.BOOL
MoveWindow.argtypes = [
wintypes.HWND,
c_int,
c_int,
c_int,
c_int,
wintypes.BOOL,
]
EnableWindow = windll.user32.EnableWindow
EnableWindow.restype = wintypes.BOOL
EnableWindow.argtypes = [
wintypes.HWND,
wintypes.BOOL,
]
SetFocus = windll.user32.SetFocus
SetFocus.restype = wintypes.HWND
SetFocus.argtypes = [
wintypes.HWND,
]
SetWindowLong = windll.user32.SetWindowLongW
SetWindowLong.restype = wintypes.LONG
SetWindowLong.argtypes = [
wintypes.HWND,
c_int,
wintypes.LONG,
]
try: try:
SetWindowLongPtr = ctypes.windll.user32.SetWindowLongPtrW SetWindowLongPtr = windll.user32.SetWindowLongPtrW
SetWindowLongPtr.argtypes = [win32structures.HWND, ctypes.c_int, win32structures.LONG_PTR] SetWindowLongPtr.argtypes = [wintypes.HWND, c_int, wintypes.LONG_PTR]
SetWindowLongPtr.restype = win32structures.LONG_PTR SetWindowLongPtr.restype = wintypes.LONG_PTR
except AttributeError: except AttributeError:
SetWindowLongPtr = SetWindowLong SetWindowLongPtr = SetWindowLong
SystemParametersInfo = ctypes.windll.user32.SystemParametersInfoW SystemParametersInfo = windll.user32.SystemParametersInfoW
VirtualAllocEx = ctypes.windll.kernel32.VirtualAllocEx SystemParametersInfo.restype = wintypes.UINT
VirtualAllocEx.restype = ctypes.c_void_p SystemParametersInfo.argtypes = [
VirtualFreeEx = ctypes.windll.kernel32.VirtualFreeEx wintypes.UINT,
DebugBreakProcess = ctypes.windll.kernel32.DebugBreakProcess wintypes.UINT,
wintypes.LPVOID, # should map well to PVOID
VirtualAlloc = ctypes.windll.kernel32.VirtualAlloc wintypes.UINT,
VirtualFree = ctypes.windll.kernel32.VirtualFree ]
WriteProcessMemory = ctypes.windll.kernel32.WriteProcessMemory VirtualAllocEx = windll.kernel32.VirtualAllocEx
GetActiveWindow = ctypes.windll.user32.GetActiveWindow VirtualAllocEx.restype = wintypes.LPVOID
GetLastActivePopup = ctypes.windll.user32.GetLastActivePopup VirtualAllocEx.argtypes = [
FindWindow = ctypes.windll.user32.FindWindowW wintypes.HANDLE,
GetTopWindow = ctypes.windll.user32.GetTopWindow wintypes.LPVOID,
c_size_t,
SetCapture = ctypes.windll.user32.SetCapture wintypes.DWORD,
ReleaseCapture = ctypes.windll.user32.ReleaseCapture wintypes.DWORD,
]
ShowOwnedPopups = ctypes.windll.user32.ShowOwnedPopups VirtualFreeEx = windll.kernel32.VirtualFreeEx
WindowFromPoint = ctypes.windll.user32.WindowFromPoint VirtualFreeEx.restype = wintypes.BOOL
VirtualFreeEx.argtypes = [
WideCharToMultiByte = ctypes.windll.kernel32.WideCharToMultiByte wintypes.HANDLE,
GetACP = ctypes.windll.kernel32.GetACP wintypes.LPVOID,
c_size_t,
WaitForSingleObject = ctypes.windll.kernel32.WaitForSingleObject wintypes.DWORD,
WaitForInputIdle = ctypes.windll.user32.WaitForInputIdle ]
VirtualAlloc = windll.kernel32.VirtualAlloc
IsHungAppWindow = ctypes.windll.user32.IsHungAppWindow VirtualAlloc.restype = wintypes.LPVOID
IsHungAppWindow.restype = win32structures.BOOL VirtualAlloc.argtypes = [
IsHungAppWindow.argtypes = [win32structures.HWND] wintypes.LPVOID,
c_size_t,
GetModuleFileNameEx = ctypes.windll.psapi.GetModuleFileNameExW wintypes.DWORD,
wintypes.DWORD,
GetClipboardData = ctypes.windll.user32.GetClipboardData ]
OpenClipboard = ctypes.windll.user32.OpenClipboard VirtualFree = windll.kernel32.VirtualFree
EmptyClipboard = ctypes.windll.user32.EmptyClipboard VirtualFree.retype = wintypes.BOOL
CloseClipboard = ctypes.windll.user32.CloseClipboard VirtualFree.argtypes = [
CountClipboardFormats = ctypes.windll.user32.CountClipboardFormats wintypes.LPVOID,
EnumClipboardFormats = ctypes.windll.user32.EnumClipboardFormats c_size_t,
GetClipboardFormatName = ctypes.windll.user32.GetClipboardFormatNameW wintypes.DWORD,
]
WriteProcessMemory = windll.kernel32.WriteProcessMemory
WriteProcessMemory.restype = wintypes.BOOL
WriteProcessMemory.argtypes = [
wintypes.HANDLE,
wintypes.LPVOID,
wintypes.LPVOID,
c_size_t,
POINTER(c_size_t),
]
ReleaseCapture = windll.user32.ReleaseCapture
ReleaseCapture.restype = wintypes.BOOL
ReleaseCapture.argtypes = [
]
WindowFromPoint = windll.user32.WindowFromPoint
WindowFromPoint.restype = wintypes.HWND
WindowFromPoint.argtypes = [
wintypes.POINT,
]
WaitForSingleObject = windll.kernel32.WaitForSingleObject
WaitForSingleObject.restype = wintypes.DWORD
WaitForSingleObject.argtypes = [
wintypes.HANDLE,
wintypes.DWORD,
]
WaitForInputIdle = windll.user32.WaitForInputIdle
WaitForInputIdle.restype = wintypes.DWORD
WaitForInputIdle.argtypes = [
wintypes.HANDLE,
wintypes.DWORD,
]
IsHungAppWindow = windll.user32.IsHungAppWindow
IsHungAppWindow.restype = wintypes.BOOL
IsHungAppWindow.argtypes = [
wintypes.HWND,
]
GetModuleFileNameEx = windll.psapi.GetModuleFileNameExW
GetModuleFileNameEx.restype = wintypes.DWORD
GetModuleFileNameEx.argtypes = [
wintypes.HANDLE,
wintypes.HMODULE,
wintypes.LPWSTR,
wintypes.DWORD,
]
GetClipboardData = windll.user32.GetClipboardData
GetClipboardData.restype = wintypes.HANDLE
GetClipboardData.argtypes = [
wintypes.UINT,
]
OpenClipboard = windll.user32.OpenClipboard
OpenClipboard.restype = wintypes.BOOL
OpenClipboard.argtypes = [
wintypes.HWND,
]
EmptyClipboard = windll.user32.EmptyClipboard
EmptyClipboard.restype = wintypes.BOOL
EmptyClipboard.argtypes = [
]
CloseClipboard = windll.user32.CloseClipboard
CloseClipboard.restype = wintypes.BOOL
CloseClipboard.argtypes = [
]
CountClipboardFormats = windll.user32.CountClipboardFormats
CountClipboardFormats.restype = c_int
CountClipboardFormats.argtypes = [
]
EnumClipboardFormats = windll.user32.EnumClipboardFormats
EnumClipboardFormats.restype = wintypes.UINT
EnumClipboardFormats.argtypes = [
wintypes.UINT,
]
GetClipboardFormatName = windll.user32.GetClipboardFormatNameW
GetClipboardFormatName.restype = c_int
GetClipboardFormatName.argtypes = [
wintypes.UINT,
wintypes.LPWSTR,
c_int,
]
# DPIAware API funcs are not available on WinXP # DPIAware API funcs are not available on WinXP
try: try:
IsProcessDPIAware = ctypes.windll.user32.IsProcessDPIAware IsProcessDPIAware = windll.user32.IsProcessDPIAware
SetProcessDPIAware = ctypes.windll.user32.SetProcessDPIAware SetProcessDPIAware = windll.user32.SetProcessDPIAware
except AttributeError: except AttributeError:
IsProcessDPIAware = None IsProcessDPIAware = None
SetProcessDPIAware = None SetProcessDPIAware = None
@ -230,7 +716,7 @@ except AttributeError:
# Process_Per_Monitor_DPI_Aware = 2 # Process_Per_Monitor_DPI_Aware = 2
# } Process_DPI_Awareness; # } Process_DPI_Awareness;
try: try:
shcore = ctypes.windll.LoadLibrary("Shcore.dll") shcore = windll.LoadLibrary("Shcore.dll")
SetProcessDpiAwareness = shcore.SetProcessDpiAwareness SetProcessDpiAwareness = shcore.SetProcessDpiAwareness
GetProcessDpiAwareness = shcore.GetProcessDpiAwareness GetProcessDpiAwareness = shcore.GetProcessDpiAwareness
Process_DPI_Awareness = { Process_DPI_Awareness = {
@ -252,26 +738,17 @@ elif SetProcessDPIAware:
ActionLogger().log("Call SetProcessDPIAware") ActionLogger().log("Call SetProcessDPIAware")
SetProcessDPIAware() SetProcessDPIAware()
GetQueueStatus = ctypes.windll.user32.GetQueueStatus GetQueueStatus = windll.user32.GetQueueStatus
LoadString = ctypes.windll.user32.LoadStringW LoadString = windll.user32.LoadStringW
#def VkKeyScanW(p1):
# # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4225
# return VkKeyScanW._api_(p1)
#VkKeyScan = stdcall(SHORT, 'user32', [c_wchar]) (VkKeyScanW)
#
#def MapVirtualKeyExW(p1, p2, p3): #def MapVirtualKeyExW(p1, p2, p3):
# # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4376 # # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4376
# return MapVirtualKeyExW._api_(p1, p2, p3) # return MapVirtualKeyExW._api_(p1, p2, p3)
#MapVirtualKeyEx = stdcall( #MapVirtualKeyEx = stdcall(
# UINT, 'user32', [c_uint, c_uint, c_long]) (MapVirtualKeyExW) # UINT, 'user32', [c_uint, c_uint, c_long]) (MapVirtualKeyExW)
# #
#def MapVirtualKeyW(p1, p2):
# # C:/PROGRA~1/MICROS~4/VC98/Include/winuser.h 4355
# return MapVirtualKeyW._api_(p1, p2)
#MapVirtualKey = stdcall(UINT, 'user32', [c_uint, c_uint]) (MapVirtualKeyW)
#==================================================================== #====================================================================
@ -297,7 +774,7 @@ def LoWord(value):
def WaitGuiThreadIdle(handle): def WaitGuiThreadIdle(handle):
"""Wait until the thread of the specified handle is ready""" """Wait until the thread of the specified handle is ready"""
process_id = wintypes.DWORD(0) process_id = wintypes.DWORD(0)
GetWindowThreadProcessId(handle, ctypes.POINTER(wintypes.DWORD)(process_id)) GetWindowThreadProcessId(handle, byref(process_id))
# ask the control if it has finished processing the message # ask the control if it has finished processing the message
hprocess = OpenProcess( hprocess = OpenProcess(
@ -327,10 +804,10 @@ def GetDpiAwarenessByPid(pid):
return dpi_awareness return dpi_awareness
try: try:
dpi_awareness = ctypes.c_int() dpi_awareness = c_int()
hRes = GetProcessDpiAwareness( hRes = GetProcessDpiAwareness(
hProcess, hProcess,
ctypes.byref(dpi_awareness)) byref(dpi_awareness))
CloseHandle(hProcess) CloseHandle(hProcess)
if hRes == 0: if hRes == 0:
return dpi_awareness.value return dpi_awareness.value

@ -32,19 +32,18 @@
"""Definition of Windows structures""" """Definition of Windows structures"""
import six import six
import ctypes from ctypes import Structure as Struct
from ctypes import \ from ctypes import \
c_int, c_uint, c_long, c_ulong, c_void_p, c_wchar, c_char, \ c_int, c_long, c_void_p, c_char, memmove, addressof, \
c_ubyte, c_ushort, \
POINTER, sizeof, alignment, Union, c_longlong, c_size_t, wintypes POINTER, sizeof, alignment, Union, c_longlong, c_size_t, wintypes
from .win32defines import LF_FACESIZE from .win32defines import LF_FACESIZE
from . import sysinfo from . import sysinfo
class Structure(ctypes.Structure): class StructureMixIn(object):
"""Override the Structure class from ctypes to add printing and comparison""" """Define printing and comparison behaviors to be used for the Structure class from ctypes"""
#---------------------------------------------------------------- #----------------------------------------------------------------
def __str__(self): def __str__(self):
@ -52,47 +51,59 @@ class Structure(ctypes.Structure):
fields in exceptList will not be printed""" fields in exceptList will not be printed"""
lines = [] lines = []
for f in self._fields_: for field_name, _ in getattr(self, "_fields_", []):
name = f[0] lines.append("%20s\t%s"% (field_name, getattr(self, field_name)))
lines.append("%20s\t%s"% (name, getattr(self, name)))
return "\n".join(lines) return "\n".join(lines)
#---------------------------------------------------------------- #----------------------------------------------------------------
def __eq__(self, other_struct): def __eq__(self, other):
"""Return True if the two structures have the same coordinates""" """Return True if the two instances have the same coordinates"""
if isinstance(other_struct, ctypes.Structure): fields = getattr(self, "_fields_", [])
if isinstance(other, Struct):
try: try:
# pretend they are two structures - check that they both # pretend they are two structures - check that they both
# have the same value for all fields # have the same value for all fields
are_equal = True if len(fields) != len(getattr(other, "_fields_", [])):
for field in self._fields_: return False
name = field[0] for field_name, _ in fields:
if getattr(self, name) != getattr(other_struct, name): if getattr(self, field_name) != getattr(other, field_name):
are_equal = False return False
break return True
return are_equal
except AttributeError: except AttributeError:
return False return False
if isinstance(other_struct, (list, tuple)): elif isinstance(other, (list, tuple)):
# Now try to see if we have been passed in a list or tuple # Now try to see if we have been passed in a list or tuple
if len(fields) != len(other):
return False
try: try:
are_equal = True for i, (field_name, _) in enumerate(fields):
for i, field in enumerate(self._fields_): if getattr(self, field_name) != other[i]:
name = field[0] return False
if getattr(self, name) != other_struct[i]: return True
are_equal = False
break
return are_equal
except Exception: except Exception:
return False return False
return False return False
#----------------------------------------------------------------
def __ne__(self, other):
"""Return False if the two instances have the same coordinates"""
return not self.__eq__(other)
__hash__ = None
class Structure(Struct, StructureMixIn):
"""Override the Structure class from ctypes to add printing and comparison"""
pass
##==================================================================== ##====================================================================
#def PrintCtypesStruct(struct, exceptList = []): #def PrintCtypesStruct(struct, exceptList = []):
# """Print out the fields of the ctypes Structure # """Print out the fields of the ctypes Structure
@ -110,7 +121,7 @@ class Structure(ctypes.Structure):
# e.g. RECT.__reduce__ = _reduce # e.g. RECT.__reduce__ = _reduce
def _construct(typ, buf): def _construct(typ, buf):
obj = typ.__new__(typ) obj = typ.__new__(typ)
ctypes.memmove(ctypes.addressof(obj), buf, len(buf)) memmove(addressof(obj), buf, len(buf))
return obj return obj
def _reduce(self): def _reduce(self):
@ -119,21 +130,21 @@ def _reduce(self):
#LPTTTOOLINFOW = POINTER(tagTOOLINFOW) #LPTTTOOLINFOW = POINTER(tagTOOLINFOW)
#PTOOLINFOW = POINTER(tagTOOLINFOW) #PTOOLINFOW = POINTER(tagTOOLINFOW)
BOOL = c_int BOOL = wintypes.BOOL
BYTE = c_ubyte BYTE = wintypes.BYTE
CHAR = c_char CHAR = c_char
DWORD = c_ulong DWORD = wintypes.DWORD
HANDLE = c_void_p HANDLE = wintypes.HANDLE
HBITMAP = c_long HBITMAP = HANDLE
LONG = c_long LONG = wintypes.LONG
LPVOID = c_void_p LPVOID = wintypes.LPVOID
PVOID = c_void_p PVOID = c_void_p
UINT = c_uint UINT = wintypes.UINT
WCHAR = c_wchar WCHAR = wintypes.WCHAR
WORD = c_ushort WORD = wintypes.WORD
LRESULT = wintypes.LPARAM LRESULT = wintypes.LPARAM
COLORREF = DWORD COLORREF = wintypes.COLORREF
LPBYTE = POINTER(BYTE) LPBYTE = POINTER(BYTE)
LPWSTR = c_size_t #POINTER(WCHAR) LPWSTR = c_size_t #POINTER(WCHAR)
DWORD_PTR = UINT_PTR = ULONG_PTR = c_size_t DWORD_PTR = UINT_PTR = ULONG_PTR = c_size_t
@ -143,26 +154,20 @@ if sysinfo.is_x64_Python():
else: else:
INT_PTR = LONG_PTR = c_long INT_PTR = LONG_PTR = c_long
HBITMAP = LONG_PTR #LONG
HINSTANCE = LONG_PTR #LONG HINSTANCE = LONG_PTR #LONG
HMENU = LONG_PTR #LONG HMENU = LONG_PTR #LONG
HBRUSH = LONG_PTR #LONG HBRUSH = wintypes.HBRUSH # LONG_PTR #LONG
HTREEITEM = LONG_PTR #LONG HTREEITEM = LONG_PTR #LONG
HWND = LONG_PTR #LONG HWND = wintypes.HWND
# TODO: switch to ctypes.wintypes.LPARAM and ctypes.wintypes.WPARAM
# Notice that wintypes definition of LPARAM/WPARAM differs between 32/64 bit # Notice that wintypes definition of LPARAM/WPARAM differs between 32/64 bit
LPARAM = LONG_PTR LPARAM = wintypes.LPARAM
WPARAM = UINT_PTR WPARAM = wintypes.WPARAM
class POINT(Structure): class POINT(wintypes.POINT, StructureMixIn):
_pack_ = 4
_fields_ = [ """Wrap the POINT structure and add extra functionality"""
# C:/PROGRA~1/MIAF9D~1/VC98/Include/windef.h 307
('x', LONG),
('y', LONG),
]
def __iter__(self): def __iter__(self):
"""Allow iteration through coordinates""" """Allow iteration through coordinates"""
@ -178,25 +183,18 @@ class POINT(Structure):
else: else:
raise IndexError("Illegal index") raise IndexError("Illegal index")
assert sizeof(POINT) == 8, sizeof(POINT) assert sizeof(POINT) == 8, sizeof(POINT)
assert alignment(POINT) == 4, alignment(POINT) assert alignment(POINT) == 4, alignment(POINT)
# ==================================================================== # ====================================================================
class RECT(Structure): class RECT(wintypes.RECT, StructureMixIn):
"""Wrap the RECT structure and add extra functionality""" """Wrap the RECT structure and add extra functionality"""
_fields_ = [
# C:/PROGRA~1/MIAF9D~1/VC98/Include/windef.h 287
('left', LONG),
('top', LONG),
('right', LONG),
('bottom', LONG),
]
# ---------------------------------------------------------------- # ----------------------------------------------------------------
def __init__(self, otherRect_or_left = 0, top = 0, right = 0, bottom = 0): def __init__(self, otherRect_or_left=0, top=0, right=0, bottom=0):
"""Provide a constructor for RECT structures """Provide a constructor for RECT structures
A RECT can be constructed by: A RECT can be constructed by:
@ -220,20 +218,6 @@ class RECT(Structure):
self.top = long_int(top) self.top = long_int(top)
self.bottom = long_int(bottom) self.bottom = long_int(bottom)
# # ----------------------------------------------------------------
# def __eq__(self, otherRect):
# "return true if the two rectangles have the same coordinates"
#
# try:
# return \
# self.left == otherRect.left and \
# self.top == otherRect.top and \
# self.right == otherRect.right and \
# self.bottom == otherRect.bottom
# except AttributeError:
# return False
# ---------------------------------------------------------------- # ----------------------------------------------------------------
def __str__(self): def __str__(self):
"""Return a string representation of the RECT""" """Return a string representation of the RECT"""
@ -286,18 +270,17 @@ class RECT(Structure):
def mid_point(self): def mid_point(self):
"""Return a POINT structure representing the mid point""" """Return a POINT structure representing the mid point"""
pt = POINT() pt = POINT()
pt.x = self.left + int(float(self.width())/2.) pt.x = self.left + int(float(self.width()) / 2.)
pt.y = self.top + int(float(self.height())/2.) pt.y = self.top + int(float(self.height()) / 2.)
return pt return pt
#def __hash__(self): __reduce__ = _reduce
# return hash (self.left, self.top, self.right, self.bottom)
RECT.__reduce__ = _reduce
assert sizeof(RECT) == 16, sizeof(RECT) assert sizeof(RECT) == 16, sizeof(RECT)
assert alignment(RECT) == 4, alignment(RECT) assert alignment(RECT) == 4, alignment(RECT)
class SETTEXTEX(Structure): class SETTEXTEX(Structure):
_pack_ = 1 _pack_ = 1
_fields_ = [ _fields_ = [

@ -3,7 +3,7 @@ r"""
The OpenRPA package (from UnicodeLabs) The OpenRPA package (from UnicodeLabs)
""" """
__version__ = 'v1.1.12' __version__ = 'v1.1.13'
__all__ = [] __all__ = []
__author__ = 'Ivan Maslov <ivan.maslov@unicodelabs.ru>' __author__ = 'Ivan Maslov <ivan.maslov@unicodelabs.ru>'
#from .Core import Robot #from .Core import Robot

@ -2,7 +2,7 @@ from setuptools import setup, find_packages
import Version import Version
import os import os
def LongDescriptionRead(): def LongDescriptionRead():
with open('pyOpenRPA/README.md') as f: with open('pyOpenRPA/README.md', "r", encoding="utf-8") as f:
return f.read() return f.read()
#Do pyOpenRPA package __init__ __version__ update #Do pyOpenRPA package __init__ __version__ update
@ -31,18 +31,25 @@ setup(name='pyOpenRPA',
long_description=LongDescriptionRead(), long_description=LongDescriptionRead(),
long_description_content_type='text/markdown', long_description_content_type='text/markdown',
classifiers=[ classifiers=[
'Development Status :: 3 - Alpha', 'Development Status :: 5 - Production/Stable',
'License :: OSI Approved :: MIT License', 'License :: OSI Approved :: MIT License',
'Intended Audience :: Developers',
'Programming Language :: Python',
'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.7',
'Topic :: Software Development :: Libraries :: Python Modules',
'Topic :: Software Development :: Testing',
'Topic :: Software Development :: User Interfaces',
'Topic :: Software Development :: Quality Assurance',
'Topic :: Home Automation'
], ],
keywords='OpenRPA RPA Robot Automation Robotization', keywords='OpenRPA RPA Robot Automation Robotization OpenSource',
url='https://gitlab.com/UnicodeLabs/OpenRPA', url='https://gitlab.com/UnicodeLabs/OpenRPA',
author='Ivan Maslov', author='Ivan Maslov',
author_email='Ivan.Maslov@unicodelabs.ru', author_email='Ivan.Maslov@unicodelabs.ru',
license='MIT', license='MIT',
packages=find_packages(), packages=find_packages(),
install_requires=[ install_requires=[
'pywinauto>=0.6.6','WMI>=1.4.9','pillow>=6.0.0','keyboard>=0.13.3','pyautogui>=0.9.44','pywin32>=224', 'crypto>=1.4.1' 'pywinauto>=0.6.8','WMI>=1.4.9','pillow>=6.0.0','keyboard>=0.13.3','pyautogui>=0.9.44','pywin32>=224', 'crypto>=1.4.1'
], ],
include_package_data=True, include_package_data=True,
#data_files = datafiles, #data_files = datafiles,

Loading…
Cancel
Save