0

I did select an item from a list (using the code bellow), I'm need now to send a ctrl+E. The problem is that somehow the SendKeys method isn't available, I can't use SendKeys('^e'). (This shortcut will edit the selected item in the ditto app)

from pywinauto.application import Application
from pywinauto import findbestmatch
from pywinauto import keyboard  #not sure if I need to import it


ditto=Application().connect(path='Ditto.exe')

#---- print all available methods of the object
print(dir(ditto.ditto.SysListView321.wrapper_object())) #( the list does not contains 'SendKeys')


#-----Find and select the item (containing 'xxx') in the SysListView321
#The list of texts to search through 
texts = ditto.ditto.SysListView321.texts()[1:] #skip window text itself, use only item texts

# The list of items corresponding (1 to 1) to the list of texts to search through.
items = ditto.ditto.SysListView321.items()   #>>[]    
found_item = findbestmatch.find_best_match('xxx', texts, items, limit_ratio=0.1).Select()

Some Errors:

ditto.ditto.SysListView321.SendKeys('^e')

... WindowSpecification class has no 'SendKeys' method

ditto.ditto.SysListView321.keyboard.SendKeys('^e')

... findbestmatch.MatchError: Could not find 'keyboard' in 'dict_keys(['', 'Header'])'

[EDIT] (More errors)

ditto.ditto.SysListView321.type_keys('^e')

win32gui.SetForegroundWindow(self.handle) pywintypes.error: (0, 'SetForegroundWindow', 'No error message is available')

 keyboard.send_keys('^e')

AttributeError: module 'pywinauto.keyboard' has no attribute 'send_keys'


(Ps. for beginners: app.Ditto is equivalent to app.window(best_match='Ditto') )

J. Does
  • 785
  • 3
  • 10
  • 23

2 Answers2

2

For the specified UI element this method is

# it will activate target window if it's not in focus
ditto.ditto.SysListView321.type_keys('^e')

but

keyboard.SendKeys('^e') # should work also if you don't change active window

It can be used without binding to any specific control.

So you shouldn't try using module name (like keyboard) as an attribute name of any object. It's Python. Just learn Python basics and you will understand pywinauto better as well.

Vasily Ryabov
  • 9,386
  • 6
  • 25
  • 78
  • thanks! concerning my question, none of your solution worked (but it's getting better!). I added the new console error on the edit in my question. The ditto.ditto.SysListView321.type_keys('^e') is not far: if I multiple click on the ditto window on the same time I launch the code, it works. So it's seems to be an issue of active window. The script select an item in the ditto list, but seems to lose the focus during the type_keys('^e'). – J. Does Mar 05 '17 at 17:17
  • I don't understand what you mean about using `.keyboard`: I used `keyboard.SendKeys` on the same way I used `findbestmatch.find_best_match` (to access the method inside the class). `SendKey`s is a method of the class `keyboard` right? The keyboard is a module and keyboard too right? If so why not calling these method as python does: `class.method`? http://pywinauto.readthedocs.io/en/latest/code/code.html#main-user-modules – J. Does Mar 05 '17 at 17:28
  • "keyboard" is a module, it's not another class member. Did you ever use classes in other programming languages? – Vasily Ryabov Mar 05 '17 at 18:28
  • You cannot use some class/object first and then module name inside an object. Because in Python modules contain classes and objects, not vice versa! – Vasily Ryabov Mar 05 '17 at 18:31
  • Module is just a .py file. – Vasily Ryabov Mar 05 '17 at 18:31
  • Is that helped? – Vasily Ryabov Mar 08 '17 at 07:31
  • Sorry for the delay. "keyboard" is a module, it's not another class member."` You are right I was confusing class and module (Since keyboard is another module, I tought it was another class ― though I'm also aware that a module can contain several class). So ok, `keyboard` is the same class, but what about `findbestmatch` : is it another class member? – J. Does Mar 09 '17 at 21:43
  • Your comment " class/object first and then module name inside an object". Helps me to realize that I'm maybe confusing `module name` and `class name`. `But` when I used `keyboard.SendKeys` I was not trying to use/call the `module name`. I called the module using `from pywinauto import keyboard` (I tought it was the only way to call a module, am I wrong?). So when I did use `keyboard.SendKeys` it was just because I wanted to call the `SendKeys method` inside the `class keyboard`. – J. Does Mar 09 '17 at 21:44
  • Apparently it's wrong but I don't understand why. And, if I understand your point, it's not wrong for the reason you mentioned, but for another reason (I was not trying to call the module name when using `keyboard.SendKeys`). (And no I didn't learn other languages, I'm just fluent in english & python, as you can see ;-) – J. Does Mar 09 '17 at 21:54
  • OK, `keyboard` is a module, `SendKeys` is a function in this module (you can find statement `def SendKeys(...)` in `keyboard.py`. `findbestmatch` is also a module containing function `find_best_match(...)`. There are no classes in these modules. It's a low level API that higher level pywinauto classes use inside. Is it more clear? – Vasily Ryabov Mar 10 '17 at 10:40
  • I guess I need to see the code above working with keyboard.send_keys('^e') to understand it. But your answer doesn't work. When I add this line at the end of it: `keyboard.send_keys('^e')` I get: `AttributeError: module 'pywinauto.keyboard' has no attribute 'send_keys'` – J. Does Mar 10 '17 at 19:50
  • 1
    Ops, sorry! My fault. `keyboard.SendKeys('^e')` should work. Of course we need to have PEP-8 compatible name `send_keys` as well but we missed it. Will add later. – Vasily Ryabov Mar 12 '17 at 09:51
  • 1
    Thanks Vasily! I did make it using `SendKeys`. But just to inform you `ditto.ditto.SysListView321.type_keys('^e')` did not work (it sends the keys on the python console: `^E`). – J. Does Mar 14 '17 at 13:10
  • This answer just solved an issue I've been trying to solve for hours – Aric Aug 14 '18 at 08:49
1

To complete Vasily's answer. Here is the code needed to edit a single ditto item (it works... most of the time)

from pywinauto import findbestmatch
from pywinauto.application import Application
from pywinauto import remote_memory_block
from pywinauto import keyboard
from pywinauto import timings
import time  #needed for time.sleep(3)


keyboard.SendKeys('^*') # custom shortcut to launch the specific ditto "group" 
time.sleep(2)  # wait 2 sec for the app

ditto=Application().connect(path='Ditto.exe')
time.sleep(0.5) 

##find & select item

#The list of texts to search through: 
texts = ditto.ditto.SysListView321.texts()[1:] #skip window text itself

# The list of items corresponding (1 to 1) to the list of texts to search through.
items = ditto.ditto.SysListView321.items()   #>>[]  

found_item = findbestmatch.find_best_match('test', texts, items, limit_ratio=0.1).Select()

## Extra: open the item in editor
# Bring the window to the foreground first
ditto.ditto.set_keyboard_focus() # (work also with set_focus but it remove the cursor) 

# edit the selected entry (it's a shortcut)
keyboard.SendKeys('^e') 

# Wait (for the windows to load)
time.sleep(1) # 1 sec

# Select all
keyboard.SendKeys('^a')

ditto.Editor.close()
J. Does
  • 785
  • 3
  • 10
  • 23