diff --git a/Fltk/FlGui.cpp b/Fltk/FlGui.cpp index 1e9c5eefb4202605557c00a925124a8dc9dee4c3..9bfff256cc3cc02c2b8ef2c6a60f535d48690b42 100644 --- a/Fltk/FlGui.cpp +++ b/Fltk/FlGui.cpp @@ -49,6 +49,7 @@ typedef unsigned long intptr_t; #include "Generator.h" #include "gl2ps.h" #include "gmshPopplerWrapper.h" +#include "PixelBuffer.h" #if defined(HAVE_3M) #include "3M.h" #endif @@ -816,6 +817,63 @@ void FlGui::splitCurrentOpenglWindow(char how) } } +void FlGui::copyCurrentOpenglWindowToClipboard() +{ +#if defined(WIN32) + GLint width = FlGui::instance()->getCurrentOpenglWindow()->w(); + GLint height = FlGui::instance()->getCurrentOpenglWindow()->h(); + + // lines have to be 32 bytes aligned, suppose 24 bits per pixel; just crop it + width -= width % 4; + + // get pixels + PixelBuffer *buffer = new PixelBuffer(width, height, GL_RGB, GL_UNSIGNED_BYTE); + buffer->fill(0); + unsigned char *pixels = (unsigned char*)buffer->getPixels(); + + // swap R and B since Windows bitmap format is BGR + int nBytes = 3 * width * height; + for(int i = 0; i < nBytes; i += 3){ + unsigned char tmp = pixels[i]; + pixels[i] = pixels[i + 2]; + pixels[i + 2] = tmp; + } + + // fill header + BITMAPINFOHEADER header; + header.biWidth = width; + header.biHeight = height; + header.biSizeImage = nBytes; + header.biSize = 40; + header.biPlanes = 1; + header.biBitCount = 3 * 8; + header.biCompression = BI_RGB; + header.biXPelsPerMeter = 0; + header.biYPelsPerMeter = 0; + header.biClrUsed = 0; + header.biClrImportant = 0; + + // generate handle + HANDLE handle = (HANDLE)::GlobalAlloc(GHND, sizeof(BITMAPINFOHEADER) + nBytes); + if(handle != NULL){ + // lock handle + char *pData = (char *)::GlobalLock((HGLOBAL)handle); + // copy header and data + memcpy(pData, &header, sizeof(BITMAPINFOHEADER)); + memcpy(pData + sizeof(BITMAPINFOHEADER), pixels, nBytes); + // unlock + ::GlobalUnlock((HGLOBAL)handle); + // push DIB in clipboard + OpenClipboard(NULL); + EmptyClipboard(); + SetClipboardData(CF_DIB, handle); + CloseClipboard(); + } + + delete buffer; +#endif +} + char FlGui::selectEntity(int type) { return getCurrentOpenglWindow()->selectEntity diff --git a/Fltk/FlGui.h b/Fltk/FlGui.h index 060a28f1448f26f00e3d3d1e5a18876fc121f95e..be140f06292cb066dbe057abec9b61828dc8edd4 100644 --- a/Fltk/FlGui.h +++ b/Fltk/FlGui.h @@ -107,6 +107,8 @@ class FlGui{ openglWindow *getCurrentOpenglWindow(); // split the current opengl window void splitCurrentOpenglWindow(char how); + // copy the current opengl window to the clipboard + void copyCurrentOpenglWindowToClipboard(); // select an entity in the most recent graphic window char selectEntity(int type); // display status message diff --git a/Fltk/graphicWindow.cpp b/Fltk/graphicWindow.cpp index fee9d895d8efe25e09c381ad803871cd8670022d..6e4a20d2745ccfbf635ab13609b82ad2cd13f399 100644 --- a/Fltk/graphicWindow.cpp +++ b/Fltk/graphicWindow.cpp @@ -246,6 +246,9 @@ static void file_window_cb(Fl_Widget *w, void *data) else if(str == "split_u"){ FlGui::instance()->splitCurrentOpenglWindow('u'); } + else if(str == "copy"){ + FlGui::instance()->copyCurrentOpenglWindowToClipboard(); + } drawContext::global()->draw(); } @@ -1949,6 +1952,9 @@ static Fl_Menu_Item bar_table[] = { {0}, {"&Window", 0, 0, 0, FL_SUBMENU}, {"New Window", 0, (Fl_Callback *)file_window_cb, (void*)"new", FL_MENU_DIVIDER}, +#if defined(WIN32) + {"Copy to Clipboard", FL_CTRL+'c', (Fl_Callback *)file_window_cb, (void*)"copy", FL_MENU_DIVIDER}, +#endif {"Split Horizontally", 0, (Fl_Callback *)file_window_cb, (void*)"split_h"}, {"Split Vertically", 0, (Fl_Callback *)file_window_cb, (void*)"split_v"}, {"Unsplit", 0, (Fl_Callback *)file_window_cb, (void*)"split_u", FL_MENU_DIVIDER},