7

I have the following Pywinauto code and timings waiting is 0.5 seconds instead of immediate. How to get itimmediately?

  • To click a button and go to the next message:
from pywinauto import application, timings, mouse
import time

app = application.Application()
app.connect(title = 'Mensagem')
app = app.Mensagem
app2 = app.TBPanel2
buttonCoord = int((app2.rectangle().right - app2.rectangle().left)/2/2), int((app2.rectangle().bottom - app2.rectangle().top)/2)
buttonCoord = buttonCoord[0]*(2*2-1),buttonCoord[1]
timings.Timings.after_clickinput_wait = 0.001
timings.Timings.after_setcursorpos_wait = 0.001

starttime = time.perf_counter()
#while app.Edit1.texts()[0] != '':
for i in range(10):
    buttonCoord = int((app2.rectangle().right - app2.rectangle().left)/2/2), int((app2.rectangle().bottom - app2.rectangle().top)/2)
    buttonCoord = buttonCoord[0]*(2*2-1),buttonCoord[1]
    app2.click_input(button='left', coords=(buttonCoord))
    print('Entre cliques demorou ', str(time.perf_counter()-starttime), ' segundos')
    starttime = time.perf_counter()

When I run, the interval between clicks is 0.5 seconds:

Entre cliques demorou  0.4614592999999999  segundos
Entre cliques demorou  0.44403170000000003  segundos
Entre cliques demorou  0.48520320000000017  segundos
Entre cliques demorou  0.4723533999999998  segundos
Entre cliques demorou  0.46825479999999997  segundos
Entre cliques demorou  0.4439942000000001  segundos
Entre cliques demorou  0.4874373999999997  segundos
Entre cliques demorou  0.47333040000000004  segundos
Entre cliques demorou  0.46036510000000064  segundos

However, when I move my mouse frantically, it goes faster:

Entre cliques demorou  0.06659199999999998  segundos
Entre cliques demorou  0.1532768000000001  segundos
Entre cliques demorou  0.05349690000000007  segundos
Entre cliques demorou  0.049827499999999914  segundos
Entre cliques demorou  0.05078930000000015  segundos
Entre cliques demorou  0.04885250000000019  segundos
Entre cliques demorou  0.06023690000000004  segundos
Entre cliques demorou  0.048675000000000024  segundos
Entre cliques demorou  0.05394080000000012  segundos
Entre cliques demorou  0.05615450000000011  segundos

What exactly am I doing wrong?

Edit: For a more generic approach and testing, tweaked code, same results

from pywinauto import application, timings
import time

app2 = application.Application()
app2.connect(title_re = '.*Notas*') #In portuguese, Notepad is translated to 'Bloco de Notas', so change to your system name
app2 = app2.window(title_re = '.*Notas*') #same here
app2 = app2.wrapper_object()
timings.Timings.after_clickinput_wait = 0.001
timings.Timings.after_setcursorpos_wait = 0.001
starttime = time.perf_counter()
for i in range(100):
    app2.click_input(button='left', coords=(100,100))
    print('Between clicks took ', str(time.perf_counter()-starttime), ' seconds')
    starttime = time.perf_counter()
Moacir
  • 617
  • 4
  • 19
  • Pywinauto line 5 `app.connect(title = 'Mensagem')` throws ***pywinauto.findwindows.ElementNotFoundError: {'title': 'Mensagem', 'backend': 'win32', 'visible_only': False}***. What should I use to test your code? Notebook? – ZF007 Dec 31 '19 at 11:09
  • I am sorry I gave no explanation to the code. It checks for a window named "Mensagem", then it gets the X/Y of the button and clicks on it. You can change it to whichever window you like, and set the buttonCoord to a fixed X/Y – Moacir Dec 31 '19 at 12:14

2 Answers2

1

You need to pre-search the element app2 and save it as wrapper object:

app2 = app.TBPanel2.wrapper_object()
# or
app2 = app.TBPanel2.wait('ready', timeout=10) # if you need non-default time to wait

In your current code app2 = app.TBPanel2 is a WindowSpecification object which is just a criteria to search. So when you're calling .rectangle() or .click_input() the search procedure is called implicitly every time. This is described in the Getting Started Guide, Chapter "Window Specification".

Also I'd recommend to name the variable tb_panel2_spec or tb_panel2_wrapper instead of app2 to avoid confusion about its type.

P.S. Also the reliable cross-platform way to measure time in Python is import timeit; timeit.default_timer().

PS2: from pywinauto import mouse is not necessary because you're using method .click_input().


EDIT3:

The real problem is win32gui.GetDoubleClickTime() which returns 500 ms. Method .click_input() tries to eliminate double click this way. We can add optional parameter to disable this wait. You can workaround it by monkey patching win32gui. Add this code at the beginning:

import win32gui

def no_double_click_time():
    return 0

win32gui.GetDoubleClickTime = no_double_click_time
Vasily Ryabov
  • 9,386
  • 6
  • 25
  • 78
  • I included the `.wrapper_object()` to the app2 line, however there is no change. It is still taking .5 seconds. Removing the mouse import also did not change that – Moacir Jan 02 '20 at 10:52
  • If it depends on mouse move, I'd suggest to move mouse out of screen first to avoid any attempt to show a tooltip, then do your actions. It can be done by `mouse.move(coords=(-500, 200))`. – Vasily Ryabov Jan 02 '20 at 14:01
  • The mouse move I said was physical mouse move. It seems like if it tries to do entirely on programming, it adds this 0.5 sec wait. Even adding a mouse.move does not skip the .5 wait – Moacir Jan 02 '20 at 14:25
  • Well, the problem is here: `win32gui.GetDoubleClickTime()` which returns 500 ms. Method `.click_input()` tries to eliminate double click this way. We can add optional parameter to disable this wait. You can workaround it by monkey patching `win32gui`. I've added the workaround code to the answer. – Vasily Ryabov Jan 05 '20 at 11:11
  • 1
    I was going to say "You just copy-pasted the github solution so no bounty for you", but then I realized it was you all along haha. Thanks. It works – Moacir Jan 07 '20 at 12:12
  • 1
    Ha-ha, I would say "GitHub reply was copy-pasted from here". :) Thanks for reporting it! – Vasily Ryabov Jan 07 '20 at 14:46
0

A bug with timeouts was fixed in version 0.6.3 maybe this is the problem in your case

Mathix420
  • 872
  • 11
  • 21