我正在使用 Python 中的以下命令将窗口设置为始终显示在顶部。我希望此设置可以切换,但是设置后我无法“取消设置”此属性。
import cv2
import numpy as np
frame = np.zeros((240, 320, 3), np.uint8)
window = "Test Window"
def show_window(window, frame):
print(cv2.getWindowProperty(window, cv2.WND_PROP_TOPMOST))
while(True):
cv2.imshow(window, frame)
if cv2.waitKey() > 0:
break
cv2.namedWindow(window)
cv2.setWindowProperty(window, cv2.WND_PROP_TOPMOST, 1)
show_window(window, frame)
cv2.setWindowProperty(window, cv2.WND_PROP_TOPMOST, 0)
show_window(window, frame)
打印出来
1.0
1.0
并且窗口保持在最顶层状态(其他窗口即使具有焦点也不会出现在上面)。
这看起来像一个错误,所以让我们证明一下。
实现看起来像这样:
static bool setPropTopmost_(CvWindow& window, bool topmost)
{
HWND flag = topmost ? HWND_TOPMOST : HWND_TOP;
BOOL success = SetWindowPos(window.frame, flag, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
// The rest is not relevant...
}
第一个语句是关键——要启用最顶层的状态,它使用
HWND_TOPMOST
,要禁用它,它使用HWND_TOP
,这就是问题所在。
SetWindowPos
的文档,我们可以看到对于 HWND_BOTTOM
它确实提到了
...如果
参数标识最顶层窗口,则该窗口将失去其最顶层状态,并放置在所有其他窗口的底部。hWnd
但是,它并没有说
HWND_TOP
,只是说它将窗口放在顶部。此外,它稍后在页面上提到(强调我的)
如果最顶层窗口重新定位到 Z 顺序的底部 (
) 或 在任何非最顶层窗口之后,则它不再是最顶层。HWND_BOTTOM
最后,有一个伪句柄
HWND_NOTOPMOST
,描述为(再次强调我的)
将窗口放置在所有非最顶层窗口上方(即 在所有最顶层窗口后面)。
因此我得出结论,
HWND_TOP
是使窗口不再位于最顶层的错误方法。相反,应该使用 HWND_NOTOPMOST
。这个假设可以使用 PyWin32 轻松验证,它让我们可以直接从 Python 使用 Windows API。我们只需将 cv2.setWindowProperty
替换为 FindWindow
,然后用右侧的伪句柄替换 SetWindowPos
。
import cv2
import numpy as np
import win32gui
import win32con
frame = np.zeros((240, 320, 3), np.uint8)
window = "Test Window"
def show_window(window, frame):
print(cv2.getWindowProperty(window, cv2.WND_PROP_TOPMOST))
while(True):
cv2.imshow(window, frame)
if cv2.waitKey() > 0:
break
cv2.namedWindow(window)
cv2.setWindowProperty(window, cv2.WND_PROP_TOPMOST, 1)
show_window(window, frame)
wnd_handle = win32gui.FindWindow(None, window)
win32gui.SetWindowPos(wnd_handle, win32con.HWND_NOTOPMOST, 0, 0, 0, 0, win32con.SWP_NOMOVE + win32con.SWP_NOSIZE);
show_window(window, frame)
此打印
1.0
0.0
事实上,按下一个键进入第二阶段后,窗口不再保持在最上面。