Python - Mouse clicks/Keyboard Clicks on window in background - python-3.x

I wanted to create a metin2 bot, nothing complicated. I am new into that so i just started to look for tutorials on youtube to find something that would lead me to world of coding, how does it work, what language is used to write it ect. So I found a tutorial on youtube about open CV Learn Code By Gaming - OpenCV and thought that's awesome thing to start with.
I got to the point where I can easily detect the names of monsters/metins and wont have any problems in finding the right points to click. After detection started working I thought about automating clicking on the window to farm some items etc. Simple things like clicking e.g 50 pixels below the name to auto attack worked just fine but the problem was that I wanted to make more bots to maximalize farming. So when i started to add more clients I got a problem where e.g you have to hold down SPACE in one window to attack from horse and click on another window which was stopping attacking from horse. So I thought about finding some code that can basically send message directly to window without controlling a mouse or keyboard so you can run multiple bots in one time and each will do perfect meanwhile you can do anything else on pc because your mouse and keyboard aren't used.
Let's start from code I found and none worked for windows in background (even with administrator privileges). Pyautogui doesn't work in background (window has to be in foreground to be clicked on and it controls mouse so there is no point in using that.
From that code I learned that I need to find "window ID" to connect to it and send messages. When i print hWnd it shows the numbers in Terminal and code passes without any fails but does nothing except printing the window ID ( Parent Handle ). Ofc I pip installed pywin32
import win32gui
import win32api
import win32con
def click(x, y):
hWnd = win32gui.FindWindow(None, "Client")
print(hWnd)
lParam = win32api.MAKELONG(x, y)
win32api.SendMessage(hWnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, lParam)
win32api.SendMessage(hWnd, win32con.WM_LBUTTONUP, win32con.MK_LBUTTON, lParam)
click(100, 100)
Than i found another code that looked similar but used different function so first i used
wdname = 'Client'
hwnd = win32gui.FindWindow(None, wdname) # parent handle
print(hwnd)
Which printed me a window ID that i used in parameters in function
def control_click(x, y, handle, button):
l_param = win32api.MAKELONG(x, y)
if button == 'left':
win32gui.PostMessage(handle, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, l_param)
win32gui.PostMessage(handle, win32con.WM_LBUTTONUP, win32con.MK_LBUTTON, l_param)
elif button == 'right':
win32gui.PostMessage(handle, win32con.WM_RBUTTONDOWN, 0, l_param)
win32gui.PostMessage(handle, win32con.WM_RBUTTONUP, 0, l_param)
control_click(200, 200, 329570, button ='left')
But it still did nothing but code passed clear
Anyone have any ideas about how to make clicks/keyboard clicks in python on window in background without taking controll of mouse/keyboard? If you have any experience in automating and know better ways to create automation for clicking ect. and want to share it please do. If that can be done in another programming language also share your toughts about that of course if you want to.
Windows 10 x64
Python used: 3.9.2
All codes i found in topics were out of date that s why i am asking for help there. Thanks in advance :)

Related

How can I close the print window only after user has printed/closed the window || How can I preview an image with the QPrintPreviewDialog

Overview:
I need a way to have a printer dialog to print an image (a modern looking one is preferred)
Description:
I tried to find a way to print an image with a printer dialog and I found win32api.ShellExecute(0, "print", "test.jpg", 'None', None, 0)
But to make that work I need a wait after that and when the wait is over the window will close.. and I want it to close ONLY when the user has pressed print or closed the window...
Is there a way of doing that?
and it would be even better if you could link me to another module/way to have that printer dialog maybe a more modern one.. (not the PyQt5 one) because the win32api one looks kinda old school
Edit: So I found this piece of code -
from PySide2.QtWidgets import QApplication, QMainWindow, QAction, QTextEdit
import sys
from PySide2.QtPrintSupport import QPrinter, QPrintPreviewDialog
myapp = QApplication(sys.argv)
window = QMainWindow()
printer = QPrinter(QPrinter.HighResolution)
previewDialog = QPrintPreviewDialog(printer, window)
previewDialog.exec_()
myapp.exec_()
sys.exit()
Source (I have minimized the code above as much as possible): https://codeloop.org/pyside2-print-preview-dialog/
But I don't know how to preview an image (this is using PySide2) please help
Acroding to the document of ShellExecuteA function, nCmdShow parameter is passed via calls to ShellExecute, so I tried every nCmdShow parameters in this function, but it didn't work like you want. It always close the print window after user has printed/closed the window.I suggest you use Print Spooler API Functions to write your own printing interface, so that you can wait for the user's further operation after printing.

PyQt5 run Multithreaded processes consicutively on single thread

I am working on an application in PyQT5 which has two docks on either side and an OCC 3d viewer and a TextEdit in the middle. The .ExportToImage() method of the OCC viewer allows taking a screenshot of the viewer. But since the Application has a responsive design, the Viewer is resized to be thin(on certain display resolutions) and thus the screenshot also comes out to be thin.
I've tried to resize the window to a particular size and then hide everything except the 3D viewer. This enlarges the viewer thus saving from a cropped screenshot. But when I hide and resize and then take the screenshot, the screenshot still comes out to be thin. Here's the code:
def take_screenshot(self):
Ww=self.frameGeometry().width()
Wh=self.frameGeometry().height()
self.resize(700,500)
self.outputDock.hide() #Dock on the right
self.inputDock.hide() #Dock on the left
self.textEdit.hide() #TextEdit on the Bottom-Middle
self.display.ExportToImage(fName) #Display is the 3d Viewer's display on the Top-Middle
self.resize(Ww,Wh)
self.outputDock.show()
self.inputDock.show()
self.textEdit.show()
I guess this happens because the above .show(), .hide(), .resize() methods of PyQt5 are multithreaded and as soon as I run them they dont run consicutively but parallely. Thus the screenshot is taken before the other processes complete.
Is there a way to resolve this? Or is there a better way?
no multiple threads. events are processed in loops, so called eventloop.
try this:
def take_screenshot(self):
Ww=self.frameGeometry().width()
Wh=self.frameGeometry().height()
self.resize(700,500)
self.outputDock.hide() #Dock on the right
self.inputDock.hide() #Dock on the left
self.textEdit.hide() #TextEdit on the Bottom-Middle
QTimer.singleShot(0, self._capture)
def _capture(self):
# app.processEvents() # open this line if it still doesn't work, I don't know why.
self.display.ExportToImage(fName) #Display is the 3d Viewer's display on the Top-Middle
self.resize(Ww,Wh)
self.outputDock.show()
self.inputDock.show()
self.textEdit.show()

Tkinter and some kind of issue when trying to display images

First off, I'm very new to Python and coding in general. I'm using Python, Tkinter, and Idle version 3.7.3. I'm using an HP Chromebook, with Chrome OS Version 81.0.4044.141.
from tkinter import *
window = Tk()
window.title('Image Example')
img = PhotoImage(file = 'python.gif')
label = Label(window, image = img)
label.pack()
window.mainloop()
As you can see above, this is the small snippet of code that I'm having issues with. As far as I understand, everything is written correctly and the file "python.gif" is in the correct directory. For reference this is what the image should look like:
python.gif (normal)
But when I run the program, this is what I get:
python.gif (screenshot of running program)
That's the result 99% of the time, but I should mention that there have been a RARE number of occasions where the image displayed correctly upon program execution. However, I do not know how to replicate that. Also for more context, I've tried other images to see what happened. I found a free .pgm image to try as an example, and upon execution either I got the same result, or half of the image would appear correctly while the bottom half (also sometimes this would be reversed and the top half would be affected) would be "blacked out".
In conclusion, I wanted to ask if anybody has an idea of what's going on. I'm not sure if this is a hardware issue (because I can view all mentioned images in a normal image viewing app with no problems), or if this has something to do with Python/Tkinter.
Any assistance is very appreciated! Please and Thank You!

Send keyboard/mouse inputs with python macro keep target window background

I'm trying to make a macro program with python 3.7 on Windows10
I want to send keyboard/mouse inputs to any specific target window while the target window keep inactivated(minimized or background)
pyautogui seems to not be able to do that (If I miss something let me know plz)
pywinauto can send inputs to specific target window but it always make the target window activate.
Is there any way keeping target window inactivated????
import pywinauto
app = pywinauto.application.Application().connect(best_match='123 - Notepad', top_level_only=False, visible_only=False)
form = app.window(title_re='123 - Notepad')
for i in range(1, 10):
form.type_keys("12e12e21e")
I found the answer!!!!
app = Application(backend="win32").connect(process=12345)
form = app.window(title_re="windowtitle")
form.send_keystrokes("1234567")
Remote Execution Guide -> Tricks to run automation on a locked machine

Gtk Window Non-Responsive During Selenium Automation

Good Afternoon :) Having a problem with my Python3 Gtk3 application and Selenium WebDriver (ChromeDriver). Also, using Linux if it matters.
Basically, the user presses a button to start the Selenium webdriver automation and then as the automation process is going, it 'SHOULD' give feedback to the user in the GUI (See Content.content_liststore.append(list(item)) and LogBox.log_text_buffer).
However, it's not adding anything into the content_liststore until after fb_driver.close() is done. In the meantime, the Gtk window just "hangs".
Now, I've been looking into multithreading in hopes of the GUI being responsive to this feedback but I've also been reading that Selenium doesn't like multithreading (but I presume thats running multiple browsers/tabs (which this is not)).
So, my question is; Is multithreading the go-to fix for getting this to work?
# ELSE IF, FACEBOOK COOKIES DO NOT EXIST, PROCEED TO LOGIN PAGE
elif os.stat('facebook_cookies').st_size == 0:
while True:
try: # look for element, if not found, refresh the webpage
assert "Facebook" in fb_driver.title
login_elem = fb_driver.find_element_by_id("m_login_email")
login_elem.send_keys(facebook_username)
login_elem = fb_driver.find_element_by_id("m_login_password")
login_elem.send_keys(facebook_password)
login_elem.send_keys(Keys.RETURN)
except ElementNotVisibleException:
fb_driver.refresh()
StatusBar.status_bar.push(StatusBar.context_id, "m_login_password element not found, trying again...")
ProblemsLog.text_buffer.set_text("Facebook has hidden the password field, refreshing page...")
else:
query_elem = fb_driver.find_element_by_name("query")
query_elem.send_keys(target)
query_elem.send_keys(Keys.RETURN)
break
m_facebook_url_remove = "query="
m_facebook_url = fb_driver.current_url.split(m_facebook_url_remove, 1)[1] # Remove string before "query="
facebook_url = "https://www.facebook.com/search/top/?q=" + m_facebook_url # Merge left-over string with the desktop url
StatusBar.status_bar.push(StatusBar.context_id, "Facebook elements found")
fb_title = fb_driver.title
fb_contents = [(target_name.title(), "Facebook", facebook_url)]
for item in fb_contents:
Content.content_liststore.append(list(item))
#progress_bar.set_fraction(0.10)
LogBox.log_text_buffer.set_text("Facebook Search Complete")
with open('facebook_cookies', 'wb') as filehandler:
pickle.dump(fb_driver.get_cookies(), filehandler)
fb_driver.close()
I've considered it not working because of the 'while' loop, but another piece of code doesn't have a loop and does the exact same thing, it waits for Selenium to finish before adding content to the GUI.
Additionally, the user can select multiple websites to do this with, so the application can first go to Facebook (do it's business then close), go to LinkedIn (do it's business then close) and so fourth. And it still waits for all the Selenium code to finish before adding anything to the Gtk GUI.
I really hope that makes sense! Thank you :)
Your`s question is the answer you are lookig for. Take a read here https://wiki.gnome.org/Projects/PyGObject/Threading

Resources