I'm creating a script that will send mouse inputs to a specific window. The only way I have found to do this is by setting focus to the window. If there is another way please explain it. Anyways, this is the code that is not working.
from win32gui import *
us_ip = input('Version of Minecraft: ')
minecraft_handle = FindWindow(None, f'Minecraft {us_ip}')
SetFocus(minecraft_handle)
I can retrieve the HWND but when I run the program I get this error.
Traceback (most recent call last):
File "c:\Users\Jacob Daniels\Desktop\python\autoclicker\windows api experimentation\py.py", line 5, in <module>
SetFocus(minecraft_handle)
pywintypes.error: (5, 'SetFocus', 'Access is denied.')
Any help will be appreciated. Documentation for library: http://timgolden.me.uk/pywin32-docs/win32_modules.html edit: posted wrong error message
According to [MS.Docs]: SetFocus function (emphasis is mine):
Sets the keyboard focus to the specified window. The window must be attached to the calling thread's message queue.
...
By using the AttachThreadInput function, a thread can attach its input processing to another thread. This allows a thread to call SetFocus to set the keyboard focus to a window attached to another thread's message queue.
Obviously the "remote" window is not attached to the Python script (main) thread, so that needs to be taken care of (with a bit of extra work).
code00.py:
#!/usr/bin/env python
import sys
import win32gui as wgui
import win32process as wproc
import win32api as wapi
def main(*argv):
if not argv:
window_name = input("Enter window name: ")
else:
window_name = argv[0]
handle = wgui.FindWindow(None, window_name)
print("Window `{0:s}` handle: 0x{1:016X}".format(window_name, handle))
if not handle:
print("Invalid window handle")
return
remote_thread, _ = wproc.GetWindowThreadProcessId(handle)
wproc.AttachThreadInput(wapi.GetCurrentThreadId(), remote_thread, True)
prev_handle = wgui.SetFocus(handle)
if __name__ == "__main__":
print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
main(*sys.argv[1:])
print("\nDone.")
Output:
[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q062649124]> "e:\Work\Dev\VEnvs\py_pc064_03.07.06_test0\Scripts\python.exe" code00.py "Untitled - Notepad" Python 3.7.6 (tags/v3.7.6:43364a7ae0, Dec 19 2019, 00:42:30) [MSC v.1916 64 bit (AMD64)] 64bit on win32 Window `Untitled - Notepad` handle: 0x0000000004A520AA Done.
Needless to say that the Notepad window popped up in front of Cmd terminal.
Note that for some windows, it might not work.