Merge branch 'image_data_object' of https://github.com/a-wi/wxWidgets
Implement wxImageDataObject to allow copying wxImage, including its metadata, to/from clipboard. See https://github.com/wxWidgets/wxWidgets/pull/2156
This commit is contained in:
@@ -36,7 +36,9 @@
|
|||||||
wxTextDataObject | wxBitmapDataObject
|
wxTextDataObject | wxBitmapDataObject
|
||||||
|
|
|
|
||||||
wxCustomDataObject
|
wxCustomDataObject
|
||||||
|
|
|
||||||
|
|
|
||||||
|
wxImageDataObject
|
||||||
*/
|
*/
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
@@ -545,6 +547,22 @@ private:
|
|||||||
wxDECLARE_NO_COPY_CLASS(wxCustomDataObject);
|
wxDECLARE_NO_COPY_CLASS(wxCustomDataObject);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxImageDataObject - data object for wxImage
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class WXDLLIMPEXP_CORE wxImageDataObject : public wxCustomDataObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit wxImageDataObject(const wxImage& image = wxNullImage);
|
||||||
|
|
||||||
|
void SetImage(const wxImage& image);
|
||||||
|
wxImage GetImage() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
wxDECLARE_NO_COPY_CLASS(wxImageDataObject);
|
||||||
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// include platform-specific declarations of wxXXXBase classes
|
// include platform-specific declarations of wxXXXBase classes
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@@ -2153,6 +2153,7 @@ enum wxDataFormatId
|
|||||||
wxDF_LOCALE = 16,
|
wxDF_LOCALE = 16,
|
||||||
wxDF_PRIVATE = 20,
|
wxDF_PRIVATE = 20,
|
||||||
wxDF_HTML = 30, /* Note: does not correspond to CF_ constant */
|
wxDF_HTML = 30, /* Note: does not correspond to CF_ constant */
|
||||||
|
wxDF_PNG = 31, /* Note: does not correspond to CF_ constant */
|
||||||
wxDF_MAX
|
wxDF_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -34,6 +34,9 @@
|
|||||||
A list of filenames.}
|
A list of filenames.}
|
||||||
@itemdef{wxDF_HTML,
|
@itemdef{wxDF_HTML,
|
||||||
An HTML string. This is currently only valid on Mac and MSW.}
|
An HTML string. This is currently only valid on Mac and MSW.}
|
||||||
|
@itemdef{wxDF_PNG,
|
||||||
|
A PNG file. This is valid only on MSW. This constant is available
|
||||||
|
since wxWidgets 3.1.5.}
|
||||||
@endDefList
|
@endDefList
|
||||||
|
|
||||||
As mentioned above, these standard formats may be passed to any function
|
As mentioned above, these standard formats may be passed to any function
|
||||||
@@ -620,6 +623,42 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@class wxImageDataObject
|
||||||
|
|
||||||
|
wxImageDataObject is a specialization of wxDataObject for image data.
|
||||||
|
It can be used e.g. when you need to put on and retrieve from the clipboard
|
||||||
|
a wxImage with its metadata (like image resolution).
|
||||||
|
|
||||||
|
@since 3.1.5
|
||||||
|
|
||||||
|
@library{wxcore}
|
||||||
|
@category{dnd}
|
||||||
|
|
||||||
|
@see @ref overview_dnd, wxDataObject, wxCustomDataObject, wxBitmapDataObject
|
||||||
|
*/
|
||||||
|
class wxImageDataObject : public wxCustomDataObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
Constructor, optionally passing an image (otherwise use SetImage()
|
||||||
|
later).
|
||||||
|
*/
|
||||||
|
explicit wxImageDataObject(const wxImage& image = wxNullImage);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the image associated with the data object.
|
||||||
|
*/
|
||||||
|
wxImage GetImage() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the image stored by the data object.
|
||||||
|
*/
|
||||||
|
void SetImage(const wxImage& image);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@class wxURLDataObject
|
@class wxURLDataObject
|
||||||
|
|
||||||
|
@@ -91,6 +91,8 @@ public:
|
|||||||
#if wxUSE_CLIPBOARD
|
#if wxUSE_CLIPBOARD
|
||||||
void OnCopy(wxCommandEvent& event);
|
void OnCopy(wxCommandEvent& event);
|
||||||
void OnPaste(wxCommandEvent& event);
|
void OnPaste(wxCommandEvent& event);
|
||||||
|
void OnCopyImage(wxCommandEvent& evt);
|
||||||
|
void OnPasteImage(wxCommandEvent& evt);
|
||||||
#endif // wxUSE_CLIPBOARD
|
#endif // wxUSE_CLIPBOARD
|
||||||
|
|
||||||
MyCanvas *m_canvas;
|
MyCanvas *m_canvas;
|
||||||
@@ -124,8 +126,39 @@ class MyImageFrame : public wxFrame
|
|||||||
public:
|
public:
|
||||||
MyImageFrame(wxFrame *parent, const wxString& desc, const wxImage& image, double scale = 1.0)
|
MyImageFrame(wxFrame *parent, const wxString& desc, const wxImage& image, double scale = 1.0)
|
||||||
{
|
{
|
||||||
Create(parent, desc, wxBitmap(image, wxBITMAP_SCREEN_DEPTH, scale),
|
// Retrieve image info
|
||||||
image.GetImageCount(desc));
|
wxString info;
|
||||||
|
int xres, yres;
|
||||||
|
switch ( GetResolutionFromOptions(image, &xres, &yres) )
|
||||||
|
{
|
||||||
|
case wxIMAGE_RESOLUTION_NONE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case wxIMAGE_RESOLUTION_CM:
|
||||||
|
// convert to DPI
|
||||||
|
xres = wxRound(xres / 10.0 * inches2mm);
|
||||||
|
yres = wxRound(yres / 10.0 * inches2mm);
|
||||||
|
wxFALLTHROUGH;
|
||||||
|
|
||||||
|
case wxIMAGE_RESOLUTION_INCHES:
|
||||||
|
info = wxString::Format("DPI %i x %i", xres, yres);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
wxFAIL_MSG("unexpected image resolution units");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int numImages = desc.StartsWith("Clipboard") ? 1 : image.GetImageCount(desc);
|
||||||
|
if ( numImages > 1 )
|
||||||
|
{
|
||||||
|
if ( !info.empty() )
|
||||||
|
info += ", ";
|
||||||
|
|
||||||
|
info += wxString::Format("%d images", numImages);
|
||||||
|
}
|
||||||
|
|
||||||
|
Create(parent, desc, wxBitmap(image, wxBITMAP_SCREEN_DEPTH, scale), info);
|
||||||
}
|
}
|
||||||
|
|
||||||
MyImageFrame(wxFrame *parent, const wxString& desc, const wxBitmap& bitmap)
|
MyImageFrame(wxFrame *parent, const wxString& desc, const wxBitmap& bitmap)
|
||||||
@@ -137,7 +170,7 @@ private:
|
|||||||
bool Create(wxFrame *parent,
|
bool Create(wxFrame *parent,
|
||||||
const wxString& desc,
|
const wxString& desc,
|
||||||
const wxBitmap& bitmap,
|
const wxBitmap& bitmap,
|
||||||
int numImages = 1)
|
wxString info = wxString())
|
||||||
{
|
{
|
||||||
if ( !wxFrame::Create(parent, wxID_ANY,
|
if ( !wxFrame::Create(parent, wxID_ANY,
|
||||||
wxString::Format("Image from %s", desc),
|
wxString::Format("Image from %s", desc),
|
||||||
@@ -169,8 +202,7 @@ private:
|
|||||||
mbar->Check(ID_PAINT_BG, true);
|
mbar->Check(ID_PAINT_BG, true);
|
||||||
|
|
||||||
CreateStatusBar(2);
|
CreateStatusBar(2);
|
||||||
if ( numImages != 1 )
|
SetStatusText(info, 1);
|
||||||
SetStatusText(wxString::Format("%d images", numImages), 1);
|
|
||||||
|
|
||||||
SetClientSize(bitmap.GetWidth(), bitmap.GetHeight());
|
SetClientSize(bitmap.GetWidth(), bitmap.GetHeight());
|
||||||
|
|
||||||
@@ -439,6 +471,41 @@ private:
|
|||||||
Refresh();
|
Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is a copy of protected wxImageHandler::GetResolutionFromOptions()
|
||||||
|
static wxImageResolution GetResolutionFromOptions(const wxImage& image, int* x, int* y)
|
||||||
|
{
|
||||||
|
wxCHECK_MSG(x && y, wxIMAGE_RESOLUTION_NONE, wxT("NULL pointer"));
|
||||||
|
|
||||||
|
if ( image.HasOption(wxIMAGE_OPTION_RESOLUTIONX) &&
|
||||||
|
image.HasOption(wxIMAGE_OPTION_RESOLUTIONY) )
|
||||||
|
{
|
||||||
|
*x = image.GetOptionInt(wxIMAGE_OPTION_RESOLUTIONX);
|
||||||
|
*y = image.GetOptionInt(wxIMAGE_OPTION_RESOLUTIONY);
|
||||||
|
}
|
||||||
|
else if ( image.HasOption(wxIMAGE_OPTION_RESOLUTION) )
|
||||||
|
{
|
||||||
|
*x =
|
||||||
|
*y = image.GetOptionInt(wxIMAGE_OPTION_RESOLUTION);
|
||||||
|
}
|
||||||
|
else // no resolution options specified
|
||||||
|
{
|
||||||
|
*x =
|
||||||
|
*y = 0;
|
||||||
|
|
||||||
|
return wxIMAGE_RESOLUTION_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the resolution unit too
|
||||||
|
int resUnit = image.GetOptionInt(wxIMAGE_OPTION_RESOLUTIONUNIT);
|
||||||
|
if ( !resUnit )
|
||||||
|
{
|
||||||
|
// this is the default
|
||||||
|
resUnit = wxIMAGE_RESOLUTION_INCHES;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (wxImageResolution)resUnit;
|
||||||
|
}
|
||||||
|
|
||||||
wxBitmap m_bitmap;
|
wxBitmap m_bitmap;
|
||||||
double m_zoom;
|
double m_zoom;
|
||||||
|
|
||||||
@@ -631,7 +698,9 @@ enum
|
|||||||
ID_INFO,
|
ID_INFO,
|
||||||
ID_SHOWRAW,
|
ID_SHOWRAW,
|
||||||
ID_GRAPHICS,
|
ID_GRAPHICS,
|
||||||
ID_SHOWTHUMBNAIL
|
ID_SHOWTHUMBNAIL,
|
||||||
|
ID_COPY_IMAGE,
|
||||||
|
ID_PASTE_IMAGE
|
||||||
};
|
};
|
||||||
|
|
||||||
wxIMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame );
|
wxIMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame );
|
||||||
@@ -651,6 +720,8 @@ wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
|
|||||||
#if wxUSE_CLIPBOARD
|
#if wxUSE_CLIPBOARD
|
||||||
EVT_MENU(wxID_COPY, MyFrame::OnCopy)
|
EVT_MENU(wxID_COPY, MyFrame::OnCopy)
|
||||||
EVT_MENU(wxID_PASTE, MyFrame::OnPaste)
|
EVT_MENU(wxID_PASTE, MyFrame::OnPaste)
|
||||||
|
EVT_MENU(ID_COPY_IMAGE, MyFrame::OnCopyImage)
|
||||||
|
EVT_MENU(ID_PASTE_IMAGE, MyFrame::OnPasteImage)
|
||||||
#endif // wxUSE_CLIPBOARD
|
#endif // wxUSE_CLIPBOARD
|
||||||
EVT_UPDATE_UI(ID_NEW_HIDPI, MyFrame::OnUpdateNewFrameHiDPI)
|
EVT_UPDATE_UI(ID_NEW_HIDPI, MyFrame::OnUpdateNewFrameHiDPI)
|
||||||
wxEND_EVENT_TABLE()
|
wxEND_EVENT_TABLE()
|
||||||
@@ -686,8 +757,11 @@ MyFrame::MyFrame()
|
|||||||
|
|
||||||
#if wxUSE_CLIPBOARD
|
#if wxUSE_CLIPBOARD
|
||||||
wxMenu *menuClipboard = new wxMenu;
|
wxMenu *menuClipboard = new wxMenu;
|
||||||
menuClipboard->Append(wxID_COPY, "&Copy test image\tCtrl-C");
|
menuClipboard->Append(wxID_COPY, "&Copy test image as wxBitmap\tCtrl-C");
|
||||||
menuClipboard->Append(wxID_PASTE, "&Paste image\tCtrl-V");
|
menuClipboard->Append(wxID_PASTE, "&Paste image as wxBitmap\tCtrl-V");
|
||||||
|
menuClipboard->AppendSeparator();
|
||||||
|
menuClipboard->Append(ID_COPY_IMAGE, "Copy image as wxImage");
|
||||||
|
menuClipboard->Append(ID_PASTE_IMAGE, "Paste image as wxImage");
|
||||||
menu_bar->Append(menuClipboard, "&Clipboard");
|
menu_bar->Append(menuClipboard, "&Clipboard");
|
||||||
#endif // wxUSE_CLIPBOARD
|
#endif // wxUSE_CLIPBOARD
|
||||||
|
|
||||||
@@ -945,6 +1019,38 @@ void MyFrame::OnPaste(wxCommandEvent& WXUNUSED(event))
|
|||||||
wxTheClipboard->Close();
|
wxTheClipboard->Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyFrame::OnCopyImage(wxCommandEvent& WXUNUSED(evt))
|
||||||
|
{
|
||||||
|
wxImage img;
|
||||||
|
wxString filename = LoadUserImage(img);
|
||||||
|
if ( filename.empty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
wxImageDataObject* dobjImage = new wxImageDataObject;
|
||||||
|
dobjImage->SetImage(img);
|
||||||
|
|
||||||
|
wxClipboardLocker clipOpener;
|
||||||
|
if ( !wxTheClipboard->SetData(dobjImage) )
|
||||||
|
{
|
||||||
|
wxLogError("Failed to copy wxImage to clipboard");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyFrame::OnPasteImage(wxCommandEvent& WXUNUSED(evt))
|
||||||
|
{
|
||||||
|
wxImageDataObject dobjImage;
|
||||||
|
|
||||||
|
wxClipboardLocker clipOpener;
|
||||||
|
if ( !wxTheClipboard->GetData(dobjImage) )
|
||||||
|
{
|
||||||
|
wxLogMessage("No wxImage data in the clipboard");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new MyImageFrame(this, "Clipboard (wxImage)", dobjImage.GetImage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif // wxUSE_CLIPBOARD
|
#endif // wxUSE_CLIPBOARD
|
||||||
|
|
||||||
void MyFrame::OnThumbnail( wxCommandEvent &WXUNUSED(event) )
|
void MyFrame::OnThumbnail( wxCommandEvent &WXUNUSED(event) )
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
#include "wx/app.h"
|
#include "wx/app.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "wx/mstream.h"
|
||||||
#include "wx/textbuf.h"
|
#include "wx/textbuf.h"
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -620,6 +621,59 @@ bool wxCustomDataObject::SetData(size_t size, const void *buf)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxImageDataObject
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if defined(__WXMSW__)
|
||||||
|
#define wxIMAGE_FORMAT_DATA wxDF_PNG
|
||||||
|
#define wxIMAGE_FORMAT_BITMAP_TYPE wxBITMAP_TYPE_PNG
|
||||||
|
#define wxIMAGE_FORMAT_NAME "PNG"
|
||||||
|
#elif defined(__WXGTK__)
|
||||||
|
#define wxIMAGE_FORMAT_DATA wxDF_BITMAP
|
||||||
|
#define wxIMAGE_FORMAT_BITMAP_TYPE wxBITMAP_TYPE_PNG
|
||||||
|
#define wxIMAGE_FORMAT_NAME "PNG"
|
||||||
|
#elif defined(__WXOSX__)
|
||||||
|
#define wxIMAGE_FORMAT_DATA wxDF_BITMAP
|
||||||
|
#define wxIMAGE_FORMAT_BITMAP_TYPE wxBITMAP_TYPE_TIFF
|
||||||
|
#define wxIMAGE_FORMAT_NAME "TIFF"
|
||||||
|
#else
|
||||||
|
#define wxIMAGE_FORMAT_DATA wxDF_BITMAP
|
||||||
|
#define wxIMAGE_FORMAT_BITMAP_TYPE wxBITMAP_TYPE_PNG
|
||||||
|
#define wxIMAGE_FORMAT_NAME "PNG"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
wxImageDataObject::wxImageDataObject(const wxImage& image)
|
||||||
|
: wxCustomDataObject(wxIMAGE_FORMAT_DATA)
|
||||||
|
{
|
||||||
|
if ( image.IsOk() )
|
||||||
|
{
|
||||||
|
SetImage(image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxImageDataObject::SetImage(const wxImage& image)
|
||||||
|
{
|
||||||
|
wxCHECK_RET(wxImage::FindHandler(wxIMAGE_FORMAT_BITMAP_TYPE) != NULL,
|
||||||
|
wxIMAGE_FORMAT_NAME " image handler must be installed to use clipboard with image");
|
||||||
|
|
||||||
|
wxMemoryOutputStream mem;
|
||||||
|
image.SaveFile(mem, wxIMAGE_FORMAT_BITMAP_TYPE);
|
||||||
|
|
||||||
|
SetData(mem.GetLength(), mem.GetOutputStreamBuffer()->GetBufferStart());
|
||||||
|
}
|
||||||
|
|
||||||
|
wxImage wxImageDataObject::GetImage() const
|
||||||
|
{
|
||||||
|
wxCHECK_MSG(wxImage::FindHandler(wxIMAGE_FORMAT_BITMAP_TYPE) != NULL, wxNullImage,
|
||||||
|
wxIMAGE_FORMAT_NAME " image handler must be installed to use clipboard with image");
|
||||||
|
|
||||||
|
wxMemoryInputStream mem(GetData(), GetSize());
|
||||||
|
wxImage image;
|
||||||
|
image.LoadFile(mem, wxIMAGE_FORMAT_BITMAP_TYPE);
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// some common dnd related code
|
// some common dnd related code
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
@@ -73,6 +73,7 @@
|
|||||||
|
|
||||||
static bool gs_wxClipboardIsOpen = false;
|
static bool gs_wxClipboardIsOpen = false;
|
||||||
static int gs_htmlcfid = 0;
|
static int gs_htmlcfid = 0;
|
||||||
|
static int gs_pngcfid = 0;
|
||||||
|
|
||||||
bool wxOpenClipboard()
|
bool wxOpenClipboard()
|
||||||
{
|
{
|
||||||
@@ -136,6 +137,8 @@ bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat)
|
|||||||
wxDataFormat::NativeFormat cf = dataFormat.GetFormatId();
|
wxDataFormat::NativeFormat cf = dataFormat.GetFormatId();
|
||||||
if (cf == wxDF_HTML)
|
if (cf == wxDF_HTML)
|
||||||
cf = gs_htmlcfid;
|
cf = gs_htmlcfid;
|
||||||
|
else if ( cf == wxDF_PNG )
|
||||||
|
cf = gs_pngcfid;
|
||||||
|
|
||||||
if ( ::IsClipboardFormatAvailable(cf) )
|
if ( ::IsClipboardFormatAvailable(cf) )
|
||||||
{
|
{
|
||||||
@@ -162,6 +165,15 @@ bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat)
|
|||||||
|
|
||||||
|
|
||||||
#if !wxUSE_OLE_CLIPBOARD
|
#if !wxUSE_OLE_CLIPBOARD
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
struct wxRawImageData
|
||||||
|
{
|
||||||
|
size_t m_size;
|
||||||
|
void* m_data;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
bool wxSetClipboardData(wxDataFormat dataFormat,
|
bool wxSetClipboardData(wxDataFormat dataFormat,
|
||||||
const void *data,
|
const void *data,
|
||||||
int width, int height)
|
int width, int height)
|
||||||
@@ -414,6 +426,16 @@ bool wxSetClipboardData(wxDataFormat dataFormat,
|
|||||||
delete [] buf;
|
delete [] buf;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case wxDF_PNG:
|
||||||
|
{
|
||||||
|
const wxRawImageData* imgData = reinterpret_cast<const wxRawImageData*>(data);
|
||||||
|
|
||||||
|
GlobalPtr hImage(imgData->m_size, GMEM_MOVEABLE | GMEM_DDESHARE);
|
||||||
|
memcpy(GlobalPtrLock(hImage).Get(), imgData->m_data, imgData->m_size);
|
||||||
|
handle = ::SetClipboardData(gs_pngcfid, hImage);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( handle == 0 )
|
if ( handle == 0 )
|
||||||
@@ -515,9 +537,11 @@ bool wxClipboard::Flush()
|
|||||||
|
|
||||||
bool wxClipboard::Open()
|
bool wxClipboard::Open()
|
||||||
{
|
{
|
||||||
// Get clipboard id for HTML format...
|
// Get clipboard id for HTML and PNG formats...
|
||||||
if(!gs_htmlcfid)
|
if(!gs_htmlcfid)
|
||||||
gs_htmlcfid = RegisterClipboardFormat(wxT("HTML Format"));
|
gs_htmlcfid = RegisterClipboardFormat(wxT("HTML Format"));
|
||||||
|
if ( !gs_pngcfid )
|
||||||
|
gs_pngcfid = ::RegisterClipboardFormat(wxT("PNG"));
|
||||||
|
|
||||||
// OLE opens clipboard for us
|
// OLE opens clipboard for us
|
||||||
m_isOpened = true;
|
m_isOpened = true;
|
||||||
@@ -636,6 +660,16 @@ bool wxClipboard::AddData( wxDataObject *data )
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case wxDF_PNG:
|
||||||
|
{
|
||||||
|
wxCustomDataObject* imageDataObject = reinterpret_cast<wxCustomDataObject*>(data);
|
||||||
|
wxRawImageData imgData;
|
||||||
|
imgData.m_size = imageDataObject->GetDataSize();
|
||||||
|
imgData.m_data = imageDataObject->GetData();
|
||||||
|
bRet = wxSetClipboardData(format, &imgData);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
#if wxUSE_METAFILE
|
#if wxUSE_METAFILE
|
||||||
case wxDF_METAFILE:
|
case wxDF_METAFILE:
|
||||||
{
|
{
|
||||||
@@ -768,6 +802,8 @@ bool wxClipboard::GetData( wxDataObject& data )
|
|||||||
|
|
||||||
if (cf == wxDF_HTML)
|
if (cf == wxDF_HTML)
|
||||||
cf = gs_htmlcfid;
|
cf = gs_htmlcfid;
|
||||||
|
else if ( cf == wxDF_PNG )
|
||||||
|
cf = gs_pngcfid;
|
||||||
// if the format is not available, try the next one
|
// if the format is not available, try the next one
|
||||||
// this test includes implicit / sythetic formats
|
// this test includes implicit / sythetic formats
|
||||||
if ( !::IsClipboardFormatAvailable(cf) )
|
if ( !::IsClipboardFormatAvailable(cf) )
|
||||||
|
@@ -64,15 +64,15 @@
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
wxDataFormat HtmlFormatFixup(wxDataFormat format)
|
wxDataFormat NonStandardFormatsFixup(wxDataFormat format)
|
||||||
{
|
{
|
||||||
// Since the HTML format is dynamically registered, the wxDF_HTML
|
// Since the HTML and PNG formats are dynamically registered, the wxDF_HTML and wxDF_PNG
|
||||||
// format does not match the native constant in the way other formats do,
|
// formats do not match the native constants in the way other formats do,
|
||||||
// so for the format checks below to work, we must change the native
|
// so for the format checks below to work, we must change the native
|
||||||
// id to the wxDF_HTML constant.
|
// id to the wxDF_HTML or wxDF_PNG constant.
|
||||||
//
|
//
|
||||||
// But skip this for the standard constants which are never going to match
|
// But skip this for the standard constants which are never going to match
|
||||||
// wxDF_HTML anyhow.
|
// wxDF_HTML or wxDF_PNG anyhow.
|
||||||
if ( !format.IsStandard() )
|
if ( !format.IsStandard() )
|
||||||
{
|
{
|
||||||
wxChar szBuf[256];
|
wxChar szBuf[256];
|
||||||
@@ -80,6 +80,8 @@ wxDataFormat HtmlFormatFixup(wxDataFormat format)
|
|||||||
{
|
{
|
||||||
if ( wxStrcmp(szBuf, wxT("HTML Format")) == 0 )
|
if ( wxStrcmp(szBuf, wxT("HTML Format")) == 0 )
|
||||||
format = wxDF_HTML;
|
format = wxDF_HTML;
|
||||||
|
else if ( wxStrcmp(szBuf, wxT("PNG")) == 0 )
|
||||||
|
format = wxDF_PNG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -347,7 +349,7 @@ wxIDataObject::SaveSystemData(FORMATETC *pformatetc,
|
|||||||
|
|
||||||
bool wxDataFormat::operator==(wxDataFormatId format) const
|
bool wxDataFormat::operator==(wxDataFormatId format) const
|
||||||
{
|
{
|
||||||
return HtmlFormatFixup(*this).m_format == (NativeFormat)format;
|
return NonStandardFormatsFixup(*this).m_format == (NativeFormat)format;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxDataFormat::operator!=(wxDataFormatId format) const
|
bool wxDataFormat::operator!=(wxDataFormatId format) const
|
||||||
@@ -357,7 +359,7 @@ bool wxDataFormat::operator!=(wxDataFormatId format) const
|
|||||||
|
|
||||||
bool wxDataFormat::operator==(const wxDataFormat& format) const
|
bool wxDataFormat::operator==(const wxDataFormat& format) const
|
||||||
{
|
{
|
||||||
return HtmlFormatFixup(*this).m_format == HtmlFormatFixup(format).m_format;
|
return NonStandardFormatsFixup(*this).m_format == NonStandardFormatsFixup(format).m_format;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxDataFormat::operator!=(const wxDataFormat& format) const
|
bool wxDataFormat::operator!=(const wxDataFormat& format) const
|
||||||
@@ -367,7 +369,7 @@ bool wxDataFormat::operator!=(const wxDataFormat& format) const
|
|||||||
|
|
||||||
bool wxDataFormat::operator==(NativeFormat format) const
|
bool wxDataFormat::operator==(NativeFormat format) const
|
||||||
{
|
{
|
||||||
return HtmlFormatFixup(*this).m_format == format;
|
return NonStandardFormatsFixup(*this).m_format == format;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxDataFormat::operator!=(NativeFormat format) const
|
bool wxDataFormat::operator!=(NativeFormat format) const
|
||||||
@@ -422,10 +424,12 @@ wxIEnumFORMATETC::wxIEnumFORMATETC(const wxDataFormat *formats, ULONG nCount)
|
|||||||
m_nCount = nCount;
|
m_nCount = nCount;
|
||||||
m_formats = new CLIPFORMAT[nCount];
|
m_formats = new CLIPFORMAT[nCount];
|
||||||
for ( ULONG n = 0; n < nCount; n++ ) {
|
for ( ULONG n = 0; n < nCount; n++ ) {
|
||||||
if (formats[n].GetFormatId() != wxDF_HTML)
|
if ( formats[n].GetFormatId() == wxDF_HTML )
|
||||||
m_formats[n] = formats[n].GetFormatId();
|
|
||||||
else
|
|
||||||
m_formats[n] = ::RegisterClipboardFormat(wxT("HTML Format"));
|
m_formats[n] = ::RegisterClipboardFormat(wxT("HTML Format"));
|
||||||
|
else if ( formats[n].GetFormatId() == wxDF_PNG )
|
||||||
|
m_formats[n] = ::RegisterClipboardFormat(wxT("PNG"));
|
||||||
|
else
|
||||||
|
m_formats[n] = formats[n].GetFormatId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -540,7 +544,7 @@ STDMETHODIMP wxIDataObject::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
|
|||||||
// for the bitmaps and metafiles we use the handles instead of global memory
|
// for the bitmaps and metafiles we use the handles instead of global memory
|
||||||
// to pass the data
|
// to pass the data
|
||||||
wxDataFormat format = (wxDataFormat::NativeFormat)pformatetcIn->cfFormat;
|
wxDataFormat format = (wxDataFormat::NativeFormat)pformatetcIn->cfFormat;
|
||||||
format = HtmlFormatFixup(format);
|
format = NonStandardFormatsFixup(format);
|
||||||
|
|
||||||
// is this system data?
|
// is this system data?
|
||||||
if ( GetSystemData(format, pmedium) )
|
if ( GetSystemData(format, pmedium) )
|
||||||
@@ -690,7 +694,7 @@ STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc,
|
|||||||
{
|
{
|
||||||
wxDataFormat format = pformatetc->cfFormat;
|
wxDataFormat format = pformatetc->cfFormat;
|
||||||
|
|
||||||
format = HtmlFormatFixup(format);
|
format = NonStandardFormatsFixup(format);
|
||||||
|
|
||||||
// check if this format is supported
|
// check if this format is supported
|
||||||
if ( !m_pDataObject->IsSupported(format, wxDataObject::Set) ) {
|
if ( !m_pDataObject->IsSupported(format, wxDataObject::Set) ) {
|
||||||
@@ -737,6 +741,9 @@ STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc,
|
|||||||
size = sizeof(METAFILEPICT);
|
size = sizeof(METAFILEPICT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case wxDF_PNG:
|
||||||
|
wxFALLTHROUGH;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
size = ptr.GetSize();
|
size = ptr.GetSize();
|
||||||
|
|
||||||
@@ -816,7 +823,7 @@ STDMETHODIMP wxIDataObject::QueryGetData(FORMATETC *pformatetc)
|
|||||||
|
|
||||||
// and now check the type of data requested
|
// and now check the type of data requested
|
||||||
wxDataFormat format = pformatetc->cfFormat;
|
wxDataFormat format = pformatetc->cfFormat;
|
||||||
format = HtmlFormatFixup(format);
|
format = NonStandardFormatsFixup(format);
|
||||||
|
|
||||||
if ( m_pDataObject->IsSupportedFormat(format) ) {
|
if ( m_pDataObject->IsSupportedFormat(format) ) {
|
||||||
wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::QueryGetData: %s ok"),
|
wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::QueryGetData: %s ok"),
|
||||||
|
@@ -26,6 +26,8 @@
|
|||||||
#include "wx/mstream.h"
|
#include "wx/mstream.h"
|
||||||
#include "wx/zstream.h"
|
#include "wx/zstream.h"
|
||||||
#include "wx/wfstream.h"
|
#include "wx/wfstream.h"
|
||||||
|
#include "wx/clipbrd.h"
|
||||||
|
#include "wx/dataobj.h"
|
||||||
|
|
||||||
#include "testimage.h"
|
#include "testimage.h"
|
||||||
|
|
||||||
@@ -1942,6 +1944,32 @@ TEST_CASE("wxImage::RGBtoHSV", "[image][rgb][hsv]")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("wxImage::Clipboard", "[image][clipboard]")
|
||||||
|
{
|
||||||
|
#if wxUSE_CLIPBOARD && wxUSE_DATAOBJ
|
||||||
|
wxInitAllImageHandlers();
|
||||||
|
|
||||||
|
wxImage imgOriginal;
|
||||||
|
REQUIRE(imgOriginal.LoadFile("horse.png") == true);
|
||||||
|
|
||||||
|
wxImageDataObject* dobj1 = new wxImageDataObject(imgOriginal);
|
||||||
|
{
|
||||||
|
wxClipboardLocker lockClip;
|
||||||
|
REQUIRE(wxTheClipboard->SetData(dobj1) == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
wxImageDataObject dobj2;
|
||||||
|
{
|
||||||
|
wxClipboardLocker lockClip;
|
||||||
|
REQUIRE(wxTheClipboard->GetData(dobj2) == true);
|
||||||
|
}
|
||||||
|
wxImage imgRetrieved = dobj2.GetImage();
|
||||||
|
REQUIRE(imgRetrieved.IsOk());
|
||||||
|
|
||||||
|
CompareImage(*wxImage::FindHandler(wxBITMAP_TYPE_PNG), imgRetrieved, 0, &imgOriginal);
|
||||||
|
#endif // wxUSE_CLIPBOARD && wxUSE_DATAOBJ
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO: add lots of more tests to wxImage functions
|
TODO: add lots of more tests to wxImage functions
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user