📄 window_w32.cpp
字号:
{
POINT p;
p.x = rect->left;
p.y = rect->top;
ScreenToClient(hwnd, &p);
OffsetRect( rect, p.x - rect->left, p.y - rect->top );
}
/* Calculatess the window coordinates relative to the upper left corner of the mainhWnd window */
static RECT icvCalcWindowRect( CvWindow* window )
{
const int gutter = 1;
RECT crect, trect, rect;
assert(window);
GetClientRect(window->frame, &crect);
if(window->toolbar.toolbar)
{
GetWindowRect(window->toolbar.toolbar, &trect);
icvScreenToClient(window->frame, &trect);
SubtractRect( &rect, &crect, &trect);
}
else
rect = crect;
rect.top += gutter;
rect.left += gutter;
rect.bottom -= gutter;
rect.right -= gutter;
return rect;
}
// returns TRUE if there is a problem such as ERROR_IO_PENDING.
static bool icvGetBitmapData( CvWindow* window, SIZE* size, int* channels, void** data )
{
BITMAP bmp;
GdiFlush();
HGDIOBJ h = GetCurrentObject( window->dc, OBJ_BITMAP );
if( size )
size->cx = size->cy = 0;
if( data )
*data = 0;
if (h == NULL)
return true;
if (GetObject(h, sizeof(bmp), &bmp) == 0)
return true;
if( size )
{
size->cx = abs(bmp.bmWidth);
size->cy = abs(bmp.bmHeight);
}
if( channels )
*channels = bmp.bmBitsPixel/8;
if( data )
*data = bmp.bmBits;
return false;
}
static void icvUpdateWindowPos( CvWindow* window )
{
RECT rect;
assert(window);
if( (window->flags & CV_WINDOW_AUTOSIZE) && window->image )
{
int i;
SIZE size = {0,0};
icvGetBitmapData( window, &size, 0, 0 );
// Repeat two times because after the first resizing of the mainhWnd window
// toolbar may resize too
for(i = 0; i < (window->toolbar.toolbar ? 2 : 1); i++)
{
RECT rmw, rw = icvCalcWindowRect(window );
MoveWindow(window->hwnd, rw.left, rw.top,
rw.right - rw.left + 1, rw.bottom - rw.top + 1, FALSE);
GetClientRect(window->hwnd, &rw);
GetWindowRect(window->frame, &rmw);
// Resize the mainhWnd window in order to make the bitmap fit into the child window
MoveWindow(window->frame, rmw.left, rmw.top,
rmw.right - rmw.left + size.cx - rw.right + rw.left,
rmw.bottom - rmw.top + size.cy - rw.bottom + rw.top, TRUE );
}
}
rect = icvCalcWindowRect(window);
MoveWindow(window->hwnd, rect.left, rect.top,
rect.right - rect.left + 1,
rect.bottom - rect.top + 1, TRUE );
}
CV_IMPL void
cvShowImage( const char* name, const CvArr* arr )
{
CV_FUNCNAME( "cvShowImage" );
__BEGIN__;
CvWindow* window;
SIZE size = { 0, 0 };
int channels = 0;
void* dst_ptr = 0;
const int channels0 = 3;
int origin = 0;
CvMat stub, dst, *image;
bool changed_size = false; // philipg
if( !name )
CV_ERROR( CV_StsNullPtr, "NULL name" );
window = icvFindWindowByName(name);
if( !window || !arr )
EXIT; // keep silence here.
if( CV_IS_IMAGE_HDR( arr ))
origin = ((IplImage*)arr)->origin;
CV_CALL( image = cvGetMat( arr, &stub ));
if (window->image)
// if there is something wrong with these system calls, we cannot display image...
if (icvGetBitmapData( window, &size, &channels, &dst_ptr ))
return;
if( size.cx != image->width || size.cy != image->height || channels != channels0 )
{
changed_size = true;
uchar buffer[sizeof(BITMAPINFO) + 255*sizeof(RGBQUAD)];
BITMAPINFO* binfo = (BITMAPINFO*)buffer;
DeleteObject( SelectObject( window->dc, window->image ));
window->image = 0;
size.cx = image->width;
size.cy = image->height;
channels = channels0;
FillBitmapInfo( binfo, size.cx, size.cy, channels*8, 1 );
window->image = SelectObject( window->dc, CreateDIBSection(window->dc, binfo,
DIB_RGB_COLORS, &dst_ptr, 0, 0));
}
cvInitMatHeader( &dst, size.cy, size.cx, CV_8UC3,
dst_ptr, (size.cx * channels + 3) & -4 );
cvConvertImage( image, &dst, origin == 0 ? CV_CVTIMG_FLIP : 0 );
// ony resize window if needed
if (changed_size)
icvUpdateWindowPos(window);
InvalidateRect(window->hwnd, 0, 0);
// philipg: this is not needed and just slows things down
// UpdateWindow(window->hwnd);
__END__;
}
CV_IMPL void cvResizeWindow(const char* name, int width, int height )
{
CV_FUNCNAME( "cvResizeWindow" );
__BEGIN__;
int i;
CvWindow* window;
RECT rmw, rw, rect;
if( !name )
CV_ERROR( CV_StsNullPtr, "NULL name" );
window = icvFindWindowByName(name);
if(!window)
EXIT;
// Repeat two times because after the first resizing of the mainhWnd window
// toolbar may resize too
for(i = 0; i < (window->toolbar.toolbar ? 2 : 1); i++)
{
rw = icvCalcWindowRect(window);
MoveWindow(window->hwnd, rw.left, rw.top,
rw.right - rw.left + 1, rw.bottom - rw.top + 1, FALSE);
GetClientRect(window->hwnd, &rw);
GetWindowRect(window->frame, &rmw);
// Resize the mainhWnd window in order to make the bitmap fit into the child window
MoveWindow(window->frame, rmw.left, rmw.top,
rmw.right - rmw.left + width - rw.right + rw.left,
rmw.bottom - rmw.top + height - rw.bottom + rw.top, TRUE);
}
rect = icvCalcWindowRect(window);
MoveWindow(window->hwnd, rect.left, rect.top,
rect.right - rect.left + 1, rect.bottom - rect.top + 1, TRUE);
__END__;
}
CV_IMPL void cvMoveWindow( const char* name, int x, int y )
{
CV_FUNCNAME( "cvMoveWindow" );
__BEGIN__;
CvWindow* window;
RECT rect;
if( !name )
CV_ERROR( CV_StsNullPtr, "NULL name" );
window = icvFindWindowByName(name);
if(!window)
EXIT;
GetWindowRect( window->frame, &rect );
MoveWindow( window->frame, x, y, rect.right - rect.left, rect.bottom - rect.top, TRUE);
__END__;
}
static LRESULT CALLBACK
MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
CvWindow* window = icvWindowByHWND( hwnd );
if( !window )
return DefWindowProc(hwnd, uMsg, wParam, lParam);
switch(uMsg)
{
case WM_DESTROY:
icvRemoveWindow(window);
// Do nothing!!!
//PostQuitMessage(0);
break;
case WM_GETMINMAXINFO:
if( !(window->flags & CV_WINDOW_AUTOSIZE) )
{
MINMAXINFO* minmax = (MINMAXINFO*)lParam;
RECT rect;
LRESULT retval = DefWindowProc(hwnd, uMsg, wParam, lParam);
minmax->ptMinTrackSize.y = 100;
minmax->ptMinTrackSize.x = 100;
if( window->toolbar.first )
{
GetWindowRect( window->toolbar.first->hwnd, &rect );
minmax->ptMinTrackSize.y += window->toolbar.rows*(rect.bottom - rect.top);
minmax->ptMinTrackSize.x = MAX(rect.right - rect.left + HG_BUDDY_WIDTH, HG_BUDDY_WIDTH*2);
}
return retval;
}
break;
case WM_WINDOWPOSCHANGED:
{
WINDOWPOS* pos = (WINDOWPOS*)lParam;
// Update the toolbar position/size
if(window->toolbar.toolbar)
{
RECT rect;
GetWindowRect(window->toolbar.toolbar, &rect);
MoveWindow(window->toolbar.toolbar, 0, 0, pos->cx, rect.bottom - rect.top, TRUE);
}
if(!(window->flags & CV_WINDOW_AUTOSIZE))
icvUpdateWindowPos(window);
break;
}
case WM_ACTIVATE:
if(LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE)
SetFocus(window->hwnd);
break;
case WM_ERASEBKGND:
{
RECT cr, tr, wrc;
HRGN rgn, rgn1, rgn2;
int ret;
HDC hdc = (HDC)wParam;
GetWindowRect(window->hwnd, &cr);
icvScreenToClient(window->frame, &cr);
if(window->toolbar.toolbar)
{
GetWindowRect(window->toolbar.toolbar, &tr);
icvScreenToClient(window->frame, &tr);
}
else
tr.left = tr.top = tr.right = tr.bottom = 0;
GetClientRect(window->frame, &wrc);
rgn = CreateRectRgn(0, 0, wrc.right, wrc.bottom);
rgn1 = CreateRectRgn(cr.left, cr.top, cr.right, cr.bottom);
rgn2 = CreateRectRgn(tr.left, tr.top, tr.right, tr.bottom);
ret = CombineRgn(rgn, rgn, rgn1, RGN_DIFF);
ret = CombineRgn(rgn, rgn, rgn2, RGN_DIFF);
if(ret != NULLREGION && ret != ERROR)
FillRgn(hdc, rgn, (HBRUSH)icvGetClassLongPtr(hwnd, CV_HBRBACKGROUND));
DeleteObject(rgn);
DeleteObject(rgn1);
DeleteObject(rgn2);
}
return 1;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
CvWindow* window = icvWindowByHWND(hwnd);
if( !window )
// This window is not mentioned in HighGUI storage
// Actually, this should be error except for the case of calls to CreateWindow
return DefWindowProc(hwnd, uMsg, wParam, lParam);
// Process the message
switch(uMsg)
{
case WM_WINDOWPOSCHANGING:
{
LPWINDOWPOS pos = (LPWINDOWPOS)lParam;
RECT rect = icvCalcWindowRect(window);
pos->x = rect.left;
pos->y = rect.top;
pos->cx = rect.right - rect.left + 1;
pos->cy = rect.bottom - rect.top + 1;
}
break;
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_LBUTTONDBLCLK:
case WM_RBUTTONDBLCLK:
case WM_MBUTTONDBLCLK:
case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
case WM_MOUSEMOVE:
if( window->on_mouse )
{
POINT pt;
RECT rect;
SIZE size = {0,0};
int flags = (wParam & MK_LBUTTON ? CV_EVENT_FLAG_LBUTTON : 0)|
(wParam & MK_RBUTTON ? CV_EVENT_FLAG_RBUTTON : 0)|
(wParam & MK_MBUTTON ? CV_EVENT_FLAG_MBUTTON : 0)|
(wParam & MK_CONTROL ? CV_EVENT_FLAG_CTRLKEY : 0)|
(wParam & MK_SHIFT ? CV_EVENT_FLAG_SHIFTKEY : 0)|
(GetKeyState(VK_MENU) < 0 ? CV_EVENT_FLAG_ALTKEY : 0);
int event = uMsg == WM_LBUTTONDOWN ? CV_EVENT_LBUTTONDOWN :
uMsg == WM_RBUTTONDOWN ? CV_EVENT_RBUTTONDOWN :
uMsg == WM_MBUTTONDOWN ? CV_EVENT_MBUTTONDOWN :
uMsg == WM_LBUTTONUP ? CV_EVENT_LBUTTONUP :
uMsg == WM_RBUTTONUP ? CV_EVENT_RBUTTONUP :
uMsg == WM_MBUTTONUP ? CV_EVENT_MBUTTONUP :
uMsg == WM_LBUTTONDBLCLK ? CV_EVENT_LBUTTONDBLCLK :
uMsg == WM_RBUTTONDBLCLK ? CV_EVENT_RBUTTONDBLCLK :
uMsg == WM_MBUTTONDBLCLK ? CV_EVENT_MBUTTONDBLCLK :
CV_EVENT_MOUSEMOVE;
if( uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN || uMsg == WM_MBUTTONDOWN )
SetCapture( hwnd );
if( uMsg == WM_LBUTTONUP || uMsg == WM_RBUTTONUP || uMsg == WM_MBUTTONUP )
ReleaseCapture();
pt.x = LOWORD( lParam );
pt.y = HIWORD( lParam );
GetClientRect( window->hwnd, &rect );
icvGetBitmapData( window, &size, 0, 0 );
window->on_mouse( event, pt.x*size.cx/MAX(rect.right - rect.left,1),
pt.y*size.cy/MAX(rect.bottom - rect.top,1), flags,
window->on_mouse_param );
}
break;
case WM_PAINT:
if(window->image != 0)
{
int nchannels = 3;
SIZE size = {0,0};
PAINTSTRUCT paint;
HDC hdc;
RGBQUAD table[256];
// Determine the bitmap's dimensions
icvGetBitmapData( window, &size, &nchannels, 0 );
hdc = BeginPaint(hwnd, &paint);
SetStretchBltMode(hdc, COLORONCOLOR);
if( nchannels == 1 )
{
int i;
for(i = 0; i < 256; i++)
{
table[i].rgbBlue = (unsigned char)i;
table[i].rgbGreen = (unsigned char)i;
table[i].rgbRed = (unsigned char)i;
}
SetDIBColorTable(window->dc, 0, 255, table);
}
if(window->flags & CV_WINDOW_AUTOSIZE)
{
BitBlt( hdc, 0, 0, size.cx, size.cy, window->dc, 0, 0, SRCCOPY );
}
else
{
RECT rect;
GetClientRect(window->hwnd, &rect);
StretchBlt( hdc, 0, 0, rect.right - rect.left, rect.bottom - rect.top,
window->dc, 0, 0, size.cx, size.cy, SRCCOPY );
}
//DeleteDC(hdc);
EndPaint(hwnd, &paint);
}
else
{
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
case WM_ERASEBKGND:
if(window->image)
return 0;
break;
case WM_DESTROY:
icvRemoveWindow(window);
// Do nothing!!!
//PostQuitMessage(0);
break;
case WM_SETCURSOR:
SetCursor((HCURSOR)icvGetClassLongPtr(hwnd, CV_HCURSOR));
return 0;
case WM_KEYDOWN:
window->last_key = (int)wParam;
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
static LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
LRESULT ret;
if( hg_on_preprocess )
{
int was_processed = 0;
int ret = hg_on_preprocess(hwnd, uMsg, wParam, lParam, &was_processed);
if( was_processed )
return ret;
}
ret = HighGUIProc(hwnd, uMsg, wParam, lParam);
if(hg_on_postprocess)
{
int was_processed = 0;
int ret = hg_on_postprocess(hwnd, uMsg, wParam, lParam, &was_processed);
if( was_processed )
return ret;
}
return ret;
}
static void icvUpdateTrackbar( CvTrackbar* trackbar, int pos )
{
const int max_name_len = 10;
const char* suffix = "";
char pos_text[32];
int name_len;
if( trackbar->data )
*trackbar->data = pos;
if( trackbar->pos != pos )
{
trackbar->pos = pos;
if( trackbar->notify )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -