///////////////////////////////////////////////////////////////////////////// // Name: dnd.cpp // Purpose: Drag and drop sample // Author: Vadim Zeitlin // Modified by: // Created: 04/01/98 // RCS-ID: // Copyright: // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "wx/intl.h" #include "wx/log.h" #include "wx/dnd.h" // ---------------------------------------------------------------------------- // Derive 2 simple classes which just put in the listbox the strings (text or // file names) we drop on them // ---------------------------------------------------------------------------- class DnDText : public wxTextDropTarget { public: DnDText(wxListBox *pOwner) { m_pOwner = pOwner; } virtual bool OnDropText(long x, long y, const char *psz); private: wxListBox *m_pOwner; }; class DnDFile : public wxFileDropTarget { public: DnDFile(wxListBox *pOwner) { m_pOwner = pOwner; } virtual bool OnDropFiles(long x, long y, size_t nFiles, const char * const aszFiles[]); private: wxListBox *m_pOwner; }; // ---------------------------------------------------------------------------- // Define a new application type // ---------------------------------------------------------------------------- class DnDApp : public wxApp { public: bool OnInit(); }; IMPLEMENT_APP(DnDApp); // ---------------------------------------------------------------------------- // Define a new frame type // ---------------------------------------------------------------------------- class DnDFrame : public wxFrame { public: DnDFrame(wxFrame *frame, char *title, int x, int y, int w, int h); ~DnDFrame(); void OnPaint(wxPaintEvent& event); void OnQuit (wxCommandEvent& event); void OnAbout(wxCommandEvent& event); void OnDrag (wxCommandEvent& event); void OnHelp (wxCommandEvent& event); void OnLogClear(wxCommandEvent& event); void OnMouseBtnDown(wxMouseEvent& event); bool OnClose(); DECLARE_EVENT_TABLE() private: wxListBox *m_ctrlFile, *m_ctrlText; wxTextCtrl *m_ctrlLog; wxLog *m_pLog, *m_pLogPrev; wxString m_strText; }; // ---------------------------------------------------------------------------- // IDs for the menu commands // ---------------------------------------------------------------------------- enum { Menu_Quit = 1, Menu_Drag, Menu_About = 101, Menu_Help, Menu_Clear, }; BEGIN_EVENT_TABLE(DnDFrame, wxFrame) EVT_MENU(Menu_Quit, DnDFrame::OnQuit) EVT_MENU(Menu_About, DnDFrame::OnAbout) EVT_MENU(Menu_Drag, DnDFrame::OnDrag) EVT_MENU(Menu_Help, DnDFrame::OnHelp) EVT_MENU(Menu_Clear, DnDFrame::OnLogClear) EVT_LEFT_DOWN(OnMouseBtnDown) EVT_RIGHT_DOWN(OnMouseBtnDown) EVT_MIDDLE_DOWN(OnMouseBtnDown) END_EVENT_TABLE() // `Main program' equivalent, creating windows and returning main app frame bool DnDApp::OnInit(void) { // create the main frame window DnDFrame *frame = new DnDFrame(NULL, "Drag & Drop wxWindows App", 50, 50, 450, 340); // activate it frame->Show(TRUE); SetTopWindow(frame); return TRUE; } DnDFrame::DnDFrame(wxFrame *frame, char *title, int x, int y, int w, int h) : wxFrame(frame, -1, title, wxPoint(x, y), wxSize(w, h)), m_strText("wxWindows drag & drop works :-)") { // frame icon and status bar SetIcon(wxIcon("mondrian")); const int widths[] = { -1 }; CreateStatusBar(); // construct menu wxMenu *file_menu = new wxMenu; file_menu->Append(Menu_Drag, "&Test drag..."); file_menu->AppendSeparator(); file_menu->Append(Menu_Quit, "E&xit"); wxMenu *log_menu = new wxMenu; log_menu->Append(Menu_Clear, "Clear"); wxMenu *help_menu = new wxMenu; help_menu->Append(Menu_Help, "&Help..."); help_menu->AppendSeparator(); help_menu->Append(Menu_About, "&About"); wxMenuBar *menu_bar = new wxMenuBar; menu_bar->Append(file_menu, "&File"); menu_bar->Append(log_menu, "&Log"); menu_bar->Append(help_menu, "&Help"); SetMenuBar(menu_bar); // make a panel with 3 subwindows wxPoint pos(0, 0); wxSize size(400, 200); wxString strFile("Drop files here!"), strText("Drop text on me"); m_ctrlFile = new wxListBox(this, -1, pos, size, 1, &strFile, wxLB_HSCROLL); m_ctrlText = new wxListBox(this, -1, pos, size, 1, &strText, wxLB_HSCROLL); m_ctrlLog = new wxTextCtrl(this, -1, "", pos, size, wxTE_MULTILINE | wxTE_READONLY | wxSUNKEN_BORDER| wxHSCROLL); // redirect log messages to the text window (don't forget to delete it!) m_pLog = new wxLogTextCtrl(m_ctrlLog); m_pLogPrev = wxLog::SetActiveTarget(m_pLog); // associate drop targets with 2 text controls m_ctrlFile->SetDropTarget(new DnDFile(m_ctrlFile)); m_ctrlText->SetDropTarget(new DnDText(m_ctrlText)); wxLayoutConstraints *c; // Top-left listbox c = new wxLayoutConstraints; c->left.SameAs (this, wxLeft); c->top.SameAs (this, wxTop); c->right.PercentOf(this, wxRight, 50); c->height.PercentOf(this, wxHeight, 40); m_ctrlFile->SetConstraints(c); // Top-right listbox c = new wxLayoutConstraints; c->left.SameAs (m_ctrlFile, wxRight); c->top.SameAs (this, wxTop); c->right.SameAs (this, wxRight); c->height.PercentOf(this, wxHeight, 40); m_ctrlText->SetConstraints(c); // Lower text control c = new wxLayoutConstraints; c->left.SameAs (this, wxLeft); c->right.SameAs (this, wxRight); c->height.PercentOf(this, wxHeight, 40); c->top.SameAs(m_ctrlText, wxBottom); m_ctrlLog->SetConstraints(c); SetAutoLayout(TRUE); } void DnDFrame::OnQuit(wxCommandEvent& /* event */) { Close(TRUE); } void DnDFrame::OnDrag(wxCommandEvent& /* event */) { wxString strText = wxGetTextFromUser ( "After you enter text in this dialog, press any mouse\n" "button in the bottom (empty) part of the frame and \n" "drag it anywhere - you will be in fact dragging the\n" "text object containing this text", "Please enter some text", m_strText, this ); m_strText = strText; } void DnDFrame::OnAbout(wxCommandEvent& /* event */) { wxMessageDialog dialog(this, "Drag-&-Drop Demo\n" "Please see \"Help|Help...\" for details\n" "Copyright (c) 1998 Vadim Zeitlin", "About wxDnD"); dialog.ShowModal(); } void DnDFrame::OnHelp(wxCommandEvent& /* event */) { wxMessageDialog dialog(this, "This small program demonstrates drag & drop support in wxWindows. " "The program window consists of 3 parts: the bottom pane is for " "debug messages, so that you can see what's going on inside. " "The top part is split into 2 listboxes, the left one accepts " "files and the right one accepts text." "\n\n" "To test wxDropTarget: open wordpad (write.exe), select some text in " "it and drag it to the right listbox (you'll notice the usual visual " "feedback, i.e. the cursor will change). Also, try dragging some " "files (you can select several at once) from Windows Explorer (or " "File Manager) to the left pane. Hold down Ctrl/Shift keys when " "you drop text (doesn't work with files) and see what changes. " "\n\n" "To test wxDropSource: just press any mouse button on the empty zone of " "the window and drag it to wordpad or any other droptarget accepting " "text (and of course you can just drag it to the right pane). Due to " "a lot of trace messages, the cursor might take some time to change, " "don't release the mouse button until it does. You can change the " "string being dragged in in \"File|Test drag...\" dialog." "\n\n" "Please send all questions/bug reports/suggestions &c to " "Vadim Zeitlin ", "wxDnD Help"); dialog.ShowModal(); } void DnDFrame::OnLogClear(wxCommandEvent& event) { m_ctrlLog->Clear(); } bool DnDFrame::OnClose() { return TRUE; } void DnDFrame::OnMouseBtnDown(wxMouseEvent& event) { if ( !m_strText.IsEmpty() ) { // start drag operation wxTextDataObject data(m_strText); wxDropSource dragSource(data); const char *pc; switch ( dragSource.DoDragDrop(TRUE) ) { case wxDropSource::Error: pc = "Error!"; break; case wxDropSource::None: pc = "Nothing"; break; case wxDropSource::Copy: pc = "Copied"; break; case wxDropSource::Move: pc = "Moved"; break; case wxDropSource::Cancel: pc = "Cancelled"; break; default: pc = "Huh?"; break; } SetStatusText(wxString("Drag result: ") + pc); } } DnDFrame::~DnDFrame() { if ( m_pLog != NULL ) { if ( wxLog::SetActiveTarget(m_pLogPrev) == m_pLog ) delete m_pLog; } } // ---------------------------------------------------------------------------- // Notifications called by the base class // ---------------------------------------------------------------------------- bool DnDText::OnDropText(long, long, const char *psz) { m_pOwner->Append(psz); return TRUE; } bool DnDFile::OnDropFiles(long, long, size_t nFiles, const char * const aszFiles[]) { wxString str; str.Printf("%d files dropped", nFiles); m_pOwner->Append(str); for ( size_t n = 0; n < nFiles; n++ ) { m_pOwner->Append(aszFiles[n]); } return TRUE; }