OpenCV WND_PROP_TOPMOST 属性未关闭

问题描述 投票:0回答:1

我正在使用 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

并且窗口保持在最顶层状态(其他窗口即使具有焦点也不会出现在上面)。

python opencv window
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

事实上,按下一个键进入第二阶段后,窗口不再保持在最上面。

The window is top-most

The window is no longer top-most


报告错误:https://github.com/opencv/opencv/issues/25833

© www.soinside.com 2019 - 2024. All rights reserved.