in modules/highgui/src/window_w32.cpp [1473:1713]
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_COPY:
{
if (!::OpenClipboard(hwnd) )
break;
HDC hDC = 0;
HDC memDC = 0;
HBITMAP memBM = 0;
// We'll use a do-while(0){} scope as a single-run breakable scope
// Upon any error we can jump out of the single-time while scope to clean up the resources.
do
{
if (!::EmptyClipboard())
break;
if(!window->image)
break;
// Get window device context
if (0 == (hDC = ::GetDC(hwnd)))
break;
// Create another DC compatible with hDC
if (0 == (memDC = ::CreateCompatibleDC( hDC )))
break;
// Determine the bitmap's dimensions
int nchannels = 3;
SIZE size = {0,0};
icvGetBitmapData( window, &size, &nchannels, 0 );
// Create bitmap to draw on and it in the new DC
if (0 == (memBM = ::CreateCompatibleBitmap ( hDC, size.cx, size.cy)))
break;
if (!::SelectObject( memDC, memBM ))
break;
// Begin drawing to DC
if (!::SetStretchBltMode(memDC, COLORONCOLOR))
break;
RGBQUAD table[256];
if( 1 == nchannels )
{
for(int i = 0; i < 256; ++i)
{
table[i].rgbBlue = (unsigned char)i;
table[i].rgbGreen = (unsigned char)i;
table[i].rgbRed = (unsigned char)i;
}
if (!::SetDIBColorTable(window->dc, 0, 255, table))
break;
}
// The image copied to the clipboard will be in its original size, regardless if the window itself was resized.
// Render the image to the dc/bitmap (at original size).
if (!::BitBlt( memDC, 0, 0, size.cx, size.cy, window->dc, 0, 0, SRCCOPY ))
break;
// Finally, set bitmap to clipboard
::SetClipboardData(CF_BITMAP, memBM);
} while (0,0); // (0,0) instead of (0) to avoid MSVC compiler warning C4127: "conditional expression is constant"
//////////////////////////////////////////////////////////////////////////
// if handle is allocated (i.e. != 0) then clean-up.
if (memBM) ::DeleteObject(memBM);
if (memDC) ::DeleteDC(memDC);
if (hDC) ::ReleaseDC(hwnd, hDC);
::CloseClipboard();
break;
}
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;
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 = GET_X_LPARAM( lParam );
pt.y = GET_Y_LPARAM( lParam );
if (window->flags & CV_WINDOW_AUTOSIZE)
{
// As user can't change window size, do not scale window coordinates. Underlying windowing system
// may prevent full window from being displayed and in this case coordinates should not be scaled.
window->on_mouse( event, pt.x, pt.y, flags, window->on_mouse_param );
} else {
// Full window is displayed using different size. Scale coordinates to match underlying positions.
RECT rect;
SIZE size = {0, 0};
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);
}
#ifdef HAVE_OPENGL
else if(window->useGl)
{
drawGl(window);
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
#endif
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;
case WM_SIZE:
window->width = LOWORD(lParam);
window->height = HIWORD(lParam);
#ifdef HAVE_OPENGL
if (window->useGl)
resizeGl(window);
#endif
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}