如果窗口没有标题,如何使窗口成为焦点?

时间:2017-11-10 12:13:08

标签: python python-3.x windows-10 openframeworks win32gui

我们有一个使用openframeworks构建的应用。启动时,它首先打开一个控制台窗口,它可以完成一些工作(并保持打开状态),然后启动另外两个子进程,每个进程都以全屏打开一个窗口,每个监视器一个。根据正在构建应用程序的人来说,不可能给这两个窗口标题。

我的工作是构建一个脚本:

  1. 检查应用是否已崩溃并重新打开
  2. 验证窗口是否在前台,其中一个是焦点,如果不是
  3. 则修复它们

    我想重用我的一个旧的python脚本,并完成了这个并改变它以适应账单。

    from time import sleep
    import subprocess
    import psutil
    import re
    import win32gui
    import win32con
    
    client_path = "C:\\path_to_app.exe"
    window_name = ""
    
    
    class WindowMgr:
        """Encapsulates some calls to the winapi for window management"""
    
        def __init__(self, ):
            """Constructor"""
            self._handle = None
    
        def find_window(self, class_name, window_name=None):
            """find a window by its class_name"""
            self._handle = win32gui.FindWindow(class_name, window_name)
    
        def _window_enum_callback(self, hwnd, wildcard):
            '''Pass to win32gui.EnumWindows() to check all the opened windows'''
            if re.match(wildcard, str(win32gui.GetWindowText(hwnd))) is not None:
                self._handle = hwnd
    
        def find_window_wildcard(self, wildcard):
            self._handle = None
            win32gui.EnumWindows(self._window_enum_callback, wildcard)
    
        def set_foreground(self):
            """put the window in the foreground"""
            win32gui.SetForegroundWindow(self._handle)
    
        def maximize(self):
            win32gui.ShowWindow(self._handle, win32con.SW_MAXIMIZE)
    
        def is_minimized(self):
            return win32gui.IsIconic(self._handle)
    
    
    def client_crashed():
        for pid in psutil.pids():
            if psutil.Process(pid).name() == "app.exe":
                return False
        return True
    
    
    if __name__ == "__main__":
    
        w = WindowMgr()
        w.find_window_wildcard(window_name)
        print("Checking")
        while True:
            if client_crashed() is True:
                print("Reopening app.exe")
                subprocess.Popen([client_path])
            else:
                print("Not crashed")
            if w.is_minimized:
                print("Maximizing")
                w.set_foreground()
                w.maximize()
            else:
                print("Not minimized")
    
            print("Sleeping for 10")
            sleep(10)
    

    现在检查崩溃和重启工作正常。但由于窗口没有标题,我到目前为止最好的方法是检查没有名称的窗口,这显然会打开像Windows 10电影程序那样的随机程序(或至少将它们带到前台,是奇怪的,因为他们不应该跑步。)

    是否有更好的方法可以在不知道名称的情况下将窗口置于焦点之外?我的一个想法是获得父进程然后从那里访问孩子并以某种方式将他们聚焦,但我还没有弄清楚如何。

    如果有更好的方法来实现我想要的东西而不是使用python,我也很乐意在这方面有任何指示。

2 个答案:

答案 0 :(得分:1)

如果您有唯一的窗口类名,可以尝试GetClassName()https://msdn.microsoft.com/en-us/library/windows/desktop/ms633582(v=vs.85).aspx

或者获取窗口进程GetWindowThreadProcessId()并检查它是否是您应用的实例。见How to get the process name in C++

答案 1 :(得分:1)

我的一个想法是获取父流程,然后 从那里接触孩子并以某种方式使他们集中注意力,但是 我还不知道怎么做。”

我经历过非常类似的问题,我想找到一个带有随机标题名称的子进程,我只有可执行文件的名称。这就是我所做的。

import win32gui


def windowFocusPassingPID(pid):
    def callback(hwnd, list_to_append):
        list_to_append.append((hwnd, win32gui.GetWindowText(hwnd)))

    window_list = []
    win32gui.EnumWindows(callback, window_list)
    for i in window_list:
        print(i)  # if you want to check each item
        if pid == i[0]:
            print(i)  # printing the found item (id, window_title)
            win32gui.ShowWindow(i[0], 5)
            win32gui.SetForegroundWindow(i[0])
            break

# Here we will call the function, providing a valid PID
windowFocusPassingPID(INSERT_PID_HERE_IT_MUST_BE_AN_INTEGER)

因此,这是一个将调用win32gui.EnumWindows的函数,该函数处理所有顶级窗口。这些窗口将被追加到window_list中,让我们知道所有ID和窗口名称... 在循环中,我们将遍历列表,并匹配您要关注的PID ... 您可以根据需要对两个print(i)进行注释。

以下是文档:

http://timgolden.me.uk/pywin32-docs/win32gui__EnumWindows_meth.html