From 575de13cc4c821ded696e6beb82f4eedeb79334f Mon Sep 17 00:00:00 2001 From: beru Date: Sun, 26 Apr 2015 15:40:58 +0900 Subject: [PATCH] add nana::system::dataexch::set(const nana::paint::graphics& g) method --- include/nana/system/dataexch.hpp | 9 +++- source/system/dataexch.cpp | 88 +++++++++++++++++++++++++++++++- 2 files changed, 94 insertions(+), 3 deletions(-) diff --git a/include/nana/system/dataexch.hpp b/include/nana/system/dataexch.hpp index a730accb..ecfe9b22 100644 --- a/include/nana/system/dataexch.hpp +++ b/include/nana/system/dataexch.hpp @@ -14,7 +14,13 @@ #define NANA_SYSTEM_DATAEXCH_HPP #include -namespace nana{ namespace system{ +namespace nana{ + +namespace paint{ + class graphics; +} + +namespace system{ /// a data exchange mechanism through Windows Clipboard, X11 Selection. class dataexch { @@ -26,6 +32,7 @@ namespace nana{ namespace system{ void set(const nana::char_t* text); void set(const nana::string& text); + bool set(const nana::paint::graphics& g); void get(nana::string& str); private: bool _m_set(unsigned type, const void* buf, std::size_t size); diff --git a/source/system/dataexch.cpp b/source/system/dataexch.cpp index 926e6f98..a7109a48 100644 --- a/source/system/dataexch.cpp +++ b/source/system/dataexch.cpp @@ -12,6 +12,10 @@ #include #include +#include +#include +#include + #if defined(NANA_WINDOWS) #include #elif defined(NANA_X11) @@ -33,6 +37,86 @@ namespace nana{ namespace system{ _m_set(std::is_same::value ? format::text : format::unicode, text.c_str(), (text.length() + 1) * sizeof(nana::char_t)); } + bool dataexch::set(const nana::paint::graphics& g) + { +#if defined(NANA_WINDOWS) + size sz = g.size(); + paint::pixel_buffer pbuffer; + rectangle r; + r.x = 0; + r.y = 0; + r.width = sz.width; + r.height = sz.height; + pbuffer.attach(g.handle(), r); + size_t bytes_per_line = pbuffer.bytes_per_line(); + size_t bitmap_bytes = bytes_per_line * r.height; + + struct { + BITMAPINFOHEADER bmiHeader; + RGBQUAD bmiColors[256]; + } bmi = {0}; + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + HDC hDC = ::GetDC(NULL); + if (::GetDIBits(hDC, (HBITMAP)g.pixmap(), 0, 1, NULL, (BITMAPINFO *)&bmi, DIB_RGB_COLORS) == 0) { + assert(false); + int err = ::GetLastError(); + ::ReleaseDC(NULL, hDC); + return false; + } + if (!::ReleaseDC(NULL, hDC)) { + return false; + } + + size_t header_size = sizeof(bmi.bmiHeader); + + // Bitmaps are huge, so to avoid unnegligible extra copy, this routine does not use private _m_set method. + HGLOBAL h_gmem = ::GlobalAlloc(GHND | GMEM_SHARE, header_size + bitmap_bytes); + void * gmem = ::GlobalLock(h_gmem); + if (!gmem) { + assert(false); + goto Label_GlobalFree; + } + char* p = (char*)gmem; + // Fix BITMAPINFOHEADER obtained from GetDIBits WinAPI + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biHeight = ::abs(bmi.bmiHeader.biHeight); + memcpy(p, &bmi, header_size); + p += header_size; + // many programs do not support bottom-up DIB, so reversing row order is needed. + for (int y=0; y