Path: blob/master/modules/highgui/src/window_w32.cpp
16337 views
/*M///////////////////////////////////////////////////////////////////////////////////////1//2// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.3//4// By downloading, copying, installing or using the software you agree to this license.5// If you do not agree to this license, do not download, install,6// copy or use the software.7//8//9// Intel License Agreement10// For Open Source Computer Vision Library11//12// Copyright (C) 2000, Intel Corporation, all rights reserved.13// Third party copyrights are property of their respective owners.14//15// Redistribution and use in source and binary forms, with or without modification,16// are permitted provided that the following conditions are met:17//18// * Redistribution's of source code must retain the above copyright notice,19// this list of conditions and the following disclaimer.20//21// * Redistribution's in binary form must reproduce the above copyright notice,22// this list of conditions and the following disclaimer in the documentation23// and/or other materials provided with the distribution.24//25// * The name of Intel Corporation may not be used to endorse or promote products26// derived from this software without specific prior written permission.27//28// This software is provided by the copyright holders and contributors "as is" and29// any express or implied warranties, including, but not limited to, the implied30// warranties of merchantability and fitness for a particular purpose are disclaimed.31// In no event shall the Intel Corporation or contributors be liable for any direct,32// indirect, incidental, special, exemplary, or consequential damages33// (including, but not limited to, procurement of substitute goods or services;34// loss of use, data, or profits; or business interruption) however caused35// and on any theory of liability, whether in contract, strict liability,36// or tort (including negligence or otherwise) arising in any way out of37// the use of this software, even if advised of the possibility of such damage.38//39//M*/4041#include "precomp.hpp"42#include <windowsx.h> // required for GET_X_LPARAM() and GET_Y_LPARAM() macros4344#if defined _WIN324546#ifdef __GNUC__47# pragma GCC diagnostic ignored "-Wmissing-declarations"48#endif4950#if (_WIN32_IE < 0x0500)51#pragma message("WARNING: Win32 UI needs to be compiled with _WIN32_IE >= 0x0500 (_WIN32_IE_IE50)")52#define _WIN32_IE 0x050053#endif5455#include <commctrl.h>56#include <stdlib.h>57#include <string.h>58#include <stdio.h>59#include <assert.h>6061#ifdef HAVE_OPENGL62#include <memory>63#include <algorithm>64#include <vector>65#include <functional>66#include "opencv2/highgui.hpp"67#include <GL/gl.h>68#endif6970static const char* trackbar_text =71" ";7273#if defined _M_X64 || defined __x86_647475#define icvGetWindowLongPtr GetWindowLongPtr76#define icvSetWindowLongPtr( hwnd, id, ptr ) SetWindowLongPtr( hwnd, id, (LONG_PTR)(ptr) )77#define icvGetClassLongPtr GetClassLongPtr7879#define CV_USERDATA GWLP_USERDATA80#define CV_WNDPROC GWLP_WNDPROC81#define CV_HCURSOR GCLP_HCURSOR82#define CV_HBRBACKGROUND GCLP_HBRBACKGROUND8384#else8586#define icvGetWindowLongPtr GetWindowLong87#define icvSetWindowLongPtr( hwnd, id, ptr ) SetWindowLong( hwnd, id, (size_t)ptr )88#define icvGetClassLongPtr GetClassLong8990#define CV_USERDATA GWL_USERDATA91#define CV_WNDPROC GWL_WNDPROC92#define CV_HCURSOR GCL_HCURSOR93#define CV_HBRBACKGROUND GCL_HBRBACKGROUND9495#endif9697#ifndef WM_MOUSEHWHEEL98#define WM_MOUSEHWHEEL 0x020E99#endif100101static void FillBitmapInfo( BITMAPINFO* bmi, int width, int height, int bpp, int origin )102{103assert( bmi && width >= 0 && height >= 0 && (bpp == 8 || bpp == 24 || bpp == 32));104105BITMAPINFOHEADER* bmih = &(bmi->bmiHeader);106107memset( bmih, 0, sizeof(*bmih));108bmih->biSize = sizeof(BITMAPINFOHEADER);109bmih->biWidth = width;110bmih->biHeight = origin ? abs(height) : -abs(height);111bmih->biPlanes = 1;112bmih->biBitCount = (unsigned short)bpp;113bmih->biCompression = BI_RGB;114115if( bpp == 8 )116{117RGBQUAD* palette = bmi->bmiColors;118int i;119for( i = 0; i < 256; i++ )120{121palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;122palette[i].rgbReserved = 0;123}124}125}126127struct CvWindow;128129typedef struct CvTrackbar130{131int signature;132HWND hwnd;133char* name;134CvTrackbar* next;135CvWindow* parent;136HWND buddy;137int* data;138int pos;139int maxval;140int minval;141void (*notify)(int);142void (*notify2)(int, void*);143void* userdata;144int id;145}146CvTrackbar;147148149typedef struct CvWindow150{151int signature;152HWND hwnd;153char* name;154CvWindow* prev;155CvWindow* next;156HWND frame;157158HDC dc;159HGDIOBJ image;160int last_key;161int flags;162int status;//0 normal, 1 fullscreen (YV)163164CvMouseCallback on_mouse;165void* on_mouse_param;166167struct168{169HWND toolbar;170int pos;171int rows;172WNDPROC toolBarProc;173CvTrackbar* first;174}175toolbar;176177int width;178int height;179180// OpenGL support181182#ifdef HAVE_OPENGL183bool useGl;184HGLRC hGLRC;185186CvOpenGlDrawCallback glDrawCallback;187void* glDrawData;188#endif189}190CvWindow;191192#define HG_BUDDY_WIDTH 130193194#ifndef TBIF_SIZE195#define TBIF_SIZE 0x40196#endif197198#ifndef TB_SETBUTTONINFO199#define TB_SETBUTTONINFO (WM_USER + 66)200#endif201202#ifndef TBM_GETTOOLTIPS203#define TBM_GETTOOLTIPS (WM_USER + 30)204#endif205206static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);207static LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);208static LRESULT CALLBACK MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);209static void icvUpdateWindowPos( CvWindow* window );210211static CvWindow* hg_windows = 0;212213typedef int (CV_CDECL * CvWin32WindowCallback)(HWND, UINT, WPARAM, LPARAM, int*);214static CvWin32WindowCallback hg_on_preprocess = 0, hg_on_postprocess = 0;215static HINSTANCE hg_hinstance = 0;216217static const char* highGUIclassName = "HighGUI class";218static const char* mainHighGUIclassName = "Main HighGUI class";219220static void icvCleanupHighgui()221{222cvDestroyAllWindows();223UnregisterClass(highGUIclassName, hg_hinstance);224UnregisterClass(mainHighGUIclassName, hg_hinstance);225}226227CV_IMPL int cvInitSystem( int, char** )228{229static int wasInitialized = 0;230231// check initialization status232if( !wasInitialized )233{234// Initialize the stogare235hg_windows = 0;236237// Register the class238WNDCLASS wndc;239wndc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;240wndc.lpfnWndProc = WindowProc;241wndc.cbClsExtra = 0;242wndc.cbWndExtra = 0;243wndc.hInstance = hg_hinstance;244wndc.lpszClassName = highGUIclassName;245wndc.lpszMenuName = highGUIclassName;246wndc.hIcon = LoadIcon(0, IDI_APPLICATION);247wndc.hCursor = (HCURSOR)LoadCursor(0, (LPSTR)(size_t)IDC_CROSS );248wndc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);249250RegisterClass(&wndc);251252wndc.lpszClassName = mainHighGUIclassName;253wndc.lpszMenuName = mainHighGUIclassName;254wndc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);255wndc.lpfnWndProc = MainWindowProc;256257RegisterClass(&wndc);258atexit( icvCleanupHighgui );259260wasInitialized = 1;261}262263setlocale(LC_NUMERIC,"C");264265return 0;266}267268CV_IMPL int cvStartWindowThread(){269return 0;270}271272static CvWindow* icvFindWindowByName( const char* name )273{274CvWindow* window = hg_windows;275276for( ; window != 0 && strcmp( name, window->name) != 0; window = window->next )277;278279return window;280}281282283static CvWindow* icvWindowByHWND( HWND hwnd )284{285CvWindow* window = (CvWindow*)icvGetWindowLongPtr( hwnd, CV_USERDATA );286return window != 0 && hg_windows != 0 &&287window->signature == CV_WINDOW_MAGIC_VAL ? window : 0;288}289290291static CvTrackbar* icvTrackbarByHWND( HWND hwnd )292{293CvTrackbar* trackbar = (CvTrackbar*)icvGetWindowLongPtr( hwnd, CV_USERDATA );294return trackbar != 0 && trackbar->signature == CV_TRACKBAR_MAGIC_VAL &&295trackbar->hwnd == hwnd ? trackbar : 0;296}297298299static const char* icvWindowPosRootKey = "Software\\OpenCV\\HighGUI\\Windows\\";300301// Window positions saving/loading added by Philip Gruebele.302//<a href="mailto:[email protected]">[email protected]</a>303// Restores the window position from the registry saved position.304static void305icvLoadWindowPos( const char* name, CvRect& rect )306{307HKEY hkey;308char szKey[1024];309strcpy_s( szKey, 1024, icvWindowPosRootKey );310strcat_s( szKey, 1024, name );311312rect.x = rect.y = CW_USEDEFAULT;313rect.width = rect.height = 320;314315if( RegOpenKeyEx(HKEY_CURRENT_USER,szKey,0,KEY_QUERY_VALUE,&hkey) == ERROR_SUCCESS )316{317// Yes we are installed.318DWORD dwType = 0;319DWORD dwSize = sizeof(int);320321RegQueryValueEx(hkey, "Left", NULL, &dwType, (BYTE*)&rect.x, &dwSize);322RegQueryValueEx(hkey, "Top", NULL, &dwType, (BYTE*)&rect.y, &dwSize);323RegQueryValueEx(hkey, "Width", NULL, &dwType, (BYTE*)&rect.width, &dwSize);324RegQueryValueEx(hkey, "Height", NULL, &dwType, (BYTE*)&rect.height, &dwSize);325326// Snap rect into closest monitor in case it falls outside it. // Adi Shavit327// set WIN32 RECT to be the loaded size328POINT tl_w32 = { rect.x, rect.y };329POINT tr_w32 = { rect.x + rect.width, rect.y };330331// find monitor containing top-left and top-right corners, or NULL332HMONITOR hMonitor_l = MonitorFromPoint(tl_w32, MONITOR_DEFAULTTONULL);333HMONITOR hMonitor_r = MonitorFromPoint(tr_w32, MONITOR_DEFAULTTONULL);334335// if neither are contained - the move window to origin of closest.336if (NULL == hMonitor_l && NULL == hMonitor_r)337{338// find monitor nearest to top-left corner339HMONITOR hMonitor_closest = MonitorFromPoint(tl_w32, MONITOR_DEFAULTTONEAREST);340341// get coordinates of nearest monitor342MONITORINFO mi;343mi.cbSize = sizeof(mi);344GetMonitorInfo(hMonitor_closest, &mi);345346rect.x = mi.rcWork.left;347rect.y = mi.rcWork.top;348}349350if (rect.width != (int)CW_USEDEFAULT && (rect.width < 0 || rect.width > 3000))351rect.width = 100;352if (rect.height != (int)CW_USEDEFAULT && (rect.height < 0 || rect.height > 3000))353rect.height = 100;354355RegCloseKey(hkey);356}357}358359360// Window positions saving/loading added by Philip Gruebele.361//<a href="mailto:[email protected]">[email protected]</a>362// philipg. Saves the window position in the registry363static void364icvSaveWindowPos( const char* name, CvRect rect )365{366static const DWORD MAX_RECORD_COUNT = 100;367HKEY hkey;368char szKey[1024];369char rootKey[1024];370strcpy_s( szKey, 1024, icvWindowPosRootKey );371strcat_s( szKey, 1024, name );372373if( RegOpenKeyEx( HKEY_CURRENT_USER,szKey,0,KEY_READ,&hkey) != ERROR_SUCCESS )374{375HKEY hroot;376DWORD count = 0;377FILETIME oldestTime = { UINT_MAX, UINT_MAX };378char oldestKey[1024];379char currentKey[1024];380381strcpy_s( rootKey, 1024, icvWindowPosRootKey );382rootKey[strlen(rootKey)-1] = '\0';383if( RegCreateKeyEx(HKEY_CURRENT_USER, rootKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ+KEY_WRITE, 0, &hroot, NULL) != ERROR_SUCCESS )384//RegOpenKeyEx( HKEY_CURRENT_USER,rootKey,0,KEY_READ,&hroot) != ERROR_SUCCESS )385return;386387for(;;)388{389DWORD csize = sizeof(currentKey);390FILETIME accesstime = { 0, 0 };391LONG code = RegEnumKeyEx( hroot, count, currentKey, &csize, NULL, NULL, NULL, &accesstime );392if( code != ERROR_SUCCESS && code != ERROR_MORE_DATA )393break;394count++;395if( oldestTime.dwHighDateTime > accesstime.dwHighDateTime ||396(oldestTime.dwHighDateTime == accesstime.dwHighDateTime &&397oldestTime.dwLowDateTime > accesstime.dwLowDateTime) )398{399oldestTime = accesstime;400strcpy_s( oldestKey, 1024, currentKey );401}402}403404if( count >= MAX_RECORD_COUNT )405RegDeleteKey( hroot, oldestKey );406RegCloseKey( hroot );407408if( RegCreateKeyEx(HKEY_CURRENT_USER,szKey,0,NULL,REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &hkey, NULL) != ERROR_SUCCESS )409return;410}411else412{413RegCloseKey( hkey );414if( RegOpenKeyEx( HKEY_CURRENT_USER,szKey,0,KEY_WRITE,&hkey) != ERROR_SUCCESS )415return;416}417418RegSetValueEx(hkey, "Left", 0, REG_DWORD, (BYTE*)&rect.x, sizeof(rect.x));419RegSetValueEx(hkey, "Top", 0, REG_DWORD, (BYTE*)&rect.y, sizeof(rect.y));420RegSetValueEx(hkey, "Width", 0, REG_DWORD, (BYTE*)&rect.width, sizeof(rect.width));421RegSetValueEx(hkey, "Height", 0, REG_DWORD, (BYTE*)&rect.height, sizeof(rect.height));422RegCloseKey(hkey);423}424425CvRect cvGetWindowRect_W32(const char* name)426{427CvRect result = cvRect(-1, -1, -1, -1);428429CV_FUNCNAME( "cvGetWindowRect_W32" );430431__BEGIN__;432433CvWindow* window;434435if (!name)436CV_ERROR( CV_StsNullPtr, "NULL name string" );437window = icvFindWindowByName( name );438if (!window)439EXIT; // keep silence here440441RECT rect;442GetClientRect(window->hwnd, &rect);443{444POINT pt = {rect.left, rect.top};445ClientToScreen(window->hwnd, &pt);446result = cvRect(pt.x, pt.y, rect.right - rect.left, rect.bottom - rect.top);447}448__END__;449return result;450}451452double cvGetModeWindow_W32(const char* name)//YV453{454double result = -1;455456CV_FUNCNAME( "cvGetModeWindow_W32" );457458__BEGIN__;459460CvWindow* window;461462if (!name)463CV_ERROR( CV_StsNullPtr, "NULL name string" );464465window = icvFindWindowByName( name );466if (!window)467EXIT; // keep silence here468469result = window->status;470471__END__;472return result;473}474475void cvSetModeWindow_W32( const char* name, double prop_value)//Yannick Verdie476{477CV_FUNCNAME( "cvSetModeWindow_W32" );478479__BEGIN__;480481CvWindow* window;482483if(!name)484CV_ERROR( CV_StsNullPtr, "NULL name string" );485486window = icvFindWindowByName( name );487if( !window )488CV_ERROR( CV_StsNullPtr, "NULL window" );489490if(window->flags & CV_WINDOW_AUTOSIZE)//if the flag CV_WINDOW_AUTOSIZE is set491EXIT;492493{494DWORD dwStyle = (DWORD)GetWindowLongPtr(window->frame, GWL_STYLE);495CvRect position;496497if (window->status==CV_WINDOW_FULLSCREEN && prop_value==CV_WINDOW_NORMAL)498{499icvLoadWindowPos(window->name,position );500SetWindowLongPtr(window->frame, GWL_STYLE, dwStyle | WS_CAPTION | WS_THICKFRAME);501502SetWindowPos(window->frame, HWND_TOP, position.x, position.y , position.width,position.height, SWP_NOZORDER | SWP_FRAMECHANGED);503window->status=CV_WINDOW_NORMAL;504505EXIT;506}507508if (window->status==CV_WINDOW_NORMAL && prop_value==CV_WINDOW_FULLSCREEN)509{510//save dimension511RECT rect;512GetWindowRect(window->frame, &rect);513CvRect RectCV = cvRect(rect.left, rect.top,rect.right - rect.left, rect.bottom - rect.top);514icvSaveWindowPos(window->name,RectCV );515516//Look at coordinate for fullscreen517HMONITOR hMonitor;518MONITORINFO mi;519hMonitor = MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST);520521mi.cbSize = sizeof(mi);522GetMonitorInfo(hMonitor, &mi);523524//fullscreen525position.x=mi.rcMonitor.left;position.y=mi.rcMonitor.top;526position.width=mi.rcMonitor.right - mi.rcMonitor.left;position.height=mi.rcMonitor.bottom - mi.rcMonitor.top;527SetWindowLongPtr(window->frame, GWL_STYLE, dwStyle & ~WS_CAPTION & ~WS_THICKFRAME);528529SetWindowPos(window->frame, HWND_TOP, position.x, position.y , position.width,position.height, SWP_NOZORDER | SWP_FRAMECHANGED);530window->status=CV_WINDOW_FULLSCREEN;531532EXIT;533}534}535536__END__;537}538539void cv::setWindowTitle(const String& winname, const String& title)540{541CvWindow* window = icvFindWindowByName(winname.c_str());542543if (!window)544{545namedWindow(winname);546window = icvFindWindowByName(winname.c_str());547}548549if (!window)550CV_Error(Error::StsNullPtr, "NULL window");551552if (!SetWindowText(window->frame, title.c_str()))553CV_Error_(Error::StsError, ("Failed to set \"%s\" window title to \"%s\"", winname.c_str(), title.c_str()));554}555556double cvGetPropWindowAutoSize_W32(const char* name)557{558double result = -1;559560CV_FUNCNAME( "cvSetCloseCallback" );561562__BEGIN__;563564CvWindow* window;565566if (!name)567CV_ERROR( CV_StsNullPtr, "NULL name string" );568569window = icvFindWindowByName( name );570if (!window)571EXIT; // keep silence here572573result = window->flags & CV_WINDOW_AUTOSIZE;574575__END__;576577return result;578}579580double cvGetRatioWindow_W32(const char* name)581{582double result = -1;583584CV_FUNCNAME( "cvGetRatioWindow_W32" );585586__BEGIN__;587588CvWindow* window;589590if (!name)591CV_ERROR( CV_StsNullPtr, "NULL name string" );592593window = icvFindWindowByName( name );594if (!window)595EXIT; // keep silence here596597result = static_cast<double>(window->width) / window->height;598599__END__;600601return result;602}603604double cvGetOpenGlProp_W32(const char* name)605{606double result = -1;607608#ifdef HAVE_OPENGL609CV_FUNCNAME( "cvGetOpenGlProp_W32" );610611__BEGIN__;612613CvWindow* window;614615if (!name)616CV_ERROR( CV_StsNullPtr, "NULL name string" );617618window = icvFindWindowByName( name );619if (!window)620EXIT; // keep silence here621622result = window->useGl;623624__END__;625#endif626CV_UNUSED(name);627628return result;629}630631632// OpenGL support633634#ifdef HAVE_OPENGL635636namespace637{638void createGlContext(HWND hWnd, HDC& hGLDC, HGLRC& hGLRC, bool& useGl)639{640CV_FUNCNAME( "createGlContext" );641642__BEGIN__;643644useGl = false;645646int PixelFormat;647648static PIXELFORMATDESCRIPTOR pfd =649{650sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor6511, // Version Number652PFD_DRAW_TO_WINDOW | // Format Must Support Window653PFD_SUPPORT_OPENGL | // Format Must Support OpenGL654PFD_DOUBLEBUFFER, // Must Support Double Buffering655PFD_TYPE_RGBA, // Request An RGBA Format65632, // Select Our Color Depth6570, 0, 0, 0, 0, 0, // Color Bits Ignored6580, // No Alpha Buffer6590, // Shift Bit Ignored6600, // No Accumulation Buffer6610, 0, 0, 0, // Accumulation Bits Ignored66232, // 32 Bit Z-Buffer (Depth Buffer)6630, // No Stencil Buffer6640, // No Auxiliary Buffer665PFD_MAIN_PLANE, // Main Drawing Layer6660, // Reserved6670, 0, 0 // Layer Masks Ignored668};669670hGLDC = GetDC(hWnd);671if (!hGLDC)672CV_ERROR( CV_OpenGlApiCallError, "Can't Create A GL Device Context" );673674PixelFormat = ChoosePixelFormat(hGLDC, &pfd);675if (!PixelFormat)676CV_ERROR( CV_OpenGlApiCallError, "Can't Find A Suitable PixelFormat" );677678if (!SetPixelFormat(hGLDC, PixelFormat, &pfd))679CV_ERROR( CV_OpenGlApiCallError, "Can't Set The PixelFormat" );680681hGLRC = wglCreateContext(hGLDC);682if (!hGLRC)683CV_ERROR( CV_OpenGlApiCallError, "Can't Create A GL Rendering Context" );684685if (!wglMakeCurrent(hGLDC, hGLRC))686CV_ERROR( CV_OpenGlApiCallError, "Can't Activate The GL Rendering Context" );687688useGl = true;689690__END__;691}692693void releaseGlContext(CvWindow* window)694{695//CV_FUNCNAME( "releaseGlContext" );696697__BEGIN__;698699if (window->hGLRC)700{701wglDeleteContext(window->hGLRC);702window->hGLRC = NULL;703}704705if (window->dc)706{707ReleaseDC(window->hwnd, window->dc);708window->dc = NULL;709}710711window->useGl = false;712713__END__;714}715716void drawGl(CvWindow* window)717{718CV_FUNCNAME( "drawGl" );719720__BEGIN__;721722if (!wglMakeCurrent(window->dc, window->hGLRC))723CV_ERROR( CV_OpenGlApiCallError, "Can't Activate The GL Rendering Context" );724725glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);726727if (window->glDrawCallback)728window->glDrawCallback(window->glDrawData);729730if (!SwapBuffers(window->dc))731CV_ERROR( CV_OpenGlApiCallError, "Can't swap OpenGL buffers" );732733__END__;734}735736void resizeGl(CvWindow* window)737{738CV_FUNCNAME( "resizeGl" );739740__BEGIN__;741742if (!wglMakeCurrent(window->dc, window->hGLRC))743CV_ERROR( CV_OpenGlApiCallError, "Can't Activate The GL Rendering Context" );744745glViewport(0, 0, window->width, window->height);746747__END__;748}749}750751#endif // HAVE_OPENGL752753754CV_IMPL int cvNamedWindow( const char* name, int flags )755{756int result = 0;757CV_FUNCNAME( "cvNamedWindow" );758759__BEGIN__;760761HWND hWnd, mainhWnd;762CvWindow* window;763DWORD defStyle = WS_VISIBLE | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU;764int len;765CvRect rect;766#ifdef HAVE_OPENGL767bool useGl;768HDC hGLDC;769HGLRC hGLRC;770#endif771772cvInitSystem(0,0);773774if( !name )775CV_ERROR( CV_StsNullPtr, "NULL name string" );776777// Check the name in the storage778window = icvFindWindowByName( name );779if (window != 0)780{781result = 1;782EXIT;783}784785if( !(flags & CV_WINDOW_AUTOSIZE))//YV add border in order to resize the window786defStyle |= WS_SIZEBOX;787788#ifdef HAVE_OPENGL789if (flags & CV_WINDOW_OPENGL)790defStyle |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;791#endif792793icvLoadWindowPos( name, rect );794795mainhWnd = CreateWindow( "Main HighGUI class", name, defStyle | WS_OVERLAPPED,796rect.x, rect.y, rect.width, rect.height, 0, 0, hg_hinstance, 0 );797if( !mainhWnd )798CV_ERROR( CV_StsError, "Frame window can not be created" );799800ShowWindow(mainhWnd, SW_SHOW);801802//YV- remove one border by changing the style803hWnd = CreateWindow("HighGUI class", "", (defStyle & ~WS_SIZEBOX) | WS_CHILD, CW_USEDEFAULT, 0, rect.width, rect.height, mainhWnd, 0, hg_hinstance, 0);804if( !hWnd )805CV_ERROR( CV_StsError, "Frame window can not be created" );806807#ifndef HAVE_OPENGL808if (flags & CV_WINDOW_OPENGL)809CV_ERROR( CV_OpenGlNotSupported, "Library was built without OpenGL support" );810#else811useGl = false;812hGLDC = 0;813hGLRC = 0;814815if (flags & CV_WINDOW_OPENGL)816createGlContext(hWnd, hGLDC, hGLRC, useGl);817#endif818819ShowWindow(hWnd, SW_SHOW);820821len = (int)strlen(name);822CV_CALL( window = (CvWindow*)cvAlloc(sizeof(CvWindow) + len + 1));823824window->signature = CV_WINDOW_MAGIC_VAL;825window->hwnd = hWnd;826window->frame = mainhWnd;827window->name = (char*)(window + 1);828memcpy( window->name, name, len + 1 );829window->flags = flags;830window->image = 0;831832#ifndef HAVE_OPENGL833window->dc = CreateCompatibleDC(0);834#else835if (!useGl)836{837window->dc = CreateCompatibleDC(0);838window->hGLRC = 0;839window->useGl = false;840}841else842{843window->dc = hGLDC;844window->hGLRC = hGLRC;845window->useGl = true;846}847848window->glDrawCallback = 0;849window->glDrawData = 0;850#endif851852window->last_key = 0;853window->status = CV_WINDOW_NORMAL;//YV854855window->on_mouse = 0;856window->on_mouse_param = 0;857858memset( &window->toolbar, 0, sizeof(window->toolbar));859860window->next = hg_windows;861window->prev = 0;862if( hg_windows )863hg_windows->prev = window;864hg_windows = window;865icvSetWindowLongPtr( hWnd, CV_USERDATA, window );866icvSetWindowLongPtr( mainhWnd, CV_USERDATA, window );867868// Recalculate window pos869icvUpdateWindowPos( window );870871result = 1;872__END__;873874return result;875}876877#ifdef HAVE_OPENGL878879CV_IMPL void cvSetOpenGlContext(const char* name)880{881CV_FUNCNAME( "cvSetOpenGlContext" );882883__BEGIN__;884885CvWindow* window;886887if(!name)888CV_ERROR( CV_StsNullPtr, "NULL name string" );889890window = icvFindWindowByName( name );891if (!window)892CV_ERROR( CV_StsNullPtr, "NULL window" );893894if (!window->useGl)895CV_ERROR( CV_OpenGlNotSupported, "Window doesn't support OpenGL" );896897if (!wglMakeCurrent(window->dc, window->hGLRC))898CV_ERROR( CV_OpenGlApiCallError, "Can't Activate The GL Rendering Context" );899900__END__;901}902903CV_IMPL void cvUpdateWindow(const char* name)904{905CV_FUNCNAME( "cvUpdateWindow" );906907__BEGIN__;908909CvWindow* window;910911if (!name)912CV_ERROR( CV_StsNullPtr, "NULL name string" );913914window = icvFindWindowByName( name );915if (!window)916EXIT;917918InvalidateRect(window->hwnd, 0, 0);919920__END__;921}922923CV_IMPL void cvSetOpenGlDrawCallback(const char* name, CvOpenGlDrawCallback callback, void* userdata)924{925CV_FUNCNAME( "cvCreateOpenGLCallback" );926927__BEGIN__;928929CvWindow* window;930931if(!name)932CV_ERROR( CV_StsNullPtr, "NULL name string" );933934window = icvFindWindowByName( name );935if( !window )936EXIT;937938if (!window->useGl)939CV_ERROR( CV_OpenGlNotSupported, "Window was created without OpenGL context" );940941window->glDrawCallback = callback;942window->glDrawData = userdata;943944__END__;945}946947#endif // HAVE_OPENGL948949static void icvRemoveWindow( CvWindow* window )950{951CvTrackbar* trackbar = NULL;952RECT wrect={0,0,0,0};953954#ifdef HAVE_OPENGL955if (window->useGl)956releaseGlContext(window);957#endif958959if( window->frame )960GetWindowRect( window->frame, &wrect );961if( window->name )962icvSaveWindowPos( window->name, cvRect(wrect.left, wrect.top,963wrect.right-wrect.left, wrect.bottom-wrect.top) );964965if( window->hwnd )966icvSetWindowLongPtr( window->hwnd, CV_USERDATA, 0 );967if( window->frame )968icvSetWindowLongPtr( window->frame, CV_USERDATA, 0 );969970if( window->toolbar.toolbar )971icvSetWindowLongPtr(window->toolbar.toolbar, CV_USERDATA, 0);972973if( window->prev )974window->prev->next = window->next;975else976hg_windows = window->next;977978if( window->next )979window->next->prev = window->prev;980981window->prev = window->next = 0;982983if( window->dc && window->image )984DeleteObject(SelectObject(window->dc,window->image));985986if( window->dc )987DeleteDC(window->dc);988989for( trackbar = window->toolbar.first; trackbar != 0; )990{991CvTrackbar* next = trackbar->next;992if( trackbar->hwnd )993{994icvSetWindowLongPtr( trackbar->hwnd, CV_USERDATA, 0 );995cvFree( &trackbar );996}997trackbar = next;998}9991000cvFree( &window );1001}100210031004CV_IMPL void cvDestroyWindow( const char* name )1005{1006CV_FUNCNAME( "cvDestroyWindow" );10071008__BEGIN__;10091010CvWindow* window;1011HWND mainhWnd;10121013if(!name)1014CV_ERROR( CV_StsNullPtr, "NULL name string" );10151016window = icvFindWindowByName( name );1017if( !window )1018EXIT;10191020mainhWnd = window->frame;10211022SendMessage(window->hwnd, WM_CLOSE, 0, 0);1023SendMessage( mainhWnd, WM_CLOSE, 0, 0);1024// Do NOT call _remove_window -- CvWindow list will be updated automatically ...10251026__END__;1027}102810291030static void icvScreenToClient( HWND hwnd, RECT* rect )1031{1032POINT p;1033p.x = rect->left;1034p.y = rect->top;1035ScreenToClient(hwnd, &p);1036OffsetRect( rect, p.x - rect->left, p.y - rect->top );1037}103810391040/* Calculatess the window coordinates relative to the upper left corner of the mainhWnd window */1041static RECT icvCalcWindowRect( CvWindow* window )1042{1043const int gutter = 1;1044RECT crect, trect, rect;10451046assert(window);10471048GetClientRect(window->frame, &crect);1049if(window->toolbar.toolbar)1050{1051GetWindowRect(window->toolbar.toolbar, &trect);1052icvScreenToClient(window->frame, &trect);1053SubtractRect( &rect, &crect, &trect);1054}1055else1056rect = crect;10571058rect.top += gutter;1059rect.left += gutter;1060rect.bottom -= gutter;1061rect.right -= gutter;10621063return rect;1064}10651066// returns TRUE if there is a problem such as ERROR_IO_PENDING.1067static bool icvGetBitmapData( CvWindow* window, SIZE* size, int* channels, void** data )1068{1069BITMAP bmp;1070GdiFlush();1071HGDIOBJ h = GetCurrentObject( window->dc, OBJ_BITMAP );1072if( size )1073size->cx = size->cy = 0;1074if( data )1075*data = 0;10761077if (h == NULL)1078return true;1079if (GetObject(h, sizeof(bmp), &bmp) == 0)1080return true;10811082if( size )1083{1084size->cx = abs(bmp.bmWidth);1085size->cy = abs(bmp.bmHeight);1086}10871088if( channels )1089*channels = bmp.bmBitsPixel/8;10901091if( data )1092*data = bmp.bmBits;10931094return false;1095}109610971098static void icvUpdateWindowPos( CvWindow* window )1099{1100RECT rect;1101assert(window);11021103if( (window->flags & CV_WINDOW_AUTOSIZE) && window->image )1104{1105int i;1106SIZE size = {0,0};1107icvGetBitmapData( window, &size, 0, 0 );11081109// Repeat two times because after the first resizing of the mainhWnd window1110// toolbar may resize too1111for(i = 0; i < (window->toolbar.toolbar ? 2 : 1); i++)1112{1113RECT rmw, rw = icvCalcWindowRect(window );1114MoveWindow(window->hwnd, rw.left, rw.top,1115rw.right - rw.left + 1, rw.bottom - rw.top + 1, FALSE);1116GetClientRect(window->hwnd, &rw);1117GetWindowRect(window->frame, &rmw);1118// Resize the mainhWnd window in order to make the bitmap fit into the child window1119MoveWindow(window->frame, rmw.left, rmw.top,1120rmw.right - rmw.left + size.cx - rw.right + rw.left,1121rmw.bottom - rmw.top + size.cy - rw.bottom + rw.top, TRUE );1122}1123}11241125rect = icvCalcWindowRect(window);1126MoveWindow(window->hwnd, rect.left, rect.top,1127rect.right - rect.left + 1,1128rect.bottom - rect.top + 1, TRUE );1129}11301131CV_IMPL void1132cvShowImage( const char* name, const CvArr* arr )1133{1134CV_FUNCNAME( "cvShowImage" );11351136__BEGIN__;11371138CvWindow* window;1139SIZE size = { 0, 0 };1140int channels = 0;1141void* dst_ptr = 0;1142const int channels0 = 3;1143int origin = 0;1144CvMat stub, dst, *image;1145bool changed_size = false; // philipg11461147if( !name )1148CV_ERROR( CV_StsNullPtr, "NULL name" );11491150window = icvFindWindowByName(name);1151if(!window)1152{1153cvNamedWindow(name, CV_WINDOW_AUTOSIZE);1154window = icvFindWindowByName(name);1155}11561157if( !window || !arr )1158EXIT; // keep silence here.11591160if( CV_IS_IMAGE_HDR( arr ))1161origin = ((IplImage*)arr)->origin;11621163CV_CALL( image = cvGetMat( arr, &stub ));11641165#ifdef HAVE_OPENGL1166if (window->useGl)1167{1168cv::imshow(name, cv::cvarrToMat(image));1169return;1170}1171#endif11721173if (window->image)1174// if there is something wrong with these system calls, we cannot display image...1175if (icvGetBitmapData( window, &size, &channels, &dst_ptr ))1176return;11771178if( size.cx != image->width || size.cy != image->height || channels != channels0 )1179{1180changed_size = true;11811182uchar buffer[sizeof(BITMAPINFO) + 255*sizeof(RGBQUAD)];1183BITMAPINFO* binfo = (BITMAPINFO*)buffer;11841185DeleteObject( SelectObject( window->dc, window->image ));1186window->image = 0;11871188size.cx = image->width;1189size.cy = image->height;1190channels = channels0;11911192FillBitmapInfo( binfo, size.cx, size.cy, channels*8, 1 );11931194window->image = SelectObject( window->dc, CreateDIBSection(window->dc, binfo,1195DIB_RGB_COLORS, &dst_ptr, 0, 0));1196}11971198cvInitMatHeader( &dst, size.cy, size.cx, CV_8UC3,1199dst_ptr, (size.cx * channels + 3) & -4 );1200cvConvertImage( image, &dst, origin == 0 ? CV_CVTIMG_FLIP : 0 );12011202// ony resize window if needed1203if (changed_size)1204icvUpdateWindowPos(window);1205InvalidateRect(window->hwnd, 0, 0);1206// philipg: this is not needed and just slows things down1207// UpdateWindow(window->hwnd);12081209__END__;1210}12111212#if 01213CV_IMPL void1214cvShowImageHWND(HWND w_hWnd, const CvArr* arr)1215{1216CV_FUNCNAME( "cvShowImageHWND" );12171218__BEGIN__;12191220SIZE size = { 0, 0 };1221int channels = 0;1222void* dst_ptr = 0;1223const int channels0 = 3;1224int origin = 0;1225CvMat stub, dst, *image;1226bool changed_size = false;1227BITMAPINFO tempbinfo;1228HDC hdc = NULL;12291230if( !arr )1231EXIT;1232if( !w_hWnd )1233EXIT;12341235hdc = GetDC(w_hWnd);12361237if( CV_IS_IMAGE_HDR( arr ) )1238origin = ((IplImage*)arr)->origin;12391240CV_CALL( image = cvGetMat( arr, &stub ) );12411242if ( hdc )1243{1244//GetBitmapData1245BITMAP bmp;1246GdiFlush();1247HGDIOBJ h = GetCurrentObject( hdc, OBJ_BITMAP );12481249if (h == NULL)1250EXIT;1251if (GetObject(h, sizeof(bmp), &bmp) == 0) //GetObject(): returns size of object, 0 if error1252EXIT;12531254channels = bmp.bmBitsPixel/8;1255dst_ptr = bmp.bmBits;1256}12571258if( size.cx != image->width || size.cy != image->height || channels != channels0 )1259{1260changed_size = true;12611262uchar buffer[sizeof(BITMAPINFO) + 255*sizeof(RGBQUAD)];1263BITMAPINFO* binfo = (BITMAPINFO*)buffer;12641265BOOL bDeleteObj = DeleteObject(GetCurrentObject(hdc, OBJ_BITMAP));1266CV_Assert( FALSE != bDeleteObj );12671268size.cx = image->width;1269size.cy = image->height;1270channels = channels0;12711272FillBitmapInfo( binfo, size.cx, size.cy, channels*8, 1 );12731274SelectObject( hdc, CreateDIBSection( hdc, binfo, DIB_RGB_COLORS, &dst_ptr, 0, 0));1275}12761277cvInitMatHeader( &dst, size.cy, size.cx, CV_8UC3, dst_ptr, (size.cx * channels + 3) & -4 );1278cvConvertImage( image, &dst, origin == 0 ? CV_CVTIMG_FLIP : 0 );12791280// Image stretching to fit the window1281RECT rect;1282GetClientRect(w_hWnd, &rect);1283StretchDIBits( hdc, 0, 0, rect.right, rect.bottom, 0, 0, image->width, image->height, dst_ptr, &tempbinfo, DIB_RGB_COLORS, SRCCOPY );12841285// ony resize window if needed1286InvalidateRect(w_hWnd, 0, 0);12871288__END__;1289}1290#endif12911292CV_IMPL void cvResizeWindow(const char* name, int width, int height )1293{1294CV_FUNCNAME( "cvResizeWindow" );12951296__BEGIN__;12971298int i;1299CvWindow* window;1300RECT rmw, rw, rect;13011302if( !name )1303CV_ERROR( CV_StsNullPtr, "NULL name" );13041305window = icvFindWindowByName(name);1306if(!window)1307EXIT;13081309// Repeat two times because after the first resizing of the mainhWnd window1310// toolbar may resize too1311for(i = 0; i < (window->toolbar.toolbar ? 2 : 1); i++)1312{1313rw = icvCalcWindowRect(window);1314MoveWindow(window->hwnd, rw.left, rw.top,1315rw.right - rw.left + 1, rw.bottom - rw.top + 1, FALSE);1316GetClientRect(window->hwnd, &rw);1317GetWindowRect(window->frame, &rmw);1318// Resize the mainhWnd window in order to make the bitmap fit into the child window1319MoveWindow(window->frame, rmw.left, rmw.top,1320rmw.right - rmw.left + width - rw.right + rw.left,1321rmw.bottom - rmw.top + height - rw.bottom + rw.top, TRUE);1322}13231324rect = icvCalcWindowRect(window);1325MoveWindow(window->hwnd, rect.left, rect.top,1326rect.right - rect.left + 1, rect.bottom - rect.top + 1, TRUE);13271328__END__;1329}133013311332CV_IMPL void cvMoveWindow( const char* name, int x, int y )1333{1334CV_FUNCNAME( "cvMoveWindow" );13351336__BEGIN__;13371338CvWindow* window;1339RECT rect;13401341if( !name )1342CV_ERROR( CV_StsNullPtr, "NULL name" );13431344window = icvFindWindowByName(name);1345if(!window)1346EXIT;13471348GetWindowRect( window->frame, &rect );1349MoveWindow( window->frame, x, y, rect.right - rect.left, rect.bottom - rect.top, TRUE);13501351__END__;1352}135313541355static LRESULT CALLBACK1356MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )1357{1358CvWindow* window = icvWindowByHWND( hwnd );1359if( !window )1360return DefWindowProc(hwnd, uMsg, wParam, lParam);13611362switch(uMsg)1363{1364case WM_COPY:1365::SendMessage(window->hwnd, uMsg, wParam, lParam);1366break;13671368case WM_DESTROY:13691370icvRemoveWindow(window);1371// Do nothing!!!1372//PostQuitMessage(0);1373break;13741375case WM_GETMINMAXINFO:1376if( !(window->flags & CV_WINDOW_AUTOSIZE) )1377{1378MINMAXINFO* minmax = (MINMAXINFO*)lParam;1379RECT rect;1380LRESULT retval = DefWindowProc(hwnd, uMsg, wParam, lParam);13811382minmax->ptMinTrackSize.y = 100;1383minmax->ptMinTrackSize.x = 100;13841385if( window->toolbar.first )1386{1387GetWindowRect( window->toolbar.first->hwnd, &rect );1388minmax->ptMinTrackSize.y += window->toolbar.rows*(rect.bottom - rect.top);1389minmax->ptMinTrackSize.x = MAX(rect.right - rect.left + HG_BUDDY_WIDTH, HG_BUDDY_WIDTH*2);1390}1391return retval;1392}1393break;13941395case WM_WINDOWPOSCHANGED:1396{1397WINDOWPOS* pos = (WINDOWPOS*)lParam;13981399// Update the toolbar pos/size1400if(window->toolbar.toolbar)1401{1402RECT rect;1403GetWindowRect(window->toolbar.toolbar, &rect);1404MoveWindow(window->toolbar.toolbar, 0, 0, pos->cx, rect.bottom - rect.top, TRUE);1405}14061407if(!(window->flags & CV_WINDOW_AUTOSIZE))1408icvUpdateWindowPos(window);14091410break;1411}14121413case WM_WINDOWPOSCHANGING:1414{1415// Snap window to screen edges with multi-monitor support. // Adi Shavit1416LPWINDOWPOS pos = (LPWINDOWPOS)lParam;14171418RECT rect;1419GetWindowRect(window->frame, &rect);14201421HMONITOR hMonitor;1422hMonitor = MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST);14231424MONITORINFO mi;1425mi.cbSize = sizeof(mi);1426GetMonitorInfo(hMonitor, &mi);14271428const int SNAP_DISTANCE = 15;14291430if (abs(pos->x - mi.rcMonitor.left) <= SNAP_DISTANCE)1431pos->x = mi.rcMonitor.left; // snap to left edge1432else1433if (abs(pos->x + pos->cx - mi.rcMonitor.right) <= SNAP_DISTANCE)1434pos->x = mi.rcMonitor.right - pos->cx; // snap to right edge14351436if (abs(pos->y - mi.rcMonitor.top) <= SNAP_DISTANCE)1437pos->y = mi.rcMonitor.top; // snap to top edge1438else1439if (abs(pos->y + pos->cy - mi.rcMonitor.bottom) <= SNAP_DISTANCE)1440pos->y = mi.rcMonitor.bottom - pos->cy; // snap to bottom edge1441}14421443case WM_ACTIVATE:1444if(LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE)1445SetFocus(window->hwnd);1446break;14471448case WM_MOUSEWHEEL:1449case WM_MOUSEHWHEEL:1450if( window->on_mouse )1451{1452int flags = (wParam & MK_LBUTTON ? CV_EVENT_FLAG_LBUTTON : 0)|1453(wParam & MK_RBUTTON ? CV_EVENT_FLAG_RBUTTON : 0)|1454(wParam & MK_MBUTTON ? CV_EVENT_FLAG_MBUTTON : 0)|1455(wParam & MK_CONTROL ? CV_EVENT_FLAG_CTRLKEY : 0)|1456(wParam & MK_SHIFT ? CV_EVENT_FLAG_SHIFTKEY : 0)|1457(GetKeyState(VK_MENU) < 0 ? CV_EVENT_FLAG_ALTKEY : 0);1458int event = (uMsg == WM_MOUSEWHEEL ? CV_EVENT_MOUSEWHEEL : CV_EVENT_MOUSEHWHEEL);14591460// Set the wheel delta of mouse wheel to be in the upper word of 'event'1461int delta = GET_WHEEL_DELTA_WPARAM(wParam);1462flags |= (delta << 16);14631464POINT pt;1465pt.x = GET_X_LPARAM( lParam );1466pt.y = GET_Y_LPARAM( lParam );1467::ScreenToClient(hwnd, &pt); // Convert screen coordinates to client coordinates.14681469RECT rect;1470GetClientRect( window->hwnd, &rect );14711472SIZE size = {0,0};1473icvGetBitmapData( window, &size, 0, 0 );14741475window->on_mouse( event, pt.x*size.cx/MAX(rect.right - rect.left,1),1476pt.y*size.cy/MAX(rect.bottom - rect.top,1), flags,1477window->on_mouse_param );1478}1479break;14801481case WM_ERASEBKGND:1482{1483RECT cr, tr, wrc;1484HRGN rgn, rgn1, rgn2;1485int ret;1486HDC hdc = (HDC)wParam;1487GetWindowRect(window->hwnd, &cr);1488icvScreenToClient(window->frame, &cr);1489if(window->toolbar.toolbar)1490{1491GetWindowRect(window->toolbar.toolbar, &tr);1492icvScreenToClient(window->frame, &tr);1493}1494else1495tr.left = tr.top = tr.right = tr.bottom = 0;14961497GetClientRect(window->frame, &wrc);14981499rgn = CreateRectRgn(0, 0, wrc.right, wrc.bottom);1500rgn1 = CreateRectRgn(cr.left, cr.top, cr.right, cr.bottom);1501rgn2 = CreateRectRgn(tr.left, tr.top, tr.right, tr.bottom);1502CV_Assert_N(rgn != 0, rgn1 != 0, rgn2 != 0);15031504ret = CombineRgn(rgn, rgn, rgn1, RGN_DIFF);1505ret = CombineRgn(rgn, rgn, rgn2, RGN_DIFF);15061507if(ret != NULLREGION && ret != ERROR)1508FillRgn(hdc, rgn, (HBRUSH)icvGetClassLongPtr(hwnd, CV_HBRBACKGROUND));15091510DeleteObject(rgn);1511DeleteObject(rgn1);1512DeleteObject(rgn2);1513}1514return 1;1515}15161517return DefWindowProc(hwnd, uMsg, wParam, lParam);1518}151915201521static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )1522{1523CvWindow* window = icvWindowByHWND(hwnd);1524if( !window )1525// This window is not mentioned in HighGUI storage1526// Actually, this should be error except for the case of calls to CreateWindow1527return DefWindowProc(hwnd, uMsg, wParam, lParam);15281529// Process the message1530switch(uMsg)1531{1532case WM_COPY:1533{1534if (!::OpenClipboard(hwnd) )1535break;15361537HDC hDC = 0;1538HDC memDC = 0;1539HBITMAP memBM = 0;15401541// We'll use a do-while(0){} scope as a single-run breakable scope1542// Upon any error we can jump out of the single-time while scope to clean up the resources.1543do1544{1545if (!::EmptyClipboard())1546break;15471548if(!window->image)1549break;15501551// Get window device context1552if (0 == (hDC = ::GetDC(hwnd)))1553break;15541555// Create another DC compatible with hDC1556if (0 == (memDC = ::CreateCompatibleDC( hDC )))1557break;15581559// Determine the bitmap's dimensions1560int nchannels = 3;1561SIZE size = {0,0};1562icvGetBitmapData( window, &size, &nchannels, 0 );15631564// Create bitmap to draw on and it in the new DC1565if (0 == (memBM = ::CreateCompatibleBitmap ( hDC, size.cx, size.cy)))1566break;15671568if (!::SelectObject( memDC, memBM ))1569break;15701571// Begin drawing to DC1572if (!::SetStretchBltMode(memDC, COLORONCOLOR))1573break;15741575RGBQUAD table[256];1576if( 1 == nchannels )1577{1578for(int i = 0; i < 256; ++i)1579{1580table[i].rgbBlue = (unsigned char)i;1581table[i].rgbGreen = (unsigned char)i;1582table[i].rgbRed = (unsigned char)i;1583}1584if (!::SetDIBColorTable(window->dc, 0, 255, table))1585break;1586}15871588// The image copied to the clipboard will be in its original size, regardless if the window itself was resized.15891590// Render the image to the dc/bitmap (at original size).1591if (!::BitBlt( memDC, 0, 0, size.cx, size.cy, window->dc, 0, 0, SRCCOPY ))1592break;15931594// Finally, set bitmap to clipboard1595::SetClipboardData(CF_BITMAP, memBM);1596} while (0,0); // (0,0) instead of (0) to avoid MSVC compiler warning C4127: "conditional expression is constant"15971598//////////////////////////////////////////////////////////////////////////1599// if handle is allocated (i.e. != 0) then clean-up.1600if (memBM) ::DeleteObject(memBM);1601if (memDC) ::DeleteDC(memDC);1602if (hDC) ::ReleaseDC(hwnd, hDC);1603::CloseClipboard();1604break;1605}16061607case WM_WINDOWPOSCHANGING:1608{1609LPWINDOWPOS pos = (LPWINDOWPOS)lParam;1610RECT rect = icvCalcWindowRect(window);1611pos->x = rect.left;1612pos->y = rect.top;1613pos->cx = rect.right - rect.left + 1;1614pos->cy = rect.bottom - rect.top + 1;1615}1616break;16171618case WM_LBUTTONDOWN:1619case WM_RBUTTONDOWN:1620case WM_MBUTTONDOWN:1621case WM_LBUTTONDBLCLK:1622case WM_RBUTTONDBLCLK:1623case WM_MBUTTONDBLCLK:1624case WM_LBUTTONUP:1625case WM_RBUTTONUP:1626case WM_MBUTTONUP:1627case WM_MOUSEMOVE:1628if( window->on_mouse )1629{1630POINT pt;16311632int flags = (wParam & MK_LBUTTON ? CV_EVENT_FLAG_LBUTTON : 0)|1633(wParam & MK_RBUTTON ? CV_EVENT_FLAG_RBUTTON : 0)|1634(wParam & MK_MBUTTON ? CV_EVENT_FLAG_MBUTTON : 0)|1635(wParam & MK_CONTROL ? CV_EVENT_FLAG_CTRLKEY : 0)|1636(wParam & MK_SHIFT ? CV_EVENT_FLAG_SHIFTKEY : 0)|1637(GetKeyState(VK_MENU) < 0 ? CV_EVENT_FLAG_ALTKEY : 0);1638int event = uMsg == WM_LBUTTONDOWN ? CV_EVENT_LBUTTONDOWN :1639uMsg == WM_RBUTTONDOWN ? CV_EVENT_RBUTTONDOWN :1640uMsg == WM_MBUTTONDOWN ? CV_EVENT_MBUTTONDOWN :1641uMsg == WM_LBUTTONUP ? CV_EVENT_LBUTTONUP :1642uMsg == WM_RBUTTONUP ? CV_EVENT_RBUTTONUP :1643uMsg == WM_MBUTTONUP ? CV_EVENT_MBUTTONUP :1644uMsg == WM_LBUTTONDBLCLK ? CV_EVENT_LBUTTONDBLCLK :1645uMsg == WM_RBUTTONDBLCLK ? CV_EVENT_RBUTTONDBLCLK :1646uMsg == WM_MBUTTONDBLCLK ? CV_EVENT_MBUTTONDBLCLK :1647CV_EVENT_MOUSEMOVE;1648if( uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN || uMsg == WM_MBUTTONDOWN )1649SetCapture( hwnd );1650if( uMsg == WM_LBUTTONUP || uMsg == WM_RBUTTONUP || uMsg == WM_MBUTTONUP )1651ReleaseCapture();16521653pt.x = GET_X_LPARAM( lParam );1654pt.y = GET_Y_LPARAM( lParam );16551656if (window->flags & CV_WINDOW_AUTOSIZE)1657{1658// As user can't change window size, do not scale window coordinates. Underlying windowing system1659// may prevent full window from being displayed and in this case coordinates should not be scaled.1660window->on_mouse( event, pt.x, pt.y, flags, window->on_mouse_param );1661} else {1662// Full window is displayed using different size. Scale coordinates to match underlying positions.1663RECT rect;1664SIZE size = {0, 0};16651666GetClientRect( window->hwnd, &rect );1667icvGetBitmapData( window, &size, 0, 0 );16681669window->on_mouse( event, pt.x*size.cx/MAX(rect.right - rect.left,1),1670pt.y*size.cy/MAX(rect.bottom - rect.top,1), flags,1671window->on_mouse_param );1672}1673}1674break;16751676case WM_PAINT:1677if(window->image != 0)1678{1679int nchannels = 3;1680SIZE size = {0,0};1681PAINTSTRUCT paint;1682HDC hdc;1683RGBQUAD table[256];16841685// Determine the bitmap's dimensions1686icvGetBitmapData( window, &size, &nchannels, 0 );16871688hdc = BeginPaint(hwnd, &paint);1689SetStretchBltMode(hdc, COLORONCOLOR);16901691if( nchannels == 1 )1692{1693int i;1694for(i = 0; i < 256; i++)1695{1696table[i].rgbBlue = (unsigned char)i;1697table[i].rgbGreen = (unsigned char)i;1698table[i].rgbRed = (unsigned char)i;1699}1700SetDIBColorTable(window->dc, 0, 255, table);1701}17021703if(window->flags & CV_WINDOW_AUTOSIZE)1704{1705BitBlt( hdc, 0, 0, size.cx, size.cy, window->dc, 0, 0, SRCCOPY );1706}1707else1708{1709RECT rect;1710GetClientRect(window->hwnd, &rect);1711StretchBlt( hdc, 0, 0, rect.right - rect.left, rect.bottom - rect.top,1712window->dc, 0, 0, size.cx, size.cy, SRCCOPY );1713}1714//DeleteDC(hdc);1715EndPaint(hwnd, &paint);1716}1717#ifdef HAVE_OPENGL1718else if(window->useGl)1719{1720drawGl(window);1721return DefWindowProc(hwnd, uMsg, wParam, lParam);1722}1723#endif1724else1725{1726return DefWindowProc(hwnd, uMsg, wParam, lParam);1727}1728return 0;17291730case WM_ERASEBKGND:1731if(window->image)1732return 0;1733break;17341735case WM_DESTROY:17361737icvRemoveWindow(window);1738// Do nothing!!!1739//PostQuitMessage(0);1740break;17411742case WM_SETCURSOR:1743SetCursor((HCURSOR)icvGetClassLongPtr(hwnd, CV_HCURSOR));1744return 0;17451746case WM_KEYDOWN:1747window->last_key = (int)wParam;1748return 0;17491750case WM_SIZE:1751window->width = LOWORD(lParam);1752window->height = HIWORD(lParam);17531754#ifdef HAVE_OPENGL1755if (window->useGl)1756resizeGl(window);1757#endif1758}17591760return DefWindowProc(hwnd, uMsg, wParam, lParam);1761}176217631764static LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )1765{1766LRESULT ret;17671768if( hg_on_preprocess )1769{1770int was_processed = 0;1771int rethg = hg_on_preprocess(hwnd, uMsg, wParam, lParam, &was_processed);1772if( was_processed )1773return rethg;1774}1775ret = HighGUIProc(hwnd, uMsg, wParam, lParam);17761777if(hg_on_postprocess)1778{1779int was_processed = 0;1780int rethg = hg_on_postprocess(hwnd, uMsg, wParam, lParam, &was_processed);1781if( was_processed )1782return rethg;1783}17841785return ret;1786}178717881789static void icvUpdateTrackbar( CvTrackbar* trackbar, int pos )1790{1791const int max_name_len = 10;1792const char* suffix = "";1793char pos_text[32];1794int name_len;17951796if( trackbar->data )1797*trackbar->data = pos;17981799if( trackbar->pos != pos )1800{1801trackbar->pos = pos;1802if( trackbar->notify2 )1803trackbar->notify2(pos, trackbar->userdata);1804if( trackbar->notify )1805trackbar->notify(pos);18061807name_len = (int)strlen(trackbar->name);18081809if( name_len > max_name_len )1810{1811int start_len = max_name_len*2/3;1812int end_len = max_name_len - start_len - 2;1813memcpy( pos_text, trackbar->name, start_len );1814memcpy( pos_text + start_len, "...", 3 );1815memcpy( pos_text + start_len + 3, trackbar->name + name_len - end_len, end_len + 1 );1816}1817else1818{1819memcpy( pos_text, trackbar->name, name_len + 1);1820}18211822sprintf( pos_text + strlen(pos_text), "%s: %d\n", suffix, pos );1823SetWindowText( trackbar->buddy, pos_text );1824}1825}182618271828static LRESULT CALLBACK HGToolbarProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )1829{1830CvWindow* window = icvWindowByHWND( hwnd );1831if(!window)1832return DefWindowProc(hwnd, uMsg, wParam, lParam);18331834// Control messages processing1835switch(uMsg)1836{1837// Slider processing1838case WM_HSCROLL:1839{1840HWND slider = (HWND)lParam;1841int pos = (int)SendMessage(slider, TBM_GETPOS, 0, 0);1842CvTrackbar* trackbar = icvTrackbarByHWND( slider );18431844if( trackbar )1845{1846if( trackbar->pos != pos )1847icvUpdateTrackbar( trackbar, pos );1848}18491850SetFocus( window->hwnd );1851return 0;1852}18531854case WM_NCCALCSIZE:1855{1856LRESULT ret = CallWindowProc(window->toolbar.toolBarProc, hwnd, uMsg, wParam, lParam);1857int rows = (int)SendMessage(hwnd, TB_GETROWS, 0, 0);18581859if(window->toolbar.rows != rows)1860{1861SendMessage(window->toolbar.toolbar, TB_BUTTONCOUNT, 0, 0);1862CvTrackbar* trackbar = window->toolbar.first;18631864for( ; trackbar != 0; trackbar = trackbar->next )1865{1866RECT rect;1867SendMessage(window->toolbar.toolbar, TB_GETITEMRECT,1868(WPARAM)trackbar->id, (LPARAM)&rect);1869MoveWindow(trackbar->hwnd, rect.left + HG_BUDDY_WIDTH, rect.top,1870rect.right - rect.left - HG_BUDDY_WIDTH,1871rect.bottom - rect.top, FALSE);1872MoveWindow(trackbar->buddy, rect.left, rect.top,1873HG_BUDDY_WIDTH, rect.bottom - rect.top, FALSE);1874}1875window->toolbar.rows = rows;1876}1877return ret;1878}1879}18801881return CallWindowProc(window->toolbar.toolBarProc, hwnd, uMsg, wParam, lParam);1882}188318841885CV_IMPL void1886cvDestroyAllWindows(void)1887{1888CvWindow* window = hg_windows;18891890while( window )1891{1892HWND mainhWnd = window->frame;1893HWND hwnd = window->hwnd;1894window = window->next;18951896SendMessage( hwnd, WM_CLOSE, 0, 0 );1897SendMessage( mainhWnd, WM_CLOSE, 0, 0 );1898}1899}19001901static void showSaveDialog(CvWindow* window)1902{1903if (!window || !window->image)1904return;19051906SIZE sz;1907int channels;1908void* data;1909if (icvGetBitmapData(window, &sz, &channels, &data))1910return; // nothing to save19111912char szFileName[MAX_PATH] = "";1913// try to use window title as file name1914GetWindowText(window->frame, szFileName, MAX_PATH);19151916OPENFILENAME ofn;1917ZeroMemory(&ofn, sizeof(ofn));1918#ifdef OPENFILENAME_SIZE_VERSION_4001919// we are not going to use new fields any way1920ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;1921#else1922ofn.lStructSize = sizeof(ofn);1923#endif1924ofn.hwndOwner = window->hwnd;1925ofn.lpstrFilter =1926#ifdef HAVE_PNG1927"Portable Network Graphics files (*.png)\0*.png\0"1928#endif1929"Windows bitmap (*.bmp;*.dib)\0*.bmp;*.dib\0"1930#ifdef HAVE_JPEG1931"JPEG files (*.jpeg;*.jpg;*.jpe)\0*.jpeg;*.jpg;*.jpe\0"1932#endif1933#ifdef HAVE_TIFF1934"TIFF Files (*.tiff;*.tif)\0*.tiff;*.tif\0"1935#endif1936#ifdef HAVE_JASPER1937"JPEG-2000 files (*.jp2)\0*.jp2\0"1938#endif1939#ifdef HAVE_WEBP1940"WebP files (*.webp)\0*.webp\0"1941#endif1942"Portable image format (*.pbm;*.pgm;*.ppm;*.pxm;*.pnm)\0*.pbm;*.pgm;*.ppm;*.pxm;*.pnm\0"1943#ifdef HAVE_OPENEXR1944"OpenEXR Image files (*.exr)\0*.exr\0"1945#endif1946"Radiance HDR (*.hdr;*.pic)\0*.hdr;*.pic\0"1947"Sun raster files (*.sr;*.ras)\0*.sr;*.ras\0"1948"All Files (*.*)\0*.*\0";1949ofn.lpstrFile = szFileName;1950ofn.nMaxFile = MAX_PATH;1951ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_NOREADONLYRETURN | OFN_NOCHANGEDIR;1952#ifdef HAVE_PNG1953ofn.lpstrDefExt = "png";1954#else1955ofn.lpstrDefExt = "bmp";1956#endif19571958if (GetSaveFileName(&ofn))1959{1960cv::Mat tmp;1961cv::flip(cv::Mat(sz.cy, sz.cx, CV_8UC(channels), data, (sz.cx * channels + 3) & -4), tmp, 0);1962cv::imwrite(szFileName, tmp);1963}1964}19651966CV_IMPL int1967cvWaitKey( int delay )1968{1969int64 time0 = cv::getTickCount();1970int64 timeEnd = time0 + (int64)(delay * 0.001f * cv::getTickFrequency());19711972for(;;)1973{1974CvWindow* window;1975MSG message;1976int is_processed = 0;19771978if( delay <= 0 )1979GetMessage(&message, 0, 0, 0);1980else if( PeekMessage(&message, 0, 0, 0, PM_REMOVE) == FALSE )1981{1982int64 t = cv::getTickCount();1983if (t - timeEnd >= 0)1984return -1; // no messages and no more time1985Sleep(1);1986continue;1987}19881989for( window = hg_windows; window != 0 && is_processed == 0; window = window->next )1990{1991if( window->hwnd == message.hwnd || window->frame == message.hwnd )1992{1993is_processed = 1;1994switch(message.message)1995{1996case WM_DESTROY:1997case WM_CHAR:1998DispatchMessage(&message);1999return (int)message.wParam;20002001case WM_SYSKEYDOWN:2002if( message.wParam == VK_F10 )2003{2004is_processed = 1;2005return (int)(message.wParam << 16);2006}2007break;20082009case WM_KEYDOWN:2010TranslateMessage(&message);2011if( (message.wParam >= VK_F1 && message.wParam <= VK_F24) ||2012message.wParam == VK_HOME || message.wParam == VK_END ||2013message.wParam == VK_UP || message.wParam == VK_DOWN ||2014message.wParam == VK_LEFT || message.wParam == VK_RIGHT ||2015message.wParam == VK_INSERT || message.wParam == VK_DELETE ||2016message.wParam == VK_PRIOR || message.wParam == VK_NEXT )2017{2018DispatchMessage(&message);2019is_processed = 1;2020return (int)(message.wParam << 16);2021}20222023// Intercept Ctrl+C for copy to clipboard2024if ('C' == message.wParam && (::GetKeyState(VK_CONTROL)>>15))2025::SendMessage(message.hwnd, WM_COPY, 0, 0);20262027// Intercept Ctrl+S for "save as" dialog2028if ('S' == message.wParam && (::GetKeyState(VK_CONTROL)>>15))2029showSaveDialog(window);20302031default:2032DispatchMessage(&message);2033is_processed = 1;2034break;2035}2036}2037}20382039if( !is_processed )2040{2041TranslateMessage(&message);2042DispatchMessage(&message);2043}2044}2045}204620472048static CvTrackbar*2049icvFindTrackbarByName( const CvWindow* window, const char* name )2050{2051CvTrackbar* trackbar = window->toolbar.first;20522053for( ; trackbar != 0 && strcmp( trackbar->name, name ) != 0; trackbar = trackbar->next )2054;20552056return trackbar;2057}205820592060static int2061icvCreateTrackbar( const char* trackbar_name, const char* window_name,2062int* val, int count, CvTrackbarCallback on_notify,2063CvTrackbarCallback2 on_notify2, void* userdata )2064{2065int result = 0;20662067CV_FUNCNAME( "icvCreateTrackbar" );20682069__BEGIN__;20702071char slider_name[32];2072CvWindow* window = 0;2073CvTrackbar* trackbar = 0;2074int pos = 0;20752076if( !window_name || !trackbar_name )2077CV_ERROR( CV_StsNullPtr, "NULL window or trackbar name" );20782079if( count < 0 )2080CV_ERROR( CV_StsOutOfRange, "Bad trackbar maximal value" );20812082window = icvFindWindowByName(window_name);2083if( !window )2084EXIT;20852086trackbar = icvFindTrackbarByName(window,trackbar_name);2087if( !trackbar )2088{2089TBBUTTON tbs = {};2090TBBUTTONINFO tbis = {};2091RECT rect;2092int bcount;2093int len = (int)strlen( trackbar_name );20942095// create toolbar if it is not created yet2096if( !window->toolbar.toolbar )2097{2098const int default_height = 30;20992100// CreateToolbarEx is deprecated and forces linking against Comctl32.lib.2101window->toolbar.toolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,2102WS_CHILD | CCS_TOP | TBSTYLE_WRAPABLE | BTNS_AUTOSIZE | BTNS_BUTTON,21030, 0, 0, 0,2104window->frame, NULL, GetModuleHandle(NULL), NULL);2105// CreateToolbarEx automatically sends this but CreateWindowEx doesn't.2106SendMessage(window->toolbar.toolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);21072108GetClientRect(window->frame, &rect);2109MoveWindow( window->toolbar.toolbar, 0, 0,2110rect.right - rect.left, default_height, TRUE);2111SendMessage(window->toolbar.toolbar, TB_AUTOSIZE, 0, 0);2112ShowWindow(window->toolbar.toolbar, SW_SHOW);21132114window->toolbar.first = 0;2115window->toolbar.pos = 0;2116window->toolbar.rows = 0;2117window->toolbar.toolBarProc =2118(WNDPROC)icvGetWindowLongPtr(window->toolbar.toolbar, CV_WNDPROC);21192120icvUpdateWindowPos(window);21212122// Subclassing from toolbar2123icvSetWindowLongPtr(window->toolbar.toolbar, CV_WNDPROC, HGToolbarProc);2124icvSetWindowLongPtr(window->toolbar.toolbar, CV_USERDATA, window);2125}21262127/* Retrieve current buttons count */2128bcount = (int)SendMessage(window->toolbar.toolbar, TB_BUTTONCOUNT, 0, 0);21292130if(bcount > 1)2131{2132/* If this is not the first button then we need to2133separate it from the previous one */2134tbs.iBitmap = 0;2135tbs.idCommand = bcount; // Set button id to it's number2136tbs.iString = 0;2137tbs.fsStyle = TBSTYLE_SEP;2138tbs.fsState = TBSTATE_ENABLED;2139SendMessage(window->toolbar.toolbar, TB_ADDBUTTONS, 1, (LPARAM)&tbs);21402141// Retrieve current buttons count2142bcount = (int)SendMessage(window->toolbar.toolbar, TB_BUTTONCOUNT, 0, 0);2143}21442145/* Add a button which we're going to cover with the slider */2146tbs.iBitmap = 0;2147tbs.idCommand = bcount; // Set button id to it's number2148tbs.fsState = TBSTATE_ENABLED;2149#if 0/*!defined WIN64 && !defined EM64T*/2150tbs.fsStyle = 0;2151tbs.iString = 0;2152#else21532154#ifndef TBSTYLE_AUTOSIZE2155#define TBSTYLE_AUTOSIZE 0x00102156#endif21572158#ifndef TBSTYLE_GROUP2159#define TBSTYLE_GROUP 0x00042160#endif2161//tbs.fsStyle = TBSTYLE_AUTOSIZE;2162tbs.fsStyle = TBSTYLE_GROUP;2163tbs.iString = (INT_PTR)trackbar_text;2164#endif2165SendMessage(window->toolbar.toolbar, TB_ADDBUTTONS, 1, (LPARAM)&tbs);21662167/* Adjust button size to the slider */2168tbis.cbSize = sizeof(tbis);2169tbis.dwMask = TBIF_SIZE;21702171GetClientRect(window->hwnd, &rect);2172tbis.cx = (unsigned short)(rect.right - rect.left);21732174SendMessage(window->toolbar.toolbar, TB_SETBUTTONINFO,2175(WPARAM)tbs.idCommand, (LPARAM)&tbis);21762177/* Get button pos */2178SendMessage(window->toolbar.toolbar, TB_GETITEMRECT,2179(WPARAM)tbs.idCommand, (LPARAM)&rect);21802181/* Create a slider */2182trackbar = (CvTrackbar*)cvAlloc( sizeof(CvTrackbar) + len + 1 );2183trackbar->signature = CV_TRACKBAR_MAGIC_VAL;2184trackbar->notify = 0;2185trackbar->notify2 = 0;2186trackbar->parent = window;2187trackbar->pos = 0;2188trackbar->data = 0;2189trackbar->id = bcount;2190trackbar->next = window->toolbar.first;2191trackbar->name = (char*)(trackbar + 1);2192memcpy( trackbar->name, trackbar_name, len + 1 );2193window->toolbar.first = trackbar;21942195sprintf(slider_name, "Trackbar%p", val);2196trackbar->hwnd = CreateWindowEx(0, TRACKBAR_CLASS, slider_name,2197WS_CHILD | WS_VISIBLE | TBS_AUTOTICKS |2198TBS_FIXEDLENGTH | TBS_HORZ | TBS_BOTTOM,2199rect.left + HG_BUDDY_WIDTH, rect.top,2200rect.right - rect.left - HG_BUDDY_WIDTH,2201rect.bottom - rect.top, window->toolbar.toolbar,2202(HMENU)(size_t)bcount, hg_hinstance, 0);22032204sprintf(slider_name,"Buddy%p", val);2205trackbar->buddy = CreateWindowEx(0, "STATIC", slider_name,2206WS_CHILD | SS_RIGHT,2207rect.left, rect.top,2208HG_BUDDY_WIDTH, rect.bottom - rect.top,2209window->toolbar.toolbar, 0, hg_hinstance, 0);22102211icvSetWindowLongPtr( trackbar->hwnd, CV_USERDATA, trackbar );22122213/* Minimize the number of rows */2214SendMessage( window->toolbar.toolbar, TB_SETROWS,2215MAKEWPARAM(1, FALSE), (LPARAM)&rect );2216}2217else2218{2219trackbar->data = 0;2220trackbar->notify = 0;2221trackbar->notify2 = 0;2222}22232224trackbar->maxval = count;22252226/* Adjust slider parameters */2227SendMessage(trackbar->hwnd, TBM_SETRANGEMIN, (WPARAM)TRUE, (LPARAM)0);2228SendMessage(trackbar->hwnd, TBM_SETRANGEMAX, (WPARAM)TRUE, (LPARAM)count);2229SendMessage(trackbar->hwnd, TBM_SETTICFREQ, (WPARAM)1, (LPARAM)0 );2230if( val )2231pos = *val;22322233SendMessage(trackbar->hwnd, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pos );2234SendMessage(window->toolbar.toolbar, TB_AUTOSIZE, 0, 0);22352236trackbar->pos = -1;2237icvUpdateTrackbar( trackbar, pos );2238ShowWindow( trackbar->buddy, SW_SHOW );2239ShowWindow( trackbar->hwnd, SW_SHOW );22402241trackbar->notify = on_notify;2242trackbar->notify2 = on_notify2;2243trackbar->userdata = userdata;2244trackbar->data = val;22452246/* Resize the window to reflect the toolbar resizing*/2247icvUpdateWindowPos(window);22482249result = 1;22502251__END__;22522253return result;2254}22552256CV_IMPL int2257cvCreateTrackbar( const char* trackbar_name, const char* window_name,2258int* val, int count, CvTrackbarCallback on_notify )2259{2260return icvCreateTrackbar( trackbar_name, window_name, val, count,2261on_notify, 0, 0 );2262}22632264CV_IMPL int2265cvCreateTrackbar2( const char* trackbar_name, const char* window_name,2266int* val, int count, CvTrackbarCallback2 on_notify2,2267void* userdata )2268{2269return icvCreateTrackbar( trackbar_name, window_name, val, count,22700, on_notify2, userdata );2271}22722273CV_IMPL void2274cvSetMouseCallback( const char* window_name, CvMouseCallback on_mouse, void* param )2275{2276CV_FUNCNAME( "cvSetMouseCallback" );22772278__BEGIN__;22792280CvWindow* window = 0;22812282if( !window_name )2283CV_ERROR( CV_StsNullPtr, "NULL window name" );22842285window = icvFindWindowByName(window_name);2286if( !window )2287EXIT;22882289window->on_mouse = on_mouse;2290window->on_mouse_param = param;22912292__END__;2293}229422952296CV_IMPL int cvGetTrackbarPos( const char* trackbar_name, const char* window_name )2297{2298int pos = -1;22992300CV_FUNCNAME( "cvGetTrackbarPos" );23012302__BEGIN__;23032304CvWindow* window;2305CvTrackbar* trackbar = 0;23062307if( trackbar_name == 0 || window_name == 0 )2308CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );23092310window = icvFindWindowByName( window_name );2311if( window )2312trackbar = icvFindTrackbarByName( window, trackbar_name );23132314if( trackbar )2315pos = trackbar->pos;23162317__END__;23182319return pos;2320}232123222323CV_IMPL void cvSetTrackbarPos( const char* trackbar_name, const char* window_name, int pos )2324{2325CV_FUNCNAME( "cvSetTrackbarPos" );23262327__BEGIN__;23282329CvWindow* window;2330CvTrackbar* trackbar = 0;23312332if( trackbar_name == 0 || window_name == 0 )2333CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );23342335window = icvFindWindowByName( window_name );2336if( window )2337trackbar = icvFindTrackbarByName( window, trackbar_name );23382339if( trackbar )2340{2341if( pos < 0 )2342pos = 0;23432344if( pos > trackbar->maxval )2345pos = trackbar->maxval;23462347SendMessage( trackbar->hwnd, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pos );2348icvUpdateTrackbar( trackbar, pos );2349}23502351__END__;2352}235323542355CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name, int maxval)2356{2357CV_FUNCNAME( "cvSetTrackbarMax" );23582359__BEGIN__;23602361if (maxval >= 0)2362{2363CvWindow* window = 0;2364CvTrackbar* trackbar = 0;2365if (trackbar_name == 0 || window_name == 0)2366{2367CV_ERROR(CV_StsNullPtr, "NULL trackbar or window name");2368}23692370window = icvFindWindowByName(window_name);2371if (window)2372{2373trackbar = icvFindTrackbarByName(window, trackbar_name);2374if (trackbar)2375{2376// The position will be min(pos, maxval).2377trackbar->maxval = (trackbar->minval>maxval)?trackbar->minval:maxval;2378SendMessage(trackbar->hwnd, TBM_SETRANGEMAX, (WPARAM)TRUE, (LPARAM)maxval);2379}2380}2381}23822383__END__;2384}238523862387CV_IMPL void cvSetTrackbarMin(const char* trackbar_name, const char* window_name, int minval)2388{2389CV_FUNCNAME( "cvSetTrackbarMin" );23902391__BEGIN__;23922393if (minval >= 0)2394{2395CvWindow* window = 0;2396CvTrackbar* trackbar = 0;2397if (trackbar_name == 0 || window_name == 0)2398{2399CV_ERROR(CV_StsNullPtr, "NULL trackbar or window name");2400}24012402window = icvFindWindowByName(window_name);2403if (window)2404{2405trackbar = icvFindTrackbarByName(window, trackbar_name);2406if (trackbar)2407{2408// The position will be min(pos, maxval).2409trackbar->minval = (minval<trackbar->maxval)?minval:trackbar->maxval;2410SendMessage(trackbar->hwnd, TBM_SETRANGEMIN, (WPARAM)TRUE, (LPARAM)minval);2411}2412}2413}24142415__END__;2416}241724182419CV_IMPL void* cvGetWindowHandle( const char* window_name )2420{2421void* hwnd = 0;24222423CV_FUNCNAME( "cvGetWindowHandle" );24242425__BEGIN__;24262427CvWindow* window;24282429if( window_name == 0 )2430CV_ERROR( CV_StsNullPtr, "NULL window name" );24312432window = icvFindWindowByName( window_name );2433if( window )2434hwnd = (void*)window->hwnd;24352436__END__;24372438return hwnd;2439}244024412442CV_IMPL const char* cvGetWindowName( void* window_handle )2443{2444const char* window_name = "";24452446CV_FUNCNAME( "cvGetWindowName" );24472448__BEGIN__;24492450CvWindow* window;24512452if( window_handle == 0 )2453CV_ERROR( CV_StsNullPtr, "NULL window" );24542455window = icvWindowByHWND( (HWND)window_handle );2456if( window )2457window_name = window->name;24582459__END__;24602461return window_name;2462}246324642465CV_IMPL void2466cvSetPreprocessFuncWin32_(const void* callback)2467{2468hg_on_preprocess = (CvWin32WindowCallback)callback;2469}24702471CV_IMPL void2472cvSetPostprocessFuncWin32_(const void* callback)2473{2474hg_on_postprocess = (CvWin32WindowCallback)callback;2475}24762477#endif //_WIN32247824792480