获取OpenCV中当前活动窗口的句柄

3
是否有OpenCV等效的GLUT glutGetWindow()/glutSetWindow()函数,允许从您自己的代码中识别当前活动窗口并切换?
基本上,我想能够在所有窗口注册的鼠标回调函数中识别当前活动窗口,并使用不同的参数调用另一个处理函数。
任何帮助都将不胜感激。
4个回答

2
在OpenCV中没有这样的功能,但是cvSetMouseCallback()的签名允许您为每个窗口注册一个回调函数。
您需要注册单独的回调函数来实现您需要做的事情。
这是HIGHGUI模块支持的完整列表
另一种(极端)替代方法是深入了解您正在使用的操作系统的本机API,并搜索可完成此操作的方法。问题在于,这种解决方案不跨平台。

真是遗憾。目前,我决定使用模板函数将一些东西凑在一起,其中窗口ID是模板参数。这并不优雅或聪明,但暂时可以用。 - TheTaintedOne

1

包含<opencv/highgui/highgui_c.h>可能是一种解决方案,但它确实不会让您转向Opencv4 +。

对于仍在使用MFC DialogBox中的Opencv的人,有一个不同的解决方案

FindWindows返回父窗口句柄,而MFC与子窗口一起工作,因此您需要FindWindow和FindWindowEx。

MFC和Opencv4+的新源代码

namedWindow(windowname, WINDOW_AUTOSIZE);

////// This will work on opencv 4.X //////

HWND hParent = (HWND)FindWindow(NULL, windowname.c_str());
HWND hWnd = (HWND)FindWindowEx(hParent, NULL, L"HighGUI class", NULL);

::SetParent(hWnd, GetDlgItem(IDC_PICTURE)->m_hWnd);
::ShowWindow(hParent, SW_HIDE);

CWnd* pWnd = new CWnd();
pWnd->CWnd::Attach(hParent);

也许您仍然因为字符串转换为LPCWSTR失败而感到困扰,而hParent返回NULL。有很多方法可以将字符串转换为LPCWSTR,但由于您正在使用MFC,请尝试。
namedWindow(windowname, WINDOW_AUTOSIZE);

////// This will work on opencv 4.X //////

CString CstrWindowname = windowname.data();
    
HWND hParent = (HWND)FindWindow(NULL, CstrWindowname);
HWND hWnd = (HWND)FindWindowEx(hParent, NULL, L"HighGUI class", NULL);

::SetParent(hWnd, GetDlgItem(IDC_PICTURE)->m_hWnd);
::ShowWindow(hParent, SW_HIDE);

CWnd* pWnd = new CWnd();
pWnd->CWnd::Attach(hParent);

新代码应替换此旧代码。
namedWindow(windowname, WINDOW_AUTOSIZE);

///// OLD version. Used on opencv 3.X on MFC Dialog Box /////

HWND hWnd = (HWND) cvGetWindowHandle(windowname.c_str());    
HWND hParent = ::GetParent(hWnd);

::SetParent(hWnd, GetDlgItem(IDC_PICTURE)->m_hWnd);
::ShowWindow(hParent, SW_HIDE);

CWnd* pWnd = new CWnd();
pWnd->CWnd::Attach(hParent);

尝试,

1
实际上,cvGetWindowHandle(const char* windowname) 可以在 opencv/highgui/highgui_c.h 中找到。这个函数在本回答编写时适用于 openCV 4 版本之前。
我建议你添加:
#include <opencv/highgui/highgui_c.h> 

and use

cvGetWindowHandle(window_name_.c_str())

0

好的,没有针对检索焦点窗口的OpenCV API,但通常操作系统GUI Shell会提供。使用这种方法会更好,因为鼠标回调无法检测ALT-TAB和编程焦点。

下面是一些在Windows上实现此功能的Python示例代码:

import ctypes
import cv2

user32 = ctypes.windll.user32

def exists_cv_window(title):
    # seems to work on python-opencv version 4.6.0
    return cv2.getWindowProperty(title, cv2.WND_PROP_VISIBLE) != 0.0


def get_active_cv_window():
    focused_window_handle = user32.GetForegroundWindow()
    length = user32.GetWindowTextLengthW(focused_window_handle)
    buffer = bytes([0]) * 2 * length
    buff_pointer = ctypes.c_char_p(buffer)
    user32.GetWindowTextW(window_handle, buff_pointer, length)
    active_window_title = buffer.decode('utf-16')
    if exists_cv_window(active_window_title):
        return active_window_title


# example use case for the function
def main():
    im1 = cv2.imread('cookie.png')
    im2 = cv2.imread('cat.png')
    cv2.imshow('figure 1', im1)
    cv2.imshow('figure 2', im2)
    while True:
        key = cv2.waitKey(10)
        if key == 23:   # CTRL + W
            title = get_active_cv_window()
            if title is not None:
                cv2.destroyWindow(title)

# in the example above the ability to target active window allows applying
# CTRL + W shortcut to a specific figure

很遗憾这不是OpenCV的一部分


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接