Python 如何关注应用程序';当任务管理器';s窗口聚焦了吗?
我有一个Python脚本,它创建了一个应用程序的实例,并显示了应用程序的窗口 我正在尝试激活/聚焦窗口,使其位于前台/顶部,并具有键盘输入焦点Python 如何关注应用程序';当任务管理器';s窗口聚焦了吗?,python,winapi,focus,foreground,Python,Winapi,Focus,Foreground,我有一个Python脚本,它创建了一个应用程序的实例,并显示了应用程序的窗口 我正在尝试激活/聚焦窗口,使其位于前台/顶部,并具有键盘输入焦点 def bring_window_to_top(window_handle): import ctypes # import win32com.client # from win32con import HWND_TOP, HWND_TOPMOST, SWP_NOMOVE, SWP_NOSIZE current_thread_id =
def bring_window_to_top(window_handle):
import ctypes
# import win32com.client
# from win32con import HWND_TOP, HWND_TOPMOST, SWP_NOMOVE, SWP_NOSIZE
current_thread_id = ctypes.windll.kernel32.GetCurrentThreadId()
foreground_window_handle = ctypes.windll.user32.GetForegroundWindow()
foreground_thread_id = ctypes.windll.user32.GetWindowThreadProcessId(foreground_window_handle, None)
ctypes.windll.user32.AttachThreadInput(current_thread_id, foreground_thread_id, True)
ctypes.windll.user32.BringWindowToTop(window_handle)
# ctypes.windll.user32.SwitchToThisWindow(window_handle, True)
# ctypes.windll.user32.SwitchToThisWindow(window_handle, False)
# ctypes.windll.user32.SetWindowPos(window_handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE)
# ctypes.windll.user32.SetWindowPos(window_handle, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE)
# wscript_shell = win32com.client.Dispatch('WScript.Shell')
# wscript_shell.SendKeys('%')
# ctypes.windll.user32.SetForegroundWindow(window_handle)
# ctypes.windll.user32.SetFocus(window_handle)
# ctypes.windll.user32.SetActiveWindow(window_handle)
# ctypes.windll.user32.AttachThreadInput(current_thread_id, foreground_thread_id, False)
下面的代码通常可以工作,但是当任务管理器的窗口在代码执行之前打开并聚焦时,应用程序的窗口会显示在任务管理器的下面,任务管理器会保持键盘输入的焦点
def bring_window_to_top(window_handle):
import ctypes
# import win32com.client
# from win32con import HWND_TOP, HWND_TOPMOST, SWP_NOMOVE, SWP_NOSIZE
current_thread_id = ctypes.windll.kernel32.GetCurrentThreadId()
foreground_window_handle = ctypes.windll.user32.GetForegroundWindow()
foreground_thread_id = ctypes.windll.user32.GetWindowThreadProcessId(foreground_window_handle, None)
ctypes.windll.user32.AttachThreadInput(current_thread_id, foreground_thread_id, True)
ctypes.windll.user32.BringWindowToTop(window_handle)
# ctypes.windll.user32.SwitchToThisWindow(window_handle, True)
# ctypes.windll.user32.SwitchToThisWindow(window_handle, False)
# ctypes.windll.user32.SetWindowPos(window_handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE)
# ctypes.windll.user32.SetWindowPos(window_handle, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE)
# wscript_shell = win32com.client.Dispatch('WScript.Shell')
# wscript_shell.SendKeys('%')
# ctypes.windll.user32.SetForegroundWindow(window_handle)
# ctypes.windll.user32.SetFocus(window_handle)
# ctypes.windll.user32.SetActiveWindow(window_handle)
# ctypes.windll.user32.AttachThreadInput(current_thread_id, foreground_thread_id, False)
代码中的注释是我试图绕过特定问题的尝试,但也没有奏效。只有在将切换到此窗口与False
或SetWindowPos
与HWND\u TOPMOST
(将窗口设置为最顶部)一起使用时,该窗口才会显示在任务管理器窗口的顶部,但任务管理器仍保持键盘输入焦点
def bring_window_to_top(window_handle):
import ctypes
# import win32com.client
# from win32con import HWND_TOP, HWND_TOPMOST, SWP_NOMOVE, SWP_NOSIZE
current_thread_id = ctypes.windll.kernel32.GetCurrentThreadId()
foreground_window_handle = ctypes.windll.user32.GetForegroundWindow()
foreground_thread_id = ctypes.windll.user32.GetWindowThreadProcessId(foreground_window_handle, None)
ctypes.windll.user32.AttachThreadInput(current_thread_id, foreground_thread_id, True)
ctypes.windll.user32.BringWindowToTop(window_handle)
# ctypes.windll.user32.SwitchToThisWindow(window_handle, True)
# ctypes.windll.user32.SwitchToThisWindow(window_handle, False)
# ctypes.windll.user32.SetWindowPos(window_handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE)
# ctypes.windll.user32.SetWindowPos(window_handle, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE)
# wscript_shell = win32com.client.Dispatch('WScript.Shell')
# wscript_shell.SendKeys('%')
# ctypes.windll.user32.SetForegroundWindow(window_handle)
# ctypes.windll.user32.SetFocus(window_handle)
# ctypes.windll.user32.SetActiveWindow(window_handle)
# ctypes.windll.user32.AttachThreadInput(current_thread_id, foreground_thread_id, False)
我还尝试使用函数AllowSetForeGroundIndow
、LockSetForeGroundIndow
和SystemParametersInfoW
将SPI\u SETFOREGROUNDLOCKTIMEOUT
设置为0
,但我收到的错误是访问被拒绝。
有什么方法可以实现吗?您需要在清单中将UIAccess设置为true以支持可访问性功能
使用UIAccess权限启动的进程具有以下特性
能力:
- 设置前景窗口。
- 使用SendInput功能驱动任何应用程序窗口
- 通过使用低级钩子、原始输入、GetKeyState、GetAsyncKeyState和GetKeyboardInput,对所有完整性级别使用读取输入
- 设置日志挂钩
- 使用
AttachThreadInput
将线程附加到更高完整性的输入队列。
首先,在清单中设置uiAccess=true
然后,在代码上签名
最后,将其放在文件系统上的安全位置:
- \程序文件\包括子目录
- \Windows\system32\
- \程序文件(x86)\n包括64位版本的
窗户
你可以参考和
更新:
要设置对python脚本的UIAccess,请执行以下操作:
安装PyInstaller:pip安装PyInstaller
使用Pyinstaller从Python脚本生成可执行文件
这是我的测试示例,它设置了一个5秒的计时器,使窗口处于顶部
hello.pyw:
import win32api, win32con, win32gui
import ctypes
class MyWindow:
def __init__(self):
win32gui.InitCommonControls()
self.hinst = win32api.GetModuleHandle(None)
className = 'MyWndClass'
message_map = {
win32con.WM_DESTROY: self.OnDestroy,
win32con.WM_TIMER: self.OnTimer,
}
wndcls = win32gui.WNDCLASS()
wndcls.style = win32con.CS_HREDRAW | win32con.CS_VREDRAW
wndcls.lpfnWndProc = message_map
wndcls.lpszClassName = className
win32gui.RegisterClass(wndcls)
style = win32con.WS_OVERLAPPEDWINDOW
self.hwnd = win32gui.CreateWindow(
className,
'Title',
style,
win32con.CW_USEDEFAULT,
win32con.CW_USEDEFAULT,
500,
500,
0,
0,
self.hinst,
None
)
win32gui.UpdateWindow(self.hwnd)
win32gui.ShowWindow(self.hwnd, win32con.SW_SHOW)
ctypes.windll.user32.SetTimer(self.hwnd,1,5000,0)
def OnDestroy(self, hwnd, message, wparam, lparam):
win32gui.PostQuitMessage(0)
return True
def OnTimer(self, hwnd, message, wparam, lparam):
current_thread_id = ctypes.windll.kernel32.GetCurrentThreadId()
foreground_window_handle = ctypes.windll.user32.GetForegroundWindow()
foreground_thread_id = ctypes.windll.user32.GetWindowThreadProcessId(foreground_window_handle, None)
ctypes.windll.user32.BringWindowToTop(hwnd)
return True
w = MyWindow()
win32gui.PumpMessages()
使用--manifest
选项或直接使用pyinstaller--uac uiaccess hello.pyw
,则exe文件位于dist\\hello
创建证书并对应用程序进行签名,示例(不要忘记将证书安装到受信任的根证书颁发机构):
将其放在文件系统上的安全位置,例如,我将dist\\hello
放在C:\\Program Files
结果:
需要。