今天想將opencv中的視窗置頂,以便在任何時候都可以看到網路攝影機顯示的內容。
opencv中通過cvGetWindowHandle可以擷取視窗控制代碼。cvGetWindowHandle的傳回值解釋如下:
函數cvGetWindowHandle返回原始的視窗控制代碼(在Win32情況下返回HWND,GTK+情況下返回GtkWidget)
剛開始處理時,通過以下方法:
HWND hWnd = (HWND)cvGetWindowHandle("raw");
if (hWnd!= NULL) {
BOOL bRet = ::SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE |SWP_NOMOVE);
assert(bRet);
}
傳回值正確,但確沒達到效果。經過一番驗證,原來hWnd指向的不是“raw”視窗的控制代碼。通過GetWindowText擷取的視窗標題為空白的。查看cvNameWindow代碼,原來cvNameWindow建立視窗的時候會建立兩個視窗,一個主視窗,一個子視窗。
代碼如下:
CV_IMPL int cvNamedWindow( const char* name, int flags )
{
...... ......
HWND hWnd, mainhWnd;
CvWindow* window;
DWORD defStyle = WS_VISIBLE | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU;
...... ......
mainhWnd = CreateWindow( "Main HighGUI class", name, defStyle | WS_OVERLAPPED,
rect.x, rect.y, rect.width, rect.height, 0, 0, hg_hinstance, 0 );
if( !mainhWnd )
CV_ERROR( CV_StsError, "Frame window can not be created" );
ShowWindow(mainhWnd, SW_SHOW);
//YV- remove one border by changing the style
hWnd = CreateWindow("HighGUI class", "", (defStyle & ~WS_SIZEBOX) | WS_CHILD, CW_USEDEFAULT, 0, rect.width, rect.height, mainhWnd, 0, hg_hinstance, 0);
if( !hWnd )
CV_ERROR( CV_StsError, "Frame window can not be created" );
ShowWindow(hWnd, SW_SHOW);
...... ......
}
恍然大悟,於是將代碼改成如下,F5運行,ok。搞定。
HWND hWnd = (HWND)cvGetWindowHandle("raw");
HWND hRawWnd = ::GetParent(hWnd);
if (hRawWnd != NULL) {
BOOL bRet = ::SetWindowPos(hRawWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE |SWP_NOMOVE);
assert(bRet);
}
看來以後要多跟跟原始碼,這樣可以減少一些不必要的功夫。