static LRESULT CALLBACK HighGUIProc()

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);
}