Select text with win32api keybd_event - python

I'm trying to create a method to select text content of a notepad file using the following keys combination: CTRL+END then SHIFT+HOME
I have the following code to press, hold and release a sequence of keys:
import win32api
import win32con
import win32gui
import time
def keyboard_press_hold_release(*keys):
for k in keys:
win32api.keybd_event(VK_CODE[k], 0, 0, 0)
time.sleep(.05)
for k in keys:
win32api.keybd_event(VK_CODE[k], 0, win32con.KEYEVENTF_KEYUP, 0)
time.sleep(.1)
and call it to combine CTRL+END and SHIFT+HOME:
keyboard_press_hold_release('ctrl', 'end')
keyboard_press_hold_release('shift', 'home')
As result the CTRL+END command is working but the SHIFT+HOME don't select the text, just move the cursor to the begin of line.
What is wrong?

You can use the keyboard module for this purpose. Here is an example:
import keyboard
import time
time.sleep(5) #You need some wait to switch to your window after executing
keyboard.press_and_release("ctrl+end")
keyboard.press_and_release("shift+home")
If Shift+Home doesn't work for you than you can use select the whole text in a single click using Ctrl+A.
keyboard.press_and_release("ctrl+a")

Related

Why is pyAutoGui not clicking in certain windows

I'm trying to make a python program to Automate the setup of a new computer. I used pyAutoGui to click on the Install button when prompted but it wont click on the button. It detects the image "Install.png" because it breaks the while loop when Adobe prompts to install. I tested it in paint and if I change the Install.png image to something on paint I can visually see it clicks. I tried the mouse library, moving it to the coordinates and then clicking, double- tripleClick, MouseDown -> sleep -> MouseUp, just MouseDown -> MouseUp, sending enter with pyAutogui, sending enter with shell, using subprocess and some other stuff. Nothing seems to work on the popup window Adobe gives. I printed the coordinates and they come out fine (I used DisplayMouseInfo to see of the coordinates were correct) I even hard coded the coordinates but it doesnt click install. Any answers would be appreciated, here is how it looks.
import os
import shutil
import subprocess
import psutil
import pyautogui as pg
import time
global path
path = os.getcwd()
def adobe_install():
adobe_setup_path = os.path.join(path, "Adobe.exe")
adobe_cmd = str("start " + adobe_setup_path)
os.system(adobe_cmd)
while pg.locateCenterOnScreen('Install.png', confidence=0.9) == None:
wait
time.sleep(2)
clk= pg.locateCenterOnScreen('Install.png', confidence=0.9)
pg.click(clk.x, clk.y)
EDIT
I tried the following
Install is just the a screenshot of the install button and the coordinates it prints (clk.x ; clk.y) are correct
import os
import shutil
import subprocess
import pyautogui as pg
import time
import pathlib
import winreg
import win32con
import win32gui
def adobe_install():
adobe_setup_path = os.path.join(path, "Adobe.exe")
adobe_cmd = str("start " + adobe_setup_path)
os.system(adobe_cmd)
while pg.locateCenterOnScreen('Install.png', confidence=0.9) == None:
wait
results = []
top_windows = []
win32gui.EnumWindows(windowEnumerationHandler, top_windows)
for i in top_windows:
if "Adobe Acrobat Reader DC (Continuous) - Setup" in i[1]:
print(i)
win32gui.ShowWindow(i[0],5)
win32gui.SetForegroundWindow(i[0])
bring_to_front(i[0])
break
time.sleep(2)
clk= pg.locateCenterOnScreen('Install.png', confidence=0.9)
print(clk.x)
print(clk.y)
pg.click(clk.x, clk.y)
pg.leftClick(x=clk.x, y=clk.y)
pg.typewrite(['enter'], interval=1)
adobe_install()
I tried clicking, left clicking, and pressing enter. I tested the in other windows like Paint and word and the clicking and they all did indeed click or send "Enter"
This is the error I recieved
File "C:\Users\***\documents\ict\software\New_comp.py", line 77, in adobe_install
bring_to_front(i[0])
File "C:\Users\***\documents\ict\software\New_comp.py", line 41, in bring_to_front
win32gui.SetWindowPos(HWND, win32con.HWND_NOTOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE + win32con.SWP_NOSIZE)
pywintypes.error: (5, 'SetWindowPos', 'Access is denied.')
Try bringing the window to front & activate it. But you need to put in the window handler
import win32gui
import win32con
def bringTOfront(HWND):
win32gui.ShowWindow(HWND, win32con.SW_RESTORE)
win32gui.SetWindowPos(HWND, win32con.HWND_NOTOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE + win32con.SWP_NOSIZE)
win32gui.SetWindowPos(HWND, win32con.HWND_TOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE + win32con.SWP_NOSIZE)
win32gui.SetWindowPos(HWND, win32con.HWND_NOTOPMOST, 0, 0, 0, 0, win32con.SWP_SHOWWINDOW + win32con.SWP_NOMOVE + win32con.SWP_NOSIZE)

How to press pause key in python

I am creating a pyautogui automation that connect to a W3270 terminal (really old :))
this terminal is expecting pause key to be pressed,
Apart pyautogui, I also tried Keyboard library, but i am unable to send pause
import pyautogui
import keyboard
import constants as const
locateOnScreen(const.IPAIRE_TERMINAL_CONNECTED)
command = '/FOR SIGNON'
pause = '\u0019'
pyautogui.write(command)
time.sleep(1)
keyboard.send('pause')
Am I suppose to use keyboard to simulate 'pause' button?
I found a solution using pynput
import pyautogui
import constants as const
from pynput.keyboard import Key, Controller
locateOnScreen(const.IPAIRE_TERMINAL_CONNECTED)
command = '/FOR SIGNON'
pyautogui.write(command)
time.sleep(1)
keyboard = Controller()
keyboard.press(Key.pause)
keyboard.release(Key.pause)

Pynput while not using text field

Im trying to make a simple code to crouch when I run it. this is my code:
from pynput.keyboard import Key, Controller
import time
import keyboard as key
keyboard = Controller()
time.sleep(2)
for i in range(30):
keyboard.press("c")
keyboard.release('c')
time.sleep(0.1)

Simulating controller dpad button being held down with Python evdev

I'm trying to simulate holding down a DPad button on a controller using Python evdev.
So far I've managed to successfully press a button like so:
import os
import time
from evdev import uinput, ecodes as e, list_devices, InputDevice, ff
dev = InputDevice(str(os.path.realpath("/dev/input/by-id/usb-Sony_Interactive_Entertainment_Wireless_Controller-if03-event-joystick")))
dev.write(e.EV_ABS, e.ABS_HAT0X, 1)
dev.write(e.EV_ABS, e.ABS_HAT0X, 0)
dev.write(e.EV_SYN, 0, 0)
but haven't been able to successfully have the application I'm simulating the input for detect the button held for any amount of time. What I've tried is this (and a couple variations on this)
...
dev.write(e.EV_ABS, e.ABS_HAT0X, 2) # evdev docs say 2 is for holding
dev.write(e.EV_SYN, 0, 0)
time.sleep(2)
dev.write(e.EV_ABS, e.ABS_HAT0X, 0)
dev.write(e.EV_SYN, 0, 0)
What am I doing wrong?

can't invoke "event" command: application has been destroyed

So I was debugging some of my code today and noticed a new message in the output:
can't invoke "event" command: application has been destroyed
while executing
"event generate $w <<ThemeChanged>>"
(procedure "ttk::ThemeChanged" line 6)
invoked from within
"ttk::ThemeChanged"
I looked at the questions regarding it on SO but they did't relate to this instance of the error. As for the ttk widget, I have not used ttk once in my code, a search for the string "ttk" in my code yields none.
Chunk of code that outputs this:
def GoToEvent(self, controller, driver):
wait = WebDriverWait(driver, 600)
var = Vars()
entertain = var.GetVars("Link")
if type(entertain) == type(""):
event = var.GetVars("Event")
entertain = driver.find_element_by_partial_link_text(event)
entertain.click()
try:
# we have to wait for the page to refresh, the last thing that seems to be updated is the title
wait.until(EC.title_contains("Entertain"))
finally:
# the page is ajaxy so the title is originally this:
msg = driver.title
label = tk.Label(self, text=msg, cursor='spinning', font="courier 24", bg="#c63f17")
label.place(x=self.winfo_width()/2, y=self.winfo_height()/2, anchor="center")
self.update() # <--- This is where the problem is
label.destroy()
This doesn't seem to actually throw any errors, and my code runs absolutely fine. I can't give enough code to replocate the problem as it is just simply too much code before this, but I can tell you all the testing I did if that helps. I debugged this code block and found that adding a breakpoint at label.destroy() would still give this error, but placing one anywhere before and stepping over to label.destroy() would not print this, leading me to believe it was some type of timing error with self.update(), but when I placed time.sleep(5) before and after self.update() the error was still there. So stepping through the code did not show the error but time.sleep() still showed the error. This puzzles me, I don't know why it would be behaving this way, I have been writing this program for 2 weeks and this is the first time this has happened. If no one knows it's fine, the code still runs perfectly, I'm just curious as to what this means and why it is happening. Thanks!
Beginning of code:
# !/usr/bin/python
# coding: utf-8
'''
Created on Jun 23, 2017
#author: jacob <---------------- Line 6
'''
from selenium import webdriver
#from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait # available since 2.4.0
from selenium.webdriver.support import expected_conditions as EC # available since 2.26.0
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
import os
import platform
import pwd
import re
import time
#import datetime
from time import strftime
import Tkinter as tk
import tkFont as tkfont
from Tkinter import Entry, Menu, Menubutton, Canvas
So this was a very hard error to find, as debugging never pointed to the right area of code I had to read through the code to try to find something off. So the program gets user input for a keyword, a website is then searched for the events containing this keyword, they are then put into a drop down menu. If there is only one or none occurrence of the keyword then there is no menu displayed and it either clicks the event or it prompts the user with a suggested event that is closest to their keyword. This seemed like the probable area where this error was happening because it only occurred when no menu was displayed. Code from this:
if (len(options) > 1):
button6 = tk.Button(selectMenu, text="Enter",
cursor='pointinghand', command=lambda: self.GetSelection(str(var.GetVars("Selection")), links, options, selectMenu, controller))
msg = "Which one would you like to attend?"
label = tk.Label(selectMenu, text=msg, font="Helvedica 14")
label.pack(side='top', pady=10)
menbutton.pack(side="top", pady=10)
button6.pack(pady=10)
self.Progress()
selectMenu.attributes('-topmost', True)
selectMenu.mainloop()
elif options:
var.SendVars("selLink", links[0])
selectMenu.destroy()
self.Progress()
else:
var.SendVars("Link", 'NO-LINK-FOUND')
selectMenu.destroy()
self.Progress()
It turns out that this error was caused by a Menubutton being created in a tk window but never reaching the mainloop, even though it was destroyed. The error is thrown when the mainloop of another tk window is reached. So to fix this you move the creation of the Menubutton to a place where it will reach it's mainloop as below.

Categories

Resources