From 0a1714b709ffa8ea18b3bcfc1632fb44c8b32350 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 25 May 2022 18:06:53 +0100 Subject: [PATCH] Start using IFileDialogEvents to get notifications about changes For now only update the currently selected file type using this interface, but it will be used for more notifications later. --- include/wx/msw/filedlg.h | 2 +- src/msw/filedlg.cpp | 96 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 95 insertions(+), 3 deletions(-) diff --git a/include/wx/msw/filedlg.h b/include/wx/msw/filedlg.h index e516bda634..b22eaf9a3d 100644 --- a/include/wx/msw/filedlg.h +++ b/include/wx/msw/filedlg.h @@ -57,7 +57,7 @@ private: // called from the hook procedure on CDN_SELCHANGE. void MSWOnSelChange(WXHWND hDlg); - // called from the hook procedure on CDN_TYPECHANGE. + // called when the currently selected type of files changes in the dialog void MSWOnTypeChange(int nFilterIndex); // The real implementation of ShowModal() using traditional common dialog diff --git a/src/msw/filedlg.cpp b/src/msw/filedlg.cpp index 698ebf4fe8..c665d37da2 100644 --- a/src/msw/filedlg.cpp +++ b/src/msw/filedlg.cpp @@ -49,6 +49,14 @@ #include "wx/msw/private/dpiaware.h" #include "wx/msw/private/filedialog.h" +// Note: this must be done after including the header above, as this is where +// wxUSE_IFILEOPENDIALOG is defined. +#if wxUSE_IFILEOPENDIALOG + #include "wx/msw/wrapshl.h" + + #include "wx/msw/ole/comimpl.h" +#endif // wxUSE_IFILEOPENDIALOG + // ---------------------------------------------------------------------------- // constants // ---------------------------------------------------------------------------- @@ -151,6 +159,34 @@ void RestoreExceptionPolicy() // wx/msw/private/filedialog.h // ---------------------------------------------------------------------------- +// Register the given event handler with the dialog during its life-time. +class FileDialogEventsRegistrar +{ +public: + // The file dialog scope must be greater than that of this object. + FileDialogEventsRegistrar(wxMSWImpl::wxIFileDialog& fileDialog, + IFileDialogEvents& eventsHandler) + : m_fileDialog(fileDialog) + { + HRESULT hr = m_fileDialog->Advise(&eventsHandler, &m_cookie); + if ( FAILED(hr) ) + wxLogApiError(wxS("IFileDialog::Advise"), hr); + } + + ~FileDialogEventsRegistrar() + { + HRESULT hr = m_fileDialog->Unadvise(m_cookie); + if ( FAILED(hr) ) + wxLogApiError(wxS("IFileDialog::Unadvise"), hr); + } + +private: + wxMSWImpl::wxIFileDialog& m_fileDialog; + DWORD m_cookie; + + wxDECLARE_NO_COPY_CLASS(FileDialogEventsRegistrar); +}; + // Return 1-based index of the currently selected file type. UINT FileDialogGetFileTypeIndex(IFileDialog* fileDialog) { @@ -175,9 +211,15 @@ UINT FileDialogGetFileTypeIndex(IFileDialog* fileDialog) // ---------------------------------------------------------------------------- class wxFileDialogMSWData +#if wxUSE_IFILEOPENDIALOG + : public IFileDialogEvents +#endif // wxUSE_IFILEOPENDIALOG { public: - wxFileDialogMSWData() + explicit wxFileDialogMSWData(wxFileDialog* fileDialog) +#if wxUSE_IFILEOPENDIALOG + : m_fileDialog(fileDialog) +#endif // wxUSE_IFILEOPENDIALOG { m_bMovedWindow = false; m_centreDir = 0; @@ -192,8 +234,41 @@ public: // treatment) was called bool m_bMovedWindow; int m_centreDir; // nothing to do if 0 + + +#if wxUSE_IFILEOPENDIALOG + // IFileDialogEvents + wxSTDMETHODIMP OnFileOk(IFileDialog*) wxOVERRIDE { return E_NOTIMPL; } + wxSTDMETHODIMP OnFolderChanging(IFileDialog*, IShellItem*) wxOVERRIDE { return E_NOTIMPL; } + wxSTDMETHODIMP OnFolderChange(IFileDialog*) wxOVERRIDE { return E_NOTIMPL; } + wxSTDMETHODIMP OnSelectionChange(IFileDialog*) wxOVERRIDE { return E_NOTIMPL; } + wxSTDMETHODIMP OnShareViolation(IFileDialog*, IShellItem*, FDE_SHAREVIOLATION_RESPONSE*) wxOVERRIDE { return E_NOTIMPL; } + + wxSTDMETHODIMP OnTypeChange(IFileDialog* pfd) wxOVERRIDE + { + m_fileDialog->MSWOnTypeChange(FileDialogGetFileTypeIndex(pfd)); + + return S_OK; + } + + wxSTDMETHODIMP OnOverwrite(IFileDialog*, IShellItem*, FDE_OVERWRITE_RESPONSE*) wxOVERRIDE { return E_NOTIMPL; } + + + wxFileDialog* const m_fileDialog; + + DECLARE_IUNKNOWN_METHODS; +#endif // wxUSE_IFILEOPENDIALOG + + wxDECLARE_NO_COPY_CLASS(wxFileDialogMSWData); }; +BEGIN_IID_TABLE(wxFileDialogMSWData) + ADD_IID(Unknown) + ADD_IID(FileDialogEvents) +END_IID_TABLE; + +IMPLEMENT_IUNKNOWN_METHODS(wxFileDialogMSWData) + // ---------------------------------------------------------------------------- // hook function for moving the dialog // ---------------------------------------------------------------------------- @@ -286,13 +361,25 @@ wxFileDialog::wxFileDialog(wxWindow *parent, wxFileDialog::~wxFileDialog() { +#if wxUSE_IFILEOPENDIALOG + if ( m_data ) + m_data->Release(); +#else // !wxUSE_IFILEOPENDIALOG delete m_data; +#endif // wxUSE_IFILEOPENDIALOG } wxFileDialogMSWData& wxFileDialog::MSWData() { if ( !m_data ) - m_data = new wxFileDialogMSWData(); + { + m_data = new wxFileDialogMSWData(this); + +#if wxUSE_IFILEOPENDIALOG + // Make sure it stays alive while we are. + m_data->AddRef(); +#endif // wxUSE_IFILEOPENDIALOG + } return *m_data; } @@ -786,6 +873,11 @@ int wxFileDialog::ShowIFileDialog(WXHWND hWndParent) if ( !fileDialog.IsOk() ) return wxID_NONE; + // Register our event handler with the dialog. + wxFileDialogMSWData& data = MSWData(); + + FileDialogEventsRegistrar registerEvents(fileDialog, data); + // Configure the dialog before showing it. fileDialog.SetTitle(m_message);