Fix regression: Handle "Default Directory" setting correctly in Open/Save File Dialog
IFileDialog doesn't modify the current directory unlike the old file dialog. Now the last used directory is remembered each time the user changes directory and then set as working directory if needed. Fix #9767, close #9775
This commit is contained in:
parent
d0afc51621
commit
acdc2517c6
|
@ -95,6 +95,7 @@ PowerEditor/src/tools/NppShell/build_x64
|
||||||
# scintilla - generated files
|
# scintilla - generated files
|
||||||
scintilla/bin/SciLexer.*
|
scintilla/bin/SciLexer.*
|
||||||
scintilla/bin/Scintilla.*
|
scintilla/bin/Scintilla.*
|
||||||
|
scintilla/bin/libscilexer.a
|
||||||
scintilla/bin/libscintilla.a
|
scintilla/bin/libscintilla.a
|
||||||
scintilla/bin/libscintilla.lib
|
scintilla/bin/libscintilla.lib
|
||||||
scintilla/win32/*.lib
|
scintilla/win32/*.lib
|
||||||
|
|
|
@ -36,9 +36,8 @@ template<class T>
|
||||||
const GUID ComTraits<T>::uid = __uuidof(T);
|
const GUID ComTraits<T>::uid = __uuidof(T);
|
||||||
|
|
||||||
// Smart pointer alias for COM objects that makes reference counting easier.
|
// Smart pointer alias for COM objects that makes reference counting easier.
|
||||||
template<class T>
|
template<class T, class InterfaceT = T>
|
||||||
using com_ptr = _com_ptr_t<_com_IIID<T, &ComTraits<T>::uid>>;
|
using com_ptr = _com_ptr_t<_com_IIID<T, &ComTraits<InterfaceT>::uid>>;
|
||||||
|
|
||||||
|
|
||||||
namespace // anonymous
|
namespace // anonymous
|
||||||
{
|
{
|
||||||
|
@ -187,12 +186,6 @@ namespace // anonymous
|
||||||
}
|
}
|
||||||
~CurrentDirBackup()
|
~CurrentDirBackup()
|
||||||
{
|
{
|
||||||
NppParameters& params = NppParameters::getInstance();
|
|
||||||
if (params.getNppGUI()._openSaveDir == dir_last)
|
|
||||||
{
|
|
||||||
::GetCurrentDirectory(MAX_PATH, _dir);
|
|
||||||
params.setWorkingDir(_dir);
|
|
||||||
}
|
|
||||||
::SetCurrentDirectory(_dir);
|
::SetCurrentDirectory(_dir);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
@ -206,21 +199,6 @@ namespace // anonymous
|
||||||
class FileDialogEventHandler : public IFileDialogEvents, public IFileDialogControlEvents
|
class FileDialogEventHandler : public IFileDialogEvents, public IFileDialogControlEvents
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static HRESULT createInstance(IFileDialog* dlg, const std::vector<Filter>& filterSpec,
|
|
||||||
int fileIndex, int wildcardIndex, REFIID riid, void **ppv)
|
|
||||||
{
|
|
||||||
*ppv = nullptr;
|
|
||||||
FileDialogEventHandler* pDialogEventHandler =
|
|
||||||
new (std::nothrow) FileDialogEventHandler(dlg, filterSpec, fileIndex, wildcardIndex);
|
|
||||||
HRESULT hr = pDialogEventHandler ? S_OK : E_OUTOFMEMORY;
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = pDialogEventHandler->QueryInterface(riid, ppv);
|
|
||||||
pDialogEventHandler->Release();
|
|
||||||
}
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// IUnknown methods
|
// IUnknown methods
|
||||||
|
|
||||||
IFACEMETHODIMP QueryInterface(REFIID riid, void** ppv) override
|
IFACEMETHODIMP QueryInterface(REFIID riid, void** ppv) override
|
||||||
|
@ -261,8 +239,9 @@ public:
|
||||||
|
|
||||||
// IFileDialogEvents methods
|
// IFileDialogEvents methods
|
||||||
|
|
||||||
IFACEMETHODIMP OnFileOk(IFileDialog*) override
|
IFACEMETHODIMP OnFileOk(IFileDialog* dlg) override
|
||||||
{
|
{
|
||||||
|
_lastUsedFolder = getDialogFolder(dlg);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
IFACEMETHODIMP OnFolderChange(IFileDialog*) override
|
IFACEMETHODIMP OnFolderChange(IFileDialog*) override
|
||||||
|
@ -270,9 +249,11 @@ public:
|
||||||
// First launch order: 3. Custom controls are added but inactive.
|
// First launch order: 3. Custom controls are added but inactive.
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
IFACEMETHODIMP OnFolderChanging(IFileDialog*, IShellItem*) override
|
IFACEMETHODIMP OnFolderChanging(IFileDialog*, IShellItem* psi) override
|
||||||
{
|
{
|
||||||
|
// Called when the current dialog folder is about to change.
|
||||||
// First launch order: 2. Buttons are added, correct window title.
|
// First launch order: 2. Buttons are added, correct window title.
|
||||||
|
_lastUsedFolder = getFilename(psi);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
IFACEMETHODIMP OnSelectionChange(IFileDialog*) override
|
IFACEMETHODIMP OnSelectionChange(IFileDialog*) override
|
||||||
|
@ -354,19 +335,22 @@ public:
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// Use createInstance() instead
|
|
||||||
FileDialogEventHandler(IFileDialog* dlg, const std::vector<Filter>& filterSpec, int fileIndex, int wildcardIndex)
|
FileDialogEventHandler(IFileDialog* dlg, const std::vector<Filter>& filterSpec, int fileIndex, int wildcardIndex)
|
||||||
: _cRef(1), _dialog(dlg), _customize(dlg), _filterSpec(filterSpec), _lastSelectedType(fileIndex + 1),
|
: _cRef(1), _dialog(dlg), _customize(dlg), _filterSpec(filterSpec), _lastSelectedType(fileIndex + 1),
|
||||||
_wildcardType(wildcardIndex >= 0 ? wildcardIndex + 1 : 0)
|
_wildcardType(wildcardIndex >= 0 ? wildcardIndex + 1 : 0)
|
||||||
{
|
{
|
||||||
_staticThis = this;
|
_staticThis = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
~FileDialogEventHandler()
|
~FileDialogEventHandler()
|
||||||
{
|
{
|
||||||
_staticThis = nullptr;
|
_staticThis = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const generic_string& getLastUsedFolder() const { return _lastUsedFolder; }
|
||||||
|
|
||||||
|
private:
|
||||||
FileDialogEventHandler(const FileDialogEventHandler&) = delete;
|
FileDialogEventHandler(const FileDialogEventHandler&) = delete;
|
||||||
FileDialogEventHandler& operator=(const FileDialogEventHandler&) = delete;
|
FileDialogEventHandler& operator=(const FileDialogEventHandler&) = delete;
|
||||||
FileDialogEventHandler(FileDialogEventHandler&&) = delete;
|
FileDialogEventHandler(FileDialogEventHandler&&) = delete;
|
||||||
|
@ -572,6 +556,7 @@ private:
|
||||||
com_ptr<IFileDialog> _dialog;
|
com_ptr<IFileDialog> _dialog;
|
||||||
com_ptr<IFileDialogCustomize> _customize;
|
com_ptr<IFileDialogCustomize> _customize;
|
||||||
const std::vector<Filter> _filterSpec;
|
const std::vector<Filter> _filterSpec;
|
||||||
|
generic_string _lastUsedFolder;
|
||||||
HWND _hwndNameEdit = nullptr;
|
HWND _hwndNameEdit = nullptr;
|
||||||
bool _monitorKeyboard = true;
|
bool _monitorKeyboard = true;
|
||||||
UINT _lastSelectedType = 0;
|
UINT _lastSelectedType = 0;
|
||||||
|
@ -610,7 +595,7 @@ public:
|
||||||
// Init the event handler.
|
// Init the event handler.
|
||||||
// Pass the initially selected file type.
|
// Pass the initially selected file type.
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
hr = FileDialogEventHandler::createInstance(_dialog, _filterSpec, _fileTypeIndex, _wildcardIndex, IID_PPV_ARGS(&_events));
|
_events.Attach(new FileDialogEventHandler(_dialog, _filterSpec, _fileTypeIndex, _wildcardIndex));
|
||||||
|
|
||||||
// If "assign type" is OFF, then change the file type to *.*
|
// If "assign type" is OFF, then change the file type to *.*
|
||||||
if (_enableFileTypeCheckbox && !_fileTypeCheckboxValue && _wildcardIndex >= 0)
|
if (_enableFileTypeCheckbox && !_fileTypeCheckboxValue && _wildcardIndex >= 0)
|
||||||
|
@ -723,11 +708,12 @@ public:
|
||||||
|
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
DWORD dwCookie = 0;
|
DWORD dwCookie = 0;
|
||||||
if (_events)
|
com_ptr<IFileDialogEvents> dialogEvents = _events;
|
||||||
|
if (dialogEvents)
|
||||||
{
|
{
|
||||||
hr = _dialog->Advise(_events, &dwCookie);
|
hr = _dialog->Advise(dialogEvents, &dwCookie);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
_events.Release();
|
dialogEvents.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool okPressed = false;
|
bool okPressed = false;
|
||||||
|
@ -735,9 +721,17 @@ public:
|
||||||
{
|
{
|
||||||
hr = _dialog->Show(_hwndOwner);
|
hr = _dialog->Show(_hwndOwner);
|
||||||
okPressed = SUCCEEDED(hr);
|
okPressed = SUCCEEDED(hr);
|
||||||
|
|
||||||
|
NppParameters& params = NppParameters::getInstance();
|
||||||
|
if (params.getNppGUI()._openSaveDir == dir_last)
|
||||||
|
{
|
||||||
|
// Note: IFileDialog doesn't modify the current directory.
|
||||||
|
// At least, after it is hidden, the current directory is the same as before it was shown.
|
||||||
|
params.setWorkingDir(_events->getLastUsedFolder().c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_events)
|
if (dialogEvents)
|
||||||
_dialog->Unadvise(dwCookie);
|
_dialog->Unadvise(dwCookie);
|
||||||
|
|
||||||
return okPressed;
|
return okPressed;
|
||||||
|
@ -827,7 +821,7 @@ public:
|
||||||
private:
|
private:
|
||||||
com_ptr<IFileDialog> _dialog;
|
com_ptr<IFileDialog> _dialog;
|
||||||
com_ptr<IFileDialogCustomize> _customize;
|
com_ptr<IFileDialogCustomize> _customize;
|
||||||
com_ptr<IFileDialogEvents> _events;
|
com_ptr<FileDialogEventHandler, IFileDialogEvents> _events;
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
Loading…
Reference in New Issue