diff --git a/include/wx/filedlgcustomize.h b/include/wx/filedlgcustomize.h index 10ff297a9f..b088cce6a1 100644 --- a/include/wx/filedlgcustomize.h +++ b/include/wx/filedlgcustomize.h @@ -25,10 +25,10 @@ class wxFileDialogCustomizeImpl; // All these controls support a very limited set of functions, but use the same // names for the things that they do support as the corresponding "normal" wx -// classes. +// classes and also generate some (but not all) of the same events. // The base class for all wxFileDialog custom controls. -class wxFileDialogCustomControl +class wxFileDialogCustomControl : public wxEvtHandler { public: void Show(bool show = true); @@ -45,6 +45,11 @@ protected: { } + // By default custom controls don't generate any events, but some of them + // override this function to allow connecting to the selected events. + virtual bool OnDynamicBind(wxDynamicEventTableEntry& entry) wxOVERRIDE; + + wxFileDialogCustomControlImpl* const m_impl; wxDECLARE_NO_COPY_CLASS(wxFileDialogCustomControl); @@ -57,6 +62,9 @@ public: // Ctor is only used by wxWidgets itself. explicit wxFileDialogButton(wxFileDialogButtonImpl* impl); +protected: + virtual bool OnDynamicBind(wxDynamicEventTableEntry& entry) wxOVERRIDE; + private: wxFileDialogButtonImpl* GetImpl() const; @@ -73,6 +81,9 @@ public: // Ctor is only used by wxWidgets itself. explicit wxFileDialogCheckBox(wxFileDialogCheckBoxImpl* impl); +protected: + virtual bool OnDynamicBind(wxDynamicEventTableEntry& entry) wxOVERRIDE; + private: wxFileDialogCheckBoxImpl* GetImpl() const; @@ -134,13 +145,13 @@ protected: { } + wxVector m_controls; + private: template T* StoreAndReturn(T* control); wxFileDialogCustomizeImpl* const m_impl; - wxVector m_controls; - wxDECLARE_NO_COPY_CLASS(wxFileDialogCustomize); }; diff --git a/samples/dialogs/dialogs.cpp b/samples/dialogs/dialogs.cpp index cbab4f178a..e7d0f25011 100644 --- a/samples/dialogs/dialogs.cpp +++ b/samples/dialogs/dialogs.cpp @@ -1694,7 +1694,9 @@ public: customizer.AddStaticText("Just some extra text:"); m_text = customizer.AddTextCtrl(); m_cb = customizer.AddCheckBox("Enable Custom Button"); + m_cb->Bind(wxEVT_CHECKBOX, &MyCustomizeHook::OnCheckBox, this); m_btn = customizer.AddButton("Custom Button"); + m_btn->Bind(wxEVT_BUTTON, &MyCustomizeHook::OnButton, this); m_label = customizer.AddStaticText("Nothing selected"); } @@ -1721,6 +1723,17 @@ public: wxString GetInfo() const { return m_info; } private: + void OnCheckBox(wxCommandEvent& event) + { + m_btn->Enable(event.IsChecked()); + } + + void OnButton(wxCommandEvent& WXUNUSED(event)) + { + wxMessageBox("Custom button pressed", "wxWidgets dialogs sample", + wxOK | wxICON_INFORMATION, m_dialog); + } + wxFileDialog* const m_dialog; wxFileDialogButton* m_btn; diff --git a/src/common/fldlgcmn.cpp b/src/common/fldlgcmn.cpp index 7fb3822864..6606ea8b8e 100644 --- a/src/common/fldlgcmn.cpp +++ b/src/common/fldlgcmn.cpp @@ -52,6 +52,19 @@ wxFileDialogCustomControlImpl::~wxFileDialogCustomControlImpl() { } +bool wxFileDialogCustomControl::OnDynamicBind(wxDynamicEventTableEntry& entry) +{ + wxUnusedVar(entry); // Needed when debug is disabled. + + wxFAIL_MSG(wxString::Format + ( + "This custom control doesn't generate the event %d.", + entry.m_eventType + )); + + return false; +} + void wxFileDialogCustomControl::Show(bool show) { return m_impl->Show(show); @@ -72,6 +85,14 @@ wxFileDialogButton::wxFileDialogButton(wxFileDialogButtonImpl* impl) { } +bool wxFileDialogButton::OnDynamicBind(wxDynamicEventTableEntry& entry) +{ + if ( entry.m_eventType == wxEVT_BUTTON ) + return true; + + return wxFileDialogCustomControl::OnDynamicBind(entry); +} + wxFileDialogButtonImpl* wxFileDialogButton::GetImpl() const { return static_cast(m_impl); @@ -82,6 +103,14 @@ wxFileDialogCheckBox::wxFileDialogCheckBox(wxFileDialogCheckBoxImpl* impl) { } +bool wxFileDialogCheckBox::OnDynamicBind(wxDynamicEventTableEntry& entry) +{ + if ( entry.m_eventType == wxEVT_CHECKBOX ) + return true; + + return wxFileDialogCustomControl::OnDynamicBind(entry); +} + wxFileDialogCheckBoxImpl* wxFileDialogCheckBox::GetImpl() const { return static_cast(m_impl); diff --git a/src/msw/filedlg.cpp b/src/msw/filedlg.cpp index a742220ada..57bbdc21f6 100644 --- a/src/msw/filedlg.cpp +++ b/src/msw/filedlg.cpp @@ -397,6 +397,18 @@ public: return true; } + wxFileDialogCustomControl* FindControl(DWORD id) const + { + // Currently there is 1-to-1 correspondence between IDs and the + // controls we create, except that we start assigning IDs with 1. + if ( id < 1 || id > m_controls.size() ) + return NULL; + + return m_controls[id - 1]; + } + + + // Implement wxFileDialogCustomizeImpl pure virtual methods. wxFileDialogButtonImpl* AddButton(const wxString& label) wxOVERRIDE { HRESULT hr = m_fdc->AddPushButton(++m_lastId, label.wc_str()); @@ -460,7 +472,8 @@ private: class wxFileDialogMSWData #if wxUSE_IFILEOPENDIALOG - : public IFileDialogEvents + : public IFileDialogEvents, + public IFileDialogControlEvents #endif // wxUSE_IFILEOPENDIALOG { public: @@ -492,7 +505,14 @@ public: { if ( iid == IID_IUnknown || iid == IID_IFileDialogEvents ) { - *ppv = this; + // The cast is unnecessary, but do it for clarity and symmetry. + *ppv = static_cast(this); + } + else if ( iid == IID_IFileDialogControlEvents ) + { + // Here the case is necessary to return the pointer of correct + // type. + *ppv = static_cast(this); } else { @@ -576,6 +596,57 @@ public: wxSTDMETHODIMP OnOverwrite(IFileDialog*, IShellItem*, FDE_OVERWRITE_RESPONSE*) wxOVERRIDE { return E_NOTIMPL; } + // IFileDialogControlEvents + + wxSTDMETHODIMP + OnItemSelected(IFileDialogCustomize*, + DWORD WXUNUSED(dwIDCtl), + DWORD WXUNUSED(dwIDItem)) wxOVERRIDE + { + return S_OK; + } + + wxSTDMETHODIMP + OnButtonClicked(IFileDialogCustomize*, DWORD dwIDCtl) wxOVERRIDE + { + if ( wxFileDialogCustomControl* const + control = m_customize.FindControl(dwIDCtl) ) + { + wxCommandEvent event(wxEVT_BUTTON, dwIDCtl); + event.SetEventObject(control); + + control->SafelyProcessEvent(event); + } + + return S_OK; + } + + wxSTDMETHODIMP + OnCheckButtonToggled(IFileDialogCustomize*, + DWORD dwIDCtl, + BOOL bChecked) wxOVERRIDE + { + if ( wxFileDialogCustomControl* const + control = m_customize.FindControl(dwIDCtl) ) + { + wxCommandEvent event(wxEVT_CHECKBOX, dwIDCtl); + event.SetEventObject(control); + event.SetInt(bChecked); // This is for wxCommandEvent::IsChecked(). + + control->SafelyProcessEvent(event); + } + + return S_OK; + } + + wxSTDMETHODIMP + OnControlActivating(IFileDialogCustomize*, + DWORD WXUNUSED(dwIDCtl)) wxOVERRIDE + { + return S_OK; + } + + wxFileDialog* const m_fileDialog; wxFileDialogCustomizeFDC m_customize;