1. more drag and drop and clipboard changes:
a) OLE clipboard works fine b) wxBitmapDataObject now accepts DIBs (but doesn't give them back :-( ) c) bugs in sample corrected 2. wxFatalExit() replaced with wxFAIL_MSG() in bitmap.cpp and dcmemory.cpp 3. wxFrame::ClientToScreen and ScreenToClient() replaced with DoXXX() - like this, they don't hide the base class versions git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@4039 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
23d277e683
commit
d59ceba572
@ -83,10 +83,17 @@ public:
|
||||
|
||||
// clears wxTheClipboard and the system's clipboard if possible
|
||||
virtual void Clear();
|
||||
|
||||
/// X11 has two clipboards which get selected by this call. Empty on MSW.
|
||||
|
||||
// flushes the clipboard: this means that the data which is currently on
|
||||
// clipboard will stay available even after the application exits (possibly
|
||||
// eating memory), otherwise the clipboard will be emptied on exit
|
||||
virtual bool Flush();
|
||||
|
||||
// X11 has two clipboards which get selected by this call. Empty on MSW.
|
||||
void UsePrimarySelection( bool WXUNUSED(primary) = FALSE ) { }
|
||||
|
||||
|
||||
private:
|
||||
bool m_clearOnExit;
|
||||
};
|
||||
|
||||
// The global clipboard object
|
||||
|
@ -57,9 +57,6 @@ public:
|
||||
|
||||
virtual bool Destroy();
|
||||
|
||||
virtual void ClientToScreen(int *x, int *y) const;
|
||||
virtual void ScreenToClient(int *x, int *y) const;
|
||||
|
||||
void OnSize(wxSizeEvent& event);
|
||||
void OnMenuHighlight(wxMenuEvent& event);
|
||||
void OnActivate(wxActivateEvent& event);
|
||||
@ -179,6 +176,9 @@ protected:
|
||||
|
||||
virtual void DoSetClientSize(int width, int height);
|
||||
|
||||
virtual void DoClientToScreen(int *x, int *y) const;
|
||||
virtual void DoScreenToClient(int *x, int *y) const;
|
||||
|
||||
// a plug in for MDI frame classes which need to do something special when
|
||||
// the menubar is set
|
||||
virtual void InternalSetMenuBar();
|
||||
|
@ -23,8 +23,12 @@ public:
|
||||
typedef unsigned int NativeFormat;
|
||||
|
||||
wxDataFormat(NativeFormat format = wxDF_INVALID) { m_format = format; }
|
||||
wxDataFormat(const wxChar *format) { SetId(format); }
|
||||
|
||||
wxDataFormat& operator=(NativeFormat format)
|
||||
{ m_format = format; return *this; }
|
||||
wxDataFormat& operator=(const wxDataFormat& format)
|
||||
{ m_format = format.m_format; return *this; }
|
||||
|
||||
// defautl copy ctor/assignment operators ok
|
||||
|
||||
@ -62,14 +66,11 @@ private:
|
||||
// ----------------------------------------------------------------------------
|
||||
// forward declarations
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
struct IDataObject;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxDataObject is a "smart" and polymorphic piece of data.
|
||||
//
|
||||
// TODO it's currently "read-only" from COM point of view, i.e. we don't
|
||||
// support SetData. We don't support all advise functions neither (but
|
||||
// it's easy to do if we really want them)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class WXDLLEXPORT wxDataObject
|
||||
@ -80,18 +81,26 @@ public:
|
||||
virtual ~wxDataObject();
|
||||
|
||||
// pure virtuals to override
|
||||
// get the best suited format for our data
|
||||
// get the best suited format for rendering our data
|
||||
virtual wxDataFormat GetPreferredFormat() const = 0;
|
||||
// get the number of formats we support
|
||||
virtual size_t GetFormatCount() const
|
||||
// get the number of formats we support: it is understood that if we
|
||||
// can accept data in some format, then we can render data in this
|
||||
// format as well, but the contrary is not necessarily true. For the
|
||||
// default value of the argument, all formats we support should be
|
||||
// returned, but if outputOnlyToo == FALSE, then we should only return
|
||||
// the formats which our SetData() understands
|
||||
virtual size_t GetFormatCount(bool outputOnlyToo = TRUE) const
|
||||
{ return 1; }
|
||||
// return all formats in the provided array (of size GetFormatCount())
|
||||
virtual void GetAllFormats(wxDataFormat *formats) const
|
||||
virtual void GetAllFormats(wxDataFormat *formats,
|
||||
bool outputOnlyToo = TRUE) const
|
||||
{ formats[0] = GetPreferredFormat(); }
|
||||
// get the (total) size of data for the given format
|
||||
virtual size_t GetDataSize(const wxDataFormat& format) const = 0;
|
||||
// copy raw data (in the specified format) to provided pointer
|
||||
virtual void GetDataHere(const wxDataFormat& format, void *pBuf) const = 0;
|
||||
virtual bool GetDataHere(const wxDataFormat& format, void *buf) const = 0;
|
||||
// get data from the buffer (in the given format)
|
||||
virtual bool SetData(const wxDataFormat& format, const void *buf) = 0;
|
||||
|
||||
// accessors
|
||||
// retrieve IDataObject interface (for other OLE related classes)
|
||||
@ -105,6 +114,13 @@ public:
|
||||
// format) -- now uses GetAllFormats()
|
||||
virtual bool IsSupportedFormat(const wxDataFormat& format) const;
|
||||
|
||||
// implementation only from now on
|
||||
// -------------------------------
|
||||
|
||||
// tell the object that it should be now owned by IDataObject - i.e. when
|
||||
// it is deleted, it should delete us as well
|
||||
void SetAutoDelete();
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
// function to return symbolic name of clipboard format (for debug messages)
|
||||
static const char *GetFormatName(wxDataFormat format);
|
||||
@ -133,8 +149,10 @@ public:
|
||||
{ return format == wxDF_TEXT || format == wxDF_LOCALE; }
|
||||
virtual size_t GetDataSize(const wxDataFormat& format) const
|
||||
{ return m_strText.Len() + 1; } // +1 for trailing '\0'of course
|
||||
virtual void GetDataHere(const wxDataFormat& format, void *pBuf) const
|
||||
{ memcpy(pBuf, m_strText.c_str(), GetDataSize(format)); }
|
||||
virtual bool GetDataHere(const wxDataFormat& format, void *buf) const
|
||||
{ memcpy(buf, m_strText.c_str(), GetDataSize(format)); return TRUE; }
|
||||
virtual bool SetData(const wxDataFormat& format, const void *buf)
|
||||
{ m_strText = (const wxChar *)buf; return TRUE; }
|
||||
|
||||
// additional helpers
|
||||
void SetText(const wxString& strText) { m_strText = strText; }
|
||||
@ -144,16 +162,10 @@ private:
|
||||
wxString m_strText;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// TODO: wx{Bitmap|Metafile|...}DataObject
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxBitmapDataObject is a specialization of wxDataObject for bitmap data
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// TODO: implement OLE side of things. At present, it's just for clipboard
|
||||
// use.
|
||||
#include "wx/bitmap.h"
|
||||
|
||||
class WXDLLEXPORT wxBitmapDataObject : public wxDataObject
|
||||
@ -168,12 +180,13 @@ public:
|
||||
const wxBitmap GetBitmap() const { return m_bitmap; }
|
||||
|
||||
// implement base class pure virtuals
|
||||
virtual wxDataFormat GetPreferredFormat() const
|
||||
{ return wxDF_BITMAP; }
|
||||
virtual bool IsSupportedFormat(const wxDataFormat& format) const
|
||||
{ return format == wxDF_BITMAP; }
|
||||
virtual wxDataFormat GetPreferredFormat() const { return wxDF_BITMAP; }
|
||||
virtual size_t GetFormatCount(bool outputOnlyToo = TRUE) const;
|
||||
virtual void GetAllFormats(wxDataFormat *formats,
|
||||
bool outputOnlyToo = TRUE) const;
|
||||
virtual size_t GetDataSize(const wxDataFormat& format) const;
|
||||
virtual void GetDataHere(const wxDataFormat& format, void *pBuf) const;
|
||||
virtual bool GetDataHere(const wxDataFormat& format, void *buf) const;
|
||||
virtual bool SetData(const wxDataFormat& format, const void *buf);
|
||||
|
||||
private:
|
||||
wxBitmap m_bitmap;
|
||||
|
@ -102,12 +102,13 @@ public:
|
||||
void OnPaste(wxCommandEvent& event);
|
||||
void OnCopyBitmap(wxCommandEvent& event);
|
||||
void OnPasteBitmap(wxCommandEvent& event);
|
||||
void OnClipboardHasText(wxCommandEvent& event);
|
||||
void OnClipboardHasBitmap(wxCommandEvent& event);
|
||||
|
||||
void OnLeftDown(wxMouseEvent& event);
|
||||
void OnRightDown(wxMouseEvent& event);
|
||||
|
||||
void OnUpdateUIPasteText(wxUpdateUIEvent& event);
|
||||
void OnUpdateUIPasteBitmap(wxUpdateUIEvent& event);
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
private:
|
||||
@ -146,11 +147,7 @@ public:
|
||||
}
|
||||
|
||||
// the functions used for drag-and-drop: they dump and restore a shape into
|
||||
// some bitwise-copiable data
|
||||
//
|
||||
// NB: here we profit from the fact that wxPoint, wxSize and wxColour are
|
||||
// POD (plain old data) and so can be copied directly - but it wouldn't
|
||||
// work for other types!
|
||||
// some bitwise-copiable data (might use streams too...)
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
// restore from buffer
|
||||
@ -179,6 +176,8 @@ public:
|
||||
const wxColour& GetColour() const { return m_col; }
|
||||
const wxSize& GetSize() const { return m_size; }
|
||||
|
||||
void Move(const wxPoint& pos) { m_pos = pos; }
|
||||
|
||||
// to implement in derived classes
|
||||
virtual Kind GetKind() const = 0;
|
||||
|
||||
@ -307,6 +306,9 @@ public:
|
||||
m_hasBitmap = FALSE;
|
||||
}
|
||||
|
||||
// accessors
|
||||
DnDShape *GetShape() const { return m_shape; }
|
||||
|
||||
// implement base class pure virtuals
|
||||
// ----------------------------------
|
||||
|
||||
@ -315,16 +317,26 @@ public:
|
||||
return m_formatShape;
|
||||
}
|
||||
|
||||
virtual size_t GetFormatCount() const
|
||||
virtual size_t GetFormatCount(bool outputOnlyToo) const
|
||||
{
|
||||
// +1 for our custom format
|
||||
return m_dataobj.GetFormatCount() + 1;
|
||||
// our custom format is supported by both GetData() and SetData()
|
||||
size_t nFormats = 1;
|
||||
if ( outputOnlyToo )
|
||||
{
|
||||
// but the bitmap format(s) are only supported for output
|
||||
nFormats += m_dataobj.GetFormatCount();
|
||||
}
|
||||
|
||||
return nFormats;
|
||||
}
|
||||
|
||||
virtual void GetAllFormats(wxDataFormat *formats) const
|
||||
virtual void GetAllFormats(wxDataFormat *formats, bool outputOnlyToo) const
|
||||
{
|
||||
formats[0] = m_formatShape;
|
||||
m_dataobj.GetAllFormats(&formats[1]);
|
||||
if ( outputOnlyToo )
|
||||
{
|
||||
m_dataobj.GetAllFormats(&formats[1]);
|
||||
}
|
||||
}
|
||||
|
||||
virtual size_t GetDataSize(const wxDataFormat& format) const
|
||||
@ -335,8 +347,6 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
wxASSERT_MSG( format == wxDF_BITMAP, "unsupported format" );
|
||||
|
||||
if ( !m_hasBitmap )
|
||||
CreateBitmap();
|
||||
|
||||
@ -344,11 +354,13 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void GetDataHere(const wxDataFormat& format, void *pBuf) const
|
||||
virtual bool GetDataHere(const wxDataFormat& format, void *pBuf) const
|
||||
{
|
||||
if ( format == m_formatShape )
|
||||
{
|
||||
m_shape->GetDataHere(pBuf);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -357,10 +369,23 @@ public:
|
||||
if ( !m_hasBitmap )
|
||||
CreateBitmap();
|
||||
|
||||
m_dataobj.GetDataHere(format, pBuf);
|
||||
return m_dataobj.GetDataHere(format, pBuf);
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool SetData(const wxDataFormat& format, const void *buf)
|
||||
{
|
||||
wxCHECK_MSG( format == m_formatShape, FALSE, "unsupported format" );
|
||||
|
||||
delete m_shape;
|
||||
m_shape = DnDShape::New(buf);
|
||||
|
||||
// the shape has changed
|
||||
m_hasBitmap = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
private:
|
||||
// creates a bitmap and assigns it to m_dataobj (also sets m_hasBitmap)
|
||||
void CreateBitmap() const;
|
||||
@ -422,14 +447,25 @@ public:
|
||||
void SetShape(DnDShape *shape);
|
||||
|
||||
// callbacks
|
||||
void OnNewShape(wxCommandEvent& event);
|
||||
void OnEditShape(wxCommandEvent& event);
|
||||
void OnClearShape(wxCommandEvent& event);
|
||||
|
||||
void OnCopyShape(wxCommandEvent& event);
|
||||
void OnPasteShape(wxCommandEvent& event);
|
||||
|
||||
void OnUpdateUICopy(wxUpdateUIEvent& event);
|
||||
void OnUpdateUIPaste(wxUpdateUIEvent& event);
|
||||
|
||||
void OnDrag(wxMouseEvent& event);
|
||||
void OnEdit(wxMouseEvent& event);
|
||||
void OnPaint(wxPaintEvent& event);
|
||||
void OnDrop(long x, long y, DnDShape *shape);
|
||||
|
||||
private:
|
||||
DnDShape *m_shape;
|
||||
|
||||
static DnDShapeFrame *ms_lastDropTarget;
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
@ -486,10 +522,13 @@ enum
|
||||
Menu_Paste,
|
||||
Menu_CopyBitmap,
|
||||
Menu_PasteBitmap,
|
||||
Menu_HasText,
|
||||
Menu_HasBitmap,
|
||||
Menu_ToBeGreyed, /* for testing */
|
||||
Menu_ToBeDeleted, /* for testing */
|
||||
Menu_Shape_New = 500,
|
||||
Menu_Shape_Edit,
|
||||
Menu_Shape_Clear,
|
||||
Menu_ShapeClipboard_Copy,
|
||||
Menu_ShapeClipboard_Paste,
|
||||
Button_Colour = 1001
|
||||
};
|
||||
|
||||
@ -504,8 +543,9 @@ BEGIN_EVENT_TABLE(DnDFrame, wxFrame)
|
||||
EVT_MENU(Menu_Paste, DnDFrame::OnPaste)
|
||||
EVT_MENU(Menu_CopyBitmap, DnDFrame::OnCopyBitmap)
|
||||
EVT_MENU(Menu_PasteBitmap,DnDFrame::OnPasteBitmap)
|
||||
EVT_MENU(Menu_HasText, DnDFrame::OnClipboardHasText)
|
||||
EVT_MENU(Menu_HasBitmap, DnDFrame::OnClipboardHasBitmap)
|
||||
|
||||
EVT_UPDATE_UI(Menu_Paste, DnDFrame::OnUpdateUIPasteText)
|
||||
EVT_UPDATE_UI(Menu_PasteBitmap, DnDFrame::OnUpdateUIPasteBitmap)
|
||||
|
||||
EVT_LEFT_DOWN( DnDFrame::OnLeftDown)
|
||||
EVT_RIGHT_DOWN( DnDFrame::OnRightDown)
|
||||
@ -513,8 +553,18 @@ BEGIN_EVENT_TABLE(DnDFrame, wxFrame)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
BEGIN_EVENT_TABLE(DnDShapeFrame, wxFrame)
|
||||
EVT_RIGHT_DOWN(DnDShapeFrame::OnDrag)
|
||||
EVT_LEFT_DCLICK(DnDShapeFrame::OnEdit)
|
||||
EVT_MENU(Menu_Shape_New, DnDShapeFrame::OnNewShape)
|
||||
EVT_MENU(Menu_Shape_Edit, DnDShapeFrame::OnEditShape)
|
||||
EVT_MENU(Menu_Shape_Clear, DnDShapeFrame::OnClearShape)
|
||||
|
||||
EVT_MENU(Menu_ShapeClipboard_Copy, DnDShapeFrame::OnCopyShape)
|
||||
EVT_MENU(Menu_ShapeClipboard_Paste, DnDShapeFrame::OnPasteShape)
|
||||
|
||||
EVT_UPDATE_UI(Menu_ShapeClipboard_Copy, DnDShapeFrame::OnUpdateUICopy)
|
||||
EVT_UPDATE_UI(Menu_ShapeClipboard_Paste, DnDShapeFrame::OnUpdateUIPaste)
|
||||
|
||||
EVT_LEFT_DOWN(DnDShapeFrame::OnDrag)
|
||||
|
||||
EVT_PAINT(DnDShapeFrame::OnPaint)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
@ -567,7 +617,7 @@ DnDFrame::DnDFrame(wxFrame *frame, char *title, int x, int y, int w, int h)
|
||||
file_menu->Append(Menu_Quit, "E&xit");
|
||||
|
||||
wxMenu *log_menu = new wxMenu;
|
||||
log_menu->Append(Menu_Clear, "Clear");
|
||||
log_menu->Append(Menu_Clear, "Clear\tDel");
|
||||
|
||||
wxMenu *help_menu = new wxMenu;
|
||||
help_menu->Append(Menu_Help, "&Help...");
|
||||
@ -578,11 +628,8 @@ DnDFrame::DnDFrame(wxFrame *frame, char *title, int x, int y, int w, int h)
|
||||
clip_menu->Append(Menu_Copy, "&Copy text\tCtrl+C");
|
||||
clip_menu->Append(Menu_Paste, "&Paste text\tCtrl+V");
|
||||
clip_menu->AppendSeparator();
|
||||
clip_menu->Append(Menu_CopyBitmap, "&Copy bitmap");
|
||||
clip_menu->Append(Menu_PasteBitmap, "&Paste bitmap");
|
||||
clip_menu->AppendSeparator();
|
||||
clip_menu->Append(Menu_HasText, "Clipboard has &text\tCtrl+T");
|
||||
clip_menu->Append(Menu_HasBitmap, "Clipboard has a &bitmap\tCtrl+B");
|
||||
clip_menu->Append(Menu_CopyBitmap, "&Copy bitmap\tAlt+C");
|
||||
clip_menu->Append(Menu_PasteBitmap, "&Paste bitmap\tAlt+V");
|
||||
|
||||
wxMenuBar *menu_bar = new wxMenuBar;
|
||||
menu_bar->Append(file_menu, "&File");
|
||||
@ -598,12 +645,14 @@ DnDFrame::DnDFrame(wxFrame *frame, char *title, int x, int y, int w, int h)
|
||||
|
||||
wxString strFile("Drop files here!"), strText("Drop text on me");
|
||||
|
||||
m_ctrlFile = new wxListBox(this, -1, pos, size, 1, &strFile, wxLB_HSCROLL | wxLB_ALWAYS_SB );
|
||||
m_ctrlText = new wxListBox(this, -1, pos, size, 1, &strText, wxLB_HSCROLL | wxLB_ALWAYS_SB );
|
||||
m_ctrlFile = new wxListBox(this, -1, pos, size, 1, &strFile,
|
||||
wxLB_HSCROLL | wxLB_ALWAYS_SB );
|
||||
m_ctrlText = new wxListBox(this, -1, pos, size, 1, &strText,
|
||||
wxLB_HSCROLL | wxLB_ALWAYS_SB );
|
||||
|
||||
m_ctrlLog = new wxTextCtrl(this, -1, "", pos, size,
|
||||
wxTE_MULTILINE | wxTE_READONLY |
|
||||
wxSUNKEN_BORDER );
|
||||
wxTE_MULTILINE | wxTE_READONLY |
|
||||
wxSUNKEN_BORDER );
|
||||
|
||||
// redirect log messages to the text window and switch on OLE messages
|
||||
// logging
|
||||
@ -637,7 +686,7 @@ DnDFrame::DnDFrame(wxFrame *frame, char *title, int x, int y, int w, int h)
|
||||
c = new wxLayoutConstraints;
|
||||
c->left.SameAs (this, wxLeft);
|
||||
c->right.SameAs (this, wxRight);
|
||||
c->height.PercentOf(this, wxHeight, 30);
|
||||
c->height.PercentOf(this, wxHeight, 50);
|
||||
c->top.SameAs(m_ctrlText, wxBottom);
|
||||
m_ctrlLog->SetConstraints(c);
|
||||
|
||||
@ -659,50 +708,23 @@ void DnDFrame::OnPaint(wxPaintEvent& WXUNUSED(event))
|
||||
dc.SetFont( wxFont( 24, wxDECORATIVE, wxNORMAL, wxNORMAL, FALSE, "charter" ) );
|
||||
dc.DrawText( "Drag text from here!", 20, h-50 );
|
||||
|
||||
if (m_bitmap.Ok())
|
||||
dc.DrawBitmap( m_bitmap, 280, h-120, TRUE );
|
||||
if ( m_bitmap.Ok() )
|
||||
{
|
||||
// 4/5 is 80% taken by other windows, 20 is arbitrary margin
|
||||
dc.DrawBitmap(m_bitmap,
|
||||
w - m_bitmap.GetWidth() - 20,
|
||||
(4*h)/5 + 20);
|
||||
}
|
||||
}
|
||||
|
||||
void DnDFrame::OnClipboardHasText(wxCommandEvent& WXUNUSED(event))
|
||||
void DnDFrame::OnUpdateUIPasteText(wxUpdateUIEvent& event)
|
||||
{
|
||||
if ( !wxTheClipboard->Open() )
|
||||
{
|
||||
wxLogError( _T("Can't open clipboard.") );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !wxTheClipboard->IsSupported( wxDF_TEXT ) )
|
||||
{
|
||||
wxLogMessage( _T("No text on the clipboard") );
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogMessage( _T("There is text on the clipboard") );
|
||||
}
|
||||
|
||||
wxTheClipboard->Close();
|
||||
event.Enable( wxTheClipboard->IsSupported(wxDF_TEXT) );
|
||||
}
|
||||
|
||||
void DnDFrame::OnClipboardHasBitmap(wxCommandEvent& WXUNUSED(event))
|
||||
void DnDFrame::OnUpdateUIPasteBitmap(wxUpdateUIEvent& event)
|
||||
{
|
||||
if ( !wxTheClipboard->Open() )
|
||||
{
|
||||
wxLogError( _T("Can't open clipboard.") );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !wxTheClipboard->IsSupported( wxDF_BITMAP ) )
|
||||
{
|
||||
wxLogMessage( _T("No bitmap on the clipboard") );
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogMessage( _T("There is a bitmap on the clipboard") );
|
||||
}
|
||||
|
||||
wxTheClipboard->Close();
|
||||
event.Enable( wxTheClipboard->IsSupported(wxDF_BITMAP) );
|
||||
}
|
||||
|
||||
void DnDFrame::OnNewFrame(wxCommandEvent& WXUNUSED(event))
|
||||
@ -1097,6 +1119,8 @@ void DnDShapeDialog::OnColour(wxCommandEvent& WXUNUSED(event))
|
||||
// DnDShapeFrame
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
DnDShapeFrame *DnDShapeFrame::ms_lastDropTarget = NULL;
|
||||
|
||||
DnDShapeFrame::DnDShapeFrame(wxFrame *parent)
|
||||
: wxFrame(parent, -1, "Shape Frame",
|
||||
wxDefaultPosition, wxSize(250, 150))
|
||||
@ -1105,7 +1129,23 @@ DnDShapeFrame::DnDShapeFrame(wxFrame *parent)
|
||||
|
||||
CreateStatusBar();
|
||||
|
||||
SetStatusText("Double click the frame to create a shape");
|
||||
wxMenu *menuShape = new wxMenu;
|
||||
menuShape->Append(Menu_Shape_New, "&New default shape\tCtrl-S");
|
||||
menuShape->Append(Menu_Shape_Edit, "&Edit shape\tCtrl-E");
|
||||
menuShape->AppendSeparator();
|
||||
menuShape->Append(Menu_Shape_Clear, "&Clear shape\tDel");
|
||||
|
||||
wxMenu *menuClipboard = new wxMenu;
|
||||
menuClipboard->Append(Menu_ShapeClipboard_Copy, "&Copy\tCtrl-C");
|
||||
menuClipboard->Append(Menu_ShapeClipboard_Paste, "&Paste\tCtrl-V");
|
||||
|
||||
wxMenuBar *menubar = new wxMenuBar;
|
||||
menubar->Append(menuShape, "&Shape");
|
||||
menubar->Append(menuClipboard, "&Clipboard");
|
||||
|
||||
SetMenuBar(menubar);
|
||||
|
||||
SetStatusText("Press Ctrl-S to create a new shape");
|
||||
|
||||
SetDropTarget(new DnDShapeDropTarget(this));
|
||||
|
||||
@ -1156,7 +1196,11 @@ void DnDShapeFrame::OnDrag(wxMouseEvent& event)
|
||||
|
||||
case wxDragMove:
|
||||
pc = "moved";
|
||||
SetShape(NULL);
|
||||
if ( ms_lastDropTarget != this )
|
||||
{
|
||||
// don't delete the shape if we dropped it on ourselves!
|
||||
SetShape(NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
case wxDragCancel:
|
||||
@ -1171,7 +1215,7 @@ void DnDShapeFrame::OnDrag(wxMouseEvent& event)
|
||||
//else: status text already set
|
||||
}
|
||||
|
||||
void DnDShapeFrame::OnEdit(wxMouseEvent& event)
|
||||
void DnDShapeFrame::OnEditShape(wxCommandEvent& event)
|
||||
{
|
||||
DnDShapeDialog dlg(this, m_shape);
|
||||
if ( dlg.ShowModal() == wxID_OK )
|
||||
@ -1180,11 +1224,52 @@ void DnDShapeFrame::OnEdit(wxMouseEvent& event)
|
||||
|
||||
if ( m_shape )
|
||||
{
|
||||
SetStatusText("Right click now drag the shape to another frame");
|
||||
SetStatusText("You can now drag the shape to another frame");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DnDShapeFrame::OnNewShape(wxCommandEvent& event)
|
||||
{
|
||||
SetShape(new DnDEllipticShape(wxPoint(10, 10), wxSize(80, 60), *wxRED));
|
||||
|
||||
SetStatusText("You can now drag the shape to another frame");
|
||||
}
|
||||
|
||||
void DnDShapeFrame::OnClearShape(wxCommandEvent& event)
|
||||
{
|
||||
SetShape(NULL);
|
||||
}
|
||||
|
||||
void DnDShapeFrame::OnCopyShape(wxCommandEvent& event)
|
||||
{
|
||||
if ( m_shape )
|
||||
wxTheClipboard->AddData(new DnDShapeDataObject(m_shape));
|
||||
}
|
||||
|
||||
void DnDShapeFrame::OnPasteShape(wxCommandEvent& event)
|
||||
{
|
||||
DnDShapeDataObject shapeDataObject(NULL);
|
||||
if ( wxTheClipboard->GetData(&shapeDataObject) )
|
||||
{
|
||||
SetShape(shapeDataObject.GetShape());
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogStatus("No shape on the clipboard");
|
||||
}
|
||||
}
|
||||
|
||||
void DnDShapeFrame::OnUpdateUICopy(wxUpdateUIEvent& event)
|
||||
{
|
||||
event.Enable( m_shape != NULL );
|
||||
}
|
||||
|
||||
void DnDShapeFrame::OnUpdateUIPaste(wxUpdateUIEvent& event)
|
||||
{
|
||||
event.Enable( wxTheClipboard->IsSupported(wxDataFormat(shapeFormatId)) );
|
||||
}
|
||||
|
||||
void DnDShapeFrame::OnPaint(wxPaintEvent& event)
|
||||
{
|
||||
if ( m_shape )
|
||||
@ -1195,10 +1280,13 @@ void DnDShapeFrame::OnPaint(wxPaintEvent& event)
|
||||
|
||||
void DnDShapeFrame::OnDrop(long x, long y, DnDShape *shape)
|
||||
{
|
||||
ms_lastDropTarget = this;
|
||||
|
||||
wxString s;
|
||||
s.Printf("Drop occured at (%ld, %ld)", x, y);
|
||||
s.Printf("Shape dropped at (%ld, %ld)", x, y);
|
||||
SetStatusText(s);
|
||||
|
||||
shape->Move(ScreenToClient(wxPoint(x, y)));
|
||||
SetShape(shape);
|
||||
}
|
||||
|
||||
@ -1238,9 +1326,15 @@ DnDShape *DnDShape::New(const void *buf)
|
||||
|
||||
void DnDShapeDataObject::CreateBitmap() const
|
||||
{
|
||||
wxBitmap bitmap;
|
||||
wxPoint pos = m_shape->GetPosition();
|
||||
wxSize size = m_shape->GetSize();
|
||||
int x = pos.x + size.x,
|
||||
y = pos.y + size.y;
|
||||
wxBitmap bitmap(x, y);
|
||||
wxMemoryDC dc;
|
||||
dc.SelectObject(bitmap);
|
||||
dc.SetBrush(wxBrush("white", wxSOLID));
|
||||
dc.Clear();
|
||||
m_shape->Draw(dc);
|
||||
dc.SelectObject(wxNullBitmap);
|
||||
|
||||
|
@ -77,22 +77,14 @@ wxBitmapRefData::wxBitmapRefData()
|
||||
|
||||
wxBitmapRefData::~wxBitmapRefData()
|
||||
{
|
||||
if (m_selectedInto)
|
||||
{
|
||||
wxChar buf[200];
|
||||
wxSprintf(buf, wxT("Bitmap was deleted without selecting out of wxMemoryDC %lX."), (unsigned long) m_selectedInto);
|
||||
wxFatalError(buf);
|
||||
}
|
||||
if (m_hBitmap)
|
||||
{
|
||||
DeleteObject((HBITMAP) m_hBitmap);
|
||||
}
|
||||
m_hBitmap = 0 ;
|
||||
wxASSERT_MSG( !m_selectedInto,
|
||||
wxT("deleting bitmap still selected into wxMemoryDC") );
|
||||
|
||||
if (m_bitmapMask)
|
||||
delete m_bitmapMask;
|
||||
m_bitmapMask = NULL;
|
||||
if ( m_hBitmap)
|
||||
DeleteObject((HBITMAP) m_hBitmap);
|
||||
|
||||
if ( m_bitmapMask )
|
||||
delete m_bitmapMask;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -143,12 +135,9 @@ bool wxBitmap::FreeResource(bool WXUNUSED(force))
|
||||
if ( !M_BITMAPDATA )
|
||||
return FALSE;
|
||||
|
||||
if (M_BITMAPDATA->m_selectedInto)
|
||||
{
|
||||
wxChar buf[200];
|
||||
wxSprintf(buf, wxT("Bitmap %lX was deleted without selecting out of wxMemoryDC %lX."), (unsigned long) this, (unsigned long) M_BITMAPDATA->m_selectedInto);
|
||||
wxFatalError(buf);
|
||||
}
|
||||
wxASSERT_MSG( !M_BITMAPDATA->m_selectedInto,
|
||||
wxT("freeing bitmap still selected into wxMemoryDC") );
|
||||
|
||||
if (M_BITMAPDATA->m_hBitmap)
|
||||
{
|
||||
DeleteObject((HBITMAP) M_BITMAPDATA->m_hBitmap);
|
||||
|
@ -57,14 +57,24 @@
|
||||
#include "wx/msw/private.h"
|
||||
#include "wx/msw/dib.h"
|
||||
|
||||
// wxDataObject is tied to OLE/drag and drop implementation,
|
||||
// therefore so is wxClipboard :-(
|
||||
#if wxUSE_DRAG_AND_DROP
|
||||
// wxDataObject is tied to OLE/drag and drop implementation, therefore so are
|
||||
// the functions using wxDataObject in wxClipboard
|
||||
#define wxUSE_DATAOBJ wxUSE_DRAG_AND_DROP
|
||||
|
||||
#if wxUSE_DATAOBJ
|
||||
#include "wx/dataobj.h"
|
||||
|
||||
static bool wxSetClipboardData(wxDataObject *data);
|
||||
// use OLE clipboard
|
||||
#define wxUSE_OLE_CLIPBOARD 1
|
||||
#else // !wxUSE_DATAOBJ
|
||||
// use Win clipboard API
|
||||
#define wxUSE_OLE_CLIPBOARD 0
|
||||
#endif
|
||||
|
||||
#if wxUSE_OLE_CLIPBOARD
|
||||
#include <ole2.h>
|
||||
#endif // wxUSE_OLE_CLIPBOARD
|
||||
|
||||
#ifdef __WIN16__
|
||||
#define memcpy hmemcpy
|
||||
#endif
|
||||
@ -136,41 +146,12 @@ bool wxIsClipboardOpened()
|
||||
|
||||
bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat)
|
||||
{
|
||||
return ::IsClipboardFormatAvailable(dataFormat) != 0;
|
||||
// for bitmaps, DIBs will also do
|
||||
return (::IsClipboardFormatAvailable(dataFormat) != 0) ||
|
||||
(dataFormat.GetFormatId() == CF_BITMAP &&
|
||||
::IsClipboardFormatAvailable(CF_DIB));
|
||||
}
|
||||
|
||||
#if wxUSE_DRAG_AND_DROP
|
||||
static bool wxSetClipboardData(wxDataObject *data)
|
||||
{
|
||||
wxDataFormat format = data->GetPreferredFormat();
|
||||
size_t size = data->GetDataSize(format);
|
||||
HANDLE hGlobal = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, size);
|
||||
if ( !hGlobal )
|
||||
{
|
||||
wxLogSysError(_("Failed to allocate %dKb of memory for clipboard "
|
||||
"transfer."), size / 1024);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LPVOID lpGlobalMemory = ::GlobalLock(hGlobal);
|
||||
|
||||
data->GetDataHere(format, lpGlobalMemory);
|
||||
|
||||
GlobalUnlock(hGlobal);
|
||||
|
||||
if ( !::SetClipboardData(format, hGlobal) )
|
||||
{
|
||||
wxLogSysError(_("Failed to set clipboard data in format %s"),
|
||||
wxDataObject::GetFormatName(format));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif // wxUSE_DRAG_AND_DROP
|
||||
|
||||
bool wxSetClipboardData(wxDataFormat dataFormat,
|
||||
const void *data,
|
||||
int width, int height)
|
||||
@ -223,7 +204,7 @@ bool wxSetClipboardData(wxDataFormat dataFormat,
|
||||
// NULL palette means to use the system one
|
||||
HANDLE hDIB = wxBitmapToDIB(hBitmap, (HPALETTE)NULL);
|
||||
handle = SetClipboardData(CF_DIB, hDIB);
|
||||
#endif
|
||||
#endif // wxUSE_IMAGE_LOADING_IN_MSW
|
||||
break;
|
||||
}
|
||||
|
||||
@ -442,20 +423,51 @@ wxClipboard* wxTheClipboard = (wxClipboard *)NULL;
|
||||
|
||||
wxClipboard::wxClipboard()
|
||||
{
|
||||
m_clearOnExit = FALSE;
|
||||
}
|
||||
|
||||
wxClipboard::~wxClipboard()
|
||||
{
|
||||
Clear();
|
||||
if ( m_clearOnExit )
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
}
|
||||
|
||||
void wxClipboard::Clear()
|
||||
{
|
||||
#if wxUSE_OLE_CLIPBOARD
|
||||
if ( FAILED(OleSetClipboard(NULL)) )
|
||||
{
|
||||
wxLogLastError("OleSetClipboard(NULL)");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool wxClipboard::Flush()
|
||||
{
|
||||
if ( FAILED(OleFlushClipboard()) )
|
||||
{
|
||||
wxLogLastError("OleFlushClipboard");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_clearOnExit = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
bool wxClipboard::Open()
|
||||
{
|
||||
// OLE opens clipboard for us
|
||||
#if wxUSE_OLE_CLIPBOARD
|
||||
return TRUE;
|
||||
#else
|
||||
return wxOpenClipboard();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool wxClipboard::SetData( wxDataObject *data )
|
||||
@ -472,7 +484,32 @@ bool wxClipboard::AddData( wxDataObject *data )
|
||||
{
|
||||
wxCHECK_MSG( data, FALSE, wxT("data is invalid") );
|
||||
|
||||
#if wxUSE_DRAG_AND_DROP
|
||||
#if wxUSE_OLE_CLIPBOARD
|
||||
HRESULT hr = OleSetClipboard(data->GetInterface());
|
||||
if ( FAILED(hr) )
|
||||
{
|
||||
wxLogSysError(hr, _("Failed to put data on the clipboard"));
|
||||
|
||||
// don't free anything in this case
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// we have a problem here because we should delete wxDataObject, but we
|
||||
// can't do it because IDataObject which we just gave to the clipboard
|
||||
// would try to use it when it will need the data. IDataObject is ref
|
||||
// counted and so doesn't suffer from such problem, so we release it now
|
||||
// and tell it to delete wxDataObject when it is deleted itself.
|
||||
data->SetAutoDelete();
|
||||
|
||||
// we have to call either OleSetClipboard(NULL) or OleFlushClipboard() when
|
||||
// using OLE clipboard when the app terminates - by default, we call
|
||||
// OleSetClipboard(NULL) which won't waste RAM, but the app can call
|
||||
// wxClipboard::Flush() to chaneg this
|
||||
m_clearOnExit = TRUE;
|
||||
|
||||
return TRUE;
|
||||
#elif wxUSE_DATAOBJ
|
||||
wxCHECK_MSG( wxIsClipboardOpened(), FALSE, wxT("clipboard not open") );
|
||||
|
||||
wxDataFormat format = data->GetFormat();
|
||||
@ -510,14 +547,17 @@ bool wxClipboard::AddData( wxDataObject *data )
|
||||
default:
|
||||
return wxSetClipboardData(data);
|
||||
}
|
||||
#else // !wxUSE_DRAG_AND_DROP
|
||||
#else // !wxUSE_DATAOBJ
|
||||
return FALSE;
|
||||
#endif // wxUSE_DRAG_AND_DROP/!wxUSE_DRAG_AND_DROP
|
||||
#endif // wxUSE_DATAOBJ/!wxUSE_DATAOBJ
|
||||
}
|
||||
|
||||
void wxClipboard::Close()
|
||||
{
|
||||
// OLE closes clipboard for us
|
||||
#if !wxUSE_OLE_CLIPBOARD
|
||||
wxCloseClipboard();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool wxClipboard::IsSupported( wxDataFormat format )
|
||||
@ -527,9 +567,145 @@ bool wxClipboard::IsSupported( wxDataFormat format )
|
||||
|
||||
bool wxClipboard::GetData( wxDataObject *data )
|
||||
{
|
||||
wxCHECK_MSG( data, FALSE, wxT("invalid data object") );
|
||||
|
||||
#if wxUSE_OLE_CLIPBOARD
|
||||
IDataObject *pDataObject = NULL;
|
||||
HRESULT hr = OleGetClipboard(&pDataObject);
|
||||
if ( FAILED(hr) || !pDataObject )
|
||||
{
|
||||
wxLogSysError(hr, _("Failed to get data from the clipboard"));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// build the list of supported formats
|
||||
size_t nFormats = data->GetFormatCount(FALSE /* for SetData() */);
|
||||
wxDataFormat format, *formats;
|
||||
if ( nFormats == 1 )
|
||||
{
|
||||
// the most common case
|
||||
formats = &format;
|
||||
}
|
||||
else
|
||||
{
|
||||
// bad luck, need to alloc mem
|
||||
formats = new wxDataFormat[nFormats];
|
||||
}
|
||||
|
||||
data->GetAllFormats(formats, FALSE);
|
||||
|
||||
// get the format enumerator
|
||||
bool result = FALSE;
|
||||
wxArrayInt supportedFormats;
|
||||
IEnumFORMATETC *pEnumFormatEtc = NULL;
|
||||
hr = pDataObject->EnumFormatEtc(DATADIR_GET, &pEnumFormatEtc);
|
||||
if ( FAILED(hr) || !pEnumFormatEtc )
|
||||
{
|
||||
wxLogSysError(hr,
|
||||
_("Failed to retrieve the supported clipboard formats"));
|
||||
}
|
||||
else
|
||||
{
|
||||
// ask for the supported formats and see if there are any we support
|
||||
FORMATETC formatEtc;
|
||||
for ( ;; )
|
||||
{
|
||||
ULONG nCount;
|
||||
hr = pEnumFormatEtc->Next(1, &formatEtc, &nCount);
|
||||
|
||||
// don't use FAILED() because S_FALSE would pass it
|
||||
if ( hr != S_OK )
|
||||
{
|
||||
// no more formats
|
||||
break;
|
||||
}
|
||||
|
||||
CLIPFORMAT cf = formatEtc.cfFormat;
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
wxLogTrace(wxTRACE_OleCalls,
|
||||
wxT("Object on the clipboard supports format %s."),
|
||||
wxDataObject::GetFormatName(cf));
|
||||
#endif // Debug
|
||||
|
||||
// is supported?
|
||||
for ( size_t n = 0; n < nFormats; n++ )
|
||||
{
|
||||
if ( formats[n].GetFormatId() == cf )
|
||||
{
|
||||
if ( supportedFormats.Index(cf) == wxNOT_FOUND )
|
||||
{
|
||||
supportedFormats.Add(cf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pEnumFormatEtc->Release();
|
||||
}
|
||||
|
||||
if ( formats != &format )
|
||||
{
|
||||
delete [] formats;
|
||||
}
|
||||
//else: we didn't allocate any memory
|
||||
|
||||
if ( !supportedFormats.IsEmpty() )
|
||||
{
|
||||
FORMATETC formatEtc;
|
||||
formatEtc.ptd = NULL;
|
||||
formatEtc.dwAspect = DVASPECT_CONTENT;
|
||||
formatEtc.lindex = -1;
|
||||
formatEtc.tymed = TYMED_HGLOBAL;
|
||||
|
||||
size_t nSupportedFormats = supportedFormats.GetCount();
|
||||
for ( size_t n = 0; !result && (n < nSupportedFormats); n++ )
|
||||
{
|
||||
STGMEDIUM medium;
|
||||
formatEtc.cfFormat = supportedFormats[n];
|
||||
|
||||
// try to get data
|
||||
hr = pDataObject->GetData(&formatEtc, &medium);
|
||||
if ( FAILED(hr) )
|
||||
{
|
||||
// try other tymed for GDI objects
|
||||
if ( formatEtc.cfFormat == CF_BITMAP )
|
||||
{
|
||||
formatEtc.tymed = TYMED_HGLOBAL;
|
||||
hr = pDataObject->GetData(&formatEtc, &medium);
|
||||
}
|
||||
}
|
||||
|
||||
if ( SUCCEEDED(hr) )
|
||||
{
|
||||
// pass the data to the data object
|
||||
hr = data->GetInterface()->SetData(&formatEtc, &medium, TRUE);
|
||||
if ( FAILED(hr) )
|
||||
{
|
||||
wxLogDebug(wxT("Failed to set data in wxIDataObject"));
|
||||
|
||||
// IDataObject only takes the ownership of data if it
|
||||
// successfully got it - which is not the case here
|
||||
ReleaseStgMedium(&medium);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = TRUE;
|
||||
}
|
||||
}
|
||||
//else: unsupported tymed?
|
||||
}
|
||||
}
|
||||
//else: unsupported format
|
||||
|
||||
// clean up and return
|
||||
pDataObject->Release();
|
||||
|
||||
return result;
|
||||
#elif wxUSE_DATAOBJ
|
||||
wxCHECK_MSG( wxIsClipboardOpened(), FALSE, wxT("clipboard not open") );
|
||||
|
||||
#if wxUSE_DRAG_AND_DROP
|
||||
wxDataFormat format = data->GetFormat();
|
||||
switch ( format )
|
||||
{
|
||||
@ -593,9 +769,9 @@ bool wxClipboard::GetData( wxDataObject *data )
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
#else // !wxUSE_DATAOBJ
|
||||
return FALSE;
|
||||
#endif
|
||||
#endif // wxUSE_DATAOBJ/!wxUSE_DATAOBJ
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -6,136 +6,137 @@
|
||||
// Created: 01/02/97
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) Julian Smart and Markus Holzem
|
||||
// Licence: wxWindows licence
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ============================================================================
|
||||
// declarations
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "dcmemory.h"
|
||||
#pragma implementation "dcmemory.h"
|
||||
#endif
|
||||
|
||||
// For compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/utils.h"
|
||||
#include "wx/utils.h"
|
||||
#endif
|
||||
|
||||
#include "wx/msw/private.h"
|
||||
|
||||
#include "wx/dcmemory.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxWin macros
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#if !USE_SHARED_LIBRARY
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxMemoryDC, wxDC)
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxMemoryDC, wxDC)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Memory DC
|
||||
*
|
||||
*/
|
||||
// ============================================================================
|
||||
// implementation
|
||||
// ============================================================================
|
||||
|
||||
wxMemoryDC::wxMemoryDC(void)
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxMemoryDC
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
wxMemoryDC::wxMemoryDC()
|
||||
{
|
||||
m_hDC = (WXHDC) ::CreateCompatibleDC((HDC) NULL);
|
||||
m_ok = (m_hDC != 0);
|
||||
m_bOwnsDC = TRUE;
|
||||
m_hDC = (WXHDC) ::CreateCompatibleDC((HDC) NULL);
|
||||
m_ok = (m_hDC != 0);
|
||||
m_bOwnsDC = TRUE;
|
||||
|
||||
SetBrush(*wxWHITE_BRUSH);
|
||||
SetPen(*wxBLACK_PEN);
|
||||
|
||||
// the background mode is only used for text background
|
||||
// and is set in DrawText() to OPAQUE as required, other-
|
||||
// wise always TRANSPARENT, RR
|
||||
::SetBkMode( GetHdc(), TRANSPARENT );
|
||||
SetBrush(*wxWHITE_BRUSH);
|
||||
SetPen(*wxBLACK_PEN);
|
||||
|
||||
// the background mode is only used for text background and is set in
|
||||
// DrawText() to OPAQUE as required, otherwise always TRANSPARENT
|
||||
::SetBkMode( GetHdc(), TRANSPARENT );
|
||||
}
|
||||
|
||||
wxMemoryDC::wxMemoryDC(wxDC *old_dc)
|
||||
{
|
||||
old_dc->BeginDrawing();
|
||||
old_dc->BeginDrawing();
|
||||
|
||||
m_hDC = (WXHDC) ::CreateCompatibleDC((HDC) old_dc->GetHDC());
|
||||
m_ok = (m_hDC != 0);
|
||||
m_hDC = (WXHDC) ::CreateCompatibleDC(GetHdcOf(*old_dc));
|
||||
m_ok = (m_hDC != 0);
|
||||
|
||||
old_dc->EndDrawing();
|
||||
old_dc->EndDrawing();
|
||||
|
||||
SetBrush(*wxWHITE_BRUSH);
|
||||
SetPen(*wxBLACK_PEN);
|
||||
|
||||
// the background mode is only used for text background
|
||||
// and is set in DrawText() to OPAQUE as required, other-
|
||||
// wise always TRANSPARENT, RR
|
||||
::SetBkMode( GetHdc(), TRANSPARENT );
|
||||
SetBrush(*wxWHITE_BRUSH);
|
||||
SetPen(*wxBLACK_PEN);
|
||||
|
||||
// the background mode is only used for text background and is set in
|
||||
// DrawText() to OPAQUE as required, otherwise always TRANSPARENT
|
||||
::SetBkMode( GetHdc(), TRANSPARENT );
|
||||
}
|
||||
|
||||
wxMemoryDC::~wxMemoryDC(void)
|
||||
wxMemoryDC::~wxMemoryDC()
|
||||
{
|
||||
}
|
||||
|
||||
void wxMemoryDC::SelectObject(const wxBitmap& bitmap)
|
||||
{
|
||||
// Select old bitmap out of the device context
|
||||
if (m_oldBitmap)
|
||||
{
|
||||
::SelectObject((HDC) m_hDC, (HBITMAP) m_oldBitmap);
|
||||
if (m_selectedBitmap.Ok())
|
||||
// select old bitmap out of the device context
|
||||
if ( m_oldBitmap )
|
||||
{
|
||||
m_selectedBitmap.SetSelectedInto(NULL);
|
||||
m_selectedBitmap = wxNullBitmap;
|
||||
::SelectObject(GetHdc(), (HBITMAP) m_oldBitmap);
|
||||
if ( m_selectedBitmap.Ok() )
|
||||
{
|
||||
m_selectedBitmap.SetSelectedInto(NULL);
|
||||
m_selectedBitmap = wxNullBitmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do own check for whether the bitmap is already selected into
|
||||
// a device context
|
||||
if (bitmap.GetSelectedInto() && (bitmap.GetSelectedInto() != this))
|
||||
{
|
||||
wxFatalError(wxT("Error in wxMemoryDC::SelectObject\nBitmap is selected in another wxMemoryDC.\nDelete the first wxMemoryDC or use SelectObject(NULL)"));
|
||||
return;
|
||||
}
|
||||
// check for whether the bitmap is already selected into a device context
|
||||
wxCHECK_RET( !bitmap.GetSelectedInto() ||
|
||||
(bitmap.GetSelectedInto() == this),
|
||||
wxT("Bitmap is selected in another wxMemoryDC, delete the "
|
||||
"first wxMemoryDC or use SelectObject(NULL)") );
|
||||
|
||||
// Check if the bitmap has the correct depth for this device context
|
||||
// if (bitmap.Ok() && (bitmap.GetDepth() != GetDepth()))
|
||||
// JACS 11/12/98: disabling this since the Forty Thieves sample
|
||||
// shows this not working properly. In fact, if loading from a resource,
|
||||
// the depth should become the screen depth, so why was it being called?
|
||||
// if (0)
|
||||
// {
|
||||
// // Make a new bitmap that has the correct depth.
|
||||
// wxBitmap newBitmap = bitmap.GetBitmapForDC(* this);
|
||||
//
|
||||
// m_selectedBitmap = newBitmap ;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
m_selectedBitmap = bitmap;
|
||||
// }
|
||||
m_selectedBitmap = bitmap;
|
||||
WXHBITMAP hBmp = m_selectedBitmap.GetHBITMAP();
|
||||
if ( !hBmp )
|
||||
return;
|
||||
|
||||
if (!m_selectedBitmap.Ok())
|
||||
return;
|
||||
m_selectedBitmap.SetSelectedInto(this);
|
||||
hBmp = (WXHBITMAP)::SelectObject(GetHdc(), (HBITMAP)hBmp);
|
||||
|
||||
m_selectedBitmap.SetSelectedInto(this);
|
||||
HBITMAP bm = (HBITMAP) ::SelectObject((HDC) m_hDC, (HBITMAP) m_selectedBitmap.GetHBITMAP());
|
||||
if ( !hBmp )
|
||||
{
|
||||
wxLogLastError("SelectObject(memDC, bitmap)");
|
||||
|
||||
if (bm == ERROR)
|
||||
{
|
||||
wxFatalError(wxT("Error in wxMemoryDC::SelectObject\nBitmap may not be loaded, or may be selected in another wxMemoryDC.\nDelete the first wxMemoryDC to deselect bitmap."));
|
||||
}
|
||||
else if (!m_oldBitmap)
|
||||
m_oldBitmap = (WXHBITMAP) bm;
|
||||
wxFAIL_MSG(wxT("Couldn't select a bitmap into wxMemoryDC"));
|
||||
}
|
||||
else if ( !m_oldBitmap )
|
||||
{
|
||||
m_oldBitmap = hBmp;
|
||||
}
|
||||
}
|
||||
|
||||
void wxMemoryDC::DoGetSize(int *width, int *height) const
|
||||
{
|
||||
if (!m_selectedBitmap.Ok())
|
||||
{
|
||||
*width = 0; *height = 0;
|
||||
return;
|
||||
}
|
||||
*width = m_selectedBitmap.GetWidth();
|
||||
*height = m_selectedBitmap.GetHeight();
|
||||
if ( m_selectedBitmap.Ok() )
|
||||
{
|
||||
*width = m_selectedBitmap.GetWidth();
|
||||
*height = m_selectedBitmap.GetHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
*width = 0;
|
||||
*height = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -705,9 +705,9 @@ wxPoint wxFrame::GetClientAreaOrigin() const
|
||||
return pt;
|
||||
}
|
||||
|
||||
void wxFrame::ScreenToClient(int *x, int *y) const
|
||||
void wxFrame::DoScreenToClient(int *x, int *y) const
|
||||
{
|
||||
wxWindow::ScreenToClient(x, y);
|
||||
wxWindow::DoScreenToClient(x, y);
|
||||
|
||||
// We may be faking the client origin.
|
||||
// So a window that's really at (0, 30) may appear
|
||||
@ -717,7 +717,7 @@ void wxFrame::ScreenToClient(int *x, int *y) const
|
||||
*y -= pt.y;
|
||||
}
|
||||
|
||||
void wxFrame::ClientToScreen(int *x, int *y) const
|
||||
void wxFrame::DoClientToScreen(int *x, int *y) const
|
||||
{
|
||||
// We may be faking the client origin.
|
||||
// So a window that's really at (0, 30) may appear
|
||||
@ -726,7 +726,7 @@ void wxFrame::ClientToScreen(int *x, int *y) const
|
||||
*x += pt1.x;
|
||||
*y += pt1.y;
|
||||
|
||||
wxWindow::ClientToScreen(x, y);
|
||||
wxWindow::DoClientToScreen(x, y);
|
||||
}
|
||||
|
||||
#if wxUSE_TOOLBAR
|
||||
|
@ -55,7 +55,7 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
static const char *GetTymedName(DWORD tymed);
|
||||
static const wxChar *GetTymedName(DWORD tymed);
|
||||
#endif // Debug
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -90,6 +90,12 @@ class wxIDataObject : public IDataObject
|
||||
{
|
||||
public:
|
||||
wxIDataObject(wxDataObject *pDataObject);
|
||||
~wxIDataObject();
|
||||
|
||||
// normally, wxDataObject controls our lifetime (i.e. we're deleted when it
|
||||
// is), but in some cases, the situation is inversed, that is we delete it
|
||||
// when this object is deleted - setting this flag enables such logic
|
||||
void SetDeleteFlag() { m_mustDelete = TRUE; }
|
||||
|
||||
DECLARE_IUNKNOWN_METHODS;
|
||||
|
||||
@ -106,6 +112,24 @@ public:
|
||||
|
||||
private:
|
||||
wxDataObject *m_pDataObject; // pointer to C++ class we belong to
|
||||
|
||||
bool m_mustDelete;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// small helper class for getting screen DC (we're working with bitmaps and
|
||||
// DIBs here)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class ScreenHDC
|
||||
{
|
||||
public:
|
||||
ScreenHDC() { m_hdc = GetDC(NULL); }
|
||||
~ScreenHDC() { ReleaseDC(NULL, m_hdc); }
|
||||
operator HDC() const { return m_hdc; }
|
||||
|
||||
private:
|
||||
HDC m_hdc;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
@ -251,6 +275,15 @@ wxIDataObject::wxIDataObject(wxDataObject *pDataObject)
|
||||
{
|
||||
m_cRef = 0;
|
||||
m_pDataObject = pDataObject;
|
||||
m_mustDelete = FALSE;
|
||||
}
|
||||
|
||||
wxIDataObject::~wxIDataObject()
|
||||
{
|
||||
if ( m_mustDelete )
|
||||
{
|
||||
delete m_pDataObject;
|
||||
}
|
||||
}
|
||||
|
||||
// get data functions
|
||||
@ -323,7 +356,8 @@ STDMETHODIMP wxIDataObject::GetDataHere(FORMATETC *pformatetc,
|
||||
switch ( pmedium->tymed )
|
||||
{
|
||||
case TYMED_GDI:
|
||||
m_pDataObject->GetDataHere(wxDF_BITMAP, &pmedium->hBitmap);
|
||||
if ( !m_pDataObject->GetDataHere(wxDF_BITMAP, &pmedium->hBitmap) )
|
||||
return E_UNEXPECTED;
|
||||
break;
|
||||
|
||||
case TYMED_MFPICT:
|
||||
@ -342,7 +376,8 @@ STDMETHODIMP wxIDataObject::GetDataHere(FORMATETC *pformatetc,
|
||||
}
|
||||
|
||||
wxDataFormat format = (wxDataFormatId)pformatetc->cfFormat;
|
||||
m_pDataObject->GetDataHere(format, pBuf);
|
||||
if ( !m_pDataObject->GetDataHere(format, pBuf) )
|
||||
return E_UNEXPECTED;
|
||||
|
||||
GlobalUnlock(pmedium->hGlobal);
|
||||
}
|
||||
@ -360,66 +395,117 @@ STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc,
|
||||
STGMEDIUM *pmedium,
|
||||
BOOL fRelease)
|
||||
{
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::SetData"));
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::SetData"));
|
||||
|
||||
return E_NOTIMPL;
|
||||
switch ( pmedium->tymed )
|
||||
{
|
||||
case TYMED_GDI:
|
||||
m_pDataObject->SetData(wxDF_BITMAP, &pmedium->hBitmap);
|
||||
break;
|
||||
|
||||
case TYMED_MFPICT:
|
||||
// this should be copied on bitmaps - but I don't have time for
|
||||
// this now
|
||||
wxFAIL_MSG(wxT("TODO - no support for metafiles in wxDataObject"));
|
||||
break;
|
||||
|
||||
case TYMED_HGLOBAL:
|
||||
{
|
||||
// copy data
|
||||
void *pBuf = GlobalLock(pmedium->hGlobal);
|
||||
if ( pBuf == NULL ) {
|
||||
wxLogLastError("GlobalLock");
|
||||
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
wxDataFormat format = (wxDataFormatId)pformatetc->cfFormat;
|
||||
m_pDataObject->SetData(format, pBuf);
|
||||
|
||||
GlobalUnlock(pmedium->hGlobal);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return DV_E_TYMED;
|
||||
}
|
||||
|
||||
if ( fRelease ) {
|
||||
// we own the medium, so we must release it - but do *not* free the
|
||||
// bitmap handle fi we have it because we have copied it elsewhere
|
||||
if ( pmedium->tymed == TYMED_GDI )
|
||||
{
|
||||
pmedium->hBitmap = 0;
|
||||
}
|
||||
|
||||
ReleaseStgMedium(pmedium);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// information functions
|
||||
STDMETHODIMP wxIDataObject::QueryGetData(FORMATETC *pformatetc)
|
||||
{
|
||||
// do we accept data in this format?
|
||||
if ( pformatetc == NULL ) {
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::QueryGetData: invalid ptr."));
|
||||
// do we accept data in this format?
|
||||
if ( pformatetc == NULL ) {
|
||||
wxLogTrace(wxTRACE_OleCalls,
|
||||
wxT("wxIDataObject::QueryGetData: invalid ptr."));
|
||||
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
// the only one allowed by current COM implementation
|
||||
if ( pformatetc->lindex != -1 ) {
|
||||
wxLogTrace(wxTRACE_OleCalls,
|
||||
wxT("wxIDataObject::QueryGetData: bad lindex %d"),
|
||||
pformatetc->lindex);
|
||||
return DV_E_LINDEX;
|
||||
}
|
||||
// the only one allowed by current COM implementation
|
||||
if ( pformatetc->lindex != -1 ) {
|
||||
wxLogTrace(wxTRACE_OleCalls,
|
||||
wxT("wxIDataObject::QueryGetData: bad lindex %d"),
|
||||
pformatetc->lindex);
|
||||
|
||||
// we don't support anything other (THUMBNAIL, ICON, DOCPRINT...)
|
||||
if ( pformatetc->dwAspect != DVASPECT_CONTENT ) {
|
||||
wxLogTrace(wxTRACE_OleCalls,
|
||||
wxT("wxIDataObject::QueryGetData: bad dwAspect %d"),
|
||||
pformatetc->dwAspect);
|
||||
return DV_E_DVASPECT;
|
||||
}
|
||||
return DV_E_LINDEX;
|
||||
}
|
||||
|
||||
// we only transfer data by global memory, except for some particular cases
|
||||
wxDataFormat format = (wxDataFormatId)pformatetc->cfFormat;
|
||||
DWORD tymed = pformatetc->tymed;
|
||||
if ( (format == wxDF_BITMAP && !(tymed & TYMED_GDI)) ||
|
||||
!(tymed & TYMED_HGLOBAL) ) {
|
||||
// it's not what we're waiting for
|
||||
// we don't support anything other (THUMBNAIL, ICON, DOCPRINT...)
|
||||
if ( pformatetc->dwAspect != DVASPECT_CONTENT ) {
|
||||
wxLogTrace(wxTRACE_OleCalls,
|
||||
wxT("wxIDataObject::QueryGetData: bad dwAspect %d"),
|
||||
pformatetc->dwAspect);
|
||||
|
||||
return DV_E_DVASPECT;
|
||||
}
|
||||
|
||||
// and now check the type of data requested
|
||||
wxDataFormat format = (wxDataFormatId)pformatetc->cfFormat;
|
||||
if ( m_pDataObject->IsSupportedFormat(format) ) {
|
||||
#ifdef __WXDEBUG__
|
||||
wxLogTrace(wxTRACE_OleCalls,
|
||||
wxT("wxIDataObject::QueryGetData: %s & %s == 0."),
|
||||
GetTymedName(tymed),
|
||||
GetTymedName(format == wxDF_BITMAP ? TYMED_GDI : TYMED_HGLOBAL));
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::QueryGetData: %s ok"),
|
||||
wxDataObject::GetFormatName(format));
|
||||
#endif // Debug
|
||||
return DV_E_TYMED;
|
||||
}
|
||||
}
|
||||
else {
|
||||
wxLogTrace(wxTRACE_OleCalls,
|
||||
wxT("wxIDataObject::QueryGetData: %s unsupported"),
|
||||
wxDataObject::GetFormatName(format));
|
||||
|
||||
// and now check the type of data requested
|
||||
if ( m_pDataObject->IsSupportedFormat(format) ) {
|
||||
return DV_E_FORMATETC;
|
||||
}
|
||||
|
||||
// we only transfer data by global memory, except for some particular cases
|
||||
DWORD tymed = pformatetc->tymed;
|
||||
if ( (format == wxDF_BITMAP && !(tymed & TYMED_GDI)) &&
|
||||
!(tymed & TYMED_HGLOBAL) ) {
|
||||
// it's not what we're waiting for
|
||||
#ifdef __WXDEBUG__
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::QueryGetData: %s ok"),
|
||||
wxDataObject::GetFormatName(format));
|
||||
wxLogTrace(wxTRACE_OleCalls,
|
||||
wxT("wxIDataObject::QueryGetData: %s != %s"),
|
||||
GetTymedName(tymed),
|
||||
GetTymedName(format == wxDF_BITMAP ? TYMED_GDI
|
||||
: TYMED_HGLOBAL));
|
||||
#endif // Debug
|
||||
|
||||
return DV_E_TYMED;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
else {
|
||||
wxLogTrace(wxTRACE_OleCalls,
|
||||
wxT("wxIDataObject::QueryGetData: %s unsupported"),
|
||||
wxDataObject::GetFormatName((wxDataFormatId)pformatetc->cfFormat));
|
||||
return DV_E_FORMATETC;
|
||||
}
|
||||
}
|
||||
|
||||
STDMETHODIMP wxIDataObject::GetCanonicalFormatEtc(FORMATETC *pFormatetcIn,
|
||||
@ -439,12 +525,9 @@ STDMETHODIMP wxIDataObject::EnumFormatEtc(DWORD dwDirection,
|
||||
{
|
||||
wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::EnumFormatEtc"));
|
||||
|
||||
if ( dwDirection == DATADIR_SET ) {
|
||||
// we don't allow setting of data anyhow
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
bool allowOutputOnly = dwDirection == DATADIR_GET;
|
||||
|
||||
size_t nFormatCount = m_pDataObject->GetFormatCount();
|
||||
size_t nFormatCount = m_pDataObject->GetFormatCount(allowOutputOnly);
|
||||
wxDataFormat format, *formats;
|
||||
if ( nFormatCount == 1 ) {
|
||||
// this is the most common case, this is why we consider it separately
|
||||
@ -454,7 +537,7 @@ STDMETHODIMP wxIDataObject::EnumFormatEtc(DWORD dwDirection,
|
||||
else {
|
||||
// bad luck, build the array with all formats
|
||||
formats = new wxDataFormat[nFormatCount];
|
||||
m_pDataObject->GetAllFormats(formats);
|
||||
m_pDataObject->GetAllFormats(formats, allowOutputOnly);
|
||||
}
|
||||
|
||||
wxIEnumFORMATETC *pEnum = new wxIEnumFORMATETC(formats, nFormatCount);
|
||||
@ -493,13 +576,22 @@ STDMETHODIMP wxIDataObject::EnumDAdvise(IEnumSTATDATA **ppenumAdvise)
|
||||
|
||||
wxDataObject::wxDataObject()
|
||||
{
|
||||
m_pIDataObject = new wxIDataObject(this);
|
||||
m_pIDataObject->AddRef();
|
||||
m_pIDataObject = new wxIDataObject(this);
|
||||
m_pIDataObject->AddRef();
|
||||
}
|
||||
|
||||
wxDataObject::~wxDataObject()
|
||||
{
|
||||
m_pIDataObject->Release();
|
||||
ReleaseInterface(m_pIDataObject);
|
||||
}
|
||||
|
||||
void wxDataObject::SetAutoDelete()
|
||||
{
|
||||
((wxIDataObject *)m_pIDataObject)->SetDeleteFlag();
|
||||
m_pIDataObject->Release();
|
||||
|
||||
// so that the dtor doesnt' crash
|
||||
m_pIDataObject = NULL;
|
||||
}
|
||||
|
||||
bool wxDataObject::IsSupportedFormat(const wxDataFormat& format) const
|
||||
@ -552,7 +644,7 @@ const char *wxDataObject::GetFormatName(wxDataFormat format)
|
||||
case CF_HDROP: return "CF_HDROP";
|
||||
case CF_LOCALE: return "CF_LOCALE";
|
||||
default:
|
||||
sprintf(s_szBuf, "clipboard format %d (unknown)", format);
|
||||
sprintf(s_szBuf, "clipboard format 0x%x (unknown)", format);
|
||||
return s_szBuf;
|
||||
}
|
||||
|
||||
@ -604,9 +696,21 @@ void wxPrivateDataObject::WriteData( const void *data, void *dest ) const
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxBitmapDataObject
|
||||
// wxBitmapDataObject: it supports standard CF_BITMAP and CF_DIB formats
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
size_t wxBitmapDataObject::GetFormatCount(bool outputOnlyToo) const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
void wxBitmapDataObject::GetAllFormats(wxDataFormat *formats,
|
||||
bool outputOnlyToo) const
|
||||
{
|
||||
formats[0] = CF_BITMAP;
|
||||
formats[1] = CF_DIB;
|
||||
}
|
||||
|
||||
// the bitmaps aren't passed by value as other types of data (i.e. by copyign
|
||||
// the data into a global memory chunk and passing it to the clipboard or
|
||||
// another application or whatever), but by handle, so these generic functions
|
||||
@ -614,15 +718,118 @@ void wxPrivateDataObject::WriteData( const void *data, void *dest ) const
|
||||
|
||||
size_t wxBitmapDataObject::GetDataSize(const wxDataFormat& format) const
|
||||
{
|
||||
// no data to copy anyhow
|
||||
return 0;
|
||||
if ( format.GetFormatId() == CF_DIB )
|
||||
{
|
||||
// create the DIB
|
||||
ScreenHDC hdc;
|
||||
|
||||
// shouldn't be selected into a DC or GetDIBits() would fail
|
||||
wxASSERT_MSG( !m_bitmap.GetSelectedInto(),
|
||||
wxT("can't copy bitmap selected into wxMemoryDC") );
|
||||
|
||||
// first get the info
|
||||
BITMAPINFO bi;
|
||||
if ( !GetDIBits(hdc, (HBITMAP)m_bitmap.GetHBITMAP(), 0, 0,
|
||||
NULL, &bi, DIB_RGB_COLORS) )
|
||||
{
|
||||
wxLogLastError("GetDIBits(NULL)");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return sizeof(BITMAPINFO) + bi.bmiHeader.biSizeImage;
|
||||
}
|
||||
else // CF_BITMAP
|
||||
{
|
||||
// no data to copy - we don't pass HBITMAP via global memory
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void wxBitmapDataObject::GetDataHere(const wxDataFormat& format,
|
||||
bool wxBitmapDataObject::GetDataHere(const wxDataFormat& format,
|
||||
void *pBuf) const
|
||||
{
|
||||
// we put a bitmap handle into pBuf
|
||||
*(WXHBITMAP *)pBuf = m_bitmap.GetHBITMAP();
|
||||
wxASSERT_MSG( m_bitmap.Ok(), wxT("copying invalid bitmap") );
|
||||
|
||||
HBITMAP hbmp = (HBITMAP)m_bitmap.GetHBITMAP();
|
||||
if ( format.GetFormatId() == CF_DIB )
|
||||
{
|
||||
// create the DIB
|
||||
ScreenHDC hdc;
|
||||
|
||||
// shouldn't be selected into a DC or GetDIBits() would fail
|
||||
wxASSERT_MSG( !m_bitmap.GetSelectedInto(),
|
||||
wxT("can't copy bitmap selected into wxMemoryDC") );
|
||||
|
||||
// first get the info
|
||||
BITMAPINFO *pbi = (BITMAPINFO *)pBuf;
|
||||
if ( !GetDIBits(hdc, hbmp, 0, 0, NULL, pbi, DIB_RGB_COLORS) )
|
||||
{
|
||||
wxLogLastError("GetDIBits(NULL)");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// and now copy the bits
|
||||
if ( !GetDIBits(hdc, hbmp, 0, pbi->bmiHeader.biHeight, pbi + 1,
|
||||
pbi, DIB_RGB_COLORS) )
|
||||
{
|
||||
wxLogLastError("GetDIBits");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else // CF_BITMAP
|
||||
{
|
||||
// we put a bitmap handle into pBuf
|
||||
*(HBITMAP *)pBuf = hbmp;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxBitmapDataObject::SetData(const wxDataFormat& format, const void *pBuf)
|
||||
{
|
||||
HBITMAP hbmp;
|
||||
if ( format.GetFormatId() == CF_DIB )
|
||||
{
|
||||
// here we get BITMAPINFO struct followed by the actual bitmap bits and
|
||||
// BITMAPINFO starts with BITMAPINFOHEADER followed by colour info
|
||||
ScreenHDC hdc;
|
||||
|
||||
BITMAPINFO *pbmi = (BITMAPINFO *)pBuf;
|
||||
BITMAPINFOHEADER *pbmih = &pbmi->bmiHeader;
|
||||
hbmp = CreateDIBitmap(hdc, pbmih, CBM_INIT,
|
||||
pbmi + 1, pbmi, DIB_RGB_COLORS);
|
||||
if ( !hbmp )
|
||||
{
|
||||
wxLogLastError("CreateDIBitmap");
|
||||
}
|
||||
|
||||
m_bitmap.SetWidth(pbmih->biWidth);
|
||||
m_bitmap.SetHeight(pbmih->biHeight);
|
||||
}
|
||||
else // CF_BITMAP
|
||||
{
|
||||
// it's easy with bitmaps: we pass them by handle
|
||||
hbmp = *(HBITMAP *)pBuf;
|
||||
|
||||
BITMAP bmp;
|
||||
if ( !GetObject(hbmp, sizeof(BITMAP), &bmp) )
|
||||
{
|
||||
wxLogLastError("GetObject(HBITMAP)");
|
||||
}
|
||||
|
||||
m_bitmap.SetWidth(bmp.bmWidth);
|
||||
m_bitmap.SetHeight(bmp.bmHeight);
|
||||
m_bitmap.SetDepth(bmp.bmPlanes);
|
||||
}
|
||||
|
||||
m_bitmap.SetHBITMAP((WXHBITMAP)hbmp);
|
||||
|
||||
wxASSERT_MSG( m_bitmap.Ok(), wxT("pasting invalid bitmap") );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -631,24 +838,24 @@ void wxBitmapDataObject::GetDataHere(const wxDataFormat& format,
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
|
||||
static const char *GetTymedName(DWORD tymed)
|
||||
static const wxChar *GetTymedName(DWORD tymed)
|
||||
{
|
||||
static char s_szBuf[128];
|
||||
switch ( tymed ) {
|
||||
case TYMED_HGLOBAL: return "TYMED_HGLOBAL";
|
||||
case TYMED_FILE: return "TYMED_FILE";
|
||||
case TYMED_ISTREAM: return "TYMED_ISTREAM";
|
||||
case TYMED_ISTORAGE: return "TYMED_ISTORAGE";
|
||||
case TYMED_GDI: return "TYMED_GDI";
|
||||
case TYMED_MFPICT: return "TYMED_MFPICT";
|
||||
case TYMED_ENHMF: return "TYMED_ENHMF";
|
||||
default:
|
||||
sprintf(s_szBuf, "type of media format %d (unknown)", tymed);
|
||||
return s_szBuf;
|
||||
}
|
||||
static wxChar s_szBuf[128];
|
||||
switch ( tymed ) {
|
||||
case TYMED_HGLOBAL: return wxT("TYMED_HGLOBAL");
|
||||
case TYMED_FILE: return wxT("TYMED_FILE");
|
||||
case TYMED_ISTREAM: return wxT("TYMED_ISTREAM");
|
||||
case TYMED_ISTORAGE: return wxT("TYMED_ISTORAGE");
|
||||
case TYMED_GDI: return wxT("TYMED_GDI");
|
||||
case TYMED_MFPICT: return wxT("TYMED_MFPICT");
|
||||
case TYMED_ENHMF: return wxT("TYMED_ENHMF");
|
||||
default:
|
||||
wxSprintf(s_szBuf, wxT("type of media format %d (unknown)"), tymed);
|
||||
return s_szBuf;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // Debug
|
||||
|
||||
#endif
|
||||
#endif // not using OLE at all
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user