|
|
|
@@ -41,12 +41,17 @@
|
|
|
|
|
|
|
|
|
|
#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
|
|
|
|
@@ -60,14 +65,12 @@ using namespace cv;
|
|
|
|
|
#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
|
|
|
|
@@ -78,7 +81,7 @@ static const char* trackbar_text =
|
|
|
|
|
#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
|
|
|
|
@@ -89,7 +92,7 @@ static const char* trackbar_text =
|
|
|
|
|
#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
|
|
|
|
@@ -116,13 +119,13 @@ static inline void mingw_strcat_s(char *dest, size_t destsz, const char *src){
|
|
|
|
|
#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);
|
|
|
|
@@ -130,11 +133,11 @@ static void FillBitmapInfo( BITMAPINFO* bmi, int width, int height, int bpp, int
|
|
|
|
|
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;
|
|
|
|
@@ -144,68 +147,91 @@ static void FillBitmapInfo( BITMAPINFO* bmi, int width, int height, int bpp, int
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
@@ -221,19 +247,50 @@ CvWindow;
|
|
|
|
|
#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()
|
|
|
|
|
{
|
|
|
|
@@ -242,15 +299,15 @@ 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;
|
|
|
|
@@ -262,7 +319,7 @@ CV_IMPL int cvInitSystem( int, char** )
|
|
|
|
|
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);
|
|
|
|
@@ -273,12 +330,12 @@ CV_IMPL int cvInitSystem( int, char** )
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
@@ -287,50 +344,58 @@ CV_IMPL int cvStartWindowThread(){
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static CvWindow* icvFindWindowByName( const char* name )
|
|
|
|
|
|
|
|
|
|
static std::shared_ptr<CvWindow> icvWindowByHWND(HWND hwnd)
|
|
|
|
|
{
|
|
|
|
|
CvWindow* window = hg_windows;
|
|
|
|
|
|
|
|
|
|
for( ; window != 0 && strcmp( name, window->name) != 0; window = window->next )
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
return window;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static 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;
|
|
|
|
@@ -379,16 +444,16 @@ icvLoadWindowPos( const char* name, CvRect& rect )
|
|
|
|
|
//<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;
|
|
|
|
@@ -396,40 +461,40 @@ icvSaveWindowPos( const char* name, CvRect rect )
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -440,96 +505,101 @@ icvSaveWindowPos( const char* name, CvRect rect )
|
|
|
|
|
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 );
|
|
|
|
|
if (!window)
|
|
|
|
|
EXIT; // keep silence here
|
|
|
|
|
CV_Error(Error::StsNullPtr, "NULL name string");
|
|
|
|
|
|
|
|
|
|
GetClientRect(window->hwnd, &rect);
|
|
|
|
|
{
|
|
|
|
|
auto window = icvFindWindowByName(name);
|
|
|
|
|
if (!window)
|
|
|
|
|
CV_Error_(Error::StsNullPtr, ("NULL window: '%s'", name));
|
|
|
|
|
|
|
|
|
|
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");
|
|
|
|
|
|
|
|
|
|
CV_FUNCNAME( "cvGetModeWindow_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 = 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;
|
|
|
|
@@ -542,60 +612,75 @@ void cvSetModeWindow_W32( const char* name, double prop_value)//Yannick Verdie
|
|
|
|
|
//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
|
|
|
|
@@ -605,40 +690,53 @@ double cvGetPropVsync_W32(const char* name)
|
|
|
|
|
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
|
|
|
|
@@ -649,11 +747,22 @@ void cvSetPropVsync_W32(const char* name, const bool enable_vsync)
|
|
|
|
|
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);
|
|
|
|
@@ -676,47 +785,44 @@ void cvSetPropVsync_W32(const char* name, const bool enable_vsync)
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -724,23 +830,19 @@ double cvGetRatioWindow_W32(const char* name)
|
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -749,23 +851,20 @@ double cvGetOpenGlProp_W32(const char* name)
|
|
|
|
|
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;
|
|
|
|
@@ -775,16 +874,15 @@ double cvGetPropVisible_W32(const char* name)
|
|
|
|
|
{
|
|
|
|
|
double result = -1;
|
|
|
|
|
|
|
|
|
|
CV_FUNCNAME( "cvGetPropVisible_W32" );
|
|
|
|
|
CV_FUNCNAME("cvGetPropVisible_W32");
|
|
|
|
|
|
|
|
|
|
__BEGIN__;
|
|
|
|
|
AutoLock lock(getWindowMutex());
|
|
|
|
|
|
|
|
|
|
if (!name)
|
|
|
|
|
CV_ERROR( CV_StsNullPtr, "NULL name string" );
|
|
|
|
|
CV_Error(Error::StsNullPtr, "NULL name string");
|
|
|
|
|
|
|
|
|
|
result = (icvFindWindowByName( name ) != NULL);
|
|
|
|
|
|
|
|
|
|
__END__;
|
|
|
|
|
auto window = icvFindWindowByName(name);
|
|
|
|
|
result = (bool)window ? 1.0 : 0.0;
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
@@ -798,9 +896,9 @@ namespace
|
|
|
|
|
{
|
|
|
|
|
void createGlContext(HWND hWnd, HDC& hGLDC, HGLRC& hGLRC, bool& useGl)
|
|
|
|
|
{
|
|
|
|
|
CV_FUNCNAME( "createGlContext" );
|
|
|
|
|
CV_FUNCNAME("createGlContext");
|
|
|
|
|
|
|
|
|
|
__BEGIN__;
|
|
|
|
|
AutoLock lock(getWindowMutex());
|
|
|
|
|
|
|
|
|
|
useGl = false;
|
|
|
|
|
|
|
|
|
@@ -830,120 +928,119 @@ namespace
|
|
|
|
|
|
|
|
|
|
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" );
|
|
|
|
|
CV_FUNCNAME("resizeGl");
|
|
|
|
|
|
|
|
|
|
__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");
|
|
|
|
|
|
|
|
|
|
glViewport(0, 0, window->width, window->height);
|
|
|
|
|
|
|
|
|
|
__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_IMPL int cvNamedWindow(const char* name, int flags)
|
|
|
|
|
{
|
|
|
|
|
int result = 0;
|
|
|
|
|
CV_FUNCNAME( "cvNamedWindow" );
|
|
|
|
|
CV_FUNCNAME("cvNamedWindow");
|
|
|
|
|
|
|
|
|
|
__BEGIN__;
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
window = namedWindow_(name, flags);
|
|
|
|
|
return (bool)window;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static std::shared_ptr<CvWindow> namedWindow_(const std::string& name, int flags)
|
|
|
|
|
{
|
|
|
|
|
AutoLock lock(getWindowMutex());
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
CvRect rect;
|
|
|
|
|
icvLoadWindowPos(name.c_str(), rect);
|
|
|
|
|
|
|
|
|
|
if( !name )
|
|
|
|
|
CV_ERROR( CV_StsNullPtr, "NULL name string" );
|
|
|
|
|
|
|
|
|
|
// Check the name in the storage
|
|
|
|
|
window = icvFindWindowByName( name );
|
|
|
|
|
if (window != 0)
|
|
|
|
|
{
|
|
|
|
|
result = 1;
|
|
|
|
|
EXIT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
@@ -951,23 +1048,21 @@ CV_IMPL int cvNamedWindow( const char* name, int flags )
|
|
|
|
|
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;
|
|
|
|
@@ -979,14 +1074,10 @@ CV_IMPL int cvNamedWindow( const char* name, int flags )
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
@@ -1016,200 +1107,175 @@ CV_IMPL int cvNamedWindow( const char* name, int flags )
|
|
|
|
|
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" );
|
|
|
|
|
CV_FUNCNAME("cvSetOpenGlContext");
|
|
|
|
|
|
|
|
|
|
__BEGIN__;
|
|
|
|
|
AutoLock lock(getWindowMutex());
|
|
|
|
|
|
|
|
|
|
CvWindow* window;
|
|
|
|
|
if (!name)
|
|
|
|
|
CV_Error(Error::StsNullPtr, "NULL name string");
|
|
|
|
|
|
|
|
|
|
if(!name)
|
|
|
|
|
CV_ERROR( CV_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(Error::StsNullPtr, "NULL name string");
|
|
|
|
|
|
|
|
|
|
if(!name)
|
|
|
|
|
CV_ERROR( CV_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.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->hwnd )
|
|
|
|
|
icvSetWindowLongPtr( window->hwnd, CV_USERDATA, 0 );
|
|
|
|
|
if( window->frame )
|
|
|
|
|
icvSetWindowLongPtr( window->frame, CV_USERDATA, 0 );
|
|
|
|
|
if (window.hwnd)
|
|
|
|
|
icvSetWindowLongPtr(window.hwnd, CV_USERDATA, 0);
|
|
|
|
|
if (window.frame)
|
|
|
|
|
icvSetWindowLongPtr(window.frame, CV_USERDATA, 0);
|
|
|
|
|
|
|
|
|
|
if( window->toolbar.toolbar )
|
|
|
|
|
icvSetWindowLongPtr(window->toolbar.toolbar, CV_USERDATA, 0);
|
|
|
|
|
if (window.toolbar.toolbar)
|
|
|
|
|
icvSetWindowLongPtr(window.toolbar.toolbar, CV_USERDATA, 0);
|
|
|
|
|
|
|
|
|
|
if( window->prev )
|
|
|
|
|
window->prev->next = window->next;
|
|
|
|
|
else
|
|
|
|
|
hg_windows = window->next;
|
|
|
|
|
if (window.dc && window.image)
|
|
|
|
|
DeleteObject(SelectObject(window.dc, window.image));
|
|
|
|
|
|
|
|
|
|
if( window->next )
|
|
|
|
|
window->next->prev = window->prev;
|
|
|
|
|
if (window.dc)
|
|
|
|
|
DeleteDC(window.dc);
|
|
|
|
|
|
|
|
|
|
window->prev = window->next = 0;
|
|
|
|
|
|
|
|
|
|
if( window->dc && window->image )
|
|
|
|
|
DeleteObject(SelectObject(window->dc,window->image));
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
mainhWnd = window->frame;
|
|
|
|
|
|
|
|
|
|
SendMessage(window->hwnd, WM_CLOSE, 0, 0);
|
|
|
|
|
SendMessage( mainhWnd, WM_CLOSE, 0, 0);
|
|
|
|
|
// Do NOT call _remove_window -- CvWindow list will be updated automatically ...
|
|
|
|
|
|
|
|
|
|
__END__;
|
|
|
|
|
window->destroy();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void icvScreenToClient( HWND hwnd, RECT* rect )
|
|
|
|
|
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 ...
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
@@ -1217,138 +1283,153 @@ static RECT icvCalcWindowRect( CvWindow* window )
|
|
|
|
|
|
|
|
|
|
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" );
|
|
|
|
|
CV_FUNCNAME("cvShowImage");
|
|
|
|
|
|
|
|
|
|
__BEGIN__;
|
|
|
|
|
if (!name)
|
|
|
|
|
CV_Error(Error::StsNullPtr, "NULL name");
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<CvWindow> window;
|
|
|
|
|
{
|
|
|
|
|
AutoLock lock(getWindowMutex());
|
|
|
|
|
|
|
|
|
|
window = icvFindWindowByName(name);
|
|
|
|
|
if (!window)
|
|
|
|
|
{
|
|
|
|
|
cvNamedWindow(name, CV_WINDOW_AUTOSIZE);
|
|
|
|
|
window = icvFindWindowByName(name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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, image);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
return showImage_(*window, image);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void showImage_(CvWindow& window, const Mat& image)
|
|
|
|
|
{
|
|
|
|
|
AutoLock lock(window.mutex);
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
if( !name )
|
|
|
|
|
CV_ERROR( CV_StsNullPtr, "NULL name" );
|
|
|
|
|
|
|
|
|
|
window = icvFindWindowByName(name);
|
|
|
|
|
if(!window)
|
|
|
|
|
if (window.image)
|
|
|
|
|
{
|
|
|
|
|
cvNamedWindow(name, CV_WINDOW_AUTOSIZE);
|
|
|
|
|
window = icvFindWindowByName(name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( !window || !arr )
|
|
|
|
|
EXIT; // keep silence here.
|
|
|
|
|
|
|
|
|
|
CV_CALL( image = cvGetMat( arr, &stub ));
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_OPENGL
|
|
|
|
|
if (window->useGl)
|
|
|
|
|
{
|
|
|
|
|
cv::imshow(name, cv::cvarrToMat(image));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
@@ -1356,98 +1437,103 @@ cvShowImage( const char* name, const CvArr* arr )
|
|
|
|
|
// 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;
|
|
|
|
|
if (!name)
|
|
|
|
|
CV_Error(Error::StsNullPtr, "NULL name");
|
|
|
|
|
|
|
|
|
|
auto window = icvFindWindowByName(name);
|
|
|
|
|
if (!window)
|
|
|
|
|
CV_Error_(Error::StsNullPtr, ("NULL window: '%s'", name));
|
|
|
|
|
|
|
|
|
|
return resizeWindow_(*window, Size(width, height));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void resizeWindow_(CvWindow& window, const Size& size)
|
|
|
|
|
{
|
|
|
|
|
RECT rmw = { 0 }, rw = { 0 }, rect = { 0 };
|
|
|
|
|
|
|
|
|
|
if( !name )
|
|
|
|
|
CV_ERROR( CV_StsNullPtr, "NULL name" );
|
|
|
|
|
|
|
|
|
|
window = icvFindWindowByName(name);
|
|
|
|
|
if(!window)
|
|
|
|
|
EXIT;
|
|
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
if (!name)
|
|
|
|
|
CV_Error(Error::StsNullPtr, "NULL name");
|
|
|
|
|
|
|
|
|
|
auto window = icvFindWindowByName(name);
|
|
|
|
|
if (!window)
|
|
|
|
|
CV_Error_(Error::StsNullPtr, ("NULL window: '%s'", name));
|
|
|
|
|
|
|
|
|
|
(void)moveWindow_(*window, Point(x, y));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void moveWindow_(CvWindow& window, const Point& pt)
|
|
|
|
|
{
|
|
|
|
|
RECT rect = { 0 };
|
|
|
|
|
|
|
|
|
|
if( !name )
|
|
|
|
|
CV_ERROR( CV_StsNullPtr, "NULL name" );
|
|
|
|
|
|
|
|
|
|
window = icvFindWindowByName(name);
|
|
|
|
|
if(!window)
|
|
|
|
|
EXIT;
|
|
|
|
|
|
|
|
|
|
GetWindowRect( window->frame, &rect );
|
|
|
|
|
MoveWindow( window->frame, x, y, rect.right - rect.left, rect.bottom - rect.top, TRUE);
|
|
|
|
|
|
|
|
|
|
__END__;
|
|
|
|
|
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 };
|
|
|
|
@@ -1456,10 +1542,10 @@ MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
|
|
|
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;
|
|
|
|
@@ -1471,14 +1557,14 @@ MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
|
|
|
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;
|
|
|
|
@@ -1490,7 +1576,7 @@ MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
|
|
|
LPWINDOWPOS pos = (LPWINDOWPOS)lParam;
|
|
|
|
|
|
|
|
|
|
RECT rect = { 0 };
|
|
|
|
|
GetWindowRect(window->frame, &rect);
|
|
|
|
|
GetWindowRect(window.frame, &rect);
|
|
|
|
|
|
|
|
|
|
HMONITOR hMonitor;
|
|
|
|
|
hMonitor = MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST);
|
|
|
|
@@ -1515,13 +1601,13 @@ MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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)|
|
|
|
|
@@ -1536,32 +1622,32 @@ MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
@@ -1571,17 +1657,17 @@ MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
|
|
|
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);
|
|
|
|
@@ -1591,7 +1677,7 @@ MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
|
|
|
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);
|
|
|
|
@@ -1605,20 +1691,24 @@ MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
@@ -1632,7 +1722,7 @@ static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
|
|
|
|
|
if (!::EmptyClipboard())
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if(!window->image)
|
|
|
|
|
if (!window.image)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// Get window device context
|
|
|
|
@@ -1640,19 +1730,20 @@ static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
|
|
|
|
|
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
|
|
|
|
@@ -1660,7 +1751,7 @@ static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
RGBQUAD table[256];
|
|
|
|
|
if( 1 == nchannels )
|
|
|
|
|
if (1 == nchannels)
|
|
|
|
|
{
|
|
|
|
|
for(int i = 0; i < 256; ++i)
|
|
|
|
|
{
|
|
|
|
@@ -1668,14 +1759,14 @@ static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
|
|
|
|
|
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
|
|
|
|
@@ -1712,7 +1803,7 @@ static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
|
|
|
|
|
case WM_RBUTTONUP:
|
|
|
|
|
case WM_MBUTTONUP:
|
|
|
|
|
case WM_MOUSEMOVE:
|
|
|
|
|
if( window->on_mouse )
|
|
|
|
|
if (window.on_mouse)
|
|
|
|
|
{
|
|
|
|
|
POINT pt;
|
|
|
|
|
|
|
|
|
@@ -1732,50 +1823,50 @@ static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
|
|
|
|
|
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};
|
|
|
|
@@ -1784,12 +1875,13 @@ static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
|
|
|
|
|
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++)
|
|
|
|
@@ -1798,25 +1890,25 @@ static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
|
|
|
|
|
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);
|
|
|
|
@@ -1829,13 +1921,13 @@ static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM 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;
|
|
|
|
@@ -1845,15 +1937,15 @@ static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
@@ -1862,24 +1954,24 @@ static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1887,51 +1979,56 @@ static LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
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)strlen(trackbar->name);
|
|
|
|
|
name_len = (int)trackbar.name.size();
|
|
|
|
|
|
|
|
|
|
if( name_len > max_name_len )
|
|
|
|
|
// 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)
|
|
|
|
|
{
|
|
|
|
@@ -1940,32 +2037,34 @@ static LRESULT CALLBACK HGToolbarProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPAR
|
|
|
|
|
{
|
|
|
|
|
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,
|
|
|
|
@@ -1973,46 +2072,63 @@ static LRESULT CALLBACK HGToolbarProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPAR
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
SendMessage( hwnd, WM_CLOSE, 0, 0 );
|
|
|
|
|
SendMessage( mainhWnd, WM_CLOSE, 0, 0 );
|
|
|
|
|
{
|
|
|
|
|
CvWindow& window = *window_;
|
|
|
|
|
|
|
|
|
|
HWND mainhWnd = window.frame;
|
|
|
|
|
HWND hwnd = window.hwnd;
|
|
|
|
|
|
|
|
|
|
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));
|
|
|
|
@@ -2022,7 +2138,7 @@ static void showSaveDialog(CvWindow* window)
|
|
|
|
|
#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"
|
|
|
|
@@ -2075,9 +2191,15 @@ static bool handleMessage(MSG& message, int& keyCode)
|
|
|
|
|
// 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;
|
|
|
|
@@ -2140,7 +2262,7 @@ static bool handleMessage(MSG& message, int& keyCode)
|
|
|
|
|
/*
|
|
|
|
|
* process until queue is empty but don't wait.
|
|
|
|
|
*/
|
|
|
|
|
int cv::pollKey()
|
|
|
|
|
int pollKey_W32()
|
|
|
|
|
{
|
|
|
|
|
CV_TRACE_FUNCTION();
|
|
|
|
|
for(;;)
|
|
|
|
@@ -2156,7 +2278,7 @@ int cv::pollKey()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CV_IMPL int
|
|
|
|
|
cvWaitKey( int delay )
|
|
|
|
|
cvWaitKey(int delay)
|
|
|
|
|
{
|
|
|
|
|
int64 time0 = cv::getTickCount();
|
|
|
|
|
int64 timeEnd = time0 + (int64)(delay * 0.001f * cv::getTickFrequency());
|
|
|
|
@@ -2165,9 +2287,9 @@ cvWaitKey( int delay )
|
|
|
|
|
{
|
|
|
|
|
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)
|
|
|
|
@@ -2183,110 +2305,135 @@ cvWaitKey( int delay )
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 )
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
icvUpdateWindowPos(window);
|
|
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
|
{
|
|
|
|
|
TBBUTTON tbs = {};
|
|
|
|
|
TBBUTTONINFO tbis = {};
|
|
|
|
|
RECT rect = { 0 };
|
|
|
|
|
int bcount;
|
|
|
|
|
int len = (int)strlen( trackbar_name );
|
|
|
|
|
createToolbar_(window);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// create toolbar if it is not created yet
|
|
|
|
|
if( !window->toolbar.toolbar )
|
|
|
|
|
{
|
|
|
|
|
const int default_height = 30;
|
|
|
|
|
TBBUTTON tbs = {};
|
|
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
/* Retrieve current buttons count */
|
|
|
|
|
int bcount = (int)SendMessage(window.toolbar.toolbar, TB_BUTTONCOUNT, 0, 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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Retrieve current buttons count */
|
|
|
|
|
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 */
|
|
|
|
|
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.fsState = TBSTATE_ENABLED;
|
|
|
|
|
#if 0/*!defined WIN64 && !defined EM64T*/
|
|
|
|
|
tbs.fsStyle = 0;
|
|
|
|
|
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;
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
#ifndef TBSTYLE_AUTOSIZE
|
|
|
|
@@ -2296,307 +2443,257 @@ icvCreateTrackbar( const char* trackbar_name, const char* window_name,
|
|
|
|
|
#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);
|
|
|
|
|
SendMessage(window.toolbar.toolbar, TB_ADDBUTTONS, 1, (LPARAM)&tbs);
|
|
|
|
|
|
|
|
|
|
/* Adjust button size to the slider */
|
|
|
|
|
tbis.cbSize = sizeof(tbis);
|
|
|
|
|
tbis.dwMask = TBIF_SIZE;
|
|
|
|
|
TBBUTTONINFO tbis = {};
|
|
|
|
|
|
|
|
|
|
GetClientRect(window->hwnd, &rect);
|
|
|
|
|
tbis.cx = (unsigned short)(rect.right - rect.left);
|
|
|
|
|
/* Adjust button size to the slider */
|
|
|
|
|
tbis.cbSize = sizeof(tbis);
|
|
|
|
|
tbis.dwMask = TBIF_SIZE;
|
|
|
|
|
|
|
|
|
|
SendMessage(window->toolbar.toolbar, TB_SETBUTTONINFO,
|
|
|
|
|
(WPARAM)tbs.idCommand, (LPARAM)&tbis);
|
|
|
|
|
RECT rect = { 0 };
|
|
|
|
|
GetClientRect(window.hwnd, &rect);
|
|
|
|
|
tbis.cx = (unsigned short)(rect.right - rect.left);
|
|
|
|
|
|
|
|
|
|
/* Get button pos */
|
|
|
|
|
SendMessage(window->toolbar.toolbar, TB_GETITEMRECT,
|
|
|
|
|
(WPARAM)tbs.idCommand, (LPARAM)&rect);
|
|
|
|
|
SendMessage(window.toolbar.toolbar, TB_SETBUTTONINFO,
|
|
|
|
|
(WPARAM)tbs.idCommand, (LPARAM)&tbis);
|
|
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
/* Get button pos */
|
|
|
|
|
SendMessage(window.toolbar.toolbar, TB_GETITEMRECT,
|
|
|
|
|
(WPARAM)tbs.idCommand, (LPARAM)&rect);
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
/* Create a slider */
|
|
|
|
|
auto trackbar = std::make_shared<CvTrackbar>(window, trackbar_name);
|
|
|
|
|
trackbar->id = bcount;
|
|
|
|
|
window.toolbar.trackbars.push_back(trackbar);
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
icvSetWindowLongPtr( trackbar->hwnd, CV_USERDATA, trackbar );
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
trackbar->onChangeCallback = onChange;
|
|
|
|
|
trackbar->userdata = userdata;
|
|
|
|
|
|
|
|
|
|
__END__;
|
|
|
|
|
|
|
|
|
|
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" );
|
|
|
|
|
CV_FUNCNAME("cvSetMouseCallback");
|
|
|
|
|
|
|
|
|
|
__BEGIN__;
|
|
|
|
|
if (!name)
|
|
|
|
|
CV_Error(Error::StsNullPtr, "NULL window name");
|
|
|
|
|
|
|
|
|
|
CvWindow* window = 0;
|
|
|
|
|
AutoLock lock(getWindowMutex());
|
|
|
|
|
|
|
|
|
|
if( !window_name )
|
|
|
|
|
CV_ERROR( CV_StsNullPtr, "NULL window name" );
|
|
|
|
|
|
|
|
|
|
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" );
|
|
|
|
|
AutoLock lock(getWindowMutex());
|
|
|
|
|
|
|
|
|
|
__BEGIN__;
|
|
|
|
|
if (trackbar_name == 0 || window_name == 0)
|
|
|
|
|
CV_Error(Error::StsNullPtr, "NULL trackbar or window name");
|
|
|
|
|
|
|
|
|
|
CvWindow* window;
|
|
|
|
|
CvTrackbar* trackbar = 0;
|
|
|
|
|
auto window = icvFindWindowByName(window_name);
|
|
|
|
|
if (!window)
|
|
|
|
|
CV_Error_(Error::StsNullPtr, ("NULL window: '%s'", window_name));
|
|
|
|
|
|
|
|
|
|
if( trackbar_name == 0 || window_name == 0 )
|
|
|
|
|
CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
|
|
|
|
|
auto trackbar = icvFindTrackbarByName(window, trackbar_name);
|
|
|
|
|
if (!trackbar)
|
|
|
|
|
CV_Error_(Error::StsNullPtr, ("NULL trackbar: '%s'", trackbar_name));
|
|
|
|
|
|
|
|
|
|
window = icvFindWindowByName( window_name );
|
|
|
|
|
if( window )
|
|
|
|
|
trackbar = icvFindTrackbarByName( window, trackbar_name );
|
|
|
|
|
|
|
|
|
|
if( trackbar )
|
|
|
|
|
pos = trackbar->pos;
|
|
|
|
|
|
|
|
|
|
__END__;
|
|
|
|
|
|
|
|
|
|
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");
|
|
|
|
|
|
|
|
|
|
__BEGIN__;
|
|
|
|
|
|
|
|
|
|
if (maxval >= 0)
|
|
|
|
|
if (trackbar_name == 0 || window_name == 0)
|
|
|
|
|
{
|
|
|
|
|
CvWindow* window = 0;
|
|
|
|
|
CvTrackbar* trackbar = 0;
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
// 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_Error(Error::StsNullPtr, "NULL trackbar or window name");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
__END__;
|
|
|
|
|
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 (maxval >= 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" );
|
|
|
|
|
CV_FUNCNAME("cvSetTrackbarMin");
|
|
|
|
|
|
|
|
|
|
__BEGIN__;
|
|
|
|
|
|
|
|
|
|
if (minval >= 0)
|
|
|
|
|
if (trackbar_name == 0 || window_name == 0)
|
|
|
|
|
{
|
|
|
|
|
CvWindow* window = 0;
|
|
|
|
|
CvTrackbar* trackbar = 0;
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
// 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_Error(Error::StsNullPtr, "NULL trackbar or window name");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
__END__;
|
|
|
|
|
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_IMPL void* cvGetWindowHandle(const char* window_name)
|
|
|
|
|
{
|
|
|
|
|
void* hwnd = 0;
|
|
|
|
|
CV_FUNCNAME("cvGetWindowHandle");
|
|
|
|
|
|
|
|
|
|
CV_FUNCNAME( "cvGetWindowHandle" );
|
|
|
|
|
AutoLock lock(getWindowMutex());
|
|
|
|
|
|
|
|
|
|
__BEGIN__;
|
|
|
|
|
if (window_name == 0)
|
|
|
|
|
CV_Error(Error::StsNullPtr, "NULL window name");
|
|
|
|
|
|
|
|
|
|
CvWindow* window;
|
|
|
|
|
auto window = icvFindWindowByName(window_name);
|
|
|
|
|
if (!window)
|
|
|
|
|
CV_Error_(Error::StsNullPtr, ("NULL window: '%s'", window_name));
|
|
|
|
|
|
|
|
|
|
if( window_name == 0 )
|
|
|
|
|
CV_ERROR( CV_StsNullPtr, "NULL window name" );
|
|
|
|
|
|
|
|
|
|
window = icvFindWindowByName( window_name );
|
|
|
|
|
if( window )
|
|
|
|
|
hwnd = (void*)window->hwnd;
|
|
|
|
|
|
|
|
|
|
__END__;
|
|
|
|
|
|
|
|
|
|
return hwnd;
|
|
|
|
|
return (void*)window->hwnd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CV_IMPL const char* cvGetWindowName( void* window_handle )
|
|
|
|
|
// FIXIT: result is not safe to use
|
|
|
|
|
CV_IMPL const char* cvGetWindowName(void* window_handle)
|
|
|
|
|
{
|
|
|
|
|
const char* window_name = "";
|
|
|
|
|
CV_FUNCNAME("cvGetWindowName");
|
|
|
|
|
|
|
|
|
|
CV_FUNCNAME( "cvGetWindowName" );
|
|
|
|
|
AutoLock lock(getWindowMutex());
|
|
|
|
|
|
|
|
|
|
__BEGIN__;
|
|
|
|
|
if (window_handle == 0)
|
|
|
|
|
CV_Error(Error::StsNullPtr, "NULL window handle");
|
|
|
|
|
|
|
|
|
|
CvWindow* window;
|
|
|
|
|
auto window = icvWindowByHWND((HWND)window_handle);
|
|
|
|
|
if (!window)
|
|
|
|
|
CV_Error_(Error::StsNullPtr, ("NULL window: '%p'", window_handle));
|
|
|
|
|
|
|
|
|
|
if( window_handle == 0 )
|
|
|
|
|
CV_ERROR( CV_StsNullPtr, "NULL window" );
|
|
|
|
|
|
|
|
|
|
window = icvWindowByHWND( (HWND)window_handle );
|
|
|
|
|
if( window )
|
|
|
|
|
window_name = window->name;
|
|
|
|
|
|
|
|
|
|
__END__;
|
|
|
|
|
|
|
|
|
|
return window_name;
|
|
|
|
|
return window->name.c_str();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -2612,4 +2709,374 @@ cvSetPostprocessFuncWin32_(const void* callback)
|
|
|
|
|
hg_on_postprocess = (CvWin32WindowCallback)callback;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif //_WIN32
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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())
|
|
|
|
|
{
|
|
|
|
|
auto window = window_.lock();
|
|
|
|
|
if (window)
|
|
|
|
|
window->destroy();
|
|
|
|
|
window_.reset();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
case WND_PROP_VSYNC:
|
|
|
|
|
return setPropVsync_(window, value != 0.0);
|
|
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void resize(int width, int height) CV_OVERRIDE
|
|
|
|
|
{
|
|
|
|
|
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::AutoLock lock(getWindowMutex());
|
|
|
|
|
trackbars_.emplace(name, ui_trackbar);
|
|
|
|
|
}
|
|
|
|
|
return std::static_pointer_cast<UITrackbar>(ui_trackbar);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<UITrackbar> findTrackbar(const std::string& name) CV_OVERRIDE
|
|
|
|
|
{
|
|
|
|
|
cv::AutoLock lock(getWindowMutex());
|
|
|
|
|
auto i = trackbars_.find(name);
|
|
|
|
|
if (i != trackbars_.end())
|
|
|
|
|
{
|
|
|
|
|
return std::static_pointer_cast<UITrackbar>(i->second);
|
|
|
|
|
}
|
|
|
|
|
return std::shared_ptr<UITrackbar>();
|
|
|
|
|
}
|
|
|
|
|
}; // Win32UIWindow
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Win32UITrackbar : public UITrackbar
|
|
|
|
|
{
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~Win32UITrackbar() CV_OVERRIDE
|
|
|
|
|
{
|
|
|
|
|
if (!trackbar_.expired())
|
|
|
|
|
destroy();
|
|
|
|
|
CV_LOG_DEBUG(NULL, "OpenCV/UI/Win32UI: Win32UITrackbar(" << name_ << ") is disposed");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::string& getID() const CV_OVERRIDE { return name_; }
|
|
|
|
|
|
|
|
|
|
bool isActive() const CV_OVERRIDE { return !trackbar_.expired(); }
|
|
|
|
|
|
|
|
|
|
void destroy() CV_OVERRIDE
|
|
|
|
|
{
|
|
|
|
|
// nothing (destroyed with parent window, dedicated trackbar removal is not supported)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Win32BackendUI : public UIBackend
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
~Win32BackendUI() CV_OVERRIDE
|
|
|
|
|
{
|
|
|
|
|
destroyAllWindows();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void destroyAllWindows() CV_OVERRIDE
|
|
|
|
|
{
|
|
|
|
|
cvDestroyAllWindows();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int waitKeyEx(int delay) CV_OVERRIDE
|
|
|
|
|
{
|
|
|
|
|
return cvWaitKey(delay);
|
|
|
|
|
}
|
|
|
|
|
int pollKey() CV_OVERRIDE
|
|
|
|
|
{
|
|
|
|
|
return pollKey_W32();
|
|
|
|
|
}
|
|
|
|
|
}; // Win32BackendUI
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
|
std::shared_ptr<Win32BackendUI>& getInstance()
|
|
|
|
|
{
|
|
|
|
|
static std::shared_ptr<Win32BackendUI> g_instance = std::make_shared<Win32BackendUI>();
|
|
|
|
|
return g_instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace impl
|
|
|
|
|
|
|
|
|
|
#ifndef BUILD_PLUGIN
|
|
|
|
|
namespace highgui_backend {
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<UIBackend> createUIBackendWin32UI()
|
|
|
|
|
{
|
|
|
|
|
return impl::getInstance();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace highgui_backend
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
} // 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
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if (!handle)
|
|
|
|
|
return CV_ERROR_FAIL;
|
|
|
|
|
*handle = cv::impl::getInstance().get();
|
|
|
|
|
return CV_ERROR_OK;
|
|
|
|
|
}
|
|
|
|
|
catch (...)
|
|
|
|
|
{
|
|
|
|
|
return CV_ERROR_FAIL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const OpenCV_UI_Plugin_API plugin_api =
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
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 // BUILD_PLUGIN
|
|
|
|
|
|
|
|
|
|
#endif // HAVE_WIN32UI
|
|
|
|
|