Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/highgui/src/window_w32.cpp
16337 views
1
/*M///////////////////////////////////////////////////////////////////////////////////////
2
//
3
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4
//
5
// By downloading, copying, installing or using the software you agree to this license.
6
// If you do not agree to this license, do not download, install,
7
// copy or use the software.
8
//
9
//
10
// Intel License Agreement
11
// For Open Source Computer Vision Library
12
//
13
// Copyright (C) 2000, Intel Corporation, all rights reserved.
14
// Third party copyrights are property of their respective owners.
15
//
16
// Redistribution and use in source and binary forms, with or without modification,
17
// are permitted provided that the following conditions are met:
18
//
19
// * Redistribution's of source code must retain the above copyright notice,
20
// this list of conditions and the following disclaimer.
21
//
22
// * Redistribution's in binary form must reproduce the above copyright notice,
23
// this list of conditions and the following disclaimer in the documentation
24
// and/or other materials provided with the distribution.
25
//
26
// * The name of Intel Corporation may not be used to endorse or promote products
27
// derived from this software without specific prior written permission.
28
//
29
// This software is provided by the copyright holders and contributors "as is" and
30
// any express or implied warranties, including, but not limited to, the implied
31
// warranties of merchantability and fitness for a particular purpose are disclaimed.
32
// In no event shall the Intel Corporation or contributors be liable for any direct,
33
// indirect, incidental, special, exemplary, or consequential damages
34
// (including, but not limited to, procurement of substitute goods or services;
35
// loss of use, data, or profits; or business interruption) however caused
36
// and on any theory of liability, whether in contract, strict liability,
37
// or tort (including negligence or otherwise) arising in any way out of
38
// the use of this software, even if advised of the possibility of such damage.
39
//
40
//M*/
41
42
#include "precomp.hpp"
43
#include <windowsx.h> // required for GET_X_LPARAM() and GET_Y_LPARAM() macros
44
45
#if defined _WIN32
46
47
#ifdef __GNUC__
48
# pragma GCC diagnostic ignored "-Wmissing-declarations"
49
#endif
50
51
#if (_WIN32_IE < 0x0500)
52
#pragma message("WARNING: Win32 UI needs to be compiled with _WIN32_IE >= 0x0500 (_WIN32_IE_IE50)")
53
#define _WIN32_IE 0x0500
54
#endif
55
56
#include <commctrl.h>
57
#include <stdlib.h>
58
#include <string.h>
59
#include <stdio.h>
60
#include <assert.h>
61
62
#ifdef HAVE_OPENGL
63
#include <memory>
64
#include <algorithm>
65
#include <vector>
66
#include <functional>
67
#include "opencv2/highgui.hpp"
68
#include <GL/gl.h>
69
#endif
70
71
static const char* trackbar_text =
72
" ";
73
74
#if defined _M_X64 || defined __x86_64
75
76
#define icvGetWindowLongPtr GetWindowLongPtr
77
#define icvSetWindowLongPtr( hwnd, id, ptr ) SetWindowLongPtr( hwnd, id, (LONG_PTR)(ptr) )
78
#define icvGetClassLongPtr GetClassLongPtr
79
80
#define CV_USERDATA GWLP_USERDATA
81
#define CV_WNDPROC GWLP_WNDPROC
82
#define CV_HCURSOR GCLP_HCURSOR
83
#define CV_HBRBACKGROUND GCLP_HBRBACKGROUND
84
85
#else
86
87
#define icvGetWindowLongPtr GetWindowLong
88
#define icvSetWindowLongPtr( hwnd, id, ptr ) SetWindowLong( hwnd, id, (size_t)ptr )
89
#define icvGetClassLongPtr GetClassLong
90
91
#define CV_USERDATA GWL_USERDATA
92
#define CV_WNDPROC GWL_WNDPROC
93
#define CV_HCURSOR GCL_HCURSOR
94
#define CV_HBRBACKGROUND GCL_HBRBACKGROUND
95
96
#endif
97
98
#ifndef WM_MOUSEHWHEEL
99
#define WM_MOUSEHWHEEL 0x020E
100
#endif
101
102
static void FillBitmapInfo( BITMAPINFO* bmi, int width, int height, int bpp, int origin )
103
{
104
assert( bmi && width >= 0 && height >= 0 && (bpp == 8 || bpp == 24 || bpp == 32));
105
106
BITMAPINFOHEADER* bmih = &(bmi->bmiHeader);
107
108
memset( bmih, 0, sizeof(*bmih));
109
bmih->biSize = sizeof(BITMAPINFOHEADER);
110
bmih->biWidth = width;
111
bmih->biHeight = origin ? abs(height) : -abs(height);
112
bmih->biPlanes = 1;
113
bmih->biBitCount = (unsigned short)bpp;
114
bmih->biCompression = BI_RGB;
115
116
if( bpp == 8 )
117
{
118
RGBQUAD* palette = bmi->bmiColors;
119
int i;
120
for( i = 0; i < 256; i++ )
121
{
122
palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;
123
palette[i].rgbReserved = 0;
124
}
125
}
126
}
127
128
struct CvWindow;
129
130
typedef struct CvTrackbar
131
{
132
int signature;
133
HWND hwnd;
134
char* name;
135
CvTrackbar* next;
136
CvWindow* parent;
137
HWND buddy;
138
int* data;
139
int pos;
140
int maxval;
141
int minval;
142
void (*notify)(int);
143
void (*notify2)(int, void*);
144
void* userdata;
145
int id;
146
}
147
CvTrackbar;
148
149
150
typedef struct CvWindow
151
{
152
int signature;
153
HWND hwnd;
154
char* name;
155
CvWindow* prev;
156
CvWindow* next;
157
HWND frame;
158
159
HDC dc;
160
HGDIOBJ image;
161
int last_key;
162
int flags;
163
int status;//0 normal, 1 fullscreen (YV)
164
165
CvMouseCallback on_mouse;
166
void* on_mouse_param;
167
168
struct
169
{
170
HWND toolbar;
171
int pos;
172
int rows;
173
WNDPROC toolBarProc;
174
CvTrackbar* first;
175
}
176
toolbar;
177
178
int width;
179
int height;
180
181
// OpenGL support
182
183
#ifdef HAVE_OPENGL
184
bool useGl;
185
HGLRC hGLRC;
186
187
CvOpenGlDrawCallback glDrawCallback;
188
void* glDrawData;
189
#endif
190
}
191
CvWindow;
192
193
#define HG_BUDDY_WIDTH 130
194
195
#ifndef TBIF_SIZE
196
#define TBIF_SIZE 0x40
197
#endif
198
199
#ifndef TB_SETBUTTONINFO
200
#define TB_SETBUTTONINFO (WM_USER + 66)
201
#endif
202
203
#ifndef TBM_GETTOOLTIPS
204
#define TBM_GETTOOLTIPS (WM_USER + 30)
205
#endif
206
207
static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
208
static LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
209
static LRESULT CALLBACK MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
210
static void icvUpdateWindowPos( CvWindow* window );
211
212
static CvWindow* hg_windows = 0;
213
214
typedef int (CV_CDECL * CvWin32WindowCallback)(HWND, UINT, WPARAM, LPARAM, int*);
215
static CvWin32WindowCallback hg_on_preprocess = 0, hg_on_postprocess = 0;
216
static HINSTANCE hg_hinstance = 0;
217
218
static const char* highGUIclassName = "HighGUI class";
219
static const char* mainHighGUIclassName = "Main HighGUI class";
220
221
static void icvCleanupHighgui()
222
{
223
cvDestroyAllWindows();
224
UnregisterClass(highGUIclassName, hg_hinstance);
225
UnregisterClass(mainHighGUIclassName, hg_hinstance);
226
}
227
228
CV_IMPL int cvInitSystem( int, char** )
229
{
230
static int wasInitialized = 0;
231
232
// check initialization status
233
if( !wasInitialized )
234
{
235
// Initialize the stogare
236
hg_windows = 0;
237
238
// Register the class
239
WNDCLASS wndc;
240
wndc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
241
wndc.lpfnWndProc = WindowProc;
242
wndc.cbClsExtra = 0;
243
wndc.cbWndExtra = 0;
244
wndc.hInstance = hg_hinstance;
245
wndc.lpszClassName = highGUIclassName;
246
wndc.lpszMenuName = highGUIclassName;
247
wndc.hIcon = LoadIcon(0, IDI_APPLICATION);
248
wndc.hCursor = (HCURSOR)LoadCursor(0, (LPSTR)(size_t)IDC_CROSS );
249
wndc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
250
251
RegisterClass(&wndc);
252
253
wndc.lpszClassName = mainHighGUIclassName;
254
wndc.lpszMenuName = mainHighGUIclassName;
255
wndc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
256
wndc.lpfnWndProc = MainWindowProc;
257
258
RegisterClass(&wndc);
259
atexit( icvCleanupHighgui );
260
261
wasInitialized = 1;
262
}
263
264
setlocale(LC_NUMERIC,"C");
265
266
return 0;
267
}
268
269
CV_IMPL int cvStartWindowThread(){
270
return 0;
271
}
272
273
static CvWindow* icvFindWindowByName( const char* name )
274
{
275
CvWindow* window = hg_windows;
276
277
for( ; window != 0 && strcmp( name, window->name) != 0; window = window->next )
278
;
279
280
return window;
281
}
282
283
284
static CvWindow* icvWindowByHWND( HWND hwnd )
285
{
286
CvWindow* window = (CvWindow*)icvGetWindowLongPtr( hwnd, CV_USERDATA );
287
return window != 0 && hg_windows != 0 &&
288
window->signature == CV_WINDOW_MAGIC_VAL ? window : 0;
289
}
290
291
292
static CvTrackbar* icvTrackbarByHWND( HWND hwnd )
293
{
294
CvTrackbar* trackbar = (CvTrackbar*)icvGetWindowLongPtr( hwnd, CV_USERDATA );
295
return trackbar != 0 && trackbar->signature == CV_TRACKBAR_MAGIC_VAL &&
296
trackbar->hwnd == hwnd ? trackbar : 0;
297
}
298
299
300
static const char* icvWindowPosRootKey = "Software\\OpenCV\\HighGUI\\Windows\\";
301
302
// Window positions saving/loading added by Philip Gruebele.
303
//<a href="mailto:[email protected]">[email protected]</a>
304
// Restores the window position from the registry saved position.
305
static void
306
icvLoadWindowPos( const char* name, CvRect& rect )
307
{
308
HKEY hkey;
309
char szKey[1024];
310
strcpy_s( szKey, 1024, icvWindowPosRootKey );
311
strcat_s( szKey, 1024, name );
312
313
rect.x = rect.y = CW_USEDEFAULT;
314
rect.width = rect.height = 320;
315
316
if( RegOpenKeyEx(HKEY_CURRENT_USER,szKey,0,KEY_QUERY_VALUE,&hkey) == ERROR_SUCCESS )
317
{
318
// Yes we are installed.
319
DWORD dwType = 0;
320
DWORD dwSize = sizeof(int);
321
322
RegQueryValueEx(hkey, "Left", NULL, &dwType, (BYTE*)&rect.x, &dwSize);
323
RegQueryValueEx(hkey, "Top", NULL, &dwType, (BYTE*)&rect.y, &dwSize);
324
RegQueryValueEx(hkey, "Width", NULL, &dwType, (BYTE*)&rect.width, &dwSize);
325
RegQueryValueEx(hkey, "Height", NULL, &dwType, (BYTE*)&rect.height, &dwSize);
326
327
// Snap rect into closest monitor in case it falls outside it. // Adi Shavit
328
// set WIN32 RECT to be the loaded size
329
POINT tl_w32 = { rect.x, rect.y };
330
POINT tr_w32 = { rect.x + rect.width, rect.y };
331
332
// find monitor containing top-left and top-right corners, or NULL
333
HMONITOR hMonitor_l = MonitorFromPoint(tl_w32, MONITOR_DEFAULTTONULL);
334
HMONITOR hMonitor_r = MonitorFromPoint(tr_w32, MONITOR_DEFAULTTONULL);
335
336
// if neither are contained - the move window to origin of closest.
337
if (NULL == hMonitor_l && NULL == hMonitor_r)
338
{
339
// find monitor nearest to top-left corner
340
HMONITOR hMonitor_closest = MonitorFromPoint(tl_w32, MONITOR_DEFAULTTONEAREST);
341
342
// get coordinates of nearest monitor
343
MONITORINFO mi;
344
mi.cbSize = sizeof(mi);
345
GetMonitorInfo(hMonitor_closest, &mi);
346
347
rect.x = mi.rcWork.left;
348
rect.y = mi.rcWork.top;
349
}
350
351
if (rect.width != (int)CW_USEDEFAULT && (rect.width < 0 || rect.width > 3000))
352
rect.width = 100;
353
if (rect.height != (int)CW_USEDEFAULT && (rect.height < 0 || rect.height > 3000))
354
rect.height = 100;
355
356
RegCloseKey(hkey);
357
}
358
}
359
360
361
// Window positions saving/loading added by Philip Gruebele.
362
//<a href="mailto:[email protected]">[email protected]</a>
363
// philipg. Saves the window position in the registry
364
static void
365
icvSaveWindowPos( const char* name, CvRect rect )
366
{
367
static const DWORD MAX_RECORD_COUNT = 100;
368
HKEY hkey;
369
char szKey[1024];
370
char rootKey[1024];
371
strcpy_s( szKey, 1024, icvWindowPosRootKey );
372
strcat_s( szKey, 1024, name );
373
374
if( RegOpenKeyEx( HKEY_CURRENT_USER,szKey,0,KEY_READ,&hkey) != ERROR_SUCCESS )
375
{
376
HKEY hroot;
377
DWORD count = 0;
378
FILETIME oldestTime = { UINT_MAX, UINT_MAX };
379
char oldestKey[1024];
380
char currentKey[1024];
381
382
strcpy_s( rootKey, 1024, icvWindowPosRootKey );
383
rootKey[strlen(rootKey)-1] = '\0';
384
if( RegCreateKeyEx(HKEY_CURRENT_USER, rootKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ+KEY_WRITE, 0, &hroot, NULL) != ERROR_SUCCESS )
385
//RegOpenKeyEx( HKEY_CURRENT_USER,rootKey,0,KEY_READ,&hroot) != ERROR_SUCCESS )
386
return;
387
388
for(;;)
389
{
390
DWORD csize = sizeof(currentKey);
391
FILETIME accesstime = { 0, 0 };
392
LONG code = RegEnumKeyEx( hroot, count, currentKey, &csize, NULL, NULL, NULL, &accesstime );
393
if( code != ERROR_SUCCESS && code != ERROR_MORE_DATA )
394
break;
395
count++;
396
if( oldestTime.dwHighDateTime > accesstime.dwHighDateTime ||
397
(oldestTime.dwHighDateTime == accesstime.dwHighDateTime &&
398
oldestTime.dwLowDateTime > accesstime.dwLowDateTime) )
399
{
400
oldestTime = accesstime;
401
strcpy_s( oldestKey, 1024, currentKey );
402
}
403
}
404
405
if( count >= MAX_RECORD_COUNT )
406
RegDeleteKey( hroot, oldestKey );
407
RegCloseKey( hroot );
408
409
if( RegCreateKeyEx(HKEY_CURRENT_USER,szKey,0,NULL,REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &hkey, NULL) != ERROR_SUCCESS )
410
return;
411
}
412
else
413
{
414
RegCloseKey( hkey );
415
if( RegOpenKeyEx( HKEY_CURRENT_USER,szKey,0,KEY_WRITE,&hkey) != ERROR_SUCCESS )
416
return;
417
}
418
419
RegSetValueEx(hkey, "Left", 0, REG_DWORD, (BYTE*)&rect.x, sizeof(rect.x));
420
RegSetValueEx(hkey, "Top", 0, REG_DWORD, (BYTE*)&rect.y, sizeof(rect.y));
421
RegSetValueEx(hkey, "Width", 0, REG_DWORD, (BYTE*)&rect.width, sizeof(rect.width));
422
RegSetValueEx(hkey, "Height", 0, REG_DWORD, (BYTE*)&rect.height, sizeof(rect.height));
423
RegCloseKey(hkey);
424
}
425
426
CvRect cvGetWindowRect_W32(const char* name)
427
{
428
CvRect result = cvRect(-1, -1, -1, -1);
429
430
CV_FUNCNAME( "cvGetWindowRect_W32" );
431
432
__BEGIN__;
433
434
CvWindow* window;
435
436
if (!name)
437
CV_ERROR( CV_StsNullPtr, "NULL name string" );
438
window = icvFindWindowByName( name );
439
if (!window)
440
EXIT; // keep silence here
441
442
RECT rect;
443
GetClientRect(window->hwnd, &rect);
444
{
445
POINT pt = {rect.left, rect.top};
446
ClientToScreen(window->hwnd, &pt);
447
result = cvRect(pt.x, pt.y, rect.right - rect.left, rect.bottom - rect.top);
448
}
449
__END__;
450
return result;
451
}
452
453
double cvGetModeWindow_W32(const char* name)//YV
454
{
455
double result = -1;
456
457
CV_FUNCNAME( "cvGetModeWindow_W32" );
458
459
__BEGIN__;
460
461
CvWindow* window;
462
463
if (!name)
464
CV_ERROR( CV_StsNullPtr, "NULL name string" );
465
466
window = icvFindWindowByName( name );
467
if (!window)
468
EXIT; // keep silence here
469
470
result = window->status;
471
472
__END__;
473
return result;
474
}
475
476
void cvSetModeWindow_W32( const char* name, double prop_value)//Yannick Verdie
477
{
478
CV_FUNCNAME( "cvSetModeWindow_W32" );
479
480
__BEGIN__;
481
482
CvWindow* window;
483
484
if(!name)
485
CV_ERROR( CV_StsNullPtr, "NULL name string" );
486
487
window = icvFindWindowByName( name );
488
if( !window )
489
CV_ERROR( CV_StsNullPtr, "NULL window" );
490
491
if(window->flags & CV_WINDOW_AUTOSIZE)//if the flag CV_WINDOW_AUTOSIZE is set
492
EXIT;
493
494
{
495
DWORD dwStyle = (DWORD)GetWindowLongPtr(window->frame, GWL_STYLE);
496
CvRect position;
497
498
if (window->status==CV_WINDOW_FULLSCREEN && prop_value==CV_WINDOW_NORMAL)
499
{
500
icvLoadWindowPos(window->name,position );
501
SetWindowLongPtr(window->frame, GWL_STYLE, dwStyle | WS_CAPTION | WS_THICKFRAME);
502
503
SetWindowPos(window->frame, HWND_TOP, position.x, position.y , position.width,position.height, SWP_NOZORDER | SWP_FRAMECHANGED);
504
window->status=CV_WINDOW_NORMAL;
505
506
EXIT;
507
}
508
509
if (window->status==CV_WINDOW_NORMAL && prop_value==CV_WINDOW_FULLSCREEN)
510
{
511
//save dimension
512
RECT rect;
513
GetWindowRect(window->frame, &rect);
514
CvRect RectCV = cvRect(rect.left, rect.top,rect.right - rect.left, rect.bottom - rect.top);
515
icvSaveWindowPos(window->name,RectCV );
516
517
//Look at coordinate for fullscreen
518
HMONITOR hMonitor;
519
MONITORINFO mi;
520
hMonitor = MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST);
521
522
mi.cbSize = sizeof(mi);
523
GetMonitorInfo(hMonitor, &mi);
524
525
//fullscreen
526
position.x=mi.rcMonitor.left;position.y=mi.rcMonitor.top;
527
position.width=mi.rcMonitor.right - mi.rcMonitor.left;position.height=mi.rcMonitor.bottom - mi.rcMonitor.top;
528
SetWindowLongPtr(window->frame, GWL_STYLE, dwStyle & ~WS_CAPTION & ~WS_THICKFRAME);
529
530
SetWindowPos(window->frame, HWND_TOP, position.x, position.y , position.width,position.height, SWP_NOZORDER | SWP_FRAMECHANGED);
531
window->status=CV_WINDOW_FULLSCREEN;
532
533
EXIT;
534
}
535
}
536
537
__END__;
538
}
539
540
void cv::setWindowTitle(const String& winname, const String& title)
541
{
542
CvWindow* window = icvFindWindowByName(winname.c_str());
543
544
if (!window)
545
{
546
namedWindow(winname);
547
window = icvFindWindowByName(winname.c_str());
548
}
549
550
if (!window)
551
CV_Error(Error::StsNullPtr, "NULL window");
552
553
if (!SetWindowText(window->frame, title.c_str()))
554
CV_Error_(Error::StsError, ("Failed to set \"%s\" window title to \"%s\"", winname.c_str(), title.c_str()));
555
}
556
557
double cvGetPropWindowAutoSize_W32(const char* name)
558
{
559
double result = -1;
560
561
CV_FUNCNAME( "cvSetCloseCallback" );
562
563
__BEGIN__;
564
565
CvWindow* window;
566
567
if (!name)
568
CV_ERROR( CV_StsNullPtr, "NULL name string" );
569
570
window = icvFindWindowByName( name );
571
if (!window)
572
EXIT; // keep silence here
573
574
result = window->flags & CV_WINDOW_AUTOSIZE;
575
576
__END__;
577
578
return result;
579
}
580
581
double cvGetRatioWindow_W32(const char* name)
582
{
583
double result = -1;
584
585
CV_FUNCNAME( "cvGetRatioWindow_W32" );
586
587
__BEGIN__;
588
589
CvWindow* window;
590
591
if (!name)
592
CV_ERROR( CV_StsNullPtr, "NULL name string" );
593
594
window = icvFindWindowByName( name );
595
if (!window)
596
EXIT; // keep silence here
597
598
result = static_cast<double>(window->width) / window->height;
599
600
__END__;
601
602
return result;
603
}
604
605
double cvGetOpenGlProp_W32(const char* name)
606
{
607
double result = -1;
608
609
#ifdef HAVE_OPENGL
610
CV_FUNCNAME( "cvGetOpenGlProp_W32" );
611
612
__BEGIN__;
613
614
CvWindow* window;
615
616
if (!name)
617
CV_ERROR( CV_StsNullPtr, "NULL name string" );
618
619
window = icvFindWindowByName( name );
620
if (!window)
621
EXIT; // keep silence here
622
623
result = window->useGl;
624
625
__END__;
626
#endif
627
CV_UNUSED(name);
628
629
return result;
630
}
631
632
633
// OpenGL support
634
635
#ifdef HAVE_OPENGL
636
637
namespace
638
{
639
void createGlContext(HWND hWnd, HDC& hGLDC, HGLRC& hGLRC, bool& useGl)
640
{
641
CV_FUNCNAME( "createGlContext" );
642
643
__BEGIN__;
644
645
useGl = false;
646
647
int PixelFormat;
648
649
static PIXELFORMATDESCRIPTOR pfd =
650
{
651
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
652
1, // Version Number
653
PFD_DRAW_TO_WINDOW | // Format Must Support Window
654
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
655
PFD_DOUBLEBUFFER, // Must Support Double Buffering
656
PFD_TYPE_RGBA, // Request An RGBA Format
657
32, // Select Our Color Depth
658
0, 0, 0, 0, 0, 0, // Color Bits Ignored
659
0, // No Alpha Buffer
660
0, // Shift Bit Ignored
661
0, // No Accumulation Buffer
662
0, 0, 0, 0, // Accumulation Bits Ignored
663
32, // 32 Bit Z-Buffer (Depth Buffer)
664
0, // No Stencil Buffer
665
0, // No Auxiliary Buffer
666
PFD_MAIN_PLANE, // Main Drawing Layer
667
0, // Reserved
668
0, 0, 0 // Layer Masks Ignored
669
};
670
671
hGLDC = GetDC(hWnd);
672
if (!hGLDC)
673
CV_ERROR( CV_OpenGlApiCallError, "Can't Create A GL Device Context" );
674
675
PixelFormat = ChoosePixelFormat(hGLDC, &pfd);
676
if (!PixelFormat)
677
CV_ERROR( CV_OpenGlApiCallError, "Can't Find A Suitable PixelFormat" );
678
679
if (!SetPixelFormat(hGLDC, PixelFormat, &pfd))
680
CV_ERROR( CV_OpenGlApiCallError, "Can't Set The PixelFormat" );
681
682
hGLRC = wglCreateContext(hGLDC);
683
if (!hGLRC)
684
CV_ERROR( CV_OpenGlApiCallError, "Can't Create A GL Rendering Context" );
685
686
if (!wglMakeCurrent(hGLDC, hGLRC))
687
CV_ERROR( CV_OpenGlApiCallError, "Can't Activate The GL Rendering Context" );
688
689
useGl = true;
690
691
__END__;
692
}
693
694
void releaseGlContext(CvWindow* window)
695
{
696
//CV_FUNCNAME( "releaseGlContext" );
697
698
__BEGIN__;
699
700
if (window->hGLRC)
701
{
702
wglDeleteContext(window->hGLRC);
703
window->hGLRC = NULL;
704
}
705
706
if (window->dc)
707
{
708
ReleaseDC(window->hwnd, window->dc);
709
window->dc = NULL;
710
}
711
712
window->useGl = false;
713
714
__END__;
715
}
716
717
void drawGl(CvWindow* window)
718
{
719
CV_FUNCNAME( "drawGl" );
720
721
__BEGIN__;
722
723
if (!wglMakeCurrent(window->dc, window->hGLRC))
724
CV_ERROR( CV_OpenGlApiCallError, "Can't Activate The GL Rendering Context" );
725
726
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
727
728
if (window->glDrawCallback)
729
window->glDrawCallback(window->glDrawData);
730
731
if (!SwapBuffers(window->dc))
732
CV_ERROR( CV_OpenGlApiCallError, "Can't swap OpenGL buffers" );
733
734
__END__;
735
}
736
737
void resizeGl(CvWindow* window)
738
{
739
CV_FUNCNAME( "resizeGl" );
740
741
__BEGIN__;
742
743
if (!wglMakeCurrent(window->dc, window->hGLRC))
744
CV_ERROR( CV_OpenGlApiCallError, "Can't Activate The GL Rendering Context" );
745
746
glViewport(0, 0, window->width, window->height);
747
748
__END__;
749
}
750
}
751
752
#endif // HAVE_OPENGL
753
754
755
CV_IMPL int cvNamedWindow( const char* name, int flags )
756
{
757
int result = 0;
758
CV_FUNCNAME( "cvNamedWindow" );
759
760
__BEGIN__;
761
762
HWND hWnd, mainhWnd;
763
CvWindow* window;
764
DWORD defStyle = WS_VISIBLE | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU;
765
int len;
766
CvRect rect;
767
#ifdef HAVE_OPENGL
768
bool useGl;
769
HDC hGLDC;
770
HGLRC hGLRC;
771
#endif
772
773
cvInitSystem(0,0);
774
775
if( !name )
776
CV_ERROR( CV_StsNullPtr, "NULL name string" );
777
778
// Check the name in the storage
779
window = icvFindWindowByName( name );
780
if (window != 0)
781
{
782
result = 1;
783
EXIT;
784
}
785
786
if( !(flags & CV_WINDOW_AUTOSIZE))//YV add border in order to resize the window
787
defStyle |= WS_SIZEBOX;
788
789
#ifdef HAVE_OPENGL
790
if (flags & CV_WINDOW_OPENGL)
791
defStyle |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
792
#endif
793
794
icvLoadWindowPos( name, rect );
795
796
mainhWnd = CreateWindow( "Main HighGUI class", name, defStyle | WS_OVERLAPPED,
797
rect.x, rect.y, rect.width, rect.height, 0, 0, hg_hinstance, 0 );
798
if( !mainhWnd )
799
CV_ERROR( CV_StsError, "Frame window can not be created" );
800
801
ShowWindow(mainhWnd, SW_SHOW);
802
803
//YV- remove one border by changing the style
804
hWnd = CreateWindow("HighGUI class", "", (defStyle & ~WS_SIZEBOX) | WS_CHILD, CW_USEDEFAULT, 0, rect.width, rect.height, mainhWnd, 0, hg_hinstance, 0);
805
if( !hWnd )
806
CV_ERROR( CV_StsError, "Frame window can not be created" );
807
808
#ifndef HAVE_OPENGL
809
if (flags & CV_WINDOW_OPENGL)
810
CV_ERROR( CV_OpenGlNotSupported, "Library was built without OpenGL support" );
811
#else
812
useGl = false;
813
hGLDC = 0;
814
hGLRC = 0;
815
816
if (flags & CV_WINDOW_OPENGL)
817
createGlContext(hWnd, hGLDC, hGLRC, useGl);
818
#endif
819
820
ShowWindow(hWnd, SW_SHOW);
821
822
len = (int)strlen(name);
823
CV_CALL( window = (CvWindow*)cvAlloc(sizeof(CvWindow) + len + 1));
824
825
window->signature = CV_WINDOW_MAGIC_VAL;
826
window->hwnd = hWnd;
827
window->frame = mainhWnd;
828
window->name = (char*)(window + 1);
829
memcpy( window->name, name, len + 1 );
830
window->flags = flags;
831
window->image = 0;
832
833
#ifndef HAVE_OPENGL
834
window->dc = CreateCompatibleDC(0);
835
#else
836
if (!useGl)
837
{
838
window->dc = CreateCompatibleDC(0);
839
window->hGLRC = 0;
840
window->useGl = false;
841
}
842
else
843
{
844
window->dc = hGLDC;
845
window->hGLRC = hGLRC;
846
window->useGl = true;
847
}
848
849
window->glDrawCallback = 0;
850
window->glDrawData = 0;
851
#endif
852
853
window->last_key = 0;
854
window->status = CV_WINDOW_NORMAL;//YV
855
856
window->on_mouse = 0;
857
window->on_mouse_param = 0;
858
859
memset( &window->toolbar, 0, sizeof(window->toolbar));
860
861
window->next = hg_windows;
862
window->prev = 0;
863
if( hg_windows )
864
hg_windows->prev = window;
865
hg_windows = window;
866
icvSetWindowLongPtr( hWnd, CV_USERDATA, window );
867
icvSetWindowLongPtr( mainhWnd, CV_USERDATA, window );
868
869
// Recalculate window pos
870
icvUpdateWindowPos( window );
871
872
result = 1;
873
__END__;
874
875
return result;
876
}
877
878
#ifdef HAVE_OPENGL
879
880
CV_IMPL void cvSetOpenGlContext(const char* name)
881
{
882
CV_FUNCNAME( "cvSetOpenGlContext" );
883
884
__BEGIN__;
885
886
CvWindow* window;
887
888
if(!name)
889
CV_ERROR( CV_StsNullPtr, "NULL name string" );
890
891
window = icvFindWindowByName( name );
892
if (!window)
893
CV_ERROR( CV_StsNullPtr, "NULL window" );
894
895
if (!window->useGl)
896
CV_ERROR( CV_OpenGlNotSupported, "Window doesn't support OpenGL" );
897
898
if (!wglMakeCurrent(window->dc, window->hGLRC))
899
CV_ERROR( CV_OpenGlApiCallError, "Can't Activate The GL Rendering Context" );
900
901
__END__;
902
}
903
904
CV_IMPL void cvUpdateWindow(const char* name)
905
{
906
CV_FUNCNAME( "cvUpdateWindow" );
907
908
__BEGIN__;
909
910
CvWindow* window;
911
912
if (!name)
913
CV_ERROR( CV_StsNullPtr, "NULL name string" );
914
915
window = icvFindWindowByName( name );
916
if (!window)
917
EXIT;
918
919
InvalidateRect(window->hwnd, 0, 0);
920
921
__END__;
922
}
923
924
CV_IMPL void cvSetOpenGlDrawCallback(const char* name, CvOpenGlDrawCallback callback, void* userdata)
925
{
926
CV_FUNCNAME( "cvCreateOpenGLCallback" );
927
928
__BEGIN__;
929
930
CvWindow* window;
931
932
if(!name)
933
CV_ERROR( CV_StsNullPtr, "NULL name string" );
934
935
window = icvFindWindowByName( name );
936
if( !window )
937
EXIT;
938
939
if (!window->useGl)
940
CV_ERROR( CV_OpenGlNotSupported, "Window was created without OpenGL context" );
941
942
window->glDrawCallback = callback;
943
window->glDrawData = userdata;
944
945
__END__;
946
}
947
948
#endif // HAVE_OPENGL
949
950
static void icvRemoveWindow( CvWindow* window )
951
{
952
CvTrackbar* trackbar = NULL;
953
RECT wrect={0,0,0,0};
954
955
#ifdef HAVE_OPENGL
956
if (window->useGl)
957
releaseGlContext(window);
958
#endif
959
960
if( window->frame )
961
GetWindowRect( window->frame, &wrect );
962
if( window->name )
963
icvSaveWindowPos( window->name, cvRect(wrect.left, wrect.top,
964
wrect.right-wrect.left, wrect.bottom-wrect.top) );
965
966
if( window->hwnd )
967
icvSetWindowLongPtr( window->hwnd, CV_USERDATA, 0 );
968
if( window->frame )
969
icvSetWindowLongPtr( window->frame, CV_USERDATA, 0 );
970
971
if( window->toolbar.toolbar )
972
icvSetWindowLongPtr(window->toolbar.toolbar, CV_USERDATA, 0);
973
974
if( window->prev )
975
window->prev->next = window->next;
976
else
977
hg_windows = window->next;
978
979
if( window->next )
980
window->next->prev = window->prev;
981
982
window->prev = window->next = 0;
983
984
if( window->dc && window->image )
985
DeleteObject(SelectObject(window->dc,window->image));
986
987
if( window->dc )
988
DeleteDC(window->dc);
989
990
for( trackbar = window->toolbar.first; trackbar != 0; )
991
{
992
CvTrackbar* next = trackbar->next;
993
if( trackbar->hwnd )
994
{
995
icvSetWindowLongPtr( trackbar->hwnd, CV_USERDATA, 0 );
996
cvFree( &trackbar );
997
}
998
trackbar = next;
999
}
1000
1001
cvFree( &window );
1002
}
1003
1004
1005
CV_IMPL void cvDestroyWindow( const char* name )
1006
{
1007
CV_FUNCNAME( "cvDestroyWindow" );
1008
1009
__BEGIN__;
1010
1011
CvWindow* window;
1012
HWND mainhWnd;
1013
1014
if(!name)
1015
CV_ERROR( CV_StsNullPtr, "NULL name string" );
1016
1017
window = icvFindWindowByName( name );
1018
if( !window )
1019
EXIT;
1020
1021
mainhWnd = window->frame;
1022
1023
SendMessage(window->hwnd, WM_CLOSE, 0, 0);
1024
SendMessage( mainhWnd, WM_CLOSE, 0, 0);
1025
// Do NOT call _remove_window -- CvWindow list will be updated automatically ...
1026
1027
__END__;
1028
}
1029
1030
1031
static void icvScreenToClient( HWND hwnd, RECT* rect )
1032
{
1033
POINT p;
1034
p.x = rect->left;
1035
p.y = rect->top;
1036
ScreenToClient(hwnd, &p);
1037
OffsetRect( rect, p.x - rect->left, p.y - rect->top );
1038
}
1039
1040
1041
/* Calculatess the window coordinates relative to the upper left corner of the mainhWnd window */
1042
static RECT icvCalcWindowRect( CvWindow* window )
1043
{
1044
const int gutter = 1;
1045
RECT crect, trect, rect;
1046
1047
assert(window);
1048
1049
GetClientRect(window->frame, &crect);
1050
if(window->toolbar.toolbar)
1051
{
1052
GetWindowRect(window->toolbar.toolbar, &trect);
1053
icvScreenToClient(window->frame, &trect);
1054
SubtractRect( &rect, &crect, &trect);
1055
}
1056
else
1057
rect = crect;
1058
1059
rect.top += gutter;
1060
rect.left += gutter;
1061
rect.bottom -= gutter;
1062
rect.right -= gutter;
1063
1064
return rect;
1065
}
1066
1067
// returns TRUE if there is a problem such as ERROR_IO_PENDING.
1068
static bool icvGetBitmapData( CvWindow* window, SIZE* size, int* channels, void** data )
1069
{
1070
BITMAP bmp;
1071
GdiFlush();
1072
HGDIOBJ h = GetCurrentObject( window->dc, OBJ_BITMAP );
1073
if( size )
1074
size->cx = size->cy = 0;
1075
if( data )
1076
*data = 0;
1077
1078
if (h == NULL)
1079
return true;
1080
if (GetObject(h, sizeof(bmp), &bmp) == 0)
1081
return true;
1082
1083
if( size )
1084
{
1085
size->cx = abs(bmp.bmWidth);
1086
size->cy = abs(bmp.bmHeight);
1087
}
1088
1089
if( channels )
1090
*channels = bmp.bmBitsPixel/8;
1091
1092
if( data )
1093
*data = bmp.bmBits;
1094
1095
return false;
1096
}
1097
1098
1099
static void icvUpdateWindowPos( CvWindow* window )
1100
{
1101
RECT rect;
1102
assert(window);
1103
1104
if( (window->flags & CV_WINDOW_AUTOSIZE) && window->image )
1105
{
1106
int i;
1107
SIZE size = {0,0};
1108
icvGetBitmapData( window, &size, 0, 0 );
1109
1110
// Repeat two times because after the first resizing of the mainhWnd window
1111
// toolbar may resize too
1112
for(i = 0; i < (window->toolbar.toolbar ? 2 : 1); i++)
1113
{
1114
RECT rmw, rw = icvCalcWindowRect(window );
1115
MoveWindow(window->hwnd, rw.left, rw.top,
1116
rw.right - rw.left + 1, rw.bottom - rw.top + 1, FALSE);
1117
GetClientRect(window->hwnd, &rw);
1118
GetWindowRect(window->frame, &rmw);
1119
// Resize the mainhWnd window in order to make the bitmap fit into the child window
1120
MoveWindow(window->frame, rmw.left, rmw.top,
1121
rmw.right - rmw.left + size.cx - rw.right + rw.left,
1122
rmw.bottom - rmw.top + size.cy - rw.bottom + rw.top, TRUE );
1123
}
1124
}
1125
1126
rect = icvCalcWindowRect(window);
1127
MoveWindow(window->hwnd, rect.left, rect.top,
1128
rect.right - rect.left + 1,
1129
rect.bottom - rect.top + 1, TRUE );
1130
}
1131
1132
CV_IMPL void
1133
cvShowImage( const char* name, const CvArr* arr )
1134
{
1135
CV_FUNCNAME( "cvShowImage" );
1136
1137
__BEGIN__;
1138
1139
CvWindow* window;
1140
SIZE size = { 0, 0 };
1141
int channels = 0;
1142
void* dst_ptr = 0;
1143
const int channels0 = 3;
1144
int origin = 0;
1145
CvMat stub, dst, *image;
1146
bool changed_size = false; // philipg
1147
1148
if( !name )
1149
CV_ERROR( CV_StsNullPtr, "NULL name" );
1150
1151
window = icvFindWindowByName(name);
1152
if(!window)
1153
{
1154
cvNamedWindow(name, CV_WINDOW_AUTOSIZE);
1155
window = icvFindWindowByName(name);
1156
}
1157
1158
if( !window || !arr )
1159
EXIT; // keep silence here.
1160
1161
if( CV_IS_IMAGE_HDR( arr ))
1162
origin = ((IplImage*)arr)->origin;
1163
1164
CV_CALL( image = cvGetMat( arr, &stub ));
1165
1166
#ifdef HAVE_OPENGL
1167
if (window->useGl)
1168
{
1169
cv::imshow(name, cv::cvarrToMat(image));
1170
return;
1171
}
1172
#endif
1173
1174
if (window->image)
1175
// if there is something wrong with these system calls, we cannot display image...
1176
if (icvGetBitmapData( window, &size, &channels, &dst_ptr ))
1177
return;
1178
1179
if( size.cx != image->width || size.cy != image->height || channels != channels0 )
1180
{
1181
changed_size = true;
1182
1183
uchar buffer[sizeof(BITMAPINFO) + 255*sizeof(RGBQUAD)];
1184
BITMAPINFO* binfo = (BITMAPINFO*)buffer;
1185
1186
DeleteObject( SelectObject( window->dc, window->image ));
1187
window->image = 0;
1188
1189
size.cx = image->width;
1190
size.cy = image->height;
1191
channels = channels0;
1192
1193
FillBitmapInfo( binfo, size.cx, size.cy, channels*8, 1 );
1194
1195
window->image = SelectObject( window->dc, CreateDIBSection(window->dc, binfo,
1196
DIB_RGB_COLORS, &dst_ptr, 0, 0));
1197
}
1198
1199
cvInitMatHeader( &dst, size.cy, size.cx, CV_8UC3,
1200
dst_ptr, (size.cx * channels + 3) & -4 );
1201
cvConvertImage( image, &dst, origin == 0 ? CV_CVTIMG_FLIP : 0 );
1202
1203
// ony resize window if needed
1204
if (changed_size)
1205
icvUpdateWindowPos(window);
1206
InvalidateRect(window->hwnd, 0, 0);
1207
// philipg: this is not needed and just slows things down
1208
// UpdateWindow(window->hwnd);
1209
1210
__END__;
1211
}
1212
1213
#if 0
1214
CV_IMPL void
1215
cvShowImageHWND(HWND w_hWnd, const CvArr* arr)
1216
{
1217
CV_FUNCNAME( "cvShowImageHWND" );
1218
1219
__BEGIN__;
1220
1221
SIZE size = { 0, 0 };
1222
int channels = 0;
1223
void* dst_ptr = 0;
1224
const int channels0 = 3;
1225
int origin = 0;
1226
CvMat stub, dst, *image;
1227
bool changed_size = false;
1228
BITMAPINFO tempbinfo;
1229
HDC hdc = NULL;
1230
1231
if( !arr )
1232
EXIT;
1233
if( !w_hWnd )
1234
EXIT;
1235
1236
hdc = GetDC(w_hWnd);
1237
1238
if( CV_IS_IMAGE_HDR( arr ) )
1239
origin = ((IplImage*)arr)->origin;
1240
1241
CV_CALL( image = cvGetMat( arr, &stub ) );
1242
1243
if ( hdc )
1244
{
1245
//GetBitmapData
1246
BITMAP bmp;
1247
GdiFlush();
1248
HGDIOBJ h = GetCurrentObject( hdc, OBJ_BITMAP );
1249
1250
if (h == NULL)
1251
EXIT;
1252
if (GetObject(h, sizeof(bmp), &bmp) == 0) //GetObject(): returns size of object, 0 if error
1253
EXIT;
1254
1255
channels = bmp.bmBitsPixel/8;
1256
dst_ptr = bmp.bmBits;
1257
}
1258
1259
if( size.cx != image->width || size.cy != image->height || channels != channels0 )
1260
{
1261
changed_size = true;
1262
1263
uchar buffer[sizeof(BITMAPINFO) + 255*sizeof(RGBQUAD)];
1264
BITMAPINFO* binfo = (BITMAPINFO*)buffer;
1265
1266
BOOL bDeleteObj = DeleteObject(GetCurrentObject(hdc, OBJ_BITMAP));
1267
CV_Assert( FALSE != bDeleteObj );
1268
1269
size.cx = image->width;
1270
size.cy = image->height;
1271
channels = channels0;
1272
1273
FillBitmapInfo( binfo, size.cx, size.cy, channels*8, 1 );
1274
1275
SelectObject( hdc, CreateDIBSection( hdc, binfo, DIB_RGB_COLORS, &dst_ptr, 0, 0));
1276
}
1277
1278
cvInitMatHeader( &dst, size.cy, size.cx, CV_8UC3, dst_ptr, (size.cx * channels + 3) & -4 );
1279
cvConvertImage( image, &dst, origin == 0 ? CV_CVTIMG_FLIP : 0 );
1280
1281
// Image stretching to fit the window
1282
RECT rect;
1283
GetClientRect(w_hWnd, &rect);
1284
StretchDIBits( hdc, 0, 0, rect.right, rect.bottom, 0, 0, image->width, image->height, dst_ptr, &tempbinfo, DIB_RGB_COLORS, SRCCOPY );
1285
1286
// ony resize window if needed
1287
InvalidateRect(w_hWnd, 0, 0);
1288
1289
__END__;
1290
}
1291
#endif
1292
1293
CV_IMPL void cvResizeWindow(const char* name, int width, int height )
1294
{
1295
CV_FUNCNAME( "cvResizeWindow" );
1296
1297
__BEGIN__;
1298
1299
int i;
1300
CvWindow* window;
1301
RECT rmw, rw, rect;
1302
1303
if( !name )
1304
CV_ERROR( CV_StsNullPtr, "NULL name" );
1305
1306
window = icvFindWindowByName(name);
1307
if(!window)
1308
EXIT;
1309
1310
// Repeat two times because after the first resizing of the mainhWnd window
1311
// toolbar may resize too
1312
for(i = 0; i < (window->toolbar.toolbar ? 2 : 1); i++)
1313
{
1314
rw = icvCalcWindowRect(window);
1315
MoveWindow(window->hwnd, rw.left, rw.top,
1316
rw.right - rw.left + 1, rw.bottom - rw.top + 1, FALSE);
1317
GetClientRect(window->hwnd, &rw);
1318
GetWindowRect(window->frame, &rmw);
1319
// Resize the mainhWnd window in order to make the bitmap fit into the child window
1320
MoveWindow(window->frame, rmw.left, rmw.top,
1321
rmw.right - rmw.left + width - rw.right + rw.left,
1322
rmw.bottom - rmw.top + height - rw.bottom + rw.top, TRUE);
1323
}
1324
1325
rect = icvCalcWindowRect(window);
1326
MoveWindow(window->hwnd, rect.left, rect.top,
1327
rect.right - rect.left + 1, rect.bottom - rect.top + 1, TRUE);
1328
1329
__END__;
1330
}
1331
1332
1333
CV_IMPL void cvMoveWindow( const char* name, int x, int y )
1334
{
1335
CV_FUNCNAME( "cvMoveWindow" );
1336
1337
__BEGIN__;
1338
1339
CvWindow* window;
1340
RECT rect;
1341
1342
if( !name )
1343
CV_ERROR( CV_StsNullPtr, "NULL name" );
1344
1345
window = icvFindWindowByName(name);
1346
if(!window)
1347
EXIT;
1348
1349
GetWindowRect( window->frame, &rect );
1350
MoveWindow( window->frame, x, y, rect.right - rect.left, rect.bottom - rect.top, TRUE);
1351
1352
__END__;
1353
}
1354
1355
1356
static LRESULT CALLBACK
1357
MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
1358
{
1359
CvWindow* window = icvWindowByHWND( hwnd );
1360
if( !window )
1361
return DefWindowProc(hwnd, uMsg, wParam, lParam);
1362
1363
switch(uMsg)
1364
{
1365
case WM_COPY:
1366
::SendMessage(window->hwnd, uMsg, wParam, lParam);
1367
break;
1368
1369
case WM_DESTROY:
1370
1371
icvRemoveWindow(window);
1372
// Do nothing!!!
1373
//PostQuitMessage(0);
1374
break;
1375
1376
case WM_GETMINMAXINFO:
1377
if( !(window->flags & CV_WINDOW_AUTOSIZE) )
1378
{
1379
MINMAXINFO* minmax = (MINMAXINFO*)lParam;
1380
RECT rect;
1381
LRESULT retval = DefWindowProc(hwnd, uMsg, wParam, lParam);
1382
1383
minmax->ptMinTrackSize.y = 100;
1384
minmax->ptMinTrackSize.x = 100;
1385
1386
if( window->toolbar.first )
1387
{
1388
GetWindowRect( window->toolbar.first->hwnd, &rect );
1389
minmax->ptMinTrackSize.y += window->toolbar.rows*(rect.bottom - rect.top);
1390
minmax->ptMinTrackSize.x = MAX(rect.right - rect.left + HG_BUDDY_WIDTH, HG_BUDDY_WIDTH*2);
1391
}
1392
return retval;
1393
}
1394
break;
1395
1396
case WM_WINDOWPOSCHANGED:
1397
{
1398
WINDOWPOS* pos = (WINDOWPOS*)lParam;
1399
1400
// Update the toolbar pos/size
1401
if(window->toolbar.toolbar)
1402
{
1403
RECT rect;
1404
GetWindowRect(window->toolbar.toolbar, &rect);
1405
MoveWindow(window->toolbar.toolbar, 0, 0, pos->cx, rect.bottom - rect.top, TRUE);
1406
}
1407
1408
if(!(window->flags & CV_WINDOW_AUTOSIZE))
1409
icvUpdateWindowPos(window);
1410
1411
break;
1412
}
1413
1414
case WM_WINDOWPOSCHANGING:
1415
{
1416
// Snap window to screen edges with multi-monitor support. // Adi Shavit
1417
LPWINDOWPOS pos = (LPWINDOWPOS)lParam;
1418
1419
RECT rect;
1420
GetWindowRect(window->frame, &rect);
1421
1422
HMONITOR hMonitor;
1423
hMonitor = MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST);
1424
1425
MONITORINFO mi;
1426
mi.cbSize = sizeof(mi);
1427
GetMonitorInfo(hMonitor, &mi);
1428
1429
const int SNAP_DISTANCE = 15;
1430
1431
if (abs(pos->x - mi.rcMonitor.left) <= SNAP_DISTANCE)
1432
pos->x = mi.rcMonitor.left; // snap to left edge
1433
else
1434
if (abs(pos->x + pos->cx - mi.rcMonitor.right) <= SNAP_DISTANCE)
1435
pos->x = mi.rcMonitor.right - pos->cx; // snap to right edge
1436
1437
if (abs(pos->y - mi.rcMonitor.top) <= SNAP_DISTANCE)
1438
pos->y = mi.rcMonitor.top; // snap to top edge
1439
else
1440
if (abs(pos->y + pos->cy - mi.rcMonitor.bottom) <= SNAP_DISTANCE)
1441
pos->y = mi.rcMonitor.bottom - pos->cy; // snap to bottom edge
1442
}
1443
1444
case WM_ACTIVATE:
1445
if(LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE)
1446
SetFocus(window->hwnd);
1447
break;
1448
1449
case WM_MOUSEWHEEL:
1450
case WM_MOUSEHWHEEL:
1451
if( window->on_mouse )
1452
{
1453
int flags = (wParam & MK_LBUTTON ? CV_EVENT_FLAG_LBUTTON : 0)|
1454
(wParam & MK_RBUTTON ? CV_EVENT_FLAG_RBUTTON : 0)|
1455
(wParam & MK_MBUTTON ? CV_EVENT_FLAG_MBUTTON : 0)|
1456
(wParam & MK_CONTROL ? CV_EVENT_FLAG_CTRLKEY : 0)|
1457
(wParam & MK_SHIFT ? CV_EVENT_FLAG_SHIFTKEY : 0)|
1458
(GetKeyState(VK_MENU) < 0 ? CV_EVENT_FLAG_ALTKEY : 0);
1459
int event = (uMsg == WM_MOUSEWHEEL ? CV_EVENT_MOUSEWHEEL : CV_EVENT_MOUSEHWHEEL);
1460
1461
// Set the wheel delta of mouse wheel to be in the upper word of 'event'
1462
int delta = GET_WHEEL_DELTA_WPARAM(wParam);
1463
flags |= (delta << 16);
1464
1465
POINT pt;
1466
pt.x = GET_X_LPARAM( lParam );
1467
pt.y = GET_Y_LPARAM( lParam );
1468
::ScreenToClient(hwnd, &pt); // Convert screen coordinates to client coordinates.
1469
1470
RECT rect;
1471
GetClientRect( window->hwnd, &rect );
1472
1473
SIZE size = {0,0};
1474
icvGetBitmapData( window, &size, 0, 0 );
1475
1476
window->on_mouse( event, pt.x*size.cx/MAX(rect.right - rect.left,1),
1477
pt.y*size.cy/MAX(rect.bottom - rect.top,1), flags,
1478
window->on_mouse_param );
1479
}
1480
break;
1481
1482
case WM_ERASEBKGND:
1483
{
1484
RECT cr, tr, wrc;
1485
HRGN rgn, rgn1, rgn2;
1486
int ret;
1487
HDC hdc = (HDC)wParam;
1488
GetWindowRect(window->hwnd, &cr);
1489
icvScreenToClient(window->frame, &cr);
1490
if(window->toolbar.toolbar)
1491
{
1492
GetWindowRect(window->toolbar.toolbar, &tr);
1493
icvScreenToClient(window->frame, &tr);
1494
}
1495
else
1496
tr.left = tr.top = tr.right = tr.bottom = 0;
1497
1498
GetClientRect(window->frame, &wrc);
1499
1500
rgn = CreateRectRgn(0, 0, wrc.right, wrc.bottom);
1501
rgn1 = CreateRectRgn(cr.left, cr.top, cr.right, cr.bottom);
1502
rgn2 = CreateRectRgn(tr.left, tr.top, tr.right, tr.bottom);
1503
CV_Assert_N(rgn != 0, rgn1 != 0, rgn2 != 0);
1504
1505
ret = CombineRgn(rgn, rgn, rgn1, RGN_DIFF);
1506
ret = CombineRgn(rgn, rgn, rgn2, RGN_DIFF);
1507
1508
if(ret != NULLREGION && ret != ERROR)
1509
FillRgn(hdc, rgn, (HBRUSH)icvGetClassLongPtr(hwnd, CV_HBRBACKGROUND));
1510
1511
DeleteObject(rgn);
1512
DeleteObject(rgn1);
1513
DeleteObject(rgn2);
1514
}
1515
return 1;
1516
}
1517
1518
return DefWindowProc(hwnd, uMsg, wParam, lParam);
1519
}
1520
1521
1522
static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
1523
{
1524
CvWindow* window = icvWindowByHWND(hwnd);
1525
if( !window )
1526
// This window is not mentioned in HighGUI storage
1527
// Actually, this should be error except for the case of calls to CreateWindow
1528
return DefWindowProc(hwnd, uMsg, wParam, lParam);
1529
1530
// Process the message
1531
switch(uMsg)
1532
{
1533
case WM_COPY:
1534
{
1535
if (!::OpenClipboard(hwnd) )
1536
break;
1537
1538
HDC hDC = 0;
1539
HDC memDC = 0;
1540
HBITMAP memBM = 0;
1541
1542
// We'll use a do-while(0){} scope as a single-run breakable scope
1543
// Upon any error we can jump out of the single-time while scope to clean up the resources.
1544
do
1545
{
1546
if (!::EmptyClipboard())
1547
break;
1548
1549
if(!window->image)
1550
break;
1551
1552
// Get window device context
1553
if (0 == (hDC = ::GetDC(hwnd)))
1554
break;
1555
1556
// Create another DC compatible with hDC
1557
if (0 == (memDC = ::CreateCompatibleDC( hDC )))
1558
break;
1559
1560
// Determine the bitmap's dimensions
1561
int nchannels = 3;
1562
SIZE size = {0,0};
1563
icvGetBitmapData( window, &size, &nchannels, 0 );
1564
1565
// Create bitmap to draw on and it in the new DC
1566
if (0 == (memBM = ::CreateCompatibleBitmap ( hDC, size.cx, size.cy)))
1567
break;
1568
1569
if (!::SelectObject( memDC, memBM ))
1570
break;
1571
1572
// Begin drawing to DC
1573
if (!::SetStretchBltMode(memDC, COLORONCOLOR))
1574
break;
1575
1576
RGBQUAD table[256];
1577
if( 1 == nchannels )
1578
{
1579
for(int i = 0; i < 256; ++i)
1580
{
1581
table[i].rgbBlue = (unsigned char)i;
1582
table[i].rgbGreen = (unsigned char)i;
1583
table[i].rgbRed = (unsigned char)i;
1584
}
1585
if (!::SetDIBColorTable(window->dc, 0, 255, table))
1586
break;
1587
}
1588
1589
// The image copied to the clipboard will be in its original size, regardless if the window itself was resized.
1590
1591
// Render the image to the dc/bitmap (at original size).
1592
if (!::BitBlt( memDC, 0, 0, size.cx, size.cy, window->dc, 0, 0, SRCCOPY ))
1593
break;
1594
1595
// Finally, set bitmap to clipboard
1596
::SetClipboardData(CF_BITMAP, memBM);
1597
} while (0,0); // (0,0) instead of (0) to avoid MSVC compiler warning C4127: "conditional expression is constant"
1598
1599
//////////////////////////////////////////////////////////////////////////
1600
// if handle is allocated (i.e. != 0) then clean-up.
1601
if (memBM) ::DeleteObject(memBM);
1602
if (memDC) ::DeleteDC(memDC);
1603
if (hDC) ::ReleaseDC(hwnd, hDC);
1604
::CloseClipboard();
1605
break;
1606
}
1607
1608
case WM_WINDOWPOSCHANGING:
1609
{
1610
LPWINDOWPOS pos = (LPWINDOWPOS)lParam;
1611
RECT rect = icvCalcWindowRect(window);
1612
pos->x = rect.left;
1613
pos->y = rect.top;
1614
pos->cx = rect.right - rect.left + 1;
1615
pos->cy = rect.bottom - rect.top + 1;
1616
}
1617
break;
1618
1619
case WM_LBUTTONDOWN:
1620
case WM_RBUTTONDOWN:
1621
case WM_MBUTTONDOWN:
1622
case WM_LBUTTONDBLCLK:
1623
case WM_RBUTTONDBLCLK:
1624
case WM_MBUTTONDBLCLK:
1625
case WM_LBUTTONUP:
1626
case WM_RBUTTONUP:
1627
case WM_MBUTTONUP:
1628
case WM_MOUSEMOVE:
1629
if( window->on_mouse )
1630
{
1631
POINT pt;
1632
1633
int flags = (wParam & MK_LBUTTON ? CV_EVENT_FLAG_LBUTTON : 0)|
1634
(wParam & MK_RBUTTON ? CV_EVENT_FLAG_RBUTTON : 0)|
1635
(wParam & MK_MBUTTON ? CV_EVENT_FLAG_MBUTTON : 0)|
1636
(wParam & MK_CONTROL ? CV_EVENT_FLAG_CTRLKEY : 0)|
1637
(wParam & MK_SHIFT ? CV_EVENT_FLAG_SHIFTKEY : 0)|
1638
(GetKeyState(VK_MENU) < 0 ? CV_EVENT_FLAG_ALTKEY : 0);
1639
int event = uMsg == WM_LBUTTONDOWN ? CV_EVENT_LBUTTONDOWN :
1640
uMsg == WM_RBUTTONDOWN ? CV_EVENT_RBUTTONDOWN :
1641
uMsg == WM_MBUTTONDOWN ? CV_EVENT_MBUTTONDOWN :
1642
uMsg == WM_LBUTTONUP ? CV_EVENT_LBUTTONUP :
1643
uMsg == WM_RBUTTONUP ? CV_EVENT_RBUTTONUP :
1644
uMsg == WM_MBUTTONUP ? CV_EVENT_MBUTTONUP :
1645
uMsg == WM_LBUTTONDBLCLK ? CV_EVENT_LBUTTONDBLCLK :
1646
uMsg == WM_RBUTTONDBLCLK ? CV_EVENT_RBUTTONDBLCLK :
1647
uMsg == WM_MBUTTONDBLCLK ? CV_EVENT_MBUTTONDBLCLK :
1648
CV_EVENT_MOUSEMOVE;
1649
if( uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN || uMsg == WM_MBUTTONDOWN )
1650
SetCapture( hwnd );
1651
if( uMsg == WM_LBUTTONUP || uMsg == WM_RBUTTONUP || uMsg == WM_MBUTTONUP )
1652
ReleaseCapture();
1653
1654
pt.x = GET_X_LPARAM( lParam );
1655
pt.y = GET_Y_LPARAM( lParam );
1656
1657
if (window->flags & CV_WINDOW_AUTOSIZE)
1658
{
1659
// As user can't change window size, do not scale window coordinates. Underlying windowing system
1660
// may prevent full window from being displayed and in this case coordinates should not be scaled.
1661
window->on_mouse( event, pt.x, pt.y, flags, window->on_mouse_param );
1662
} else {
1663
// Full window is displayed using different size. Scale coordinates to match underlying positions.
1664
RECT rect;
1665
SIZE size = {0, 0};
1666
1667
GetClientRect( window->hwnd, &rect );
1668
icvGetBitmapData( window, &size, 0, 0 );
1669
1670
window->on_mouse( event, pt.x*size.cx/MAX(rect.right - rect.left,1),
1671
pt.y*size.cy/MAX(rect.bottom - rect.top,1), flags,
1672
window->on_mouse_param );
1673
}
1674
}
1675
break;
1676
1677
case WM_PAINT:
1678
if(window->image != 0)
1679
{
1680
int nchannels = 3;
1681
SIZE size = {0,0};
1682
PAINTSTRUCT paint;
1683
HDC hdc;
1684
RGBQUAD table[256];
1685
1686
// Determine the bitmap's dimensions
1687
icvGetBitmapData( window, &size, &nchannels, 0 );
1688
1689
hdc = BeginPaint(hwnd, &paint);
1690
SetStretchBltMode(hdc, COLORONCOLOR);
1691
1692
if( nchannels == 1 )
1693
{
1694
int i;
1695
for(i = 0; i < 256; i++)
1696
{
1697
table[i].rgbBlue = (unsigned char)i;
1698
table[i].rgbGreen = (unsigned char)i;
1699
table[i].rgbRed = (unsigned char)i;
1700
}
1701
SetDIBColorTable(window->dc, 0, 255, table);
1702
}
1703
1704
if(window->flags & CV_WINDOW_AUTOSIZE)
1705
{
1706
BitBlt( hdc, 0, 0, size.cx, size.cy, window->dc, 0, 0, SRCCOPY );
1707
}
1708
else
1709
{
1710
RECT rect;
1711
GetClientRect(window->hwnd, &rect);
1712
StretchBlt( hdc, 0, 0, rect.right - rect.left, rect.bottom - rect.top,
1713
window->dc, 0, 0, size.cx, size.cy, SRCCOPY );
1714
}
1715
//DeleteDC(hdc);
1716
EndPaint(hwnd, &paint);
1717
}
1718
#ifdef HAVE_OPENGL
1719
else if(window->useGl)
1720
{
1721
drawGl(window);
1722
return DefWindowProc(hwnd, uMsg, wParam, lParam);
1723
}
1724
#endif
1725
else
1726
{
1727
return DefWindowProc(hwnd, uMsg, wParam, lParam);
1728
}
1729
return 0;
1730
1731
case WM_ERASEBKGND:
1732
if(window->image)
1733
return 0;
1734
break;
1735
1736
case WM_DESTROY:
1737
1738
icvRemoveWindow(window);
1739
// Do nothing!!!
1740
//PostQuitMessage(0);
1741
break;
1742
1743
case WM_SETCURSOR:
1744
SetCursor((HCURSOR)icvGetClassLongPtr(hwnd, CV_HCURSOR));
1745
return 0;
1746
1747
case WM_KEYDOWN:
1748
window->last_key = (int)wParam;
1749
return 0;
1750
1751
case WM_SIZE:
1752
window->width = LOWORD(lParam);
1753
window->height = HIWORD(lParam);
1754
1755
#ifdef HAVE_OPENGL
1756
if (window->useGl)
1757
resizeGl(window);
1758
#endif
1759
}
1760
1761
return DefWindowProc(hwnd, uMsg, wParam, lParam);
1762
}
1763
1764
1765
static LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
1766
{
1767
LRESULT ret;
1768
1769
if( hg_on_preprocess )
1770
{
1771
int was_processed = 0;
1772
int rethg = hg_on_preprocess(hwnd, uMsg, wParam, lParam, &was_processed);
1773
if( was_processed )
1774
return rethg;
1775
}
1776
ret = HighGUIProc(hwnd, uMsg, wParam, lParam);
1777
1778
if(hg_on_postprocess)
1779
{
1780
int was_processed = 0;
1781
int rethg = hg_on_postprocess(hwnd, uMsg, wParam, lParam, &was_processed);
1782
if( was_processed )
1783
return rethg;
1784
}
1785
1786
return ret;
1787
}
1788
1789
1790
static void icvUpdateTrackbar( CvTrackbar* trackbar, int pos )
1791
{
1792
const int max_name_len = 10;
1793
const char* suffix = "";
1794
char pos_text[32];
1795
int name_len;
1796
1797
if( trackbar->data )
1798
*trackbar->data = pos;
1799
1800
if( trackbar->pos != pos )
1801
{
1802
trackbar->pos = pos;
1803
if( trackbar->notify2 )
1804
trackbar->notify2(pos, trackbar->userdata);
1805
if( trackbar->notify )
1806
trackbar->notify(pos);
1807
1808
name_len = (int)strlen(trackbar->name);
1809
1810
if( name_len > max_name_len )
1811
{
1812
int start_len = max_name_len*2/3;
1813
int end_len = max_name_len - start_len - 2;
1814
memcpy( pos_text, trackbar->name, start_len );
1815
memcpy( pos_text + start_len, "...", 3 );
1816
memcpy( pos_text + start_len + 3, trackbar->name + name_len - end_len, end_len + 1 );
1817
}
1818
else
1819
{
1820
memcpy( pos_text, trackbar->name, name_len + 1);
1821
}
1822
1823
sprintf( pos_text + strlen(pos_text), "%s: %d\n", suffix, pos );
1824
SetWindowText( trackbar->buddy, pos_text );
1825
}
1826
}
1827
1828
1829
static LRESULT CALLBACK HGToolbarProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
1830
{
1831
CvWindow* window = icvWindowByHWND( hwnd );
1832
if(!window)
1833
return DefWindowProc(hwnd, uMsg, wParam, lParam);
1834
1835
// Control messages processing
1836
switch(uMsg)
1837
{
1838
// Slider processing
1839
case WM_HSCROLL:
1840
{
1841
HWND slider = (HWND)lParam;
1842
int pos = (int)SendMessage(slider, TBM_GETPOS, 0, 0);
1843
CvTrackbar* trackbar = icvTrackbarByHWND( slider );
1844
1845
if( trackbar )
1846
{
1847
if( trackbar->pos != pos )
1848
icvUpdateTrackbar( trackbar, pos );
1849
}
1850
1851
SetFocus( window->hwnd );
1852
return 0;
1853
}
1854
1855
case WM_NCCALCSIZE:
1856
{
1857
LRESULT ret = CallWindowProc(window->toolbar.toolBarProc, hwnd, uMsg, wParam, lParam);
1858
int rows = (int)SendMessage(hwnd, TB_GETROWS, 0, 0);
1859
1860
if(window->toolbar.rows != rows)
1861
{
1862
SendMessage(window->toolbar.toolbar, TB_BUTTONCOUNT, 0, 0);
1863
CvTrackbar* trackbar = window->toolbar.first;
1864
1865
for( ; trackbar != 0; trackbar = trackbar->next )
1866
{
1867
RECT rect;
1868
SendMessage(window->toolbar.toolbar, TB_GETITEMRECT,
1869
(WPARAM)trackbar->id, (LPARAM)&rect);
1870
MoveWindow(trackbar->hwnd, rect.left + HG_BUDDY_WIDTH, rect.top,
1871
rect.right - rect.left - HG_BUDDY_WIDTH,
1872
rect.bottom - rect.top, FALSE);
1873
MoveWindow(trackbar->buddy, rect.left, rect.top,
1874
HG_BUDDY_WIDTH, rect.bottom - rect.top, FALSE);
1875
}
1876
window->toolbar.rows = rows;
1877
}
1878
return ret;
1879
}
1880
}
1881
1882
return CallWindowProc(window->toolbar.toolBarProc, hwnd, uMsg, wParam, lParam);
1883
}
1884
1885
1886
CV_IMPL void
1887
cvDestroyAllWindows(void)
1888
{
1889
CvWindow* window = hg_windows;
1890
1891
while( window )
1892
{
1893
HWND mainhWnd = window->frame;
1894
HWND hwnd = window->hwnd;
1895
window = window->next;
1896
1897
SendMessage( hwnd, WM_CLOSE, 0, 0 );
1898
SendMessage( mainhWnd, WM_CLOSE, 0, 0 );
1899
}
1900
}
1901
1902
static void showSaveDialog(CvWindow* window)
1903
{
1904
if (!window || !window->image)
1905
return;
1906
1907
SIZE sz;
1908
int channels;
1909
void* data;
1910
if (icvGetBitmapData(window, &sz, &channels, &data))
1911
return; // nothing to save
1912
1913
char szFileName[MAX_PATH] = "";
1914
// try to use window title as file name
1915
GetWindowText(window->frame, szFileName, MAX_PATH);
1916
1917
OPENFILENAME ofn;
1918
ZeroMemory(&ofn, sizeof(ofn));
1919
#ifdef OPENFILENAME_SIZE_VERSION_400
1920
// we are not going to use new fields any way
1921
ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1922
#else
1923
ofn.lStructSize = sizeof(ofn);
1924
#endif
1925
ofn.hwndOwner = window->hwnd;
1926
ofn.lpstrFilter =
1927
#ifdef HAVE_PNG
1928
"Portable Network Graphics files (*.png)\0*.png\0"
1929
#endif
1930
"Windows bitmap (*.bmp;*.dib)\0*.bmp;*.dib\0"
1931
#ifdef HAVE_JPEG
1932
"JPEG files (*.jpeg;*.jpg;*.jpe)\0*.jpeg;*.jpg;*.jpe\0"
1933
#endif
1934
#ifdef HAVE_TIFF
1935
"TIFF Files (*.tiff;*.tif)\0*.tiff;*.tif\0"
1936
#endif
1937
#ifdef HAVE_JASPER
1938
"JPEG-2000 files (*.jp2)\0*.jp2\0"
1939
#endif
1940
#ifdef HAVE_WEBP
1941
"WebP files (*.webp)\0*.webp\0"
1942
#endif
1943
"Portable image format (*.pbm;*.pgm;*.ppm;*.pxm;*.pnm)\0*.pbm;*.pgm;*.ppm;*.pxm;*.pnm\0"
1944
#ifdef HAVE_OPENEXR
1945
"OpenEXR Image files (*.exr)\0*.exr\0"
1946
#endif
1947
"Radiance HDR (*.hdr;*.pic)\0*.hdr;*.pic\0"
1948
"Sun raster files (*.sr;*.ras)\0*.sr;*.ras\0"
1949
"All Files (*.*)\0*.*\0";
1950
ofn.lpstrFile = szFileName;
1951
ofn.nMaxFile = MAX_PATH;
1952
ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_NOREADONLYRETURN | OFN_NOCHANGEDIR;
1953
#ifdef HAVE_PNG
1954
ofn.lpstrDefExt = "png";
1955
#else
1956
ofn.lpstrDefExt = "bmp";
1957
#endif
1958
1959
if (GetSaveFileName(&ofn))
1960
{
1961
cv::Mat tmp;
1962
cv::flip(cv::Mat(sz.cy, sz.cx, CV_8UC(channels), data, (sz.cx * channels + 3) & -4), tmp, 0);
1963
cv::imwrite(szFileName, tmp);
1964
}
1965
}
1966
1967
CV_IMPL int
1968
cvWaitKey( int delay )
1969
{
1970
int64 time0 = cv::getTickCount();
1971
int64 timeEnd = time0 + (int64)(delay * 0.001f * cv::getTickFrequency());
1972
1973
for(;;)
1974
{
1975
CvWindow* window;
1976
MSG message;
1977
int is_processed = 0;
1978
1979
if( delay <= 0 )
1980
GetMessage(&message, 0, 0, 0);
1981
else if( PeekMessage(&message, 0, 0, 0, PM_REMOVE) == FALSE )
1982
{
1983
int64 t = cv::getTickCount();
1984
if (t - timeEnd >= 0)
1985
return -1; // no messages and no more time
1986
Sleep(1);
1987
continue;
1988
}
1989
1990
for( window = hg_windows; window != 0 && is_processed == 0; window = window->next )
1991
{
1992
if( window->hwnd == message.hwnd || window->frame == message.hwnd )
1993
{
1994
is_processed = 1;
1995
switch(message.message)
1996
{
1997
case WM_DESTROY:
1998
case WM_CHAR:
1999
DispatchMessage(&message);
2000
return (int)message.wParam;
2001
2002
case WM_SYSKEYDOWN:
2003
if( message.wParam == VK_F10 )
2004
{
2005
is_processed = 1;
2006
return (int)(message.wParam << 16);
2007
}
2008
break;
2009
2010
case WM_KEYDOWN:
2011
TranslateMessage(&message);
2012
if( (message.wParam >= VK_F1 && message.wParam <= VK_F24) ||
2013
message.wParam == VK_HOME || message.wParam == VK_END ||
2014
message.wParam == VK_UP || message.wParam == VK_DOWN ||
2015
message.wParam == VK_LEFT || message.wParam == VK_RIGHT ||
2016
message.wParam == VK_INSERT || message.wParam == VK_DELETE ||
2017
message.wParam == VK_PRIOR || message.wParam == VK_NEXT )
2018
{
2019
DispatchMessage(&message);
2020
is_processed = 1;
2021
return (int)(message.wParam << 16);
2022
}
2023
2024
// Intercept Ctrl+C for copy to clipboard
2025
if ('C' == message.wParam && (::GetKeyState(VK_CONTROL)>>15))
2026
::SendMessage(message.hwnd, WM_COPY, 0, 0);
2027
2028
// Intercept Ctrl+S for "save as" dialog
2029
if ('S' == message.wParam && (::GetKeyState(VK_CONTROL)>>15))
2030
showSaveDialog(window);
2031
2032
default:
2033
DispatchMessage(&message);
2034
is_processed = 1;
2035
break;
2036
}
2037
}
2038
}
2039
2040
if( !is_processed )
2041
{
2042
TranslateMessage(&message);
2043
DispatchMessage(&message);
2044
}
2045
}
2046
}
2047
2048
2049
static CvTrackbar*
2050
icvFindTrackbarByName( const CvWindow* window, const char* name )
2051
{
2052
CvTrackbar* trackbar = window->toolbar.first;
2053
2054
for( ; trackbar != 0 && strcmp( trackbar->name, name ) != 0; trackbar = trackbar->next )
2055
;
2056
2057
return trackbar;
2058
}
2059
2060
2061
static int
2062
icvCreateTrackbar( const char* trackbar_name, const char* window_name,
2063
int* val, int count, CvTrackbarCallback on_notify,
2064
CvTrackbarCallback2 on_notify2, void* userdata )
2065
{
2066
int result = 0;
2067
2068
CV_FUNCNAME( "icvCreateTrackbar" );
2069
2070
__BEGIN__;
2071
2072
char slider_name[32];
2073
CvWindow* window = 0;
2074
CvTrackbar* trackbar = 0;
2075
int pos = 0;
2076
2077
if( !window_name || !trackbar_name )
2078
CV_ERROR( CV_StsNullPtr, "NULL window or trackbar name" );
2079
2080
if( count < 0 )
2081
CV_ERROR( CV_StsOutOfRange, "Bad trackbar maximal value" );
2082
2083
window = icvFindWindowByName(window_name);
2084
if( !window )
2085
EXIT;
2086
2087
trackbar = icvFindTrackbarByName(window,trackbar_name);
2088
if( !trackbar )
2089
{
2090
TBBUTTON tbs = {};
2091
TBBUTTONINFO tbis = {};
2092
RECT rect;
2093
int bcount;
2094
int len = (int)strlen( trackbar_name );
2095
2096
// create toolbar if it is not created yet
2097
if( !window->toolbar.toolbar )
2098
{
2099
const int default_height = 30;
2100
2101
// CreateToolbarEx is deprecated and forces linking against Comctl32.lib.
2102
window->toolbar.toolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
2103
WS_CHILD | CCS_TOP | TBSTYLE_WRAPABLE | BTNS_AUTOSIZE | BTNS_BUTTON,
2104
0, 0, 0, 0,
2105
window->frame, NULL, GetModuleHandle(NULL), NULL);
2106
// CreateToolbarEx automatically sends this but CreateWindowEx doesn't.
2107
SendMessage(window->toolbar.toolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
2108
2109
GetClientRect(window->frame, &rect);
2110
MoveWindow( window->toolbar.toolbar, 0, 0,
2111
rect.right - rect.left, default_height, TRUE);
2112
SendMessage(window->toolbar.toolbar, TB_AUTOSIZE, 0, 0);
2113
ShowWindow(window->toolbar.toolbar, SW_SHOW);
2114
2115
window->toolbar.first = 0;
2116
window->toolbar.pos = 0;
2117
window->toolbar.rows = 0;
2118
window->toolbar.toolBarProc =
2119
(WNDPROC)icvGetWindowLongPtr(window->toolbar.toolbar, CV_WNDPROC);
2120
2121
icvUpdateWindowPos(window);
2122
2123
// Subclassing from toolbar
2124
icvSetWindowLongPtr(window->toolbar.toolbar, CV_WNDPROC, HGToolbarProc);
2125
icvSetWindowLongPtr(window->toolbar.toolbar, CV_USERDATA, window);
2126
}
2127
2128
/* Retrieve current buttons count */
2129
bcount = (int)SendMessage(window->toolbar.toolbar, TB_BUTTONCOUNT, 0, 0);
2130
2131
if(bcount > 1)
2132
{
2133
/* If this is not the first button then we need to
2134
separate it from the previous one */
2135
tbs.iBitmap = 0;
2136
tbs.idCommand = bcount; // Set button id to it's number
2137
tbs.iString = 0;
2138
tbs.fsStyle = TBSTYLE_SEP;
2139
tbs.fsState = TBSTATE_ENABLED;
2140
SendMessage(window->toolbar.toolbar, TB_ADDBUTTONS, 1, (LPARAM)&tbs);
2141
2142
// Retrieve current buttons count
2143
bcount = (int)SendMessage(window->toolbar.toolbar, TB_BUTTONCOUNT, 0, 0);
2144
}
2145
2146
/* Add a button which we're going to cover with the slider */
2147
tbs.iBitmap = 0;
2148
tbs.idCommand = bcount; // Set button id to it's number
2149
tbs.fsState = TBSTATE_ENABLED;
2150
#if 0/*!defined WIN64 && !defined EM64T*/
2151
tbs.fsStyle = 0;
2152
tbs.iString = 0;
2153
#else
2154
2155
#ifndef TBSTYLE_AUTOSIZE
2156
#define TBSTYLE_AUTOSIZE 0x0010
2157
#endif
2158
2159
#ifndef TBSTYLE_GROUP
2160
#define TBSTYLE_GROUP 0x0004
2161
#endif
2162
//tbs.fsStyle = TBSTYLE_AUTOSIZE;
2163
tbs.fsStyle = TBSTYLE_GROUP;
2164
tbs.iString = (INT_PTR)trackbar_text;
2165
#endif
2166
SendMessage(window->toolbar.toolbar, TB_ADDBUTTONS, 1, (LPARAM)&tbs);
2167
2168
/* Adjust button size to the slider */
2169
tbis.cbSize = sizeof(tbis);
2170
tbis.dwMask = TBIF_SIZE;
2171
2172
GetClientRect(window->hwnd, &rect);
2173
tbis.cx = (unsigned short)(rect.right - rect.left);
2174
2175
SendMessage(window->toolbar.toolbar, TB_SETBUTTONINFO,
2176
(WPARAM)tbs.idCommand, (LPARAM)&tbis);
2177
2178
/* Get button pos */
2179
SendMessage(window->toolbar.toolbar, TB_GETITEMRECT,
2180
(WPARAM)tbs.idCommand, (LPARAM)&rect);
2181
2182
/* Create a slider */
2183
trackbar = (CvTrackbar*)cvAlloc( sizeof(CvTrackbar) + len + 1 );
2184
trackbar->signature = CV_TRACKBAR_MAGIC_VAL;
2185
trackbar->notify = 0;
2186
trackbar->notify2 = 0;
2187
trackbar->parent = window;
2188
trackbar->pos = 0;
2189
trackbar->data = 0;
2190
trackbar->id = bcount;
2191
trackbar->next = window->toolbar.first;
2192
trackbar->name = (char*)(trackbar + 1);
2193
memcpy( trackbar->name, trackbar_name, len + 1 );
2194
window->toolbar.first = trackbar;
2195
2196
sprintf(slider_name, "Trackbar%p", val);
2197
trackbar->hwnd = CreateWindowEx(0, TRACKBAR_CLASS, slider_name,
2198
WS_CHILD | WS_VISIBLE | TBS_AUTOTICKS |
2199
TBS_FIXEDLENGTH | TBS_HORZ | TBS_BOTTOM,
2200
rect.left + HG_BUDDY_WIDTH, rect.top,
2201
rect.right - rect.left - HG_BUDDY_WIDTH,
2202
rect.bottom - rect.top, window->toolbar.toolbar,
2203
(HMENU)(size_t)bcount, hg_hinstance, 0);
2204
2205
sprintf(slider_name,"Buddy%p", val);
2206
trackbar->buddy = CreateWindowEx(0, "STATIC", slider_name,
2207
WS_CHILD | SS_RIGHT,
2208
rect.left, rect.top,
2209
HG_BUDDY_WIDTH, rect.bottom - rect.top,
2210
window->toolbar.toolbar, 0, hg_hinstance, 0);
2211
2212
icvSetWindowLongPtr( trackbar->hwnd, CV_USERDATA, trackbar );
2213
2214
/* Minimize the number of rows */
2215
SendMessage( window->toolbar.toolbar, TB_SETROWS,
2216
MAKEWPARAM(1, FALSE), (LPARAM)&rect );
2217
}
2218
else
2219
{
2220
trackbar->data = 0;
2221
trackbar->notify = 0;
2222
trackbar->notify2 = 0;
2223
}
2224
2225
trackbar->maxval = count;
2226
2227
/* Adjust slider parameters */
2228
SendMessage(trackbar->hwnd, TBM_SETRANGEMIN, (WPARAM)TRUE, (LPARAM)0);
2229
SendMessage(trackbar->hwnd, TBM_SETRANGEMAX, (WPARAM)TRUE, (LPARAM)count);
2230
SendMessage(trackbar->hwnd, TBM_SETTICFREQ, (WPARAM)1, (LPARAM)0 );
2231
if( val )
2232
pos = *val;
2233
2234
SendMessage(trackbar->hwnd, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pos );
2235
SendMessage(window->toolbar.toolbar, TB_AUTOSIZE, 0, 0);
2236
2237
trackbar->pos = -1;
2238
icvUpdateTrackbar( trackbar, pos );
2239
ShowWindow( trackbar->buddy, SW_SHOW );
2240
ShowWindow( trackbar->hwnd, SW_SHOW );
2241
2242
trackbar->notify = on_notify;
2243
trackbar->notify2 = on_notify2;
2244
trackbar->userdata = userdata;
2245
trackbar->data = val;
2246
2247
/* Resize the window to reflect the toolbar resizing*/
2248
icvUpdateWindowPos(window);
2249
2250
result = 1;
2251
2252
__END__;
2253
2254
return result;
2255
}
2256
2257
CV_IMPL int
2258
cvCreateTrackbar( const char* trackbar_name, const char* window_name,
2259
int* val, int count, CvTrackbarCallback on_notify )
2260
{
2261
return icvCreateTrackbar( trackbar_name, window_name, val, count,
2262
on_notify, 0, 0 );
2263
}
2264
2265
CV_IMPL int
2266
cvCreateTrackbar2( const char* trackbar_name, const char* window_name,
2267
int* val, int count, CvTrackbarCallback2 on_notify2,
2268
void* userdata )
2269
{
2270
return icvCreateTrackbar( trackbar_name, window_name, val, count,
2271
0, on_notify2, userdata );
2272
}
2273
2274
CV_IMPL void
2275
cvSetMouseCallback( const char* window_name, CvMouseCallback on_mouse, void* param )
2276
{
2277
CV_FUNCNAME( "cvSetMouseCallback" );
2278
2279
__BEGIN__;
2280
2281
CvWindow* window = 0;
2282
2283
if( !window_name )
2284
CV_ERROR( CV_StsNullPtr, "NULL window name" );
2285
2286
window = icvFindWindowByName(window_name);
2287
if( !window )
2288
EXIT;
2289
2290
window->on_mouse = on_mouse;
2291
window->on_mouse_param = param;
2292
2293
__END__;
2294
}
2295
2296
2297
CV_IMPL int cvGetTrackbarPos( const char* trackbar_name, const char* window_name )
2298
{
2299
int pos = -1;
2300
2301
CV_FUNCNAME( "cvGetTrackbarPos" );
2302
2303
__BEGIN__;
2304
2305
CvWindow* window;
2306
CvTrackbar* trackbar = 0;
2307
2308
if( trackbar_name == 0 || window_name == 0 )
2309
CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
2310
2311
window = icvFindWindowByName( window_name );
2312
if( window )
2313
trackbar = icvFindTrackbarByName( window, trackbar_name );
2314
2315
if( trackbar )
2316
pos = trackbar->pos;
2317
2318
__END__;
2319
2320
return pos;
2321
}
2322
2323
2324
CV_IMPL void cvSetTrackbarPos( const char* trackbar_name, const char* window_name, int pos )
2325
{
2326
CV_FUNCNAME( "cvSetTrackbarPos" );
2327
2328
__BEGIN__;
2329
2330
CvWindow* window;
2331
CvTrackbar* trackbar = 0;
2332
2333
if( trackbar_name == 0 || window_name == 0 )
2334
CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" );
2335
2336
window = icvFindWindowByName( window_name );
2337
if( window )
2338
trackbar = icvFindTrackbarByName( window, trackbar_name );
2339
2340
if( trackbar )
2341
{
2342
if( pos < 0 )
2343
pos = 0;
2344
2345
if( pos > trackbar->maxval )
2346
pos = trackbar->maxval;
2347
2348
SendMessage( trackbar->hwnd, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pos );
2349
icvUpdateTrackbar( trackbar, pos );
2350
}
2351
2352
__END__;
2353
}
2354
2355
2356
CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name, int maxval)
2357
{
2358
CV_FUNCNAME( "cvSetTrackbarMax" );
2359
2360
__BEGIN__;
2361
2362
if (maxval >= 0)
2363
{
2364
CvWindow* window = 0;
2365
CvTrackbar* trackbar = 0;
2366
if (trackbar_name == 0 || window_name == 0)
2367
{
2368
CV_ERROR(CV_StsNullPtr, "NULL trackbar or window name");
2369
}
2370
2371
window = icvFindWindowByName(window_name);
2372
if (window)
2373
{
2374
trackbar = icvFindTrackbarByName(window, trackbar_name);
2375
if (trackbar)
2376
{
2377
// The position will be min(pos, maxval).
2378
trackbar->maxval = (trackbar->minval>maxval)?trackbar->minval:maxval;
2379
SendMessage(trackbar->hwnd, TBM_SETRANGEMAX, (WPARAM)TRUE, (LPARAM)maxval);
2380
}
2381
}
2382
}
2383
2384
__END__;
2385
}
2386
2387
2388
CV_IMPL void cvSetTrackbarMin(const char* trackbar_name, const char* window_name, int minval)
2389
{
2390
CV_FUNCNAME( "cvSetTrackbarMin" );
2391
2392
__BEGIN__;
2393
2394
if (minval >= 0)
2395
{
2396
CvWindow* window = 0;
2397
CvTrackbar* trackbar = 0;
2398
if (trackbar_name == 0 || window_name == 0)
2399
{
2400
CV_ERROR(CV_StsNullPtr, "NULL trackbar or window name");
2401
}
2402
2403
window = icvFindWindowByName(window_name);
2404
if (window)
2405
{
2406
trackbar = icvFindTrackbarByName(window, trackbar_name);
2407
if (trackbar)
2408
{
2409
// The position will be min(pos, maxval).
2410
trackbar->minval = (minval<trackbar->maxval)?minval:trackbar->maxval;
2411
SendMessage(trackbar->hwnd, TBM_SETRANGEMIN, (WPARAM)TRUE, (LPARAM)minval);
2412
}
2413
}
2414
}
2415
2416
__END__;
2417
}
2418
2419
2420
CV_IMPL void* cvGetWindowHandle( const char* window_name )
2421
{
2422
void* hwnd = 0;
2423
2424
CV_FUNCNAME( "cvGetWindowHandle" );
2425
2426
__BEGIN__;
2427
2428
CvWindow* window;
2429
2430
if( window_name == 0 )
2431
CV_ERROR( CV_StsNullPtr, "NULL window name" );
2432
2433
window = icvFindWindowByName( window_name );
2434
if( window )
2435
hwnd = (void*)window->hwnd;
2436
2437
__END__;
2438
2439
return hwnd;
2440
}
2441
2442
2443
CV_IMPL const char* cvGetWindowName( void* window_handle )
2444
{
2445
const char* window_name = "";
2446
2447
CV_FUNCNAME( "cvGetWindowName" );
2448
2449
__BEGIN__;
2450
2451
CvWindow* window;
2452
2453
if( window_handle == 0 )
2454
CV_ERROR( CV_StsNullPtr, "NULL window" );
2455
2456
window = icvWindowByHWND( (HWND)window_handle );
2457
if( window )
2458
window_name = window->name;
2459
2460
__END__;
2461
2462
return window_name;
2463
}
2464
2465
2466
CV_IMPL void
2467
cvSetPreprocessFuncWin32_(const void* callback)
2468
{
2469
hg_on_preprocess = (CvWin32WindowCallback)callback;
2470
}
2471
2472
CV_IMPL void
2473
cvSetPostprocessFuncWin32_(const void* callback)
2474
{
2475
hg_on_postprocess = (CvWin32WindowCallback)callback;
2476
}
2477
2478
#endif //_WIN32
2479
2480