Sending keyboard input to Notepad++ via windows api in Python - python

I'm aware of the fact that not all windows process keyboard input. However, ONE of the windows of my Notepad++ tree should have an effect on the editor, i.e. write the 'A' that I'm trying to send. I have tried all child windows but nothing works:
def mycallback(hwnd, data):
data[hwnd] = win32gui.GetClassName(hwnd)
win32gui.EnumChildWindows(hwnd, mycallback, data)
return True
mywindows = {}
win32gui.EnumChildWindows(197788, mycallback, mywindows) # 197788 is the notepad++ handle whose parent is 0
# at this point, mywindows contains: {'#32770': 66908, 'Button': 66922, 'Static': 66924, 'SysTabControl32': 132272, 'Scintilla': 132276, 'splitterContainer': 263444, 'wespliter': 328982, 'msctls_statusbar32': 394476, 'dockingManager': 394474, 'wedockspliter': 132328, 'nsdockspliter': 132336, 'ReBarWindow32': 66906, 'ToolbarWindow32': 66902, 'Edit': 66914}
for v in mywindows.values():
win32api.SendMessage(v, win32con.WM_CHAR, 0x41, 0) # trying to send an 'A' to notepad++ without knowing to which window I need to send it to. I had already noticed before that sending the 'A' to the "Edit" window doesn't work (the EXACT same win32api.SendMessage command works for the "Edit" window of the Microsoft-Windows-notepad-editor by the way)
# the return values of this loop are: 0,0,0,0,0,0,0,0,0,0,0,0,0,1
Only the "Edit" window returns 1. And 1 means error, so I'm assuming "Edit" is the right window to target but why does it return error?
And by the way: the "Edit" window of the Microsoft-Windows-notepad-editor also returns 1, but it prints the 'A' to the editor.

Related

SendMessage returns 0 when reading contents from notepad window using Python and Win32 API

I'm making a program that reads contents from a notepad window but it always returns "0". I tried to do it by multiple ways and all of them did the same thing so this is what I came up with. Am I doing something wrong?
import win32gui
#Message for getting the text
WM_GETTEXT = 0x000D
hNotepad = win32gui.FindWindow("Notepad", None)
Window = win32gui.FindWindowEx(hNotepad, 0, "Notepad", None)
message = win32gui.SendMessage(Window, WM_GETTEXT, 0, 0)
print(message)
I tested your code (on win11), your problem is that you use FindWindowEx incorrectly, the handle of the edit window is not found, FindWindowEx returns 0.
You can use the SPY++ tool to see the correct window name.
In win11, you need use "RichEditD2DPT".
Window = win32gui.FindWindowEx(hNotepad, 0, "RichEditD2DPT", None)
In win10, you need use "Edit".
Window = win32gui.FindWindowEx(hNotepad, 0, "Edit", None)
EDIT
When you use WM_GETTEXT, the return value of SendMessage is the number of characters copied, not including the terminating null character.
To get the Edited Text Content, you need to define a variable to store the string. The third parameter of SendMessage is the length you want to get, and the fourth parameter is to the string.
buffer=' '*255
hNotepad = win32gui.FindWindow("Notepad", None)
Window = win32gui.FindWindowEx(hNotepad, 0, "Edit", None)
message = win32gui.SendMessage(Window, WM_GETTEXT, 255, buffer)
print(buffer)

My python pyw file isn't opening though there's no error

I invented a secret code for converting messages. I thought of making a python program which will do the tough steps(basically encoding the messages and decoding them) and saved the code into a .pyw file. But it seems its not opening, I've renamed the file to .py and when I run it the console window opens, no error, and then closes. If I run the program via IDLE the program works fine and there's no error, is this some sort of bug and I should re install python or something else
from tkinter import Text,Button,Tk,Label,Scrollbar,Frame
alphabets={'a':1,'b':2,'c':3,'d':4,'e':5,'f':6,'g':7,'h':8,'i':9,'j':10,'k':11,'l':12,'m':13,'n':14,'o':15,'p':16,'q':17,'r':18,'s':19,'t':20,'u':21,'v':22,'w':23,'x':24,'y':25,'z':26,' ':' '}
inv={k:v for v,k in alphabets.items()}
#scripting the program
def insert(msg,char,index):
return msg[:index]+char+msg[index:]
def encode():
msg=_input.get('1.0','end').strip().lower()
if msg=='':
return ''
if msg[-1]=='\n':
msg=msg[:-1]
nonconvertable={}
for x in msg:
if x not in alphabets:
print(x)
nonconvertable.update({x:msg.index(x)})
msg=msg.replace(x,'')
char=[]
msg=msg.split()
for item in msg:
for x in item:
number=len(item)
num=alphabets[x]-number
if num<=0:
num+=26
char.append(num)
char.append(' ')
msg=''
for x in char:
msg+=inv[x]
for x in nonconvertable:
msg=insert(msg,x,nonconvertable[x])
return msg[:-1]
def decode():
msg=_input.get('1.0','end').strip()
if msg=='':
return
nonconvertable={}
for x in msg:
if x not in alphabets:
nonconvertable.update({x:msg.index(x)})
msg=msg.replace(x,'')
char=[]
msg=msg.lower().split()
for item in msg:
for x in item:
number=len(item)
num=alphabets[x]+number
if num>26:
num-=26
char.append(num)
char.append(' ')
msg=''
for x in char:
msg+=inv[x]
for x in nonconvertable:
msg=insert(msg,x,nonconvertable[x])
return msg[:-1]
#script for interaction of the user(through the GUI) with the script
def encodeGUI():
msg=encode()
output.delete('1.0','end')
output.insert('1.0',msg)
def decodeGUI():
msg=decode()
output.delete('1.0','end')
output.insert('1.0',msg)
#building the GUI
root=Tk()
root.state('zoomed')
root.title('converter')
root.configure(background='#747f91')
note=Label(root,text="NOTE: Don't use a dot(.) in your message",bg='#747f91')
note.grid(row=1,column=5)
inputlabel=Label(root,text='Input',bg='#747f91')
outputlabel=Label(root,text='Output',bg='#747f91')
inputlabel.grid(row=1,column=1)
outputlabel.grid(row=3,column=1)
_input=Text(root,height=15,borderwidth=1)
_input.grid(row=2,column=1)
frame1=Frame(root,width=_input.winfo_width(),height=_input.winfo_height())
frame2=Frame(root,width=_input.winfo_width(),height=_input.winfo_height())
inputscrollbar=Scrollbar(frame1,command=_input.yview)
frame1.grid(row=2,column=3)
frame2.grid(row=4,column=3)
inputscrollbar.pack(fill='y')
output=Text(root,height=15,borderwidth=1)
output.grid(row=4,column=1)
outputscrollbar=Scrollbar(frame2,command=output.yview)
outputscrollbar.pack(fill='y')
encodebutton=Button(root,text='encode',command=encodeGUI,bg='#6179c9')
decodebutton=Button(root,text='decode',command=decodeGUI,bg='#6179c9')
encodebutton.grid(row=4,column=4)
decodebutton.grid(row=4,column=6)
First, you forgot to add:
root.mainloop()
at the end of the file.
But if the pyw file still won't run, these steps may help you:
Create a .pyw file
Right-click on it and select properties
In "Opens with:" press change
Navigate to your python directory and choose "pythonw.exe"

Sending keystrokes to inactive window

Hello i am trying to make a app that sends a key press 2 chrome the current code i have is:
#you will need the win32 libraries for this snippet of code to work, Links below
import win32gui
import win32con
import win32api
from time import sleep
#[hwnd] No matter what people tell you, this is the handle meaning unique ID,
#["Notepad"] This is the application main/parent name, an easy way to check for examples is in Task Manager
#["test - Notepad"] This is the application sub/child name, an easy way to check for examples is in Task Manager clicking dropdown arrow
#hwndMain = win32gui.FindWindow("Notepad", "test - Notepad") this returns the main/parent Unique ID
hwndMain = win32gui.FindWindow("Notepad", "test - Notepad")
#["hwndMain"] this is the main/parent Unique ID used to get the sub/child Unique ID
#[win32con.GW_CHILD] I havent tested it full, but this DOES get a sub/child Unique ID, if there are multiple you'd have too loop through it, or look for other documention, or i may edit this at some point ;)
#hwndChild = win32gui.GetWindow(hwndMain, win32con.GW_CHILD) this returns the sub/child Unique ID
hwndChild = win32gui.GetWindow(hwndMain, win32con.GW_CHILD)
#print(hwndMain) #you can use this to see main/parent Unique ID
#print(hwndChild) #you can use this to see sub/child Unique ID
#While(True) Will always run and continue to run indefinitely
while(True):
#[hwndChild] this is the Unique ID of the sub/child application/proccess
#[win32con.WM_CHAR] This sets what PostMessage Expects for input theres KeyDown and KeyUp as well
#[0x44] hex code for D
#[0]No clue, good luck!
#temp = win32api.PostMessage(hwndChild, win32con.WM_CHAR, 0x44, 0) returns key sent
temp = win32api.PostMessage(hwndChild, win32con.WM_CHAR, 0x44, 0)
#print(temp) prints the returned value of temp, into the console
print(temp)
#sleep(1) this waits 1 second before looping through again
sleep(1)
but my issue is how i find chrome seing as it changes it name to the active tab and using this does not work either:
hwndMain = win32gui.FindWindow("Google Chrome", None)
in similar thread i saw this worked for people. and your code as is by changing title name works for me but you need to modify the title input order to this format.
hwndMain = win32gui.FindWindow( "Google Chrome" , None)
TO
hwndMain = win32gui.FindWindow( None , "Google Chrome")

Sublime Text 3 Plugin changing run to on_pre_save

I have been working on a Sublime Text 3 plugin that fixes some coding standards I have at work(That I have a bad habit of missing) I currently have this working with a command run in the console. Most of the code was originally from this thread.
import sublime, sublime_plugin
class ReplaceCommand(sublime_plugin.TextCommand):
def run(self, edit):
#for each selected region
region = sublime.Region(0, self.view.size())
#if there is slected text
if not region.empty():
#get the selected region
s = self.view.substr(region)
#perform the replacements
s = s.replace('){', ') {')
s = s.replace('}else', '} else')
s = s.replace('else{', 'else {')
#send the updated string back to the selection
self.view.replace(edit, region, s)
Then you just need to run:
view.run_command('replace')
And it will apply the coding standards(there are more I plan to implement but for now i'll stick with these) I would like this to run on save.
I tried just changing run(self, edit) to on_pre_save(self, edit) but it does not work. I don't get any syntax errors but It just doesn't work.
Can anyone tell me how to make this run on save instead of having to run the command?
On ST3 the only way to get an Edit object is by running a TextCommand. (It's in the docs, but they're not terribly clear). But, fortunately, you can run the command pretty much the same way you have been doing.
Events handlers, like on_pre_save, can only be defined on an EventListener. The on_pre_save() event is passed a view object so you just need to add something like this, which kicks-off the command you've already written.
class ReplaceEventListener(sublime_plugin.EventListener):
def on_pre_save(self, view):
view.run_command('replace')
The Solutions I came to was to create an on_pre_save() function that runs the command I listed earlier:
import sublime, sublime_plugin
class ReplaceCodeStandardsCommand(sublime_plugin.TextCommand):
def run(self, edit):
#for each selected region
region = sublime.Region(0, self.view.size())
#if there is slected text
if not region.empty():
#get the selected region
s = self.view.substr(region)
#perform the replacements
s = s.replace('){', ') {')
s = s.replace('}else', '} else')
s = s.replace('else{', 'else {')
#send the updated string back to the selection
self.view.replace(edit, region, s)
class ReplaceCodeStandardsOnSave(sublime_plugin.EventListener):
# Run ST's 'unexpand_tabs' command when saving a file
def on_pre_save(self, view):
if view.settings().get('update_code_standard_on_save') == 1:
view.window().run_command('replace_code_standards')
Hopefully this code helps someone!

Selenium python interact with FileOpen window

From Selenium, I managed to automate my tasks for a website.
However I ran into a problem:I need to upload a file to my web-page before submitting the form.
It is NOT an option to write the uploaded file into it's input element, because it is more complicated than this.
So basically I need to launch the FileUpload dialog by clicking a button, sendKeys there, and then close it by clicking on Ok.
I am wondering if this is even possible using just Selenium?
I am using it from python (so I don't have access to Robot class)
I tried so far:
element.click()
time.sleep(5)
alert = driver.switch_to.alert
alert.send_keys("path.to.myfile.txt")
alert.accept()
(nothing happens - I mean, the file open dialog works fine, but it does not send the keys )
I also tried:
alert = driver.switch_to.alert
buildu = ActionChains(driver).send_keys('path.to.my.file.txt')
buildu.perform()
(also not working)
Maybe I am looking at it wrong...
Maybe the alerts is not a good approach?
Do you have any idea?
I would prefere not having to use AUTOIT (for my own reasons)
So my goal is to click on a link element (DONE) then the link opens the File Upload open file dialog (DONE), then I need to be able to enter a text in the only textBox of the new window, and click on the Ok button
EDIT
This is the Open File dialog that shows up.
All I want to do is send the filename directly to the window (the textBox is focused when the dialog shows up, so no need to make more actions). After I send the keys (text) I need to be able to click on the Open button
You can create a Java program that will paste the filename and press the enter key. I had this same problem exactly. This is how I implemented:
package myaots_basic;
import java.io.*;
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.datatransfer.StringSelection;
import java.awt.event.KeyEvent;
public class trial {
public static void main(String[] args) throws AWTException {
System.out.println("HELLO WORLD");
StringSelection attach1 = new StringSelection ("C:\\My Office Documents\\Selinium projects\\Data\\attachment1.doc");
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(attach1, null);
Robot rb1 = new Robot();
rb1.delay(3000);
rb1.keyPress(KeyEvent.VK_CONTROL);
rb1.keyPress(KeyEvent.VK_V);
rb1.keyRelease(KeyEvent.VK_V);
rb1.keyRelease(KeyEvent.VK_CONTROL);
rb1.delay(500);
rb1.keyPress(KeyEvent.VK_ENTER); // press Enter
rb1.keyRelease(KeyEvent.VK_ENTER);
}
}
Name it to trial.jar. Make this class a an executable.
Then in your python code just add a simple step:
import subprocess
subprocess.call("java -jar trial.jar", shell=True)
I don't know if this is restricted to windows 10 or works slightly different in other Windows versions but you can use the following code/idea.
Open the windows shell with win32com.client.Dispatch("WScript.Shell")
Send Tab keys to navigate through the open file dialog
Paste your absolute file path into the top of the dialog and also into the file selection text field and send enter key when
tab-navigating to the "open" button
Make a sleep of at least 1 second between each action.. otherwise Windows blocks this action.
import win32com.client as comclt
...
def handle_upload_file_dialog(self, file_path):
sleep = 1
windowsShell = comclt.Dispatch("WScript.Shell")
time.sleep(sleep)
windowsShell.SendKeys("{TAB}{TAB}{TAB}{TAB}{TAB}")
time.sleep(sleep)
windowsShell.SendKeys("{ENTER}")
time.sleep(sleep)
windowsShell.SendKeys(file_path)
time.sleep(sleep)
windowsShell.SendKeys("{TAB}{TAB}{TAB}{TAB}{TAB}")
time.sleep(sleep)
windowsShell.SendKeys(file_path)
time.sleep(sleep)
windowsShell.SendKeys("{TAB}{TAB}")
time.sleep(sleep)
windowsShell.SendKeys("{ENTER}")
...

Categories