From 68827072c903e4cee6c9bd683f71294521051c09 Mon Sep 17 00:00:00 2001 From: Adi Shavit Date: Mon, 20 Jan 2014 21:44:27 +0200 Subject: [PATCH 1/4] [HighGUI] On Windows: Support Ctrl+C to copy image to clipboard. --- modules/highgui/src/window_w32.cpp | 84 ++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/modules/highgui/src/window_w32.cpp b/modules/highgui/src/window_w32.cpp index 8b317dff71..a7aca0ec47 100644 --- a/modules/highgui/src/window_w32.cpp +++ b/modules/highgui/src/window_w32.cpp @@ -1286,6 +1286,10 @@ MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) switch(uMsg) { + case WM_COPY: + ::WindowProc(hwnd, uMsg, wParam, lParam); // call highgui proc. There may be a better way to do this. + break; + case WM_DESTROY: icvRemoveWindow(window); @@ -1448,6 +1452,81 @@ static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM 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. + memBM && ::DeleteObject(memBM); + memDC && ::DeleteDC(memDC); + hDC && ::ReleaseDC(hwnd, hDC); + ::CloseClipboard(); + break; + } + case WM_WINDOWPOSCHANGING: { LPWINDOWPOS pos = (LPWINDOWPOS)lParam; @@ -1798,6 +1877,11 @@ cvWaitKey( int delay ) is_processed = 1; return (int)(message.wParam << 16); } + + // Intercept Ctrl+C for copy to clipboard + if ('C' == message.wParam && (::GetKeyState(VK_CONTROL)>>15)) + ::PostMessage(message.hwnd, WM_COPY, 0, 0); + default: DispatchMessage(&message); is_processed = 1; From d44e3c369d58579013d42c4ea573215385fe51d9 Mon Sep 17 00:00:00 2001 From: Adi Shavit Date: Mon, 20 Jan 2014 22:09:52 +0200 Subject: [PATCH 2/4] Added documentation. --- modules/highgui/doc/user_interface.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/highgui/doc/user_interface.rst b/modules/highgui/doc/user_interface.rst index 0d0ccde946..565ea6d449 100644 --- a/modules/highgui/doc/user_interface.rst +++ b/modules/highgui/doc/user_interface.rst @@ -83,6 +83,9 @@ If window was created with OpenGL support, ``imshow`` also support :ocv:class:`o .. note:: This function should be followed by ``waitKey`` function which displays the image for specified milliseconds. Otherwise, it won't display the image. For example, ``waitKey(0)`` will display the window infinitely until any keypress (it is suitable for image display). ``waitKey(25)`` will display a frame for 25 ms, after which display will be automatically closed. (If you put it in a loop to read videos, it will display the video frame-by-frame) +.. note:: + + [Windows Backend Only] Pressing Ctrl+C will copy the image to the clipboard. namedWindow --------------- From e25dca21d18c1a6af4cf87e697b5612dd34d0175 Mon Sep 17 00:00:00 2001 From: Adi Shavit Date: Mon, 27 Jan 2014 10:14:49 +0200 Subject: [PATCH 3/4] Fixed indentation. --- modules/highgui/src/window_w32.cpp | 106 ++++++++++++++--------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/modules/highgui/src/window_w32.cpp b/modules/highgui/src/window_w32.cpp index a7aca0ec47..658bb4f481 100644 --- a/modules/highgui/src/window_w32.cpp +++ b/modules/highgui/src/window_w32.cpp @@ -1287,8 +1287,8 @@ MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) switch(uMsg) { case WM_COPY: - ::WindowProc(hwnd, uMsg, wParam, lParam); // call highgui proc. There may be a better way to do this. - break; + ::WindowProc(hwnd, uMsg, wParam, lParam); // call highgui proc. There may be a better way to do this. + break; case WM_DESTROY: @@ -1465,57 +1465,57 @@ static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM // 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); + 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" ////////////////////////////////////////////////////////////////////////// From b449bd5150076535e984805860fbe23484bec840 Mon Sep 17 00:00:00 2001 From: Adi Shavit Date: Thu, 3 Jul 2014 22:45:11 +0300 Subject: [PATCH 4/4] Clarified code. --- modules/highgui/src/window_w32.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/highgui/src/window_w32.cpp b/modules/highgui/src/window_w32.cpp index 658bb4f481..bcf1bae8be 100644 --- a/modules/highgui/src/window_w32.cpp +++ b/modules/highgui/src/window_w32.cpp @@ -1520,9 +1520,9 @@ static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM ////////////////////////////////////////////////////////////////////////// // if handle is allocated (i.e. != 0) then clean-up. - memBM && ::DeleteObject(memBM); - memDC && ::DeleteDC(memDC); - hDC && ::ReleaseDC(hwnd, hDC); + if (memBM) ::DeleteObject(memBM); + if (memDC) ::DeleteDC(memDC); + if (hDC) ::ReleaseDC(hwnd, hDC); ::CloseClipboard(); break; }