📄 window_w32.cpp
字号:
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "_highgui.h"
#if defined WIN32 || defined WIN64
#if _MSC_VER >= 1200
#pragma warning( disable: 4710 )
#endif
#include <commctrl.h>
#include <winuser.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
static const char* trackbar_text =
" ";
#if defined WIN64 || defined EM64T
#define icvGetWindowLongPtr GetWindowLongPtr
#define icvSetWindowLongPtr( hwnd, id, ptr ) SetWindowLongPtr( hwnd, id, (LONG_PTR)(ptr) )
#define icvGetClassLongPtr GetClassLongPtr
#define CV_USERDATA GWLP_USERDATA
#define CV_WNDPROC GWLP_WNDPROC
#define CV_HCURSOR GCLP_HCURSOR
#define CV_HBRBACKGROUND GCLP_HBRBACKGROUND
#else
#define icvGetWindowLongPtr GetWindowLong
#define icvSetWindowLongPtr( hwnd, id, ptr ) SetWindowLong( hwnd, id, (size_t)ptr )
#define icvGetClassLongPtr GetClassLong
#define CV_USERDATA GWL_USERDATA
#define CV_WNDPROC GWL_WNDPROC
#define CV_HCURSOR GCL_HCURSOR
#define CV_HBRBACKGROUND GCL_HBRBACKGROUND
#endif
void FillBitmapInfo( BITMAPINFO* bmi, int width, int height, int bpp, int origin )
{
assert( bmi && width >= 0 && height >= 0 && (bpp == 8 || bpp == 24 || bpp == 32));
BITMAPINFOHEADER* bmih = &(bmi->bmiHeader);
memset( bmih, 0, sizeof(*bmih));
bmih->biSize = sizeof(BITMAPINFOHEADER);
bmih->biWidth = width;
bmih->biHeight = origin ? abs(height) : -abs(height);
bmih->biPlanes = 1;
bmih->biBitCount = (unsigned short)bpp;
bmih->biCompression = BI_RGB;
if( bpp == 8 )
{
RGBQUAD* palette = bmi->bmiColors;
int i;
for( i = 0; i < 256; i++ )
{
palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;
palette[i].rgbReserved = 0;
}
}
}
struct CvWindow;
typedef struct CvTrackbar
{
int signature;
HWND hwnd;
char* name;
CvTrackbar* next;
CvWindow* parent;
HWND buddy;
int* data;
int pos;
int maxval;
void (*notify)(int);
int id;
}
CvTrackbar;
typedef struct CvWindow
{
int signature;
HWND hwnd;
char* name;
CvWindow* prev;
CvWindow* next;
HWND frame;
HDC dc;
HGDIOBJ image;
int last_key;
int flags;
CvMouseCallback on_mouse;
void* on_mouse_param;
struct
{
HWND toolbar;
int pos;
int rows;
WNDPROC toolBarProc;
CvTrackbar* first;
}
toolbar;
}
CvWindow;
#define HG_BUDDY_WIDTH 130
#ifndef TBIF_SIZE
#define TBIF_SIZE 0x40
#endif
#ifndef TB_SETBUTTONINFO
#define TB_SETBUTTONINFO (WM_USER + 66)
#endif
#ifndef TBM_GETTOOLTIPS
#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 CvWindow* hg_windows = 0;
static CvWin32WindowCallback hg_on_preprocess = 0, hg_on_postprocess = 0;
static HINSTANCE hg_hinstance = 0;
static void icvCleanupHighgui()
{
cvDestroyAllWindows();
}
CV_IMPL int cvInitSystem( int, char** )
{
static int wasInitialized = 0;
// check initialization status
if( !wasInitialized )
{
// Initialize the stogare
hg_windows = 0;
// Register the class
WNDCLASS wndc;
wndc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
wndc.lpfnWndProc = WindowProc;
wndc.cbClsExtra = 0;
wndc.cbWndExtra = 0;
wndc.hInstance = hg_hinstance;
wndc.lpszClassName = "HighGUI class";
wndc.lpszMenuName = "HighGUI class";
wndc.hIcon = LoadIcon(0, IDI_APPLICATION);
wndc.hCursor = (HCURSOR)LoadCursor(0, (LPSTR)(size_t)IDC_CROSS );
wndc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
RegisterClass(&wndc);
wndc.lpszClassName = "Main HighGUI class";
wndc.lpszMenuName = "Main HighGUI class";
wndc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
wndc.lpfnWndProc = MainWindowProc;
RegisterClass(&wndc);
atexit( icvCleanupHighgui );
wasInitialized = 1;
}
return 0;
}
CV_IMPL int cvStartWindowThread(){
return 0;
}
static CvWindow* icvFindWindowByName( const char* name )
{
CvWindow* window = hg_windows;
for( ; window != 0 && strcmp( name, window->name) != 0; window = window->next )
;
return window;
}
static CvWindow* icvWindowByHWND( HWND hwnd )
{
CvWindow* window = (CvWindow*)icvGetWindowLongPtr( hwnd, CV_USERDATA );
return window != 0 && hg_windows != 0 &&
window->signature == CV_WINDOW_MAGIC_VAL ? window : 0;
}
static CvTrackbar* icvTrackbarByHWND( HWND hwnd )
{
CvTrackbar* trackbar = (CvTrackbar*)icvGetWindowLongPtr( hwnd, CV_USERDATA );
return trackbar != 0 && trackbar->signature == CV_TRACKBAR_MAGIC_VAL &&
trackbar->hwnd == hwnd ? trackbar : 0;
}
static const char* 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 )
{
HKEY hkey;
char szKey[1024];
strcpy( szKey, icvWindowPosRootKey );
strcat( szKey, 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 )
{
// Yes we are installed.
DWORD dwType = 0;
DWORD dwSize = sizeof(int);
RegQueryValueEx(hkey, "Left", NULL, &dwType, (BYTE*)&rect.x, &dwSize);
RegQueryValueEx(hkey, "Top", NULL, &dwType, (BYTE*)&rect.y, &dwSize);
RegQueryValueEx(hkey, "Width", NULL, &dwType, (BYTE*)&rect.width, &dwSize);
RegQueryValueEx(hkey, "Height", NULL, &dwType, (BYTE*)&rect.height, &dwSize);
if( rect.x != (int)CW_USEDEFAULT && (rect.x < -200 || rect.x > 3000) )
rect.x = 100;
if( rect.y != (int)CW_USEDEFAULT && (rect.y < -200 || rect.y > 3000) )
rect.y = 100;
if( rect.width != (int)CW_USEDEFAULT && (rect.width < 0 || rect.width > 3000) )
rect.width = 100;
if( rect.height != (int)CW_USEDEFAULT && (rect.height < 0 || rect.height > 3000) )
rect.height = 100;
RegCloseKey(hkey);
}
}
// Window positions saving/loading added by Philip Gruebele.
//<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 )
{
static const DWORD MAX_RECORD_COUNT = 100;
HKEY hkey;
char szKey[1024];
char rootKey[1024];
strcpy( szKey, icvWindowPosRootKey );
strcat( szKey, name );
if( RegOpenKeyEx( HKEY_CURRENT_USER,szKey,0,KEY_READ,&hkey) != ERROR_SUCCESS )
{
HKEY hroot;
DWORD count = 0;
FILETIME oldestTime = { UINT_MAX, UINT_MAX };
char oldestKey[1024];
char currentKey[1024];
strcpy( rootKey, 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 )
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 )
break;
count++;
if( oldestTime.dwHighDateTime > accesstime.dwHighDateTime ||
oldestTime.dwHighDateTime == accesstime.dwHighDateTime &&
oldestTime.dwLowDateTime > accesstime.dwLowDateTime )
{
oldestTime = accesstime;
strcpy( oldestKey, currentKey );
}
}
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 )
return;
}
else
{
RegCloseKey( hkey );
if( RegOpenKeyEx( HKEY_CURRENT_USER,szKey,0,KEY_WRITE,&hkey) != ERROR_SUCCESS )
return;
}
RegSetValueEx(hkey, "Left", 0, REG_DWORD, (BYTE*)&rect.x, sizeof(rect.x));
RegSetValueEx(hkey, "Top", 0, REG_DWORD, (BYTE*)&rect.y, sizeof(rect.y));
RegSetValueEx(hkey, "Width", 0, REG_DWORD, (BYTE*)&rect.width, sizeof(rect.width));
RegSetValueEx(hkey, "Height", 0, REG_DWORD, (BYTE*)&rect.height, sizeof(rect.height));
RegCloseKey(hkey);
}
CV_IMPL int cvNamedWindow( const char* name, int flags )
{
int result = 0;
CV_FUNCNAME( "cvNamedWindow" );
__BEGIN__;
HWND hWnd, mainhWnd;
CvWindow* window;
DWORD defStyle = WS_VISIBLE | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU;
int len;
CvRect rect;
cvInitSystem(0,0);
if( !name )
CV_ERROR( CV_StsNullPtr, "NULL name string" );
// Check the name in the storage
if( icvFindWindowByName( name ) != 0 )
{
result = 1;
EXIT;
}
if( (flags & CV_WINDOW_AUTOSIZE) == 0 )
defStyle |= WS_SIZEBOX;
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" );
ShowWindow(mainhWnd, SW_SHOW);
hWnd = CreateWindow("HighGUI class", "", defStyle | WS_CHILD | WS_SIZEBOX,
CW_USEDEFAULT, 0, rect.width, rect.height, mainhWnd, 0, hg_hinstance, 0);
if( !hWnd )
CV_ERROR( CV_StsError, "Frame window can not be created" );
ShowWindow(hWnd, SW_SHOW);
len = (int)strlen(name);
CV_CALL( window = (CvWindow*)cvAlloc(sizeof(CvWindow) + len + 1));
window->signature = CV_WINDOW_MAGIC_VAL;
window->hwnd = hWnd;
window->frame = mainhWnd;
window->name = (char*)(window + 1);
memcpy( window->name, name, len + 1 );
window->flags = flags;
window->image = 0;
window->dc = CreateCompatibleDC(0);
window->last_key = 0;
window->on_mouse = 0;
window->on_mouse_param = 0;
memset( &window->toolbar, 0, sizeof(window->toolbar));
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 );
// Recalculate window position
icvUpdateWindowPos( window );
result = 1;
__END__;
return result;
}
static void icvRemoveWindow( CvWindow* window )
{
CvTrackbar* trackbar;
RECT wrect;
GetWindowRect( window->frame, &wrect );
icvSaveWindowPos( window->name, cvRect(wrect.left, wrect.top,
wrect.right-wrect.left, wrect.bottom-wrect.top) );
icvSetWindowLongPtr( window->hwnd, CV_USERDATA, 0 );
icvSetWindowLongPtr( window->frame, CV_USERDATA, 0 );
if( window->prev )
window->prev->next = window->next;
else
hg_windows = window->next;
if( window->next )
window->next->prev = window->prev;
window->prev = window->next = 0;
if( window->image )
DeleteObject(SelectObject(window->dc,window->image));
if( window->dc )
DeleteDC(window->dc);
for( trackbar = window->toolbar.first; trackbar != 0; )
{
CvTrackbar* next = trackbar->next;
icvSetWindowLongPtr( trackbar->hwnd, CV_USERDATA, 0 );
cvFree( &trackbar );
trackbar = next;
}
cvFree( &window );
}
CV_IMPL void cvDestroyWindow( const char* name )
{
CV_FUNCNAME( "cvDestroyWindow" );
__BEGIN__;
CvWindow* window;
HWND mainhWnd;
if(!name)
CV_ERROR( CV_StsNullPtr, "NULL name string" );
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__;
}
static void icvScreenToClient( HWND hwnd, RECT* rect )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -