#include "precomp.hpp"
+#ifdef HAVE_WIN32UI
+
+#include <opencv2/core/utils/logger.hpp>
+#include <opencv2/core/utils/trace.hpp>
+
+#include "backend.hpp"
+
using namespace cv;
#include <windowsx.h> // required for GET_X_LPARAM() and GET_Y_LPARAM() macros
-#if defined _WIN32
-
#ifdef __GNUC__
# pragma GCC diagnostic ignored "-Wmissing-declarations"
#endif
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
-#include <assert.h>
#ifdef HAVE_OPENGL
#include <memory>
#include <algorithm>
#include <vector>
#include <functional>
-#include "opencv2/highgui.hpp"
#include <GL/gl.h>
#include "opencv2/core/opengl.hpp"
#endif
#if defined _M_X64 || defined __x86_64 || defined _M_ARM64
#define icvGetWindowLongPtr GetWindowLongPtr
-#define icvSetWindowLongPtr( hwnd, id, ptr ) SetWindowLongPtr( hwnd, id, (LONG_PTR)(ptr) )
+#define icvSetWindowLongPtr(hwnd, id, ptr) SetWindowLongPtr(hwnd, id, (LONG_PTR)(ptr))
#define icvGetClassLongPtr GetClassLongPtr
#define CV_USERDATA GWLP_USERDATA
#else
#define icvGetWindowLongPtr GetWindowLong
-#define icvSetWindowLongPtr( hwnd, id, ptr ) SetWindowLong( hwnd, id, (size_t)ptr )
+#define icvSetWindowLongPtr(hwnd, id, ptr) SetWindowLong(hwnd, id, (size_t)ptr)
#define icvGetClassLongPtr GetClassLong
#define CV_USERDATA GWL_USERDATA
#define strcat_s mingw_strcat_s
#endif
-static void FillBitmapInfo( BITMAPINFO* bmi, int width, int height, int bpp, int origin )
+static void FillBitmapInfo(BITMAPINFO* bmi, int width, int height, int bpp, int origin)
{
- assert( bmi && width >= 0 && height >= 0 && (bpp == 8 || bpp == 24 || bpp == 32));
+ CV_Assert(bmi && width >= 0 && height >= 0 && (bpp == 8 || bpp == 24 || bpp == 32));
BITMAPINFOHEADER* bmih = &(bmi->bmiHeader);
- memset( bmih, 0, sizeof(*bmih));
+ memset(bmih, 0, sizeof(*bmih));
bmih->biSize = sizeof(BITMAPINFOHEADER);
bmih->biWidth = width;
bmih->biHeight = origin ? abs(height) : -abs(height);
bmih->biBitCount = (unsigned short)bpp;
bmih->biCompression = BI_RGB;
- if( bpp == 8 )
+ if (bpp == 8)
{
RGBQUAD* palette = bmi->bmiColors;
int i;
- for( i = 0; i < 256; i++ )
+ for (i = 0; i < 256; i++)
{
palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;
palette[i].rgbReserved = 0;
struct CvWindow;
-typedef struct CvTrackbar
+struct CvTrackbar : public std::enable_shared_from_this<CvTrackbar>
{
+ CvTrackbar(CvWindow& window, const std::string& name_)
+ : signature(CV_TRACKBAR_MAGIC_VAL)
+ , name(name_)
+ , parent(&window)
+ {
+ // nothing
+ }
+ ~CvTrackbar()
+ {
+ signature = -1;
+ }
+
int signature;
- HWND hwnd;
- char* name;
- CvTrackbar* next;
- CvWindow* parent;
- HWND buddy;
- int* data;
- int pos;
- int maxval;
- int minval;
- void (*notify)(int);
- void (*notify2)(int, void*);
- void* userdata;
- int id;
-}
-CvTrackbar;
+ HWND hwnd = 0;
+ std::string name;
+ CvWindow* parent; // TODO weak_ptr
+ HWND buddy = 0;
+ int* data = nullptr;
+ int pos = 0;
+ int maxval = 0;
+ int minval = 0;
+ void (*notify)(int) = nullptr; // deprecated
+ void (*notify2)(int, void*) = nullptr; // deprecated
+ TrackbarCallback onChangeCallback = nullptr;
+ void* userdata = nullptr;
+ int id = -1;
+};
-typedef struct CvWindow
+struct CvWindow : public std::enable_shared_from_this<CvWindow>
{
+ CvWindow(const std::string& name_)
+ : signature(CV_WINDOW_MAGIC_VAL)
+ , name(name_)
+ {
+ // nothing
+ }
+
+ ~CvWindow()
+ {
+ signature = -1;
+ }
+
+ void destroy();
+
int signature;
- HWND hwnd;
- char* name;
- CvWindow* prev;
- CvWindow* next;
- HWND frame;
+ cv::Mutex mutex;
+ HWND hwnd = 0;
+ std::string name;
+ HWND frame = 0;
- HDC dc;
- HGDIOBJ image;
- int last_key;
- int flags;
- int status;//0 normal, 1 fullscreen (YV)
+ HDC dc = 0;
+ HGDIOBJ image = 0;
+ int last_key = 0;
+ int flags = 0;
+ int status = 0;//0 normal, 1 fullscreen (YV)
- CvMouseCallback on_mouse;
- void* on_mouse_param;
+ CvMouseCallback on_mouse = nullptr;
+ void* on_mouse_param = nullptr;
struct
{
- HWND toolbar;
- int pos;
- int rows;
- WNDPROC toolBarProc;
- CvTrackbar* first;
+ HWND toolbar = 0;
+ int pos = 0;
+ int rows = 0;
+ WNDPROC toolBarProc = nullptr;
+ std::vector< std::shared_ptr<CvTrackbar> > trackbars;
}
toolbar;
- int width;
- int height;
+ int width = -1;
+ int height = -1;
// OpenGL support
#ifdef HAVE_OPENGL
- bool useGl;
- HGLRC hGLRC;
+ bool useGl = false;
+ HGLRC hGLRC = 0;
- CvOpenGlDrawCallback glDrawCallback;
- void* glDrawData;
+ CvOpenGlDrawCallback glDrawCallback = nullptr;
+ void* glDrawData = nullptr;
#endif
-}
-CvWindow;
+};
#define HG_BUDDY_WIDTH 130
#define TBM_GETTOOLTIPS (WM_USER + 30)
#endif
-static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
-static LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
-static LRESULT CALLBACK MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
-static void icvUpdateWindowPos( CvWindow* window );
+static
+std::vector< std::shared_ptr<CvWindow> >& getWindowsList()
+{
+ static std::vector< std::shared_ptr<CvWindow> > g_windows;
+ return g_windows;
+}
-static CvWindow* hg_windows = 0;
+
+// Mutex must be locked
+static
+std::shared_ptr<CvWindow> icvFindWindowByName(const std::string& name)
+{
+ auto& g_windows = getWindowsList();
+ for (auto it = g_windows.begin(); it != g_windows.end(); ++it)
+ {
+ auto window = *it;
+ if (!window)
+ continue;
+ if (window->name == name)
+ return window;
+ }
+ return std::shared_ptr<CvWindow>();
+}
+
+static inline
+std::shared_ptr<CvWindow> icvFindWindowByName(const char* name)
+{
+ CV_Assert(name);
+ return icvFindWindowByName(std::string(name));
+}
+
+
+
+static LRESULT CALLBACK HighGUIProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+static LRESULT CALLBACK MainWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+static void icvUpdateWindowPos(CvWindow& window);
typedef int (CV_CDECL * CvWin32WindowCallback)(HWND, UINT, WPARAM, LPARAM, int*);
static CvWin32WindowCallback hg_on_preprocess = 0, hg_on_postprocess = 0;
static HINSTANCE hg_hinstance = 0;
-static const char* highGUIclassName = "HighGUI class";
-static const char* mainHighGUIclassName = "Main HighGUI class";
+static const char* const highGUIclassName = "HighGUI class";
+static const char* const mainHighGUIclassName = "Main HighGUI class";
static void icvCleanupHighgui()
{
UnregisterClass(mainHighGUIclassName, hg_hinstance);
}
-CV_IMPL int cvInitSystem( int, char** )
+CV_IMPL int cvInitSystem(int, char**)
{
static int wasInitialized = 0;
// check initialization status
- if( !wasInitialized )
+ if (!wasInitialized)
{
- // Initialize the storage
- hg_windows = 0;
+ (void)getWindowMutex(); // force mutex initialization
+ (void)getWindowsList(); // Initialize the storage
// Register the class
WNDCLASS wndc;
wndc.lpszClassName = highGUIclassName;
wndc.lpszMenuName = highGUIclassName;
wndc.hIcon = LoadIcon(0, IDI_APPLICATION);
- wndc.hCursor = (HCURSOR)LoadCursor(0, (LPSTR)(size_t)IDC_CROSS );
+ wndc.hCursor = (HCURSOR)LoadCursor(0, (LPSTR)(size_t)IDC_CROSS);
wndc.hbrBackground = (HBRUSH)GetStockObject(DKGRAY_BRUSH);
RegisterClass(&wndc);
wndc.lpfnWndProc = MainWindowProc;
RegisterClass(&wndc);
- atexit( icvCleanupHighgui );
+ atexit(icvCleanupHighgui);
wasInitialized = 1;
}
- setlocale(LC_NUMERIC,"C");
+ setlocale(LC_NUMERIC,"C"); // FIXIT must be removed
return 0;
}
return 0;
}
-static CvWindow* icvFindWindowByName( const char* name )
-{
- CvWindow* window = hg_windows;
-
- for( ; window != 0 && strcmp( name, window->name) != 0; window = window->next )
- ;
- return window;
-}
-
-
-static CvWindow* icvWindowByHWND( HWND hwnd )
+static std::shared_ptr<CvWindow> icvWindowByHWND(HWND hwnd)
{
- CvWindow* window = (CvWindow*)icvGetWindowLongPtr( hwnd, CV_USERDATA );
- return window != 0 && hg_windows != 0 &&
+ AutoLock lock(getWindowMutex());
+ CvWindow* window = (CvWindow*)icvGetWindowLongPtr(hwnd, CV_USERDATA);
+ window = window != 0 &&
window->signature == CV_WINDOW_MAGIC_VAL ? window : 0;
+ if (window)
+ {
+ return window->shared_from_this();
+ }
+ else
+ {
+ return std::shared_ptr<CvWindow>();
+ }
}
-static CvTrackbar* icvTrackbarByHWND( HWND hwnd )
+static std::shared_ptr<CvTrackbar> icvTrackbarByHWND(HWND hwnd)
{
- CvTrackbar* trackbar = (CvTrackbar*)icvGetWindowLongPtr( hwnd, CV_USERDATA );
- return trackbar != 0 && trackbar->signature == CV_TRACKBAR_MAGIC_VAL &&
+ AutoLock lock(getWindowMutex());
+ CvTrackbar* trackbar = (CvTrackbar*)icvGetWindowLongPtr(hwnd, CV_USERDATA);
+ trackbar = trackbar != 0 && trackbar->signature == CV_TRACKBAR_MAGIC_VAL &&
trackbar->hwnd == hwnd ? trackbar : 0;
+ if (trackbar)
+ {
+ return trackbar->shared_from_this();
+ }
+ else
+ {
+ return std::shared_ptr<CvTrackbar>();
+ }
}
-static const char* icvWindowPosRootKey = "Software\\OpenCV\\HighGUI\\Windows\\";
+static const char* const icvWindowPosRootKey = "Software\\OpenCV\\HighGUI\\Windows\\";
// Window positions saving/loading added by Philip Gruebele.
//<a href="mailto:pgruebele@cox.net">pgruebele@cox.net</a>
// Restores the window position from the registry saved position.
static void
-icvLoadWindowPos( const char* name, CvRect& rect )
+icvLoadWindowPos(const char* name, CvRect& rect)
{
HKEY hkey;
char szKey[1024];
- strcpy_s( szKey, 1024, icvWindowPosRootKey );
- strcat_s( szKey, 1024, name );
+ strcpy_s(szKey, 1024, icvWindowPosRootKey);
+ strcat_s(szKey, 1024, name);
rect.x = rect.y = CW_USEDEFAULT;
rect.width = rect.height = 320;
- if( RegOpenKeyEx(HKEY_CURRENT_USER,szKey,0,KEY_QUERY_VALUE,&hkey) == ERROR_SUCCESS )
+ if (RegOpenKeyEx(HKEY_CURRENT_USER,szKey,0,KEY_QUERY_VALUE,&hkey) == ERROR_SUCCESS)
{
// Yes we are installed.
DWORD dwType = 0;
//<a href="mailto:pgruebele@cox.net">pgruebele@cox.net</a>
// philipg. Saves the window position in the registry
static void
-icvSaveWindowPos( const char* name, CvRect rect )
+icvSaveWindowPos(const char* name, CvRect rect)
{
static const DWORD MAX_RECORD_COUNT = 100;
HKEY hkey;
char szKey[1024];
char rootKey[1024];
- strcpy_s( szKey, 1024, icvWindowPosRootKey );
- strcat_s( szKey, 1024, name );
+ strcpy_s(szKey, 1024, icvWindowPosRootKey);
+ strcat_s(szKey, 1024, name);
- if( RegOpenKeyEx( HKEY_CURRENT_USER,szKey,0,KEY_READ,&hkey) != ERROR_SUCCESS )
+ if (RegOpenKeyEx(HKEY_CURRENT_USER,szKey,0,KEY_READ,&hkey) != ERROR_SUCCESS)
{
HKEY hroot;
DWORD count = 0;
char oldestKey[1024];
char currentKey[1024];
- strcpy_s( rootKey, 1024, icvWindowPosRootKey );
+ strcpy_s(rootKey, 1024, icvWindowPosRootKey);
rootKey[strlen(rootKey)-1] = '\0';
- if( RegCreateKeyEx(HKEY_CURRENT_USER, rootKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ+KEY_WRITE, 0, &hroot, NULL) != ERROR_SUCCESS )
- //RegOpenKeyEx( HKEY_CURRENT_USER,rootKey,0,KEY_READ,&hroot) != ERROR_SUCCESS )
+ if (RegCreateKeyEx(HKEY_CURRENT_USER, rootKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ+KEY_WRITE, 0, &hroot, NULL) != ERROR_SUCCESS)
+ //RegOpenKeyEx(HKEY_CURRENT_USER,rootKey,0,KEY_READ,&hroot) != ERROR_SUCCESS)
return;
for(;;)
{
DWORD csize = sizeof(currentKey);
FILETIME accesstime = { 0, 0 };
- LONG code = RegEnumKeyEx( hroot, count, currentKey, &csize, NULL, NULL, NULL, &accesstime );
- if( code != ERROR_SUCCESS && code != ERROR_MORE_DATA )
+ LONG code = RegEnumKeyEx(hroot, count, currentKey, &csize, NULL, NULL, NULL, &accesstime);
+ if (code != ERROR_SUCCESS && code != ERROR_MORE_DATA)
break;
count++;
- if( oldestTime.dwHighDateTime > accesstime.dwHighDateTime ||
+ if (oldestTime.dwHighDateTime > accesstime.dwHighDateTime ||
(oldestTime.dwHighDateTime == accesstime.dwHighDateTime &&
- oldestTime.dwLowDateTime > accesstime.dwLowDateTime) )
+ oldestTime.dwLowDateTime > accesstime.dwLowDateTime))
{
oldestTime = accesstime;
- strcpy_s( oldestKey, 1024, currentKey );
+ strcpy_s(oldestKey, 1024, currentKey);
}
}
- if( count >= MAX_RECORD_COUNT )
- RegDeleteKey( hroot, oldestKey );
- RegCloseKey( hroot );
+ if (count >= MAX_RECORD_COUNT)
+ RegDeleteKey(hroot, oldestKey);
+ RegCloseKey(hroot);
- if( RegCreateKeyEx(HKEY_CURRENT_USER,szKey,0,NULL,REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &hkey, NULL) != ERROR_SUCCESS )
+ if (RegCreateKeyEx(HKEY_CURRENT_USER,szKey,0,NULL,REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &hkey, NULL) != ERROR_SUCCESS)
return;
}
else
{
- RegCloseKey( hkey );
- if( RegOpenKeyEx( HKEY_CURRENT_USER,szKey,0,KEY_WRITE,&hkey) != ERROR_SUCCESS )
+ RegCloseKey(hkey);
+ if (RegOpenKeyEx(HKEY_CURRENT_USER,szKey,0,KEY_WRITE,&hkey) != ERROR_SUCCESS)
return;
}
RegCloseKey(hkey);
}
+static Rect getImageRect_(CvWindow& window);
+
CvRect cvGetWindowRect_W32(const char* name)
{
- RECT rect = { 0 };
- CvRect result = cvRect(-1, -1, -1, -1);
-
- CV_FUNCNAME( "cvGetWindowRect_W32" );
+ CV_FUNCNAME("cvGetWindowRect_W32");
- __BEGIN__;
-
- CvWindow* window;
+ AutoLock lock(getWindowMutex());
if (!name)
- CV_ERROR( CV_StsNullPtr, "NULL name string" );
- window = icvFindWindowByName( name );
+ CV_Error(Error::StsNullPtr, "NULL name string");
+
+ auto window = icvFindWindowByName(name);
if (!window)
- EXIT; // keep silence here
+ CV_Error_(Error::StsNullPtr, ("NULL window: '%s'", name));
- GetClientRect(window->hwnd, &rect);
- {
+ Rect r = getImageRect_(*window);
+
+ CvRect result = cvRect(r.x, r.y, r.width, r.height);
+ return result;
+}
+
+static Rect getImageRect_(CvWindow& window)
+{
+ RECT rect = { 0 };
+ GetClientRect(window.hwnd, &rect);
POINT pt = {rect.left, rect.top};
- ClientToScreen(window->hwnd, &pt);
- result = cvRect(pt.x, pt.y, rect.right - rect.left, rect.bottom - rect.top);
- }
- __END__;
+ ClientToScreen(window.hwnd, &pt);
+ Rect result(pt.x, pt.y, rect.right - rect.left, rect.bottom - rect.top);
return result;
}
double cvGetModeWindow_W32(const char* name)//YV
{
- double result = -1;
-
- CV_FUNCNAME( "cvGetModeWindow_W32" );
-
- __BEGIN__;
+ CV_FUNCNAME("cvGetModeWindow_W32");
- CvWindow* window;
+ AutoLock lock(getWindowMutex());
if (!name)
- CV_ERROR( CV_StsNullPtr, "NULL name string" );
+ CV_Error(Error::StsNullPtr, "NULL name string");
- window = icvFindWindowByName( name );
+ auto window = icvFindWindowByName(name);
if (!window)
- EXIT; // keep silence here
+ CV_Error_(Error::StsNullPtr, ("NULL window: '%s'", name));
- result = window->status;
-
- __END__;
- return result;
+ return window->status;
}
-void cvSetModeWindow_W32( const char* name, double prop_value)//Yannick Verdie
+static bool setModeWindow_(CvWindow& window, int mode);
+
+void cvSetModeWindow_W32(const char* name, double prop_value)//Yannick Verdie
{
- CV_FUNCNAME( "cvSetModeWindow_W32" );
+ CV_FUNCNAME("cvSetModeWindow_W32");
- __BEGIN__;
+ AutoLock lock(getWindowMutex());
- CvWindow* window;
+ if (!name)
+ CV_Error(Error::StsNullPtr, "NULL name string");
- if(!name)
- CV_ERROR( CV_StsNullPtr, "NULL name string" );
+ auto window = icvFindWindowByName(name);
+ if (!window)
+ CV_Error_(Error::StsNullPtr, ("NULL window: '%s'", name));
- window = icvFindWindowByName( name );
- if( !window )
- CV_ERROR( CV_StsNullPtr, "NULL window" );
+ (void)setModeWindow_(*window, (int)prop_value);
+}
- if(window->flags & CV_WINDOW_AUTOSIZE)//if the flag CV_WINDOW_AUTOSIZE is set
- EXIT;
+static bool setModeWindow_(CvWindow& window, int mode)
+{
+ if (window.flags & CV_WINDOW_AUTOSIZE)//if the flag CV_WINDOW_AUTOSIZE is set
+ return false;
+
+ if (window.status == mode)
+ return true;
{
- DWORD dwStyle = (DWORD)GetWindowLongPtr(window->frame, GWL_STYLE);
+ DWORD dwStyle = (DWORD)GetWindowLongPtr(window.frame, GWL_STYLE);
CvRect position;
- if (window->status==CV_WINDOW_FULLSCREEN && prop_value==CV_WINDOW_NORMAL)
+ if (window.status == CV_WINDOW_FULLSCREEN && mode == CV_WINDOW_NORMAL)
{
- icvLoadWindowPos(window->name,position );
- SetWindowLongPtr(window->frame, GWL_STYLE, dwStyle | WS_CAPTION | WS_THICKFRAME);
+ icvLoadWindowPos(window.name.c_str(), position);
+ SetWindowLongPtr(window.frame, GWL_STYLE, dwStyle | WS_CAPTION | WS_THICKFRAME);
- SetWindowPos(window->frame, HWND_TOP, position.x, position.y , position.width,position.height, SWP_NOZORDER | SWP_FRAMECHANGED);
- window->status=CV_WINDOW_NORMAL;
+ SetWindowPos(window.frame, HWND_TOP, position.x, position.y , position.width,position.height, SWP_NOZORDER | SWP_FRAMECHANGED);
+ window.status=CV_WINDOW_NORMAL;
- EXIT;
+ return true;
}
- if (window->status==CV_WINDOW_NORMAL && prop_value==CV_WINDOW_FULLSCREEN)
+ if (window.status == CV_WINDOW_NORMAL && mode == CV_WINDOW_FULLSCREEN)
{
//save dimension
RECT rect = { 0 };
- GetWindowRect(window->frame, &rect);
- CvRect RectCV = cvRect(rect.left, rect.top,rect.right - rect.left, rect.bottom - rect.top);
- icvSaveWindowPos(window->name,RectCV );
+ GetWindowRect(window.frame, &rect);
+ CvRect rectCV = cvRect(rect.left, rect.top,rect.right - rect.left, rect.bottom - rect.top);
+ icvSaveWindowPos(window.name.c_str(), rectCV);
//Look at coordinate for fullscreen
HMONITOR hMonitor;
//fullscreen
position.x=mi.rcMonitor.left;position.y=mi.rcMonitor.top;
position.width=mi.rcMonitor.right - mi.rcMonitor.left;position.height=mi.rcMonitor.bottom - mi.rcMonitor.top;
- SetWindowLongPtr(window->frame, GWL_STYLE, dwStyle & ~WS_CAPTION & ~WS_THICKFRAME);
+ SetWindowLongPtr(window.frame, GWL_STYLE, dwStyle & ~WS_CAPTION & ~WS_THICKFRAME);
- SetWindowPos(window->frame, HWND_TOP, position.x, position.y , position.width,position.height, SWP_NOZORDER | SWP_FRAMECHANGED);
- window->status=CV_WINDOW_FULLSCREEN;
+ SetWindowPos(window.frame, HWND_TOP, position.x, position.y , position.width,position.height, SWP_NOZORDER | SWP_FRAMECHANGED);
+ window.status=CV_WINDOW_FULLSCREEN;
- EXIT;
+ return true;
}
}
- __END__;
+ return false;
}
+static double getPropTopmost_(CvWindow& window);
+
double cvGetPropTopmost_W32(const char* name)
{
- double result = -1;
-
CV_Assert(name);
- CvWindow* window = icvFindWindowByName(name);
+ auto window = icvFindWindowByName(name);
if (!window)
CV_Error(Error::StsNullPtr, "NULL window");
- LONG style = GetWindowLongA(window->frame, GWL_EXSTYLE); // -20
+ return getPropTopmost_(*window);
+}
+
+static double getPropTopmost_(CvWindow& window)
+{
+ LONG style = GetWindowLongA(window.frame, GWL_EXSTYLE); // -20
if (!style)
{
std::ostringstream errorMsg;
- errorMsg << "window(" << name << "): failed to retrieve extended window style using GetWindowLongA(); error code: " << GetLastError();
- CV_Error(Error::StsError, errorMsg.str().c_str());
+ errorMsg << "window(" << window.name << "): failed to retrieve extended window style using GetWindowLongA(); error code: " << GetLastError();
+ CV_Error(Error::StsError, errorMsg.str());
}
- result = (style & WS_EX_TOPMOST) == WS_EX_TOPMOST;
-
- return result;
+ bool result = (style & WS_EX_TOPMOST) == WS_EX_TOPMOST;
+ return result ? 1.0 : 0.0;
}
+static bool setPropTopmost_(CvWindow& window, bool topmost);
+
void cvSetPropTopmost_W32(const char* name, const bool topmost)
{
CV_Assert(name);
- CvWindow* window = icvFindWindowByName(name);
+ auto window = icvFindWindowByName(name);
if (!window)
CV_Error(Error::StsNullPtr, "NULL window");
+ (void)setPropTopmost_(*window, topmost);
+}
+
+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);
+ BOOL success = SetWindowPos(window.frame, flag, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
if (!success)
{
std::ostringstream errorMsg;
- errorMsg << "window(" << name << "): error reported by SetWindowPos(" << (topmost ? "HWND_TOPMOST" : "HWND_TOP") << "), error code: " << GetLastError();
- CV_Error(Error::StsError, errorMsg.str().c_str());
+ errorMsg << "window(" << window.name << "): error reported by SetWindowPos(" << (topmost ? "HWND_TOPMOST" : "HWND_TOP") << "), error code: " << GetLastError();
+ CV_Error(Error::StsError, errorMsg.str());
+ return false;
}
+ return true;
}
+static double getPropVsync_(CvWindow& window);
+
double cvGetPropVsync_W32(const char* name)
{
#ifndef HAVE_OPENGL
if (!name)
CV_Error(Error::StsNullPtr, "'name' argument must not be NULL");
- CvWindow* window = icvFindWindowByName(name);
+ auto window = icvFindWindowByName(name);
if (!window)
CV_Error_(Error::StsBadArg, ("there is no window named '%s'", name));
+ double result = getPropVsync_(*window);
+ return cvIsNaN(result) ? -1.0 : result;
+#endif
+}
+
+static double getPropVsync_(CvWindow& window)
+{
+#ifndef HAVE_OPENGL
+ CV_UNUSED(window);
+ CV_Error(Error::OpenGlNotSupported, "Library was built without OpenGL support");
+#else
// https://www.khronos.org/opengl/wiki/Swap_Interval
// https://www.khronos.org/registry/OpenGL/extensions/EXT/WGL_EXT_extensions_string.txt
// https://www.khronos.org/registry/OpenGL/extensions/EXT/WGL_EXT_swap_control.txt
- if (!wglMakeCurrent(window->dc, window->hGLRC))
+ if (!wglMakeCurrent(window.dc, window.hGLRC))
CV_Error(Error::OpenGlApiCallError, "Can't Activate The GL Rendering Context");
typedef const char* (APIENTRY* PFNWGLGETEXTENSIONSSTRINGEXTPROC)(void);
PFNWGLGETEXTENSIONSSTRINGEXTPROC wglGetExtensionsString = NULL;
wglGetExtensionsString = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)wglGetProcAddress("wglGetExtensionsStringEXT");
if (wglGetExtensionsString == NULL)
- return -1; // wglGetProcAddress failed to get wglGetExtensionsStringEXT
+ return std::numeric_limits<double>::quiet_NaN(); // wglGetProcAddress failed to get wglGetExtensionsStringEXT
const char* wgl_extensions = wglGetExtensionsString();
if (wgl_extensions == NULL)
- return -1; // Can't get WGL extensions string
+ return std::numeric_limits<double>::quiet_NaN(); // Can't get WGL extensions string
if (strstr(wgl_extensions, "WGL_EXT_swap_control") == NULL)
- return -1; // WGL extensions don't contain WGL_EXT_swap_control
+ return std::numeric_limits<double>::quiet_NaN(); // WGL extensions don't contain WGL_EXT_swap_control
typedef int (APIENTRY* PFNWGLGETSWAPINTERVALPROC)(void);
PFNWGLGETSWAPINTERVALPROC wglGetSwapInterval = 0;
wglGetSwapInterval = (PFNWGLGETSWAPINTERVALPROC)wglGetProcAddress("wglGetSwapIntervalEXT");
if (wglGetSwapInterval == NULL)
- return -1; // wglGetProcAddress failed to get wglGetSwapIntervalEXT
+ return std::numeric_limits<double>::quiet_NaN(); // wglGetProcAddress failed to get wglGetSwapIntervalEXT
return wglGetSwapInterval();
#endif
}
+static bool setPropVsync_(CvWindow& window, bool enable_vsync);
+
void cvSetPropVsync_W32(const char* name, const bool enable_vsync)
{
#ifndef HAVE_OPENGL
if (!name)
CV_Error(Error::StsNullPtr, "'name' argument must not be NULL");
- CvWindow* window = icvFindWindowByName(name);
+ auto window = icvFindWindowByName(name);
if (!window)
CV_Error_(Error::StsBadArg, ("there is no window named '%s'", name));
- if (!wglMakeCurrent(window->dc, window->hGLRC))
+ (void)setPropVsync_(*window, enable_vsync);
+#endif
+}
+
+static bool setPropVsync_(CvWindow& window, bool enable_vsync)
+{
+#ifndef HAVE_OPENGL
+ CV_UNUSED(window);
+ CV_UNUSED(enable_vsync);
+ CV_Error(Error::OpenGlNotSupported, "Library was built without OpenGL support");
+#else
+ if (!wglMakeCurrent(window.dc, window.hGLRC))
CV_Error(Error::OpenGlApiCallError, "Can't Activate The GL Rendering Context");
typedef const char* (APIENTRY* PFNWGLGETEXTENSIONSSTRINGEXTPROC)(void);
CV_Error(Error::OpenGlApiCallError, "wglGetProcAddress failed to get wglSwapIntervalEXT");
wglSwapInterval(enable_vsync);
+ return true;
#endif
}
-void cv::setWindowTitle(const String& winname, const String& title)
+void setWindowTitle_W32(const std::string& name, const std::string& title)
{
- CvWindow* window = icvFindWindowByName(winname.c_str());
+ auto window = icvFindWindowByName(name);
if (!window)
{
- namedWindow(winname);
- window = icvFindWindowByName(winname.c_str());
+ namedWindow(name);
+ window = icvFindWindowByName(name);
}
if (!window)
CV_Error(Error::StsNullPtr, "NULL window");
if (!SetWindowText(window->frame, title.c_str()))
- CV_Error_(Error::StsError, ("Failed to set \"%s\" window title to \"%s\"", winname.c_str(), title.c_str()));
+ CV_Error_(Error::StsError, ("Failed to set \"%s\" window title to \"%s\"", name.c_str(), title.c_str()));
}
double cvGetPropWindowAutoSize_W32(const char* name)
{
double result = -1;
- CV_FUNCNAME( "cvSetCloseCallback" );
+ CV_FUNCNAME("cvSetCloseCallback");
- __BEGIN__;
-
- CvWindow* window;
+ AutoLock lock(getWindowMutex());
if (!name)
- CV_ERROR( CV_StsNullPtr, "NULL name string" );
+ CV_Error(Error::StsNullPtr, "NULL name string");
- window = icvFindWindowByName( name );
+ auto window = icvFindWindowByName(name);
if (!window)
- EXIT; // keep silence here
+ CV_Error_(Error::StsNullPtr, ("NULL window: '%s'", name));
result = window->flags & CV_WINDOW_AUTOSIZE;
- __END__;
-
return result;
}
{
double result = -1;
- CV_FUNCNAME( "cvGetRatioWindow_W32" );
+ CV_FUNCNAME("cvGetRatioWindow_W32");
- __BEGIN__;
-
- CvWindow* window;
+ AutoLock lock(getWindowMutex());
if (!name)
- CV_ERROR( CV_StsNullPtr, "NULL name string" );
+ CV_Error(Error::StsNullPtr, "NULL name string");
- window = icvFindWindowByName( name );
+ auto window = icvFindWindowByName(name);
if (!window)
- EXIT; // keep silence here
+ CV_Error_(Error::StsNullPtr, ("NULL window: '%s'", name));
result = static_cast<double>(window->width) / window->height;
- __END__;
-
return result;
}
double result = -1;
#ifdef HAVE_OPENGL
- CV_FUNCNAME( "cvGetOpenGlProp_W32" );
+ CV_FUNCNAME("cvGetOpenGlProp_W32");
- __BEGIN__;
-
- CvWindow* window;
+ AutoLock lock(getWindowMutex());
if (!name)
- CV_ERROR( CV_StsNullPtr, "NULL name string" );
+ CV_Error(Error::StsNullPtr, "NULL name string");
- window = icvFindWindowByName( name );
+ auto window = icvFindWindowByName(name);
if (!window)
- EXIT; // keep silence here
+ return -1;
result = window->useGl;
-
- __END__;
#endif
+
CV_UNUSED(name);
return result;
{
double result = -1;
- CV_FUNCNAME( "cvGetPropVisible_W32" );
+ CV_FUNCNAME("cvGetPropVisible_W32");
- __BEGIN__;
+ AutoLock lock(getWindowMutex());
if (!name)
- CV_ERROR( CV_StsNullPtr, "NULL name string" );
-
- result = (icvFindWindowByName( name ) != NULL);
+ CV_Error(Error::StsNullPtr, "NULL name string");
- __END__;
+ auto window = icvFindWindowByName(name);
+ result = (bool)window ? 1.0 : 0.0;
return result;
}
{
void createGlContext(HWND hWnd, HDC& hGLDC, HGLRC& hGLRC, bool& useGl)
{
- CV_FUNCNAME( "createGlContext" );
+ CV_FUNCNAME("createGlContext");
- __BEGIN__;
+ AutoLock lock(getWindowMutex());
useGl = false;
hGLDC = GetDC(hWnd);
if (!hGLDC)
- CV_ERROR( CV_OpenGlApiCallError, "Can't Create A GL Device Context" );
+ CV_Error(Error::OpenGlApiCallError, "Can't Create A GL Device Context");
PixelFormat = ChoosePixelFormat(hGLDC, &pfd);
if (!PixelFormat)
- CV_ERROR( CV_OpenGlApiCallError, "Can't Find A Suitable PixelFormat" );
+ CV_Error(Error::OpenGlApiCallError, "Can't Find A Suitable PixelFormat");
if (!SetPixelFormat(hGLDC, PixelFormat, &pfd))
- CV_ERROR( CV_OpenGlApiCallError, "Can't Set The PixelFormat" );
+ CV_Error(Error::OpenGlApiCallError, "Can't Set The PixelFormat");
hGLRC = wglCreateContext(hGLDC);
if (!hGLRC)
- CV_ERROR( CV_OpenGlApiCallError, "Can't Create A GL Rendering Context" );
+ CV_Error(Error::OpenGlApiCallError, "Can't Create A GL Rendering Context");
if (!wglMakeCurrent(hGLDC, hGLRC))
- CV_ERROR( CV_OpenGlApiCallError, "Can't Activate The GL Rendering Context" );
+ CV_Error(Error::OpenGlApiCallError, "Can't Activate The GL Rendering Context");
useGl = true;
-
- __END__;
}
- void releaseGlContext(CvWindow* window)
+ void releaseGlContext(CvWindow& window)
{
- //CV_FUNCNAME( "releaseGlContext" );
+ //CV_FUNCNAME("releaseGlContext");
- __BEGIN__;
+ AutoLock lock(getWindowMutex());
- if (window->hGLRC)
+ if (window.hGLRC)
{
- wglDeleteContext(window->hGLRC);
- window->hGLRC = NULL;
+ wglDeleteContext(window.hGLRC);
+ window.hGLRC = NULL;
}
- if (window->dc)
+ if (window.dc)
{
- ReleaseDC(window->hwnd, window->dc);
- window->dc = NULL;
+ ReleaseDC(window.hwnd, window.dc);
+ window.dc = NULL;
}
- window->useGl = false;
-
- __END__;
+ window.useGl = false;
}
- void drawGl(CvWindow* window)
+ void drawGl(CvWindow& window)
{
- CV_FUNCNAME( "drawGl" );
+ CV_FUNCNAME("drawGl");
- __BEGIN__;
+ AutoLock lock(getWindowMutex());
- if (!wglMakeCurrent(window->dc, window->hGLRC))
- CV_ERROR( CV_OpenGlApiCallError, "Can't Activate The GL Rendering Context" );
+ if (!wglMakeCurrent(window.dc, window.hGLRC))
+ CV_Error(Error::OpenGlApiCallError, "Can't Activate The GL Rendering Context");
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- if (window->glDrawCallback)
- window->glDrawCallback(window->glDrawData);
+ if (window.glDrawCallback)
+ window.glDrawCallback(window.glDrawData);
- if (!SwapBuffers(window->dc))
- CV_ERROR( CV_OpenGlApiCallError, "Can't swap OpenGL buffers" );
-
- __END__;
+ if (!SwapBuffers(window.dc))
+ CV_Error(Error::OpenGlApiCallError, "Can't swap OpenGL buffers");
}
- void resizeGl(CvWindow* window)
+ void resizeGl(CvWindow& window)
{
- CV_FUNCNAME( "resizeGl" );
-
- __BEGIN__;
+ CV_FUNCNAME("resizeGl");
- if (!wglMakeCurrent(window->dc, window->hGLRC))
- CV_ERROR( CV_OpenGlApiCallError, "Can't Activate The GL Rendering Context" );
+ AutoLock lock(getWindowMutex());
- glViewport(0, 0, window->width, window->height);
+ if (!wglMakeCurrent(window.dc, window.hGLRC))
+ CV_Error(Error::OpenGlApiCallError, "Can't Activate The GL Rendering Context");
- __END__;
+ glViewport(0, 0, window.width, window.height);
}
}
#endif // HAVE_OPENGL
+static std::shared_ptr<CvWindow> namedWindow_(const std::string& name, int flags);
+
+CV_IMPL int cvNamedWindow(const char* name, int flags)
+{
+ CV_FUNCNAME("cvNamedWindow");
+
+ AutoLock lock(getWindowMutex());
+
+ if (!name)
+ CV_Error(Error::StsNullPtr, "NULL name string");
+
+ // Check the name in the storage
+ auto window = icvFindWindowByName(name);
+ if (window)
+ {
+ return 1;
+ }
-CV_IMPL int cvNamedWindow( const char* name, int flags )
+ window = namedWindow_(name, flags);
+ return (bool)window;
+}
+
+static std::shared_ptr<CvWindow> namedWindow_(const std::string& name, int flags)
{
- int result = 0;
- CV_FUNCNAME( "cvNamedWindow" );
+ AutoLock lock(getWindowMutex());
- __BEGIN__;
+ cvInitSystem(0,0);
HWND hWnd, mainhWnd;
- CvWindow* window;
DWORD defStyle = WS_VISIBLE | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU;
- int len;
- CvRect rect;
#ifdef HAVE_OPENGL
bool useGl;
HDC hGLDC;
HGLRC hGLRC;
#endif
- cvInitSystem(0,0);
-
- if( !name )
- CV_ERROR( CV_StsNullPtr, "NULL name string" );
-
- // Check the name in the storage
- window = icvFindWindowByName( name );
- if (window != 0)
- {
- result = 1;
- EXIT;
- }
+ CvRect rect;
+ icvLoadWindowPos(name.c_str(), rect);
- if( !(flags & CV_WINDOW_AUTOSIZE))//YV add border in order to resize the window
+ if (!(flags & CV_WINDOW_AUTOSIZE))//YV add border in order to resize the window
defStyle |= WS_SIZEBOX;
#ifdef HAVE_OPENGL
defStyle |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
#endif
- icvLoadWindowPos( name, rect );
-
- 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" );
+ mainhWnd = CreateWindow(mainHighGUIclassName, name.c_str(), defStyle | WS_OVERLAPPED,
+ rect.x, rect.y, rect.width, rect.height, 0, 0, hg_hinstance, 0);
+ if (!mainhWnd)
+ CV_Error_(Error::StsError, ("Frame window can not be created: '%s'", name.c_str()));
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" );
+ hWnd = CreateWindow(highGUIclassName, "", (defStyle & ~WS_SIZEBOX) | WS_CHILD, CW_USEDEFAULT, 0, rect.width, rect.height, mainhWnd, 0, hg_hinstance, 0);
+ if (!hWnd)
+ CV_Error(Error::StsError, "Frame window can not be created");
#ifndef HAVE_OPENGL
if (flags & CV_WINDOW_OPENGL)
- CV_ERROR( CV_OpenGlNotSupported, "Library was built without OpenGL support" );
+ CV_Error(Error::OpenGlNotSupported, "Library was built without OpenGL support");
#else
useGl = false;
hGLDC = 0;
ShowWindow(hWnd, SW_SHOW);
- len = (int)strlen(name);
- CV_CALL( window = (CvWindow*)cvAlloc(sizeof(CvWindow) + len + 1));
+ auto window = std::make_shared<CvWindow>(name);
- window->signature = CV_WINDOW_MAGIC_VAL;
window->hwnd = hWnd;
window->frame = mainhWnd;
- window->name = (char*)(window + 1);
- memcpy( window->name, name, len + 1 );
window->flags = flags;
window->image = 0;
window->on_mouse = 0;
window->on_mouse_param = 0;
- memset( &window->toolbar, 0, sizeof(window->toolbar));
+ icvSetWindowLongPtr(hWnd, CV_USERDATA, window.get());
+ icvSetWindowLongPtr(mainhWnd, CV_USERDATA, window.get());
- window->next = hg_windows;
- window->prev = 0;
- if( hg_windows )
- hg_windows->prev = window;
- hg_windows = window;
- icvSetWindowLongPtr( hWnd, CV_USERDATA, window );
- icvSetWindowLongPtr( mainhWnd, CV_USERDATA, window );
+ auto& g_windows = getWindowsList();
+ g_windows.push_back(window);
// Recalculate window pos
- icvUpdateWindowPos( window );
+ icvUpdateWindowPos(*window);
- result = 1;
- __END__;
-
- return result;
+ return window;
}
#ifdef HAVE_OPENGL
CV_IMPL void cvSetOpenGlContext(const char* name)
{
- CV_FUNCNAME( "cvSetOpenGlContext" );
-
- __BEGIN__;
+ CV_FUNCNAME("cvSetOpenGlContext");
- CvWindow* window;
+ AutoLock lock(getWindowMutex());
- if(!name)
- CV_ERROR( CV_StsNullPtr, "NULL name string" );
+ if (!name)
+ CV_Error(Error::StsNullPtr, "NULL name string");
- window = icvFindWindowByName( name );
+ auto window = icvFindWindowByName(name);
if (!window)
- CV_ERROR( CV_StsNullPtr, "NULL window" );
+ CV_Error_(Error::StsNullPtr, ("NULL window: '%s'", name));
if (!window->useGl)
- CV_ERROR( CV_OpenGlNotSupported, "Window doesn't support OpenGL" );
+ CV_Error(Error::OpenGlNotSupported, "Window doesn't support OpenGL");
if (!wglMakeCurrent(window->dc, window->hGLRC))
- CV_ERROR( CV_OpenGlApiCallError, "Can't Activate The GL Rendering Context" );
-
- __END__;
+ CV_Error(Error::OpenGlApiCallError, "Can't Activate The GL Rendering Context");
}
CV_IMPL void cvUpdateWindow(const char* name)
{
- CV_FUNCNAME( "cvUpdateWindow" );
+ CV_FUNCNAME("cvUpdateWindow");
- __BEGIN__;
-
- CvWindow* window;
+ AutoLock lock(getWindowMutex());
if (!name)
- CV_ERROR( CV_StsNullPtr, "NULL name string" );
+ CV_Error(Error::StsNullPtr, "NULL name string");
- window = icvFindWindowByName( name );
+ auto window = icvFindWindowByName(name);
if (!window)
- EXIT;
+ CV_Error_(Error::StsNullPtr, ("NULL window: '%s'", name));
InvalidateRect(window->hwnd, 0, 0);
-
- __END__;
}
CV_IMPL void cvSetOpenGlDrawCallback(const char* name, CvOpenGlDrawCallback callback, void* userdata)
{
- CV_FUNCNAME( "cvCreateOpenGLCallback" );
+ CV_FUNCNAME("cvCreateOpenGLCallback");
- __BEGIN__;
+ AutoLock lock(getWindowMutex());
- CvWindow* window;
-
- if(!name)
- CV_ERROR( CV_StsNullPtr, "NULL name string" );
+ if (!name)
+ CV_Error(Error::StsNullPtr, "NULL name string");
- window = icvFindWindowByName( name );
- if( !window )
- EXIT;
+ auto window = icvFindWindowByName(name);
+ if (!window)
+ CV_Error_(Error::StsNullPtr, ("NULL window: '%s'", name));
if (!window->useGl)
- CV_ERROR( CV_OpenGlNotSupported, "Window was created without OpenGL context" );
+ CV_Error(Error::OpenGlNotSupported, "Window was created without OpenGL context");
window->glDrawCallback = callback;
window->glDrawData = userdata;
-
- __END__;
}
#endif // HAVE_OPENGL
-static void icvRemoveWindow( CvWindow* window )
+static void icvRemoveWindow(const std::shared_ptr<CvWindow>& window_)
{
- CvTrackbar* trackbar = NULL;
+ CV_Assert(window_);
+ AutoLock lock(getWindowMutex());
+ CvWindow& window = *window_;
+
RECT wrect={0,0,0,0};
+ auto& g_windows = getWindowsList();
+ for (auto it = g_windows.begin(); it != g_windows.end(); ++it)
+ {
+ const std::shared_ptr<CvWindow>& w = *it;
+ if (w.get() == &window)
+ {
+ g_windows.erase(it);
+ break;
+ }
+ }
+
#ifdef HAVE_OPENGL
- if (window->useGl)
+ if (window.useGl)
releaseGlContext(window);
#endif
- if( window->frame )
- GetWindowRect( window->frame, &wrect );
- if( window->name )
- icvSaveWindowPos( window->name, cvRect(wrect.left, wrect.top,
- wrect.right-wrect.left, wrect.bottom-wrect.top) );
-
- if( window->hwnd )
- icvSetWindowLongPtr( window->hwnd, CV_USERDATA, 0 );
- if( window->frame )
- icvSetWindowLongPtr( window->frame, CV_USERDATA, 0 );
+ if (window.frame)
+ GetWindowRect(window.frame, &wrect);
+ icvSaveWindowPos(window.name.c_str(), cvRect(wrect.left, wrect.top, wrect.right-wrect.left, wrect.bottom-wrect.top));
- if( window->toolbar.toolbar )
- icvSetWindowLongPtr(window->toolbar.toolbar, CV_USERDATA, 0);
+ if (window.hwnd)
+ icvSetWindowLongPtr(window.hwnd, CV_USERDATA, 0);
+ if (window.frame)
+ icvSetWindowLongPtr(window.frame, CV_USERDATA, 0);
- if( window->prev )
- window->prev->next = window->next;
- else
- hg_windows = window->next;
-
- if( window->next )
- window->next->prev = window->prev;
+ if (window.toolbar.toolbar)
+ icvSetWindowLongPtr(window.toolbar.toolbar, CV_USERDATA, 0);
- window->prev = window->next = 0;
+ if (window.dc && window.image)
+ DeleteObject(SelectObject(window.dc, window.image));
- if( window->dc && window->image )
- DeleteObject(SelectObject(window->dc,window->image));
+ if (window.dc)
+ DeleteDC(window.dc);
- if( window->dc )
- DeleteDC(window->dc);
-
- for( trackbar = window->toolbar.first; trackbar != 0; )
+ for (auto it = window.toolbar.trackbars.begin(); it != window.toolbar.trackbars.end(); ++it)
{
- CvTrackbar* next = trackbar->next;
- if( trackbar->hwnd )
+ auto trackbar = (*it).get();
+ if (trackbar && trackbar->hwnd)
{
- icvSetWindowLongPtr( trackbar->hwnd, CV_USERDATA, 0 );
- cvFree( &trackbar );
+ icvSetWindowLongPtr(trackbar->hwnd, CV_USERDATA, 0);
}
- trackbar = next;
}
-
- cvFree( &window );
}
-CV_IMPL void cvDestroyWindow( const char* name )
+CV_IMPL void cvDestroyWindow(const char* name)
{
- CV_FUNCNAME( "cvDestroyWindow" );
+ CV_FUNCNAME("cvDestroyWindow");
- __BEGIN__;
+ AutoLock lock(getWindowMutex());
- CvWindow* window;
- HWND mainhWnd;
+ if (!name)
+ CV_Error(Error::StsNullPtr, "NULL name string");
- if(!name)
- CV_ERROR( CV_StsNullPtr, "NULL name string" );
+ auto window = icvFindWindowByName(name);
+ if (!window)
+ CV_Error_(Error::StsNullPtr, ("NULL window: '%s'", name));
- window = icvFindWindowByName( name );
- if( !window )
- EXIT;
+ window->destroy();
+}
- mainhWnd = window->frame;
- SendMessage(window->hwnd, WM_CLOSE, 0, 0);
- SendMessage( mainhWnd, WM_CLOSE, 0, 0);
+void CvWindow::destroy()
+{
+ SendMessage(hwnd, WM_CLOSE, 0, 0);
+ SendMessage(frame, WM_CLOSE, 0, 0);
// Do NOT call _remove_window -- CvWindow list will be updated automatically ...
-
- __END__;
}
-
-static void icvScreenToClient( HWND hwnd, RECT* rect )
+static void icvScreenToClient(HWND hwnd, RECT* rect)
{
POINT p;
p.x = rect->left;
p.y = rect->top;
ScreenToClient(hwnd, &p);
- OffsetRect( rect, p.x - rect->left, p.y - rect->top );
+ OffsetRect(rect, p.x - rect->left, p.y - rect->top);
}
/* Calculatess the window coordinates relative to the upper left corner of the mainhWnd window */
-static RECT icvCalcWindowRect( CvWindow* window )
+static RECT icvCalcWindowRect(CvWindow& window)
{
RECT crect = { 0 }, trect = { 0 }, rect = { 0 };
- assert(window);
-
- GetClientRect(window->frame, &crect);
- if (window->toolbar.toolbar)
+ GetClientRect(window.frame, &crect);
+ if (window.toolbar.toolbar)
{
- GetWindowRect(window->toolbar.toolbar, &trect);
- icvScreenToClient(window->frame, &trect);
+ GetWindowRect(window.toolbar.toolbar, &trect);
+ icvScreenToClient(window.frame, &trect);
SubtractRect(&rect, &crect, &trect);
}
else
return rect;
}
+static inline RECT icvCalcWindowRect(CvWindow* window) { CV_Assert(window); return icvCalcWindowRect(*window); }
+
-// returns TRUE if there is a problem such as ERROR_IO_PENDING.
-static bool icvGetBitmapData( CvWindow* window, SIZE* size, int* channels, void** data )
+// returns FALSE if there is a problem such as ERROR_IO_PENDING.
+static bool icvGetBitmapData(CvWindow& window, SIZE& size, int& channels, void*& data)
{
- BITMAP bmp;
GdiFlush();
- HGDIOBJ h = GetCurrentObject( window->dc, OBJ_BITMAP );
- if( size )
- size->cx = size->cy = 0;
- if( data )
- *data = 0;
+
+ HGDIOBJ h = GetCurrentObject(window.dc, OBJ_BITMAP);
+ size.cx = size.cy = 0;
+ data = 0;
if (h == NULL)
- return true;
+ return false;
+
+ BITMAP bmp = {};
if (GetObject(h, sizeof(bmp), &bmp) == 0)
- return true;
+ return false;
- if( size )
- {
- size->cx = abs(bmp.bmWidth);
- size->cy = abs(bmp.bmHeight);
- }
+ size.cx = abs(bmp.bmWidth);
+ size.cy = abs(bmp.bmHeight);
- if( channels )
- *channels = bmp.bmBitsPixel/8;
+ channels = bmp.bmBitsPixel/8;
- if( data )
- *data = bmp.bmBits;
+ data = bmp.bmBits;
- return false;
+ return true;
+}
+static bool icvGetBitmapData(CvWindow& window, SIZE& size)
+{
+ int channels = 0;
+ void* data = nullptr;
+ return icvGetBitmapData(window, size, channels, data);
}
-static void icvUpdateWindowPos( CvWindow* window )
+static void icvUpdateWindowPos(CvWindow& window)
{
RECT rect = { 0 };
- assert(window);
- if( (window->flags & CV_WINDOW_AUTOSIZE) && window->image )
+ if ((window.flags & CV_WINDOW_AUTOSIZE) && window.image)
{
int i;
SIZE size = {0,0};
- icvGetBitmapData( window, &size, 0, 0 );
+ icvGetBitmapData(window, size); // TODO check return value?
// Repeat two times because after the first resizing of the mainhWnd window
// toolbar may resize too
- for(i = 0; i < (window->toolbar.toolbar ? 2 : 1); i++)
+ for(i = 0; i < (window.toolbar.toolbar ? 2 : 1); i++)
{
- RECT rmw = { 0 }, rw = icvCalcWindowRect(window );
- MoveWindow(window->hwnd, rw.left, rw.top,
+ RECT rmw = { 0 }, rw = icvCalcWindowRect(&window);
+ MoveWindow(window.hwnd, rw.left, rw.top,
rw.right - rw.left, rw.bottom - rw.top, FALSE);
- GetClientRect(window->hwnd, &rw);
- GetWindowRect(window->frame, &rmw);
+ GetClientRect(window.hwnd, &rw);
+ GetWindowRect(window.frame, &rmw);
// Resize the mainhWnd window in order to make the bitmap fit into the child window
- MoveWindow(window->frame, rmw.left, rmw.top,
+ MoveWindow(window.frame, rmw.left, rmw.top,
size.cx + (rmw.right - rmw.left) - (rw.right - rw.left),
- size.cy + (rmw.bottom - rmw.top) - (rw.bottom - rw.top), TRUE );
+ size.cy + (rmw.bottom - rmw.top) - (rw.bottom - rw.top), TRUE);
}
}
rect = icvCalcWindowRect(window);
- MoveWindow(window->hwnd, rect.left, rect.top,
+ MoveWindow(window.hwnd, rect.left, rect.top,
rect.right - rect.left,
- rect.bottom - rect.top, TRUE );
+ rect.bottom - rect.top, TRUE);
}
+static void showImage_(CvWindow& window, const Mat& image);
+
CV_IMPL void
-cvShowImage( const char* name, const CvArr* arr )
+cvShowImage(const char* name, const CvArr* arr)
{
- CV_FUNCNAME( "cvShowImage" );
-
- __BEGIN__;
-
- CvWindow* window;
- SIZE size = { 0, 0 };
- int channels = 0;
- void* dst_ptr = 0;
- const int channels0 = 3;
- CvMat stub, *image;
- bool changed_size = false; // philipg
+ CV_FUNCNAME("cvShowImage");
- if( !name )
- CV_ERROR( CV_StsNullPtr, "NULL name" );
+ if (!name)
+ CV_Error(Error::StsNullPtr, "NULL name");
- window = icvFindWindowByName(name);
- if(!window)
+ std::shared_ptr<CvWindow> window;
{
- cvNamedWindow(name, CV_WINDOW_AUTOSIZE);
+ AutoLock lock(getWindowMutex());
+
window = icvFindWindowByName(name);
+ if (!window)
+ {
+ cvNamedWindow(name, CV_WINDOW_AUTOSIZE);
+ window = icvFindWindowByName(name);
+ }
}
- if( !window || !arr )
- EXIT; // keep silence here.
-
- CV_CALL( image = cvGetMat( arr, &stub ));
+ if (!window || !arr)
+ return; // keep silence here.
+ CvMat stub = {};
+ CvMat* image_c = cvGetMat(arr, &stub);
+ Mat image = cv::cvarrToMat(image_c);
#ifdef HAVE_OPENGL
if (window->useGl)
{
- cv::imshow(name, cv::cvarrToMat(image));
+ cv::imshow(name, image);
return;
}
#endif
+ return showImage_(*window, image);
+}
+
+static void showImage_(CvWindow& window, const Mat& image)
+{
+ AutoLock lock(window.mutex);
- if (window->image)
+ SIZE size = { 0, 0 };
+ int channels = 0;
+ void* dst_ptr = 0;
+ const int channels0 = 3;
+ bool changed_size = false; // philipg
+
+ if (window.image)
+ {
// if there is something wrong with these system calls, we cannot display image...
- if (icvGetBitmapData( window, &size, &channels, &dst_ptr ))
+ if (!icvGetBitmapData(window, size, channels, dst_ptr))
return;
+ }
- if( size.cx != image->width || size.cy != image->height || channels != channels0 )
+ if (size.cx != image.cols || size.cy != image.rows || channels != channels0)
{
changed_size = true;
uchar buffer[sizeof(BITMAPINFO) + 255*sizeof(RGBQUAD)];
BITMAPINFO* binfo = (BITMAPINFO*)buffer;
- DeleteObject( SelectObject( window->dc, window->image ));
- window->image = 0;
+ DeleteObject(SelectObject(window.dc, window.image));
+ window.image = 0;
- size.cx = image->width;
- size.cy = image->height;
+ size.cx = image.cols;
+ size.cy = image.rows;
channels = channels0;
- FillBitmapInfo( binfo, size.cx, size.cy, channels*8, 1 );
+ FillBitmapInfo(binfo, size.cx, size.cy, channels*8, 1);
- window->image = SelectObject( window->dc, CreateDIBSection(window->dc, binfo,
- DIB_RGB_COLORS, &dst_ptr, 0, 0));
+ window.image = SelectObject(window.dc,
+ CreateDIBSection(window.dc, binfo, DIB_RGB_COLORS, &dst_ptr, 0, 0)
+ );
}
{
cv::Mat dst(size.cy, size.cx, CV_8UC3, dst_ptr, (size.cx * channels + 3) & -4);
- convertToShow(cv::cvarrToMat(image), dst, false);
+ convertToShow(image, dst, false);
CV_Assert(dst.data == (uchar*)dst_ptr);
cv::flip(dst, dst, 0);
}
// only resize window if needed
if (changed_size)
icvUpdateWindowPos(window);
- InvalidateRect(window->hwnd, 0, 0);
+ InvalidateRect(window.hwnd, 0, 0);
// philipg: this is not needed and just slows things down
// UpdateWindow(window->hwnd);
-
- __END__;
}
-CV_IMPL void cvResizeWindow(const char* name, int width, int height )
+static void resizeWindow_(CvWindow& window, const Size& size);
+
+CV_IMPL void cvResizeWindow(const char* name, int width, int height)
{
- CV_FUNCNAME( "cvResizeWindow" );
+ CV_FUNCNAME("cvResizeWindow");
- __BEGIN__;
+ AutoLock lock(getWindowMutex());
- int i;
- CvWindow* window;
- RECT rmw = { 0 }, rw = { 0 }, rect = { 0 };
+ if (!name)
+ CV_Error(Error::StsNullPtr, "NULL name");
- if( !name )
- CV_ERROR( CV_StsNullPtr, "NULL name" );
+ auto window = icvFindWindowByName(name);
+ if (!window)
+ CV_Error_(Error::StsNullPtr, ("NULL window: '%s'", name));
- window = icvFindWindowByName(name);
- if(!window)
- EXIT;
+ return resizeWindow_(*window, Size(width, height));
+}
+
+static void resizeWindow_(CvWindow& window, const Size& size)
+{
+ RECT rmw = { 0 }, rw = { 0 }, rect = { 0 };
// Repeat two times because after the first resizing of the mainhWnd window
// toolbar may resize too
- for(i = 0; i < (window->toolbar.toolbar ? 2 : 1); i++)
+ for (int i = 0; i < (window.toolbar.toolbar ? 2 : 1); i++)
{
rw = icvCalcWindowRect(window);
- MoveWindow(window->hwnd, rw.left, rw.top,
+ MoveWindow(window.hwnd, rw.left, rw.top,
rw.right - rw.left, rw.bottom - rw.top, FALSE);
- GetClientRect(window->hwnd, &rw);
- GetWindowRect(window->frame, &rmw);
+ GetClientRect(window.hwnd, &rw);
+ GetWindowRect(window.frame, &rmw);
// Resize the mainhWnd window in order to make the bitmap fit into the child window
- MoveWindow(window->frame, rmw.left, rmw.top,
- width + (rmw.right - rmw.left) - (rw.right - rw.left),
- height + (rmw.bottom - rmw.top) - (rw.bottom - rw.top), TRUE);
+ MoveWindow(window.frame, rmw.left, rmw.top,
+ size.width + (rmw.right - rmw.left) - (rw.right - rw.left),
+ size.height + (rmw.bottom - rmw.top) - (rw.bottom - rw.top), TRUE);
}
rect = icvCalcWindowRect(window);
- MoveWindow(window->hwnd, rect.left, rect.top,
+ MoveWindow(window.hwnd, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top, TRUE);
-
- __END__;
}
+static void moveWindow_(CvWindow& window, const Point& pt);
-CV_IMPL void cvMoveWindow( const char* name, int x, int y )
+CV_IMPL void cvMoveWindow(const char* name, int x, int y)
{
- CV_FUNCNAME( "cvMoveWindow" );
+ CV_FUNCNAME("cvMoveWindow");
- __BEGIN__;
+ AutoLock lock(getWindowMutex());
- CvWindow* window;
- RECT rect = { 0 };
-
- if( !name )
- CV_ERROR( CV_StsNullPtr, "NULL name" );
+ if (!name)
+ CV_Error(Error::StsNullPtr, "NULL name");
- window = icvFindWindowByName(name);
- if(!window)
- EXIT;
+ auto window = icvFindWindowByName(name);
+ if (!window)
+ CV_Error_(Error::StsNullPtr, ("NULL window: '%s'", name));
- GetWindowRect( window->frame, &rect );
- MoveWindow( window->frame, x, y, rect.right - rect.left, rect.bottom - rect.top, TRUE);
+ (void)moveWindow_(*window, Point(x, y));
+}
- __END__;
+static void moveWindow_(CvWindow& window, const Point& pt)
+{
+ RECT rect = { 0 };
+ GetWindowRect(window.frame, &rect); // TODO check return value
+ MoveWindow(window.frame, pt.x, pt.y, rect.right - rect.left, rect.bottom - rect.top, TRUE);
}
static LRESULT CALLBACK
-MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+MainWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
- CvWindow* window = icvWindowByHWND( hwnd );
- if( !window )
+ auto window_ = icvWindowByHWND(hwnd);
+ if (!window_)
return DefWindowProc(hwnd, uMsg, wParam, lParam);
+ CvWindow& window = *window_;
+
switch(uMsg)
{
case WM_COPY:
- ::SendMessage(window->hwnd, uMsg, wParam, lParam);
+ ::SendMessage(window.hwnd, uMsg, wParam, lParam);
break;
case WM_DESTROY:
- icvRemoveWindow(window);
+ icvRemoveWindow(window_);
// Do nothing!!!
//PostQuitMessage(0);
break;
case WM_GETMINMAXINFO:
- if( !(window->flags & CV_WINDOW_AUTOSIZE) )
+ if (!(window.flags & CV_WINDOW_AUTOSIZE))
{
MINMAXINFO* minmax = (MINMAXINFO*)lParam;
RECT rect = { 0 };
minmax->ptMinTrackSize.y = 100;
minmax->ptMinTrackSize.x = 100;
- if( window->toolbar.first )
+ if (!window.toolbar.trackbars.empty())
{
- GetWindowRect( window->toolbar.first->hwnd, &rect );
- minmax->ptMinTrackSize.y += window->toolbar.rows*(rect.bottom - rect.top);
+ GetWindowRect(window.toolbar.trackbars[0]->hwnd, &rect);
+ minmax->ptMinTrackSize.y += window.toolbar.rows*(rect.bottom - rect.top);
minmax->ptMinTrackSize.x = MAX(rect.right - rect.left + HG_BUDDY_WIDTH, HG_BUDDY_WIDTH*2);
}
return retval;
WINDOWPOS* pos = (WINDOWPOS*)lParam;
// Update the toolbar pos/size
- if(window->toolbar.toolbar)
+ if (window.toolbar.toolbar)
{
RECT rect = { 0 };
- GetWindowRect(window->toolbar.toolbar, &rect);
- MoveWindow(window->toolbar.toolbar, 0, 0, pos->cx, rect.bottom - rect.top, TRUE);
+ GetWindowRect(window.toolbar.toolbar, &rect);
+ MoveWindow(window.toolbar.toolbar, 0, 0, pos->cx, rect.bottom - rect.top, TRUE);
}
- if(!(window->flags & CV_WINDOW_AUTOSIZE))
+ if (!(window.flags & CV_WINDOW_AUTOSIZE))
icvUpdateWindowPos(window);
break;
LPWINDOWPOS pos = (LPWINDOWPOS)lParam;
RECT rect = { 0 };
- GetWindowRect(window->frame, &rect);
+ GetWindowRect(window.frame, &rect);
HMONITOR hMonitor;
hMonitor = MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST);
}
case WM_ACTIVATE:
- if(LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE)
- SetFocus(window->hwnd);
+ if (LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE)
+ SetFocus(window.hwnd);
break;
case WM_MOUSEWHEEL:
case WM_MOUSEHWHEEL:
- if( window->on_mouse )
+ if (window.on_mouse)
{
int flags = (wParam & MK_LBUTTON ? CV_EVENT_FLAG_LBUTTON : 0)|
(wParam & MK_RBUTTON ? CV_EVENT_FLAG_RBUTTON : 0)|
flags |= (delta << 16);
POINT pt;
- pt.x = GET_X_LPARAM( lParam );
- pt.y = GET_Y_LPARAM( lParam );
+ pt.x = GET_X_LPARAM(lParam);
+ pt.y = GET_Y_LPARAM(lParam);
::ScreenToClient(hwnd, &pt); // Convert screen coordinates to client coordinates.
RECT rect = { 0 };
- GetClientRect( window->hwnd, &rect );
+ GetClientRect(window.hwnd, &rect);
SIZE size = {0,0};
#ifdef HAVE_OPENGL
- if (window->useGl)
+ if (window.useGl)
{
- cv::ogl::Texture2D* texObj = static_cast<cv::ogl::Texture2D*>(window->glDrawData);
+ cv::ogl::Texture2D* texObj = static_cast<cv::ogl::Texture2D*>(window.glDrawData);
size.cx = texObj->cols();
size.cy = texObj->rows();
}
else
{
- icvGetBitmapData(window, &size, 0, 0);
+ icvGetBitmapData(window, size);
}
#else
- icvGetBitmapData(window, &size, 0, 0);
+ icvGetBitmapData(window, size);
#endif
- window->on_mouse( event, pt.x*size.cx/MAX(rect.right - rect.left,1),
- pt.y*size.cy/MAX(rect.bottom - rect.top,1), flags,
- window->on_mouse_param );
+ int x = cvRound((float)pt.x*size.cx/MAX(rect.right - rect.left,1));
+ int y = cvRound((float)pt.y*size.cy/MAX(rect.bottom - rect.top,1));
+ window.on_mouse(event, x, y, flags, window.on_mouse_param);
}
break;
HRGN rgn, rgn1, rgn2;
int ret;
HDC hdc = (HDC)wParam;
- GetWindowRect(window->hwnd, &cr);
- icvScreenToClient(window->frame, &cr);
- if(window->toolbar.toolbar)
+ GetWindowRect(window.hwnd, &cr);
+ icvScreenToClient(window.frame, &cr);
+ if (window.toolbar.toolbar)
{
- GetWindowRect(window->toolbar.toolbar, &tr);
- icvScreenToClient(window->frame, &tr);
+ GetWindowRect(window.toolbar.toolbar, &tr);
+ icvScreenToClient(window.frame, &tr);
}
else
tr.left = tr.top = tr.right = tr.bottom = 0;
- GetClientRect(window->frame, &wrc);
+ GetClientRect(window.frame, &wrc);
rgn = CreateRectRgn(0, 0, wrc.right, wrc.bottom);
rgn1 = CreateRectRgn(cr.left, cr.top, cr.right, cr.bottom);
ret = CombineRgn(rgn, rgn, rgn1, RGN_DIFF);
ret = CombineRgn(rgn, rgn, rgn2, RGN_DIFF);
- if(ret != NULLREGION && ret != ERROR)
+ if (ret != NULLREGION && ret != ERROR)
FillRgn(hdc, rgn, (HBRUSH)icvGetClassLongPtr(hwnd, CV_HBRBACKGROUND));
DeleteObject(rgn);
}
-static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+static LRESULT CALLBACK HighGUIProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
- CvWindow* window = icvWindowByHWND(hwnd);
- if( !window )
+ auto window_ = icvWindowByHWND(hwnd);
+ if (!window_)
+ {
// This window is not mentioned in HighGUI storage
// Actually, this should be error except for the case of calls to CreateWindow
return DefWindowProc(hwnd, uMsg, wParam, lParam);
+ }
+
+ CvWindow& window = *window_;
// Process the message
switch(uMsg)
{
case WM_COPY:
{
- if (!::OpenClipboard(hwnd) )
+ if (!::OpenClipboard(hwnd))
break;
HDC hDC = 0;
if (!::EmptyClipboard())
break;
- if(!window->image)
+ if (!window.image)
break;
// Get window device context
break;
// Create another DC compatible with hDC
- if (0 == (memDC = ::CreateCompatibleDC( hDC )))
+ if (0 == (memDC = ::CreateCompatibleDC(hDC)))
break;
// Determine the bitmap's dimensions
- int nchannels = 3;
SIZE size = {0,0};
- icvGetBitmapData( window, &size, &nchannels, 0 );
+ int nchannels = 3;
+ void* data = NULL; // unused
+ icvGetBitmapData(window, size, nchannels, data);
// Create bitmap to draw on and it in the new DC
- if (0 == (memBM = ::CreateCompatibleBitmap ( hDC, size.cx, size.cy)))
+ if (0 == (memBM = ::CreateCompatibleBitmap(hDC, size.cx, size.cy)))
break;
- if (!::SelectObject( memDC, memBM ))
+ if (!::SelectObject(memDC, memBM))
break;
// Begin drawing to DC
break;
RGBQUAD table[256];
- if( 1 == nchannels )
+ if (1 == nchannels)
{
for(int i = 0; i < 256; ++i)
{
table[i].rgbGreen = (unsigned char)i;
table[i].rgbRed = (unsigned char)i;
}
- if (!::SetDIBColorTable(window->dc, 0, 255, table))
+ if (!::SetDIBColorTable(window.dc, 0, 255, table))
break;
}
// The image copied to the clipboard will be in its original size, regardless if the window itself was resized.
// Render the image to the dc/bitmap (at original size).
- if (!::BitBlt( memDC, 0, 0, size.cx, size.cy, window->dc, 0, 0, SRCCOPY ))
+ if (!::BitBlt(memDC, 0, 0, size.cx, size.cy, window.dc, 0, 0, SRCCOPY))
break;
// Finally, set bitmap to clipboard
case WM_RBUTTONUP:
case WM_MBUTTONUP:
case WM_MOUSEMOVE:
- if( window->on_mouse )
+ if (window.on_mouse)
{
POINT pt;
uMsg == WM_RBUTTONDBLCLK ? CV_EVENT_RBUTTONDBLCLK :
uMsg == WM_MBUTTONDBLCLK ? CV_EVENT_MBUTTONDBLCLK :
CV_EVENT_MOUSEMOVE;
- if( uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN || uMsg == WM_MBUTTONDOWN )
- SetCapture( hwnd );
- if( uMsg == WM_LBUTTONUP || uMsg == WM_RBUTTONUP || uMsg == WM_MBUTTONUP )
+ if (uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN || uMsg == WM_MBUTTONDOWN)
+ SetCapture(hwnd);
+ if (uMsg == WM_LBUTTONUP || uMsg == WM_RBUTTONUP || uMsg == WM_MBUTTONUP)
ReleaseCapture();
- pt.x = GET_X_LPARAM( lParam );
- pt.y = GET_Y_LPARAM( lParam );
+ pt.x = GET_X_LPARAM(lParam);
+ pt.y = GET_Y_LPARAM(lParam);
- if (window->flags & CV_WINDOW_AUTOSIZE)
+ if (window.flags & CV_WINDOW_AUTOSIZE)
{
// As user can't change window size, do not scale window coordinates. Underlying windowing system
// may prevent full window from being displayed and in this case coordinates should not be scaled.
- window->on_mouse( event, pt.x, pt.y, flags, window->on_mouse_param );
+ window.on_mouse(event, pt.x, pt.y, flags, window.on_mouse_param);
} else {
// Full window is displayed using different size. Scale coordinates to match underlying positions.
RECT rect = { 0 };
SIZE size = {0, 0};
- GetClientRect( window->hwnd, &rect );
+ GetClientRect(window.hwnd, &rect);
#ifdef HAVE_OPENGL
- if (window->useGl)
+ if (window.useGl)
{
- cv::ogl::Texture2D* texObj = static_cast<cv::ogl::Texture2D*>(window->glDrawData);
+ cv::ogl::Texture2D* texObj = static_cast<cv::ogl::Texture2D*>(window.glDrawData);
size.cx = texObj->cols();
size.cy = texObj->rows();
}
else
{
- icvGetBitmapData(window, &size, 0, 0);
+ icvGetBitmapData(window, size);
}
#else
- icvGetBitmapData( window, &size, 0, 0 );
+ icvGetBitmapData(window, size);
#endif
- window->on_mouse( event, pt.x*size.cx/MAX(rect.right - rect.left,1),
- pt.y*size.cy/MAX(rect.bottom - rect.top,1), flags,
- window->on_mouse_param );
+ int x = cvRound((float)pt.x*size.cx/MAX(rect.right - rect.left,1));
+ int y = cvRound((float)pt.y*size.cy/MAX(rect.bottom - rect.top,1));
+ window.on_mouse(event, x, y, flags, window.on_mouse_param);
}
}
break;
case WM_PAINT:
- if(window->image != 0)
+ if (window.image != 0)
{
int nchannels = 3;
SIZE size = {0,0};
RGBQUAD table[256];
// Determine the bitmap's dimensions
- icvGetBitmapData( window, &size, &nchannels, 0 );
+ void* data = 0; // unused
+ icvGetBitmapData(window, size, nchannels, data);
hdc = BeginPaint(hwnd, &paint);
SetStretchBltMode(hdc, COLORONCOLOR);
- if( nchannels == 1 )
+ if (nchannels == 1)
{
int i;
for(i = 0; i < 256; i++)
table[i].rgbGreen = (unsigned char)i;
table[i].rgbRed = (unsigned char)i;
}
- SetDIBColorTable(window->dc, 0, 255, table);
+ SetDIBColorTable(window.dc, 0, 255, table);
}
- if(window->flags & CV_WINDOW_AUTOSIZE)
+ if (window.flags & CV_WINDOW_AUTOSIZE)
{
- BitBlt( hdc, 0, 0, size.cx, size.cy, window->dc, 0, 0, SRCCOPY );
+ BitBlt(hdc, 0, 0, size.cx, size.cy, window.dc, 0, 0, SRCCOPY);
}
else
{
RECT rect = { 0 };
- GetClientRect(window->hwnd, &rect);
- StretchBlt( hdc, 0, 0, rect.right - rect.left, rect.bottom - rect.top,
- window->dc, 0, 0, size.cx, size.cy, SRCCOPY );
+ GetClientRect(window.hwnd, &rect);
+ StretchBlt(hdc, 0, 0, rect.right - rect.left, rect.bottom - rect.top,
+ window.dc, 0, 0, size.cx, size.cy, SRCCOPY);
}
//DeleteDC(hdc);
EndPaint(hwnd, &paint);
}
#ifdef HAVE_OPENGL
- else if(window->useGl)
+ else if (window.useGl)
{
drawGl(window);
return DefWindowProc(hwnd, uMsg, wParam, lParam);
return 0;
case WM_ERASEBKGND:
- if(window->image)
+ if (window.image)
return 0;
break;
case WM_DESTROY:
- icvRemoveWindow(window);
+ icvRemoveWindow(window_);
// Do nothing!!!
//PostQuitMessage(0);
break;
return 0;
case WM_KEYDOWN:
- window->last_key = (int)wParam;
+ window.last_key = (int)wParam;
return 0;
case WM_SIZE:
- window->width = LOWORD(lParam);
- window->height = HIWORD(lParam);
+ window.width = LOWORD(lParam);
+ window.height = HIWORD(lParam);
#ifdef HAVE_OPENGL
- if (window->useGl)
+ if (window.useGl)
resizeGl(window);
#endif
}
}
-static LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT ret;
- if( hg_on_preprocess )
+ if (hg_on_preprocess)
{
int was_processed = 0;
int rethg = hg_on_preprocess(hwnd, uMsg, wParam, lParam, &was_processed);
- if( was_processed )
+ if (was_processed)
return rethg;
}
ret = HighGUIProc(hwnd, uMsg, wParam, lParam);
- if(hg_on_postprocess)
+ if (hg_on_postprocess)
{
int was_processed = 0;
int rethg = hg_on_postprocess(hwnd, uMsg, wParam, lParam, &was_processed);
- if( was_processed )
+ if (was_processed)
return rethg;
}
}
-static void icvUpdateTrackbar( CvTrackbar* trackbar, int pos )
+static void icvUpdateTrackbar(CvTrackbar& trackbar, int pos)
{
const int max_name_len = 10;
const char* suffix = "";
char pos_text[32];
int name_len;
- if( trackbar->data )
- *trackbar->data = pos;
+ if (trackbar.data)
+ *trackbar.data = pos;
- if( trackbar->pos != pos )
+ if (trackbar.pos != pos)
{
- trackbar->pos = pos;
- if( trackbar->notify2 )
- trackbar->notify2(pos, trackbar->userdata);
- if( trackbar->notify )
- trackbar->notify(pos);
-
- name_len = (int)strlen(trackbar->name);
-
- if( name_len > max_name_len )
+ trackbar.pos = pos;
+ if (trackbar.onChangeCallback)
+ trackbar.onChangeCallback(pos, trackbar.userdata);
+ if (trackbar.notify2)
+ trackbar.notify2(pos, trackbar.userdata);
+ if (trackbar.notify)
+ trackbar.notify(pos);
+
+ name_len = (int)trackbar.name.size();
+
+ // TODO replace C strings manipulation
+ if (name_len > max_name_len)
{
int start_len = max_name_len*2/3;
int end_len = max_name_len - start_len - 2;
- memcpy( pos_text, trackbar->name, start_len );
- memcpy( pos_text + start_len, "...", 3 );
- memcpy( pos_text + start_len + 3, trackbar->name + name_len - end_len, end_len + 1 );
+ memcpy(pos_text, trackbar.name.c_str(), start_len);
+ memcpy(pos_text + start_len, "...", 3);
+ memcpy(pos_text + start_len + 3, trackbar.name.c_str() + name_len - end_len, end_len + 1);
}
else
{
- memcpy( pos_text, trackbar->name, name_len + 1);
+ memcpy(pos_text, trackbar.name.c_str(), name_len + 1);
}
- sprintf( pos_text + strlen(pos_text), "%s: %d\n", suffix, pos );
- SetWindowText( trackbar->buddy, pos_text );
+ sprintf(pos_text + strlen(pos_text), "%s: %d\n", suffix, pos);
+ SetWindowText(trackbar.buddy, pos_text);
}
}
-static LRESULT CALLBACK HGToolbarProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+static LRESULT CALLBACK HGToolbarProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
- CvWindow* window = icvWindowByHWND( hwnd );
- if(!window)
+ auto window_ = icvWindowByHWND(hwnd);
+ if (!window_)
return DefWindowProc(hwnd, uMsg, wParam, lParam);
+ CvWindow& window = *window_;
+
// Control messages processing
switch(uMsg)
{
{
HWND slider = (HWND)lParam;
int pos = (int)SendMessage(slider, TBM_GETPOS, 0, 0);
- CvTrackbar* trackbar = icvTrackbarByHWND( slider );
+ auto trackbar = icvTrackbarByHWND(slider);
- if( trackbar )
+ if (trackbar)
{
- if( trackbar->pos != pos )
- icvUpdateTrackbar( trackbar, pos );
+ if (trackbar->pos != pos)
+ icvUpdateTrackbar(*trackbar, pos);
}
- SetFocus( window->hwnd );
+ SetFocus(window.hwnd);
return 0;
}
case WM_NCCALCSIZE:
{
- LRESULT ret = CallWindowProc(window->toolbar.toolBarProc, hwnd, uMsg, wParam, lParam);
+ LRESULT ret = CallWindowProc(window.toolbar.toolBarProc, hwnd, uMsg, wParam, lParam);
int rows = (int)SendMessage(hwnd, TB_GETROWS, 0, 0);
- if(window->toolbar.rows != rows)
+ if (window.toolbar.rows != rows)
{
- SendMessage(window->toolbar.toolbar, TB_BUTTONCOUNT, 0, 0);
- CvTrackbar* trackbar = window->toolbar.first;
+ SendMessage(window.toolbar.toolbar, TB_BUTTONCOUNT, 0, 0);
+ auto& trakbars = window.toolbar.trackbars;
- for( ; trackbar != 0; trackbar = trackbar->next )
+ for (auto it = trakbars.begin(); it != trakbars.end(); ++it)
{
+ auto trackbar = *it;
+ CV_Assert(trackbar);
RECT rect = { 0 };
- SendMessage(window->toolbar.toolbar, TB_GETITEMRECT,
+ SendMessage(window.toolbar.toolbar, TB_GETITEMRECT,
(WPARAM)trackbar->id, (LPARAM)&rect);
MoveWindow(trackbar->hwnd, rect.left + HG_BUDDY_WIDTH, rect.top,
rect.right - rect.left - HG_BUDDY_WIDTH,
MoveWindow(trackbar->buddy, rect.left, rect.top,
HG_BUDDY_WIDTH, rect.bottom - rect.top, FALSE);
}
- window->toolbar.rows = rows;
+ window.toolbar.rows = rows;
}
return ret;
}
}
- return CallWindowProc(window->toolbar.toolBarProc, hwnd, uMsg, wParam, lParam);
+ return CallWindowProc(window.toolbar.toolBarProc, hwnd, uMsg, wParam, lParam);
}
CV_IMPL void
cvDestroyAllWindows(void)
{
- CvWindow* window = hg_windows;
-
- while( window )
+ std::vector< std::shared_ptr<CvWindow> > g_windows;
{
- HWND mainhWnd = window->frame;
- HWND hwnd = window->hwnd;
- window = window->next;
+ AutoLock lock(getWindowMutex());
+ g_windows = getWindowsList(); // copy
+ }
+ for (auto it = g_windows.begin(); it != g_windows.end(); ++it)
+ {
+ auto window_ = *it;
+ if (!window_)
+ continue;
+
+ {
+ CvWindow& window = *window_;
+
+ HWND mainhWnd = window.frame;
+ HWND hwnd = window.hwnd;
+
+ SendMessage(hwnd, WM_CLOSE, 0, 0);
+ SendMessage(mainhWnd, WM_CLOSE, 0, 0);
+ }
- SendMessage( hwnd, WM_CLOSE, 0, 0 );
- SendMessage( mainhWnd, WM_CLOSE, 0, 0 );
+ window_.reset();
+ }
+ // TODO needed?
+ {
+ AutoLock lock(getWindowMutex());
+ getWindowsList().clear();
}
}
-static void showSaveDialog(CvWindow* window)
+static void showSaveDialog(CvWindow& window)
{
- if (!window || !window->image)
+ if (!window.image)
return;
SIZE sz;
int channels;
void* data;
- if (icvGetBitmapData(window, &sz, &channels, &data))
+ if (icvGetBitmapData(window, sz, channels, data))
return; // nothing to save
char szFileName[MAX_PATH] = "";
// try to use window title as file name
- GetWindowText(window->frame, szFileName, MAX_PATH);
+ GetWindowText(window.frame, szFileName, MAX_PATH);
OPENFILENAME ofn;
ZeroMemory(&ofn, sizeof(ofn));
#else
ofn.lStructSize = sizeof(ofn);
#endif
- ofn.hwndOwner = window->hwnd;
+ ofn.hwndOwner = window.hwnd;
ofn.lpstrFilter =
#ifdef HAVE_PNG
"Portable Network Graphics files (*.png)\0*.png\0"
// otherwise the message was handled specifically
bool is_processed = false;
- for (CvWindow* window = hg_windows; window != 0 && is_processed == 0; window = window->next)
+ AutoLock lock(getWindowMutex());
+ auto& g_windows = getWindowsList();
+ for (auto it = g_windows.begin(); it != g_windows.end() && !is_processed; ++it)
{
- if (!(window->hwnd == message.hwnd || window->frame == message.hwnd))
+ auto window_ = *it;
+ if (!window_)
+ continue;
+ CvWindow& window = *window_;
+ if (!(window.hwnd == message.hwnd || window.frame == message.hwnd))
continue;
is_processed = true;
/*
* process until queue is empty but don't wait.
*/
-int cv::pollKey()
+int pollKey_W32()
{
CV_TRACE_FUNCTION();
for(;;)
}
CV_IMPL int
-cvWaitKey( int delay )
+cvWaitKey(int delay)
{
int64 time0 = cv::getTickCount();
int64 timeEnd = time0 + (int64)(delay * 0.001f * cv::getTickFrequency());
{
MSG message;
- if( (delay <= 0) && hg_windows)
+ if ((delay <= 0) && !getWindowsList().empty())
GetMessage(&message, 0, 0, 0);
- else if( PeekMessage(&message, 0, 0, 0, PM_REMOVE) == FALSE )
+ else if (PeekMessage(&message, 0, 0, 0, PM_REMOVE) == FALSE)
{
int64 t = cv::getTickCount();
if (t - timeEnd >= 0)
}
-static CvTrackbar*
-icvFindTrackbarByName( const CvWindow* window, const char* name )
+static
+std::shared_ptr<CvTrackbar> icvFindTrackbarByName(CvWindow& window, const std::string& name)
{
- CvTrackbar* trackbar = window->toolbar.first;
-
- for( ; trackbar != 0 && strcmp( trackbar->name, name ) != 0; trackbar = trackbar->next )
- ;
-
- return trackbar;
+ auto trackbars = window.toolbar.trackbars;
+ for (auto it = trackbars.begin(); it != trackbars.end(); ++it)
+ {
+ auto& trackbar = *it;
+ CV_Assert(trackbar);
+ if (trackbar->name == name)
+ return trackbar;
+ }
+ return std::shared_ptr<CvTrackbar>();
+}
+static inline
+std::shared_ptr<CvTrackbar> icvFindTrackbarByName(const std::shared_ptr<CvWindow>& window, const std::string& name)
+{
+ CV_Assert(window);
+ return icvFindTrackbarByName(window, name);
}
+static
+std::shared_ptr<CvTrackbar> createTrackbar_(CvWindow& window, const std::string& trackbar_name,
+ int count,
+ TrackbarCallback onChange, void* userdata);
static int
-icvCreateTrackbar( const char* trackbar_name, const char* window_name,
- int* val, int count, CvTrackbarCallback on_notify,
- CvTrackbarCallback2 on_notify2, void* userdata )
+icvCreateTrackbar(const char* trackbar_name, const char* window_name,
+ int* val, int count, CvTrackbarCallback on_notify,
+ CvTrackbarCallback2 on_notify2, void* userdata)
{
- int result = 0;
+ CV_FUNCNAME("icvCreateTrackbar");
- CV_FUNCNAME( "icvCreateTrackbar" );
+ AutoLock lock(getWindowMutex());
- __BEGIN__;
+ if (!window_name || !trackbar_name)
+ CV_Error(Error::StsNullPtr, "NULL window or trackbar name");
- char slider_name[32];
- CvWindow* window = 0;
- CvTrackbar* trackbar = 0;
- int pos = 0;
+ if (count < 0)
+ CV_Error(Error::StsOutOfRange, "Bad trackbar maximal value");
- if( !window_name || !trackbar_name )
- CV_ERROR( CV_StsNullPtr, "NULL window or trackbar name" );
+ auto window = icvFindWindowByName(window_name);
+ if (!window)
+ CV_Error_(Error::StsNullPtr, ("NULL window: '%s'", window_name));
- if( count < 0 )
- CV_ERROR( CV_StsOutOfRange, "Bad trackbar maximal value" );
+ auto trackbar = icvFindTrackbarByName(*window, trackbar_name);
+ if (!trackbar)
+ trackbar = createTrackbar_(*window, trackbar_name, count, nullptr, userdata);
+ CV_Assert(trackbar);
- window = icvFindWindowByName(window_name);
- if( !window )
- EXIT;
+ trackbar->notify = on_notify;
+ trackbar->notify2 = on_notify2;
+ trackbar->userdata = userdata;
+ trackbar->data = val;
- trackbar = icvFindTrackbarByName(window,trackbar_name);
- if( !trackbar )
- {
- TBBUTTON tbs = {};
- TBBUTTONINFO tbis = {};
- RECT rect = { 0 };
- int bcount;
- int len = (int)strlen( trackbar_name );
+ return 1;
+}
- // create toolbar if it is not created yet
- if( !window->toolbar.toolbar )
- {
- const int default_height = 30;
-
- // CreateToolbarEx is deprecated and forces linking against Comctl32.lib.
- window->toolbar.toolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
- WS_CHILD | CCS_TOP | TBSTYLE_WRAPABLE | BTNS_AUTOSIZE | BTNS_BUTTON,
- 0, 0, 0, 0,
- window->frame, NULL, GetModuleHandle(NULL), NULL);
- // CreateToolbarEx automatically sends this but CreateWindowEx doesn't.
- SendMessage(window->toolbar.toolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
-
- GetClientRect(window->frame, &rect);
- MoveWindow( window->toolbar.toolbar, 0, 0,
- rect.right - rect.left, default_height, TRUE);
- SendMessage(window->toolbar.toolbar, TB_AUTOSIZE, 0, 0);
- ShowWindow(window->toolbar.toolbar, SW_SHOW);
-
- window->toolbar.first = 0;
- window->toolbar.pos = 0;
- window->toolbar.rows = 0;
- window->toolbar.toolBarProc =
- (WNDPROC)icvGetWindowLongPtr(window->toolbar.toolbar, CV_WNDPROC);
-
- icvUpdateWindowPos(window);
-
- // Subclassing from toolbar
- icvSetWindowLongPtr(window->toolbar.toolbar, CV_WNDPROC, HGToolbarProc);
- icvSetWindowLongPtr(window->toolbar.toolbar, CV_USERDATA, window);
- }
+static void createToolbar_(CvWindow& window)
+{
+ CV_Assert(!window.toolbar.toolbar);
+
+ const int default_height = 30;
+
+ // CreateToolbarEx is deprecated and forces linking against Comctl32.lib.
+ window.toolbar.toolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
+ WS_CHILD | CCS_TOP | TBSTYLE_WRAPABLE | BTNS_AUTOSIZE | BTNS_BUTTON,
+ 0, 0, 0, 0,
+ window.frame, NULL, GetModuleHandle(NULL), NULL);
+ // CreateToolbarEx automatically sends this but CreateWindowEx doesn't.
+ SendMessage(window.toolbar.toolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
+
+ RECT rect;
+ GetClientRect(window.frame, &rect);
+ MoveWindow(window.toolbar.toolbar, 0, 0,
+ rect.right - rect.left, default_height, TRUE);
+ SendMessage(window.toolbar.toolbar, TB_AUTOSIZE, 0, 0);
+ ShowWindow(window.toolbar.toolbar, SW_SHOW);
+
+ window.toolbar.pos = 0;
+ window.toolbar.rows = 0;
+ window.toolbar.toolBarProc =
+ (WNDPROC)icvGetWindowLongPtr(window.toolbar.toolbar, CV_WNDPROC);
- /* Retrieve current buttons count */
- bcount = (int)SendMessage(window->toolbar.toolbar, TB_BUTTONCOUNT, 0, 0);
+ icvUpdateWindowPos(window);
- if(bcount > 1)
- {
- /* If this is not the first button then we need to
- separate it from the previous one */
- tbs.iBitmap = 0;
- tbs.idCommand = bcount; // Set button id to it's number
- tbs.iString = 0;
- tbs.fsStyle = TBSTYLE_SEP;
- tbs.fsState = TBSTATE_ENABLED;
- SendMessage(window->toolbar.toolbar, TB_ADDBUTTONS, 1, (LPARAM)&tbs);
-
- // Retrieve current buttons count
- bcount = (int)SendMessage(window->toolbar.toolbar, TB_BUTTONCOUNT, 0, 0);
- }
+ // Subclassing from toolbar
+ icvSetWindowLongPtr(window.toolbar.toolbar, CV_WNDPROC, HGToolbarProc);
+ icvSetWindowLongPtr(window.toolbar.toolbar, CV_USERDATA, (void*)&window);
+
+}
+
+static
+std::shared_ptr<CvTrackbar> createTrackbar_(CvWindow& window, const std::string& trackbar_name,
+ int count,
+ TrackbarCallback onChange, void* userdata)
+{
+ // create toolbar if it is not created yet
+ if (!window.toolbar.toolbar)
+ {
+ createToolbar_(window);
+ }
+
+ TBBUTTON tbs = {};
- /* Add a button which we're going to cover with the slider */
+ /* Retrieve current buttons count */
+ int bcount = (int)SendMessage(window.toolbar.toolbar, TB_BUTTONCOUNT, 0, 0);
+
+ if (bcount > 1)
+ {
+ /* If this is not the first button then we need to
+ separate it from the previous one */
tbs.iBitmap = 0;
tbs.idCommand = bcount; // Set button id to it's number
+ tbs.iString = 0;
+ tbs.fsStyle = TBSTYLE_SEP;
tbs.fsState = TBSTATE_ENABLED;
+ SendMessage(window.toolbar.toolbar, TB_ADDBUTTONS, 1, (LPARAM)&tbs);
+
+ // Retrieve current buttons count
+ bcount = (int)SendMessage(window.toolbar.toolbar, TB_BUTTONCOUNT, 0, 0);
+ }
+
+ /* Add a button which we're going to cover with the slider */
+ tbs.iBitmap = 0;
+ tbs.idCommand = bcount; // Set button id to it's number
+ tbs.fsState = TBSTATE_ENABLED;
#if 0/*!defined WIN64 && !defined EM64T*/
- tbs.fsStyle = 0;
- tbs.iString = 0;
+ tbs.fsStyle = 0;
+ tbs.iString = 0;
#else
#ifndef TBSTYLE_AUTOSIZE
#ifndef TBSTYLE_GROUP
#define TBSTYLE_GROUP 0x0004
#endif
- //tbs.fsStyle = TBSTYLE_AUTOSIZE;
- tbs.fsStyle = TBSTYLE_GROUP;
- tbs.iString = (INT_PTR)trackbar_text;
+ //tbs.fsStyle = TBSTYLE_AUTOSIZE;
+ tbs.fsStyle = TBSTYLE_GROUP;
+ tbs.iString = (INT_PTR)trackbar_text;
#endif
- SendMessage(window->toolbar.toolbar, TB_ADDBUTTONS, 1, (LPARAM)&tbs);
-
- /* Adjust button size to the slider */
- tbis.cbSize = sizeof(tbis);
- tbis.dwMask = TBIF_SIZE;
-
- GetClientRect(window->hwnd, &rect);
- tbis.cx = (unsigned short)(rect.right - rect.left);
-
- SendMessage(window->toolbar.toolbar, TB_SETBUTTONINFO,
- (WPARAM)tbs.idCommand, (LPARAM)&tbis);
-
- /* Get button pos */
- SendMessage(window->toolbar.toolbar, TB_GETITEMRECT,
- (WPARAM)tbs.idCommand, (LPARAM)&rect);
-
- /* Create a slider */
- trackbar = (CvTrackbar*)cvAlloc( sizeof(CvTrackbar) + len + 1 );
- trackbar->signature = CV_TRACKBAR_MAGIC_VAL;
- trackbar->notify = 0;
- trackbar->notify2 = 0;
- trackbar->parent = window;
- trackbar->pos = 0;
- trackbar->data = 0;
- trackbar->id = bcount;
- trackbar->next = window->toolbar.first;
- trackbar->name = (char*)(trackbar + 1);
- memcpy( trackbar->name, trackbar_name, len + 1 );
- window->toolbar.first = trackbar;
-
- sprintf(slider_name, "Trackbar%p", val);
- trackbar->hwnd = CreateWindowEx(0, TRACKBAR_CLASS, slider_name,
- WS_CHILD | WS_VISIBLE | TBS_AUTOTICKS |
- TBS_FIXEDLENGTH | TBS_HORZ | TBS_BOTTOM,
- rect.left + HG_BUDDY_WIDTH, rect.top,
- rect.right - rect.left - HG_BUDDY_WIDTH,
- rect.bottom - rect.top, window->toolbar.toolbar,
- (HMENU)(size_t)bcount, hg_hinstance, 0);
-
- sprintf(slider_name,"Buddy%p", val);
- trackbar->buddy = CreateWindowEx(0, "STATIC", slider_name,
- WS_CHILD | SS_RIGHT,
- rect.left, rect.top,
- HG_BUDDY_WIDTH, rect.bottom - rect.top,
- window->toolbar.toolbar, 0, hg_hinstance, 0);
-
- icvSetWindowLongPtr( trackbar->hwnd, CV_USERDATA, trackbar );
-
- /* Minimize the number of rows */
- SendMessage( window->toolbar.toolbar, TB_SETROWS,
- MAKEWPARAM(1, FALSE), (LPARAM)&rect );
- }
- else
- {
- trackbar->data = 0;
- trackbar->notify = 0;
- trackbar->notify2 = 0;
- }
+ SendMessage(window.toolbar.toolbar, TB_ADDBUTTONS, 1, (LPARAM)&tbs);
+
+ TBBUTTONINFO tbis = {};
+
+ /* Adjust button size to the slider */
+ tbis.cbSize = sizeof(tbis);
+ tbis.dwMask = TBIF_SIZE;
+
+ RECT rect = { 0 };
+ GetClientRect(window.hwnd, &rect);
+ tbis.cx = (unsigned short)(rect.right - rect.left);
+
+ SendMessage(window.toolbar.toolbar, TB_SETBUTTONINFO,
+ (WPARAM)tbs.idCommand, (LPARAM)&tbis);
+
+ /* Get button pos */
+ SendMessage(window.toolbar.toolbar, TB_GETITEMRECT,
+ (WPARAM)tbs.idCommand, (LPARAM)&rect);
+
+ /* Create a slider */
+ auto trackbar = std::make_shared<CvTrackbar>(window, trackbar_name);
+ trackbar->id = bcount;
+ window.toolbar.trackbars.push_back(trackbar);
+
+ auto slider_name = cv::format("Trackbar%p", trackbar.get());
+ trackbar->hwnd = CreateWindowEx(0, TRACKBAR_CLASS, slider_name.c_str(),
+ WS_CHILD | WS_VISIBLE | TBS_AUTOTICKS |
+ TBS_FIXEDLENGTH | TBS_HORZ | TBS_BOTTOM,
+ rect.left + HG_BUDDY_WIDTH, rect.top,
+ rect.right - rect.left - HG_BUDDY_WIDTH,
+ rect.bottom - rect.top, window.toolbar.toolbar,
+ (HMENU)(size_t)bcount, hg_hinstance, 0);
+
+ slider_name = cv::format("Buddy%p", trackbar.get());
+ trackbar->buddy = CreateWindowEx(0, "STATIC", slider_name.c_str(),
+ WS_CHILD | SS_RIGHT,
+ rect.left, rect.top,
+ HG_BUDDY_WIDTH, rect.bottom - rect.top,
+ window.toolbar.toolbar, 0, hg_hinstance, 0);
+
+ icvSetWindowLongPtr(trackbar->hwnd, CV_USERDATA, (void*)trackbar.get());
+
+ /* Minimize the number of rows */
+ SendMessage(window.toolbar.toolbar, TB_SETROWS,
+ MAKEWPARAM(1, FALSE), (LPARAM)&rect);
trackbar->maxval = count;
/* Adjust slider parameters */
SendMessage(trackbar->hwnd, TBM_SETRANGEMIN, (WPARAM)TRUE, (LPARAM)0);
SendMessage(trackbar->hwnd, TBM_SETRANGEMAX, (WPARAM)TRUE, (LPARAM)count);
- SendMessage(trackbar->hwnd, TBM_SETTICFREQ, (WPARAM)1, (LPARAM)0 );
- if( val )
- pos = *val;
+ SendMessage(trackbar->hwnd, TBM_SETTICFREQ, (WPARAM)1, (LPARAM)0);
- SendMessage(trackbar->hwnd, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pos );
- SendMessage(window->toolbar.toolbar, TB_AUTOSIZE, 0, 0);
+ int pos = 0;
+ SendMessage(trackbar->hwnd, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pos);
+ SendMessage(window.toolbar.toolbar, TB_AUTOSIZE, 0, 0);
trackbar->pos = -1;
- icvUpdateTrackbar( trackbar, pos );
- ShowWindow( trackbar->buddy, SW_SHOW );
- ShowWindow( trackbar->hwnd, SW_SHOW );
-
- trackbar->notify = on_notify;
- trackbar->notify2 = on_notify2;
- trackbar->userdata = userdata;
- trackbar->data = val;
+ icvUpdateTrackbar(*trackbar, pos);
+ ShowWindow(trackbar->buddy, SW_SHOW);
+ ShowWindow(trackbar->hwnd, SW_SHOW);
/* Resize the window to reflect the toolbar resizing*/
icvUpdateWindowPos(window);
- result = 1;
-
- __END__;
+ trackbar->onChangeCallback = onChange;
+ trackbar->userdata = userdata;
- return result;
+ return trackbar;
}
CV_IMPL int
-cvCreateTrackbar( const char* trackbar_name, const char* window_name,
- int* val, int count, CvTrackbarCallback on_notify )
+cvCreateTrackbar(const char* trackbar_name, const char* window_name,
+ int* val, int count, CvTrackbarCallback on_notify)
{
- return icvCreateTrackbar( trackbar_name, window_name, val, count,
- on_notify, 0, 0 );
+ return icvCreateTrackbar(trackbar_name, window_name, val, count,
+ on_notify, 0, 0);
}
CV_IMPL int
-cvCreateTrackbar2( const char* trackbar_name, const char* window_name,
- int* val, int count, CvTrackbarCallback2 on_notify2,
- void* userdata )
+cvCreateTrackbar2(const char* trackbar_name, const char* window_name,
+ int* val, int count, CvTrackbarCallback2 on_notify2,
+ void* userdata)
{
- return icvCreateTrackbar( trackbar_name, window_name, val, count,
- 0, on_notify2, userdata );
+ return icvCreateTrackbar(trackbar_name, window_name, val, count,
+ 0, on_notify2, userdata);
}
CV_IMPL void
-cvSetMouseCallback( const char* window_name, CvMouseCallback on_mouse, void* param )
+cvSetMouseCallback(const char* name, CvMouseCallback on_mouse, void* param)
{
- CV_FUNCNAME( "cvSetMouseCallback" );
-
- __BEGIN__;
+ CV_FUNCNAME("cvSetMouseCallback");
- CvWindow* window = 0;
+ if (!name)
+ CV_Error(Error::StsNullPtr, "NULL window name");
- if( !window_name )
- CV_ERROR( CV_StsNullPtr, "NULL window name" );
+ AutoLock lock(getWindowMutex());
- window = icvFindWindowByName(window_name);
- if( !window )
- EXIT;
+ auto window = icvFindWindowByName(name);
+ if (!window)
+ CV_Error_(Error::StsNullPtr, ("NULL window: '%s'", name));
window->on_mouse = on_mouse;
window->on_mouse_param = param;
-
- __END__;
}
-CV_IMPL int cvGetTrackbarPos( const char* trackbar_name, const char* window_name )
+CV_IMPL int cvGetTrackbarPos(const char* trackbar_name, const char* window_name)
{
- int pos = -1;
-
- CV_FUNCNAME( "cvGetTrackbarPos" );
+ CV_FUNCNAME("cvGetTrackbarPos");
- __BEGIN__;
+ AutoLock lock(getWindowMutex());
- CvWindow* window;
- CvTrackbar* trackbar = 0;
+ if (trackbar_name == 0 || window_name == 0)
+ CV_Error(Error::StsNullPtr, "NULL trackbar or window name");
- if( trackbar_name == 0 || window_name == 0 )
- CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
-
- window = icvFindWindowByName( window_name );
- if( window )
- trackbar = icvFindTrackbarByName( window, trackbar_name );
-
- if( trackbar )
- pos = trackbar->pos;
+ auto window = icvFindWindowByName(window_name);
+ if (!window)
+ CV_Error_(Error::StsNullPtr, ("NULL window: '%s'", window_name));
- __END__;
+ auto trackbar = icvFindTrackbarByName(window, trackbar_name);
+ if (!trackbar)
+ CV_Error_(Error::StsNullPtr, ("NULL trackbar: '%s'", trackbar_name));
- return pos;
+ return trackbar->pos;
}
-CV_IMPL void cvSetTrackbarPos( const char* trackbar_name, const char* window_name, int pos )
+CV_IMPL void cvSetTrackbarPos(const char* trackbar_name, const char* window_name, int pos)
{
- CV_FUNCNAME( "cvSetTrackbarPos" );
+ CV_FUNCNAME("cvSetTrackbarPos");
- __BEGIN__;
+ AutoLock lock(getWindowMutex());
- CvWindow* window;
- CvTrackbar* trackbar = 0;
+ if (trackbar_name == 0 || window_name == 0)
+ CV_Error(Error::StsNullPtr, "NULL trackbar or window name");
- if( trackbar_name == 0 || window_name == 0 )
- CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
+ auto window = icvFindWindowByName(window_name);
+ if (!window)
+ CV_Error_(Error::StsNullPtr, ("NULL window: '%s'", window_name));
- window = icvFindWindowByName( window_name );
- if( window )
- trackbar = icvFindTrackbarByName( window, trackbar_name );
+ auto trackbar = icvFindTrackbarByName(window, trackbar_name);
+ if (!trackbar)
+ CV_Error_(Error::StsNullPtr, ("NULL trackbar: '%s'", trackbar_name));
- if( trackbar )
{
- if( pos < 0 )
+ if (pos < 0)
pos = 0;
- if( pos > trackbar->maxval )
+ if (pos > trackbar->maxval)
pos = trackbar->maxval;
- SendMessage( trackbar->hwnd, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pos );
- icvUpdateTrackbar( trackbar, pos );
+ SendMessage(trackbar->hwnd, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pos);
+ icvUpdateTrackbar(*trackbar, pos);
}
-
- __END__;
}
CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name, int maxval)
{
- CV_FUNCNAME( "cvSetTrackbarMax" );
+ CV_FUNCNAME("cvSetTrackbarMax");
+
+ if (trackbar_name == 0 || window_name == 0)
+ {
+ CV_Error(Error::StsNullPtr, "NULL trackbar or window name");
+ }
+
+ AutoLock lock(getWindowMutex());
+
+ auto window = icvFindWindowByName(window_name);
+ if (!window)
+ CV_Error_(Error::StsNullPtr, ("NULL window: '%s'", window_name));
- __BEGIN__;
+ auto trackbar = icvFindTrackbarByName(window, trackbar_name);
+ if (!trackbar)
+ CV_Error_(Error::StsNullPtr, ("NULL trackbar: '%s'", trackbar_name));
+ // FIXIT
if (maxval >= 0)
{
- CvWindow* window = 0;
- CvTrackbar* trackbar = 0;
- if (trackbar_name == 0 || window_name == 0)
+ // The position will be min(pos, maxval).
+ trackbar->maxval = (trackbar->minval>maxval)?trackbar->minval:maxval;
+ SendMessage(trackbar->hwnd, TBM_SETRANGEMAX, (WPARAM)TRUE, (LPARAM)maxval);
+ }
+}
+
+
+CV_IMPL void cvSetTrackbarMin(const char* trackbar_name, const char* window_name, int minval)
+{
+ CV_FUNCNAME("cvSetTrackbarMin");
+
+ if (trackbar_name == 0 || window_name == 0)
+ {
+ CV_Error(Error::StsNullPtr, "NULL trackbar or window name");
+ }
+
+ AutoLock lock(getWindowMutex());
+
+ auto window = icvFindWindowByName(window_name);
+ if (!window)
+ CV_Error_(Error::StsNullPtr, ("NULL window: '%s'", window_name));
+
+ auto trackbar = icvFindTrackbarByName(window, trackbar_name);
+ if (!trackbar)
+ CV_Error_(Error::StsNullPtr, ("NULL trackbar: '%s'", trackbar_name));
+
+ // FIXIT
+ if (minval >= 0)
+ {
+ // The position will be min(pos, maxval).
+ trackbar->minval = (minval<trackbar->maxval)?minval:trackbar->maxval;
+ SendMessage(trackbar->hwnd, TBM_SETRANGEMIN, (WPARAM)TRUE, (LPARAM)minval);
+ }
+}
+
+
+CV_IMPL void* cvGetWindowHandle(const char* window_name)
+{
+ CV_FUNCNAME("cvGetWindowHandle");
+
+ AutoLock lock(getWindowMutex());
+
+ if (window_name == 0)
+ CV_Error(Error::StsNullPtr, "NULL window name");
+
+ auto window = icvFindWindowByName(window_name);
+ if (!window)
+ CV_Error_(Error::StsNullPtr, ("NULL window: '%s'", window_name));
+
+ return (void*)window->hwnd;
+}
+
+// FIXIT: result is not safe to use
+CV_IMPL const char* cvGetWindowName(void* window_handle)
+{
+ CV_FUNCNAME("cvGetWindowName");
+
+ AutoLock lock(getWindowMutex());
+
+ if (window_handle == 0)
+ CV_Error(Error::StsNullPtr, "NULL window handle");
+
+ auto window = icvWindowByHWND((HWND)window_handle);
+ if (!window)
+ CV_Error_(Error::StsNullPtr, ("NULL window: '%p'", window_handle));
+
+ return window->name.c_str();
+}
+
+
+CV_IMPL void
+cvSetPreprocessFuncWin32_(const void* callback)
+{
+ hg_on_preprocess = (CvWin32WindowCallback)callback;
+}
+
+CV_IMPL void
+cvSetPostprocessFuncWin32_(const void* callback)
+{
+ hg_on_postprocess = (CvWin32WindowCallback)callback;
+}
+
+
+
+namespace cv { namespace impl {
+
+using namespace cv::highgui_backend;
+
+class Win32UITrackbar;
+
+class Win32UIWindow
+ : public UIWindow
+ , public std::enable_shared_from_this<Win32UIWindow>
+{
+protected:
+ const std::string name_;
+ std::weak_ptr<CvWindow> window_;
+ std::map<std::string, std::shared_ptr<Win32UITrackbar> > trackbars_;
+public:
+ Win32UIWindow(const std::string& name, const std::shared_ptr<CvWindow>& window)
+ : name_(name)
+ , window_(window)
+ {
+ // nothing
+ }
+
+ ~Win32UIWindow() CV_OVERRIDE
+ {
+ if (!window_.expired())
+ destroy();
+ CV_LOG_DEBUG(NULL, "OpenCV/UI/Win32UI: Win32UIWindow(" << name_ << ") is disposed");
+ }
+
+ const std::string& getID() const CV_OVERRIDE { return name_; }
+
+ bool isActive() const CV_OVERRIDE { return !window_.expired(); }
+
+ void destroy() CV_OVERRIDE
+ {
+ cv::AutoLock lock(getWindowMutex());
+ if (!window_.expired())
{
- CV_ERROR(CV_StsNullPtr, "NULL trackbar or window name");
+ auto window = window_.lock();
+ if (window)
+ window->destroy();
+ window_.reset();
}
+ }
- window = icvFindWindowByName(window_name);
- if (window)
+ void imshow(InputArray image) CV_OVERRIDE
+ {
+ auto window_ptr = window_.lock();
+ CV_Assert(window_ptr);
+ CvWindow& window = *window_ptr;
+ Mat image_mat = image.getMat();
+ showImage_(window, image_mat);
+ }
+
+ double getProperty(int prop) const CV_OVERRIDE
+ {
+ auto window_ptr = window_.lock();
+ CV_Assert(window_ptr);
+ CvWindow& window = *window_ptr;
+ // see cvGetWindowProperty
+ switch ((WindowPropertyFlags)prop)
{
- trackbar = icvFindTrackbarByName(window, trackbar_name);
- if (trackbar)
- {
- // The position will be min(pos, maxval).
- trackbar->maxval = (trackbar->minval>maxval)?trackbar->minval:maxval;
- SendMessage(trackbar->hwnd, TBM_SETRANGEMAX, (WPARAM)TRUE, (LPARAM)maxval);
- }
+ case WND_PROP_FULLSCREEN:
+ return (double)window.status;
+
+ case WND_PROP_AUTOSIZE:
+ return (window.flags & WINDOW_AUTOSIZE) ? 1.0 : 0.0;
+
+ case WND_PROP_ASPECT_RATIO:
+ return static_cast<double>(window.width) / window.height;
+
+#ifdef HAVE_OPENGL
+ case WND_PROP_OPENGL:
+ return window.useGl ? 1.0 : 0.0;
+#endif
+
+ case WND_PROP_VISIBLE:
+ return 1.0;
+
+ case WND_PROP_TOPMOST:
+ return getPropTopmost_(window);
+
+ case WND_PROP_VSYNC:
+ return getPropVsync_(window);
+
+ // don't use default, add unsupported cases below:
+ // case WND_PROP_UNSUPPORTED: // fallthru
+ // break;
}
+ return std::numeric_limits<double>::quiet_NaN();
}
- __END__;
-}
+ bool setProperty(int prop, double value) CV_OVERRIDE
+ {
+ auto window_ptr = window_.lock();
+ CV_Assert(window_ptr);
+ CvWindow& window = *window_ptr;
+ // see cvSetWindowProperty
+ switch ((WindowPropertyFlags)prop)
+ {
+ case WND_PROP_FULLSCREEN:
+ if (value != WINDOW_NORMAL && value != WINDOW_FULLSCREEN) // bad arg
+ break;
+ setModeWindow_(window, (int)value);
+ return true;
+ case WND_PROP_TOPMOST:
+ return setPropTopmost_(window, value != 0.0);
-CV_IMPL void cvSetTrackbarMin(const char* trackbar_name, const char* window_name, int minval)
-{
- CV_FUNCNAME( "cvSetTrackbarMin" );
+ case WND_PROP_VSYNC:
+ return setPropVsync_(window, value != 0.0);
- __BEGIN__;
+ // don't use default, add unsupported cases below:
+ // case WND_PROP_UNSUPPORTED: // fallthru
+ case WND_PROP_AUTOSIZE: // fallthru
+ case WND_PROP_ASPECT_RATIO: // fallthru
+ case WND_PROP_OPENGL: // fallthru
+ case WND_PROP_VISIBLE: // fallthru
+ break;
+ }
+ return false;
+ }
- if (minval >= 0)
+ void resize(int width, int height) CV_OVERRIDE
{
- CvWindow* window = 0;
- CvTrackbar* trackbar = 0;
- if (trackbar_name == 0 || window_name == 0)
+ auto window_ptr = window_.lock();
+ CV_Assert(window_ptr);
+ CvWindow& window = *window_ptr;
+ resizeWindow_(window, Size(width, height));
+ }
+
+ void move(int x, int y) CV_OVERRIDE
+ {
+ auto window_ptr = window_.lock();
+ CV_Assert(window_ptr);
+ CvWindow& window = *window_ptr;
+ moveWindow_(window, Point(x, y));
+ }
+
+ Rect getImageRect() const CV_OVERRIDE
+ {
+ auto window_ptr = window_.lock();
+ CV_Assert(window_ptr);
+ CvWindow& window = *window_ptr;
+ return getImageRect_(window);
+ }
+
+ void setTitle(const std::string& title) CV_OVERRIDE
+ {
+ auto window_ptr = window_.lock();
+ CV_Assert(window_ptr);
+ CvWindow& window = *window_ptr;
+ if (!SetWindowText(window.frame, title.c_str()))
+ CV_Error_(Error::StsError, ("Failed to set \"%s\" window title to \"%s\"", window.name.c_str(), title.c_str()));
+ }
+
+ void setMouseCallback(MouseCallback onMouse, void* userdata /*= 0*/) CV_OVERRIDE
+ {
+ auto window_ptr = window_.lock();
+ CV_Assert(window_ptr);
+ CvWindow& window = *window_ptr;
+ window.on_mouse = onMouse;
+ window.on_mouse_param = userdata;
+ }
+
+ std::shared_ptr<UITrackbar> createTrackbar(
+ const std::string& name,
+ int count,
+ TrackbarCallback onChange /*= 0*/,
+ void* userdata /*= 0*/
+ ) CV_OVERRIDE
+ {
+ auto window_ptr = window_.lock();
+ CV_Assert(window_ptr);
+ CvWindow& window = *window_ptr;
+ CV_LOG_INFO(NULL, "OpenCV/UI: Creating Win32UI trackbar at '" << name_ << "': '" << name << "'");
+ auto trackbar = createTrackbar_(window, name, count, onChange, userdata);
+ auto ui_trackbar = std::make_shared<Win32UITrackbar>(name, trackbar, shared_from_this());
{
- CV_ERROR(CV_StsNullPtr, "NULL trackbar or window name");
+ cv::AutoLock lock(getWindowMutex());
+ trackbars_.emplace(name, ui_trackbar);
}
+ return std::static_pointer_cast<UITrackbar>(ui_trackbar);
+ }
- window = icvFindWindowByName(window_name);
- if (window)
+ std::shared_ptr<UITrackbar> findTrackbar(const std::string& name) CV_OVERRIDE
+ {
+ cv::AutoLock lock(getWindowMutex());
+ auto i = trackbars_.find(name);
+ if (i != trackbars_.end())
{
- trackbar = icvFindTrackbarByName(window, trackbar_name);
- if (trackbar)
- {
- // The position will be min(pos, maxval).
- trackbar->minval = (minval<trackbar->maxval)?minval:trackbar->maxval;
- SendMessage(trackbar->hwnd, TBM_SETRANGEMIN, (WPARAM)TRUE, (LPARAM)minval);
- }
+ return std::static_pointer_cast<UITrackbar>(i->second);
}
+ return std::shared_ptr<UITrackbar>();
}
-
- __END__;
-}
+}; // Win32UIWindow
-CV_IMPL void* cvGetWindowHandle( const char* window_name )
+class Win32UITrackbar : public UITrackbar
{
- void* hwnd = 0;
+protected:
+ /*const*/ std::string name_;
+ std::weak_ptr<CvTrackbar> trackbar_;
+ std::weak_ptr<Win32UIWindow> parent_;
+ std::map<std::string, std::shared_ptr<Win32UITrackbar> > trackbars_;
+public:
+ Win32UITrackbar(const std::string& name, const std::shared_ptr<CvTrackbar>& trackbar, const std::shared_ptr<Win32UIWindow>& parent)
+ : trackbar_(trackbar)
+ , parent_(parent)
+ {
+ name_ = std::string("<") + name + ">@" + parent->getID();
+ }
- CV_FUNCNAME( "cvGetWindowHandle" );
+ ~Win32UITrackbar() CV_OVERRIDE
+ {
+ if (!trackbar_.expired())
+ destroy();
+ CV_LOG_DEBUG(NULL, "OpenCV/UI/Win32UI: Win32UITrackbar(" << name_ << ") is disposed");
+ }
- __BEGIN__;
+ const std::string& getID() const CV_OVERRIDE { return name_; }
- CvWindow* window;
+ bool isActive() const CV_OVERRIDE { return !trackbar_.expired(); }
- if( window_name == 0 )
- CV_ERROR( CV_StsNullPtr, "NULL window name" );
+ void destroy() CV_OVERRIDE
+ {
+ // nothing (destroyed with parent window, dedicated trackbar removal is not supported)
+ }
- window = icvFindWindowByName( window_name );
- if( window )
- hwnd = (void*)window->hwnd;
+ int getPos() const CV_OVERRIDE
+ {
+ auto trackbar_ptr = trackbar_.lock();
+ CV_Assert(trackbar_ptr);
+ CvTrackbar& trackbar = *trackbar_ptr;
+ return trackbar.pos;
+ }
+ void setPos(int pos) CV_OVERRIDE
+ {
+ auto trackbar_ptr = trackbar_.lock();
+ CV_Assert(trackbar_ptr);
+ CvTrackbar& trackbar = *trackbar_ptr;
+ SendMessage(trackbar.hwnd, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pos);
+ icvUpdateTrackbar(trackbar, pos);
+ }
- __END__;
+ cv::Range getRange() const CV_OVERRIDE
+ {
+ auto trackbar_ptr = trackbar_.lock();
+ CV_Assert(trackbar_ptr);
+ CvTrackbar& trackbar = *trackbar_ptr;
+ return cv::Range(trackbar.minval, trackbar.maxval);
+ }
- return hwnd;
-}
+ void setRange(const cv::Range& range) CV_OVERRIDE
+ {
+ auto trackbar_ptr = trackbar_.lock();
+ CV_Assert(trackbar_ptr);
+ CvTrackbar& trackbar = *trackbar_ptr;
+ CV_CheckLE(range.start, range.end, "Invalid trackbar range");
+ trackbar.minval = range.start;
+ trackbar.maxval = range.start;
+ SendMessage(trackbar.hwnd, TBM_SETRANGEMIN, (WPARAM)TRUE, (LPARAM)trackbar.minval);
+ SendMessage(trackbar.hwnd, TBM_SETRANGEMAX, (WPARAM)TRUE, (LPARAM)trackbar.maxval);
+ }
+}; // Win32UITrackbar
-CV_IMPL const char* cvGetWindowName( void* window_handle )
+class Win32BackendUI : public UIBackend
{
- const char* window_name = "";
+public:
+ ~Win32BackendUI() CV_OVERRIDE
+ {
+ destroyAllWindows();
+ }
- CV_FUNCNAME( "cvGetWindowName" );
+ void destroyAllWindows() CV_OVERRIDE
+ {
+ cvDestroyAllWindows();
+ }
- __BEGIN__;
+ // namedWindow
+ virtual std::shared_ptr<UIWindow> createWindow(
+ const std::string& winname,
+ int flags
+ ) CV_OVERRIDE
+ {
+ CV_LOG_INFO(NULL, "OpenCV/UI: Creating Win32UI window: " << winname << " (" << flags << ")");
+ auto window = namedWindow_(winname, flags);
+ auto ui_window = std::make_shared<Win32UIWindow>(winname, window);
+ return ui_window;
+ }
- CvWindow* window;
+ int waitKeyEx(int delay) CV_OVERRIDE
+ {
+ return cvWaitKey(delay);
+ }
+ int pollKey() CV_OVERRIDE
+ {
+ return pollKey_W32();
+ }
+}; // Win32BackendUI
- if( window_handle == 0 )
- CV_ERROR( CV_StsNullPtr, "NULL window" );
+static
+std::shared_ptr<Win32BackendUI>& getInstance()
+{
+ static std::shared_ptr<Win32BackendUI> g_instance = std::make_shared<Win32BackendUI>();
+ return g_instance;
+}
- window = icvWindowByHWND( (HWND)window_handle );
- if( window )
- window_name = window->name;
+} // namespace impl
- __END__;
+#ifndef BUILD_PLUGIN
+namespace highgui_backend {
- return window_name;
+std::shared_ptr<UIBackend> createUIBackendWin32UI()
+{
+ return impl::getInstance();
}
+} // namespace highgui_backend
+#endif
-CV_IMPL void
-cvSetPreprocessFuncWin32_(const void* callback)
+} // namespace
+
+
+#ifdef BUILD_PLUGIN
+
+#define ABI_VERSION 0
+#define API_VERSION 0
+#include "plugin_api.hpp"
+
+static
+CvResult cv_getInstance(CV_OUT CvPluginUIBackend* handle) CV_NOEXCEPT
{
- hg_on_preprocess = (CvWin32WindowCallback)callback;
+ try
+ {
+ if (!handle)
+ return CV_ERROR_FAIL;
+ *handle = cv::impl::getInstance().get();
+ return CV_ERROR_OK;
+ }
+ catch (...)
+ {
+ return CV_ERROR_FAIL;
+ }
}
-CV_IMPL void
-cvSetPostprocessFuncWin32_(const void* callback)
+static const OpenCV_UI_Plugin_API plugin_api =
{
- hg_on_postprocess = (CvWin32WindowCallback)callback;
+ {
+ sizeof(OpenCV_UI_Plugin_API), ABI_VERSION, API_VERSION,
+ CV_VERSION_MAJOR, CV_VERSION_MINOR, CV_VERSION_REVISION, CV_VERSION_STATUS,
+ "Win32 OpenCV UI plugin"
+ },
+ {
+ /* 1*/cv_getInstance
+ }
+};
+
+const OpenCV_UI_Plugin_API* CV_API_CALL opencv_ui_plugin_init_v0(int requested_abi_version, int requested_api_version, void* /*reserved=NULL*/) CV_NOEXCEPT
+{
+ if (requested_abi_version == ABI_VERSION && requested_api_version <= API_VERSION)
+ return &plugin_api;
+ return NULL;
}
-#endif //_WIN32
+#endif // BUILD_PLUGIN
+
+#endif // HAVE_WIN32UI