使终端保持焦点

Posted

技术标签:

【中文标题】使终端保持焦点【英文标题】:Keeping the terminal in focus 【发布时间】:2015-08-11 07:09:30 【问题描述】:

我有一个使用 selenium 自动化网页的 python 脚本,将焦点从需要用户输入的终端上移开。

python 中有没有以编程方式将焦点切换回终端?

如果重要的话,我将在 Windows 7 上的 Windows 命令提示符中运行我的程序,但跨平台答案将是最有用的。


尝试

查看 win32 API 的 pywin32 包绑定我有以下内容:

import win32console
import win32gui
from selenium import webdriver as wd

d = wd.Firefox()
win32gui.SetFocus(win32console.GetConsoleWindow())
win32gui.FlashWindow(win32console.GetConsoleWindow(), False)
input('Should have focus: ')

SetFocus 导致错误 pywintypes.error: (5, 'SetFocus', 'Access is denied.'),因为 Microsoft 删除了从另一个应用程序获取焦点的能力。

FlashWindow 似乎什么也没做。

【问题讨论】:

javascript提示不是用户输入的选项吗? @Saifur 不是真的,我的脚本是用 python 编写的(所以很难让它在浏览器开发者控制台中运行)并且自动化涉及关闭和打开多个浏览器,它们都带有自己的开发者控制台.理想情况下,我正在寻找一个可以从 python 执行的单个 python 包或脚本,它将焦点带回终端。 为什么不使用虚拟机来托管所有与硒相关的活动?也许使用 selenium grid 或 ssh 来启动任何 selenium 脚本? 执行win32gui.SetFocus(win32console.GetConsoleWindow()),我收到以下错误:“pywintypes.error: (5, 'SetFocus', 'Access is denied.')”。看来你没有..知道为什么吗? (我运行 Python 2.7+) 【参考方案1】:

这并不能真正回答您的问题,但简单的解决方案是首先不要将注意力转移:

driver = webdriver.PhantomJS()
# ...

PhantomJS webdriver 没有任何 UI,因此不会窃取焦点。

【讨论】:

感谢您的建议,但我使用 selenium 的原因是通过 UI 自动化多个浏览器。 啊,所以你用它来做跨浏览器测试? 是,也不是,我的自动化有多个用例,其中之一是程序测试,但我也将它们用于展示和视觉检查。【参考方案2】:

要获得焦点,请检查 cmets 至 this answer。

一种跨平台的方法可能是将 Tkinter 用于用户 GUI,因为它具有抓取和设置其窗口焦点的方法。

【讨论】:

我已尝试按照您的建议使用 win32 API,但遇到了问题,请参阅我的问题编辑。 您能否解释一下我将如何在我的用例中使用 Tkinter,我查看了文档但找不到解决方案。 使用Tkinter,您将创建自己的控制台类型窗口来与用户交互,而Tkinter 有自己的获取焦点的方法。【参考方案3】:

这是我想出的似乎可行的方法。

class WindowManager:
    def __init__(self):
        self._handle = None

    def _window_enum_callback( self, hwnd, wildcard ):
        if re.match(wildcard, str(win32gui.GetWindowText(hwnd))) != None:
            self._handle = hwnd

    #CASE SENSITIVE
    def find_window_wildcard(self, wildcard):
        self._handle = None
        win32gui.EnumWindows(self._window_enum_callback, wildcard)

    def set_foreground(self):
        win32gui.ShowWindow(self._handle, win32con.SW_RESTORE)
        win32gui.SetWindowPos(self._handle,win32con.HWND_NOTOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE + win32con.SWP_NOSIZE)  
        win32gui.SetWindowPos(self._handle,win32con.HWND_TOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE + win32con.SWP_NOSIZE)  
        win32gui.SetWindowPos(self._handle,win32con.HWND_NOTOPMOST, 0, 0, 0, 0, win32con.SWP_SHOWWINDOW + win32con.SWP_NOMOVE + win32con.SWP_NOSIZE)
        shell = win32com.client.Dispatch("WScript.Shell")
        shell.SendKeys('%')
        win32gui.SetForegroundWindow(self._handle)

    def find_and_set(self, search):
        self.find_window_wildcard(search)
        self.set_foreground()

然后要找到一个窗口并使其处于活动状态,您可以...

w = WindowManager()
w.find_and_set(".*cmd.exe*")

这是在 python 2.7 中,还有一些我找到的链接来解释为什么你必须经历这么多麻烦来切换活动窗口。

win32gui.SetActiveWindow() ERROR : The specified procedure could not be found

Windows 7: how to bring a window to the front no matter what other window has focus?

【讨论】:

这很受启发!有很好的理由,它完美地回答了我的问题。这里有一些赏金!【参考方案4】:

如果您不关心清除 matplotlib 框架中显示的任何图形——我相信通常情况下,当人们想要将焦点重新放在控制台上以供用户输入时——只需使用这个:

plt.close("all")

【讨论】:

以上是关于使终端保持焦点的主要内容,如果未能解决你的问题,请参考以下文章

如何使焦点保持在同一对话框上的所有列表控件上?

保持终端对焦

Python GUI 窗口在没有焦点的情况下保持在顶部

使导航栏活动链接背景颜色保持突出显示

选择后保持焦点 Select2

ListView 内的 EditText 不会保持焦点[重复]