Bring window to focus with python periodically - python

import win32gui
import time
def windowEnumerationHandler(hwnd, top_windows):
top_windows.append((hwnd, win32gui.GetWindowText(hwnd)))
if __name__ == "__main__":
top_windows = []
win32gui.EnumWindows(windowEnumerationHandler, top_windows)
for i in top_windows:
print(i)
if "zoom" in i[1].lower():
print(i, 'is found')
while True:
win32gui.ShowWindow(i[0],5)
win32gui.SetForegroundWindow(i[0])
time.sleep(1)
I've heard that zoom monitors whether the window is not in focus for more than 30 seconds, so I've been working on a way to repetitively throw it to the front while I work on other projects. The problem is the code raises an exception
0, 'SetForegroundWindow', 'No error message is available'
and the window just flashes yellow. Same problem with chrome as well. Would appreciate some help here :)

I had the same problem while I was trying to SetForegroundWindow(hwnd). The icon on the taskbar was just flashing, but the program stayed in the background. As you can read here:
https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-setforegroundwindow?redirectedfrom=MSDN
"An application cannot force a window to the foreground while the user is working with another window. Instead, Windows flashes the taskbar button of the window to notify the user."
For me helped:
import win32gui, win32com.client
shell = win32com.client.Dispatch("WScript.Shell")
shell.SendKeys('%')
win32gui.SetForegroundWindow(hwnd)

Related

Simulating mouse click using python and win32api

I am trying to simulate a mouse left click on a window (Samsung Flow) but unfortunately it is not working. When I try on a google chrome window it works, but I have tried on Paint and on Samsung Flow but it does not work. Here is my code:
import win32api
import win32con
import time
import random
def enumHandler(hwnd, lParam):
if win32gui.IsWindowVisible(hwnd):
# if 'Stack Overflow' in win32gui.GetWindowText(hwnd):
if 'Samsung Flow' in win32gui.GetWindowText(hwnd):
print(win32gui.GetWindowText(hwnd))
for _ in range(50):
l_param = win32api.MAKELONG(random.randint(10, 500), random.randint(10, 500))
win32gui.PostMessage(hwnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, l_param)
time.sleep(0.1)
win32gui.PostMessage(hwnd, win32con.WM_LBUTTONUP, win32con.MK_LBUTTON, l_param)
time.sleep(0.1)
win32gui.EnumWindows(enumHandler, None)
I know that it detects the window as I am printing the detected text, but I do not know why it only work on the Chrome window.
Update
I have tried the following code, to search two windows notepad and browser:
import win32gui
import win32api
import win32con
import time
def enumHandler(hwnd, lParam):
if win32gui.IsWindowVisible(hwnd):
# if 'Notepad' in win32gui.GetWindowText(hwnd):
if 'Stack Overflow' in win32gui.GetWindowText(hwnd):
print(win32gui.GetWindowText(hwnd))
win32gui.SetForegroundWindow(hwnd)
win32api.SendMessage(hwnd, win32con.WM_CHAR, ord("c"), 0)
time.sleep(0.1)
win32gui.EnumWindows(enumHandler, None)
And the result was:
when using on the browser (searching for Stack Overflow window), the window came to foreground and printed the letter c
when using the notepad the window came to foreground but the letter was not printed! and I have no idea why.
Well, I found the problem.
With the example trying to send the letter C to notepad and the chrome browser I assumed that the first hwnd is the right one BUT in some cases, you have to interact with a child window. A window may have more than one child window, so, I will post a code here where you can find the window to interact with.
import win32gui
import win32con
import win32api
import time
def send_char(hwnd, lparam):
s = win32gui.GetWindowText(hwnd)
print("child_hwnd: %d txt: %s" % (hwnd, s))
win32api.PostMessage(hwnd, win32con.WM_CHAR, ord('c'), 0)
time.sleep(5)
return 1
def main():
main_app = 'Untitled - Notepad'
hwnd = win32gui.FindWindow(None, main_app)
if hwnd:
win32gui.EnumChildWindows(hwnd, send_char, None)
main()
With that you can find the child window that you should send the messages to (the code print the window id and name, send the character and wait 5 seconds, so when you notice the character on your window just get the last printed window id and use it instead of the parent window).
I hope it help someone facing the same problem.

Handling Context Menu of the taskbar icon with pywinauto

I am trying to automate the exiting operation on one of the apps. The app's icon is located in the taskbar. I was successfull in opening that icon's context menu with the modified code that I have found on stackoverflow:
import pywinauto
from pywinauto.application import Application
import time
app= "Service is enabled."
app = Application(backend="uia").connect(path="explorer.exe")
st = app.window(class_name="Shell_TrayWnd")
t = st.child_window(title="Notification Chevron").wrapper_object()
t.click()
time.sleep(1)
list_box = Application(backend="uia").connect(class_name="NotifyIconOverflowWindow")
list_box_win = list_box.window(class_name="NotifyIconOverflowWindow")
list_box_win.wait('visible', timeout=30, retry_interval=3)
# time.sleep(1)
appOpened= list_box_win.child_window(title = app)
appOpened.click_input(button = "right")
After the execution of the code above I get to the point when the context menu is opened:
The next thing that I want to do is to click on Exit, I have tried doing it by specifying the mouse click coordinates, but I have noticed that the position of the parent icon is changing from time to time.
What I would like to do is to get the handle on the Exit button and send click automatically.
------Edit-------
The icon is located in the hidden icons
So you want to access to the right click context menu. As said in this answer, you can do something like :
listbox.PopupMenu["Exit"].set_focus().click_input()

How to close two windows of the same application using python?

I'm working on an automation program in python, I've two windows of cmd open on my screen. I want my code to only close the first window, and leave the second window as it is. How will I make my code determine which window to close?
To close the window I'm using the keyboard package in python, the code writes exit in the cmd window and generates an enter key press to exit the window.
keyboard.write("exit") # closes main cmd window
keyboard.press_and_release("enter") # window closes
If you use Windows OS, you can use the pywin32 and win32gui libraries which contain the modules win32gui and win32con which will help search through windows matching a certain name and getting the window handle number (hwnd). Given a hwnd, you can then close the first window that was opened.
You will first need to install pywin32 and wind32gui:
pip install win32gui
pip install pywin32
Here's the code to close the first command prompt window:
import win32gui
import win32con
def windowEnumerationHandler(hwnd, top_windows):
top_windows.append((hwnd, win32gui.GetWindowText(hwnd)))
def return_window_hwnd(window_name):
'''Return list window handles of that match a given window name'''
windows = []
win32gui.EnumWindows(windowEnumerationHandler, windows)
print(windows) #[(67084, 'Command Prompt'), (65868, ''), (722426, 'Command Prompt'), ...]
hwnds = []
for wind in windows:
if window_name in wind[1] or window_name == wind[1]:
hwnds.append(wind[0])
return hwnds
# search for Command Prompt windows and return the list of hwnd
command_hwnd_arr = return_window_hwnd('Command Prompt')
# if more than 1 is window open, close the first opened window
if len(command_hwnd_arr) > 1:
window_handle_to_close = command_hwnd_arr[1]
win32gui.PostMessage(window_handle_to_close, win32con.WM_CLOSE, 0, 0)

Python - How to interact with system tray popup

I want to autologin to an app via its system tray icon.
I use the pywinauto module to interact with the tray icon to launch the app and now I have a popup who ask me to log on.
But... I don't know how to interact with it !
This is my icon :
Tray Icon
Here, an extract of my code (works fine) :
_pApp = Application().connect(path='my_app_dir')
taskbar.ClickSystemTrayIcon(1)
_pApp.PopupMenu.menu_item('submenu').click_input()
_pApp.PopupMenu.menu_item('another_submenu').click_input()
How can I interact with the popup authentication window below ?
Popup window
Thanks for your help.
I finally found a solution with pywinauto.keyboard. I don't know if it's clean but it works.
from pywinauto.keyboard import *
[...]
send_keys(_user)
send_keys("{VK_TAB}")
send_keys(_pass)
send_keys("{ENTER}")
Finally, I found exactly the expected behavior :)
Thank you Vasily Ryabov ! Your method is very helpful !
I do not use 'send_keys' anymore.
from tkinter.messagebox import *
from pywinauto import taskbar
from pywinauto.application import Application
[...]
_user = "TOTO"
_pass = "TOTOPASS"
app_dir = r'C:\Program Files\Common Files\App\App.exe'
icon_list = list()
# Getting the name of the icons in the sys tray
for i in range(0, 13):
app_sti = taskbar.SystemTrayIcons.wrapper_object()
app_stv = pulse_sti.button(i).info.text
icon_list.append(app_stv)
# Looking for my app name
try:
if "App_name" in str(icon_list):
app = Application().connect(path=app_dir)
taskbar.ClickSystemTrayIcon("App name")
app.PopupMenu.menu_item('menu').click_input()
app.PopupMenu.menu_item('menu -> submenu').click_input()
app_auth = Application(backend="uia").connect(title_re="Title*", timeout=5)
app_auth_window = app_auth.window(title_re="Title*")
app_auth_window.child_window(title="User :", control_type="Edit").set_text(_user)
app_auth_window.child_window(title="Password :", control_type="Edit").set_text(_pass)
app_auth_window.child_window(title="Connect", control_type="Button").click()
except Exception as error:
showwarning("Error", "App not found !")
Currently, I re-write a part of my code :
from pywinauto import taskbar
from pywinauto.application import Application
from pywinauto.keyboard import *
from tkinter.messagebox import *
[...]
app_dir = r'C:\Program Files\Common Files\App\App.exe'
_user = "TOTO"
_pass = "TOTOPASS"
# Check if my app has its system tray icon in the taskbar
for i in range(0, 10):
tsIcon = taskbar.SystemTrayIcons.wrapper_object()
tsValue = tsIcon.button(i).info.text
# If I find it, the code click on it and its menu until the popup auth window come
if "App_name" in tsValue:
_pApp = Application().connect(path=app_dir)
taskbar.ClickSystemTrayIcon(i)
_pApp.PopupMenu.menu_item('menu').click_input()
_pApp.PopupMenu.menu_item('menu->submenu').click_input()
time.sleep(2)
# When the popup window comes out, I run 'send_keys'
send_keys(_user)
send_keys("{VK_TAB}")
send_keys(_pass)
send_keys("{ENTER}")
else:
showwarning("Error", "App not found !")
[...]
My code seems good ? There is another "most clean" method ?
Thanks

Python win32api get "stack" of windows

I'm looking for a way to find out what order windows are open on my desktop in order to tell what parts of what windows are visible to the user.
Say, in order, I open up a maximized chrome window, a maximized notepad++ window, and then a command prompt that only covers a small portion of the screen. Is there a way using the win32api (or possibly other library) that can tell me the stack of windows open so I can take the window dimensions and find out what is visible? I already know how to get which window has focus and the top-level window, but I'm looking for more info than that.
In the example I mentioned above, I'd return that the full command prompt is visible but in the places it isn't, the notepad++ window is visible for example. No part of the chrome window would be visible.
import win32gui
import win32con
def get_windows():
def sort_windows(windows):
sorted_windows = []
# Find the first entry
for window in windows:
if window["hwnd_above"] == 0:
sorted_windows.append(window)
break
else:
raise(IndexError("Could not find first entry"))
# Follow the trail
while True:
for window in windows:
if sorted_windows[-1]["hwnd"] == window["hwnd_above"]:
sorted_windows.append(window)
break
else:
break
# Remove hwnd_above
for window in windows:
del(window["hwnd_above"])
return sorted_windows
def enum_handler(hwnd, results):
window_placement = win32gui.GetWindowPlacement(hwnd)
results.append({
"hwnd":hwnd,
"hwnd_above":win32gui.GetWindow(hwnd, win32con.GW_HWNDPREV), # Window handle to above window
"title":win32gui.GetWindowText(hwnd),
"visible":win32gui.IsWindowVisible(hwnd) == 1,
"minimized":window_placement[1] == win32con.SW_SHOWMINIMIZED,
"maximized":window_placement[1] == win32con.SW_SHOWMAXIMIZED,
"rectangle":win32gui.GetWindowRect(hwnd) #(left, top, right, bottom)
})
enumerated_windows = []
win32gui.EnumWindows(enum_handler, enumerated_windows)
return sort_windows(enumerated_windows)
if __name__ == "__main__":
windows = get_windows()
for window in windows:
print(window)
print()
# Pretty print
for window in windows:
if window["title"] == "" or not window["visible"]:
continue
print(window)
Microsoft MSDN has good artice on zorder info with GetWindow() and GW_HWNDNEXT
https://msdn.microsoft.com/en-us/library/windows/desktop/ms633515(v=vs.85).aspx

Categories

Resources