Add "Append extension" checkbox to Save As dialog
Add "Append extension" checkbox to Save As dialog for replacing option "Save dialog file extension filter to *.*" in Preferences dialog. Fix #9515, close #9732
This commit is contained in:
parent
af56713079
commit
e3dbeda4c9
|
@ -1061,7 +1061,6 @@ You can define several column markers by using white space to separate the diffe
|
||||||
<Item id="6325" name="Scroll to the last line after update"/>
|
<Item id="6325" name="Scroll to the last line after update"/>
|
||||||
<Item id="6322" name="Session file ext.:"/>
|
<Item id="6322" name="Session file ext.:"/>
|
||||||
<Item id="6323" name="Enable Notepad++ auto-updater"/>
|
<Item id="6323" name="Enable Notepad++ auto-updater"/>
|
||||||
<Item id="6351" name="Set Save dialog file extension filter to *.*"/>
|
|
||||||
<Item id="6324" name="Document Switcher (Ctrl+TAB)"/>
|
<Item id="6324" name="Document Switcher (Ctrl+TAB)"/>
|
||||||
<Item id="6331" name="Show only filename in title bar"/>
|
<Item id="6331" name="Show only filename in title bar"/>
|
||||||
<Item id="6334" name="Autodetect character encoding"/>
|
<Item id="6334" name="Autodetect character encoding"/>
|
||||||
|
@ -1422,6 +1421,7 @@ Find in all files except exe, obj && log:
|
||||||
<find-regex-zero-length-match value="zero length match" />
|
<find-regex-zero-length-match value="zero length match" />
|
||||||
<session-save-folder-as-workspace value="Save Folder as Workspace" />
|
<session-save-folder-as-workspace value="Save Folder as Workspace" />
|
||||||
<tab-untitled-string value="new " />
|
<tab-untitled-string value="new " />
|
||||||
|
<file-save-assign-type value="&Append extension" />
|
||||||
</MiscStrings>
|
</MiscStrings>
|
||||||
</Native-Langue>
|
</Native-Langue>
|
||||||
</NotepadPlus>
|
</NotepadPlus>
|
||||||
|
|
|
@ -1637,16 +1637,17 @@ bool Notepad_plus::fileSaveAs(BufferID id, bool isSaveCopy)
|
||||||
|
|
||||||
LangType langType = buf->getLangType();
|
LangType langType = buf->getLangType();
|
||||||
|
|
||||||
int langTypeIndex = 0;
|
const bool defaultAllTypes = NppParameters::getInstance().getNppGUI()._setSaveDlgExtFiltToAllTypes;
|
||||||
if (!((NppParameters::getInstance()).getNppGUI()._setSaveDlgExtFiltToAllTypes))
|
const int langTypeIndex = setFileOpenSaveDlgFilters(fDlg, false, langType);
|
||||||
{
|
|
||||||
langTypeIndex = setFileOpenSaveDlgFilters(fDlg, false, langType);
|
|
||||||
}
|
|
||||||
|
|
||||||
fDlg.setDefFileName(buf->getFileName());
|
fDlg.setDefFileName(buf->getFileName());
|
||||||
|
|
||||||
fDlg.setExtIndex(langTypeIndex + 1); // +1 for "All types"
|
fDlg.setExtIndex(langTypeIndex + 1); // +1 for "All types"
|
||||||
|
|
||||||
|
const generic_string checkboxLabel = _nativeLangSpeaker.getLocalizedStrFromID("file-save-assign-type",
|
||||||
|
TEXT("&Append extension"));
|
||||||
|
fDlg.enableFileTypeCheckbox(checkboxLabel, !defaultAllTypes);
|
||||||
|
|
||||||
// Disable file autodetection before opening save dialog to prevent use-after-delete bug.
|
// Disable file autodetection before opening save dialog to prevent use-after-delete bug.
|
||||||
NppParameters& nppParam = NppParameters::getInstance();
|
NppParameters& nppParam = NppParameters::getInstance();
|
||||||
auto cdBefore = nppParam.getNppGUI()._fileAutoDetection;
|
auto cdBefore = nppParam.getNppGUI()._fileAutoDetection;
|
||||||
|
@ -1654,6 +1655,9 @@ bool Notepad_plus::fileSaveAs(BufferID id, bool isSaveCopy)
|
||||||
|
|
||||||
generic_string fn = fDlg.doSaveDlg();
|
generic_string fn = fDlg.doSaveDlg();
|
||||||
|
|
||||||
|
// Remember the selected state
|
||||||
|
const_cast<NppGUI&>(nppParam.getNppGUI())._setSaveDlgExtFiltToAllTypes = !fDlg.getFileTypeCheckboxValue();
|
||||||
|
|
||||||
// Enable file autodetection again.
|
// Enable file autodetection again.
|
||||||
(const_cast<NppGUI &>(nppParam.getNppGUI()))._fileAutoDetection = cdBefore;
|
(const_cast<NppGUI &>(nppParam.getNppGUI()))._fileAutoDetection = cdBefore;
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,9 @@ namespace // anonymous
|
||||||
generic_string ext;
|
generic_string ext;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const int IDC_FILE_CUSTOM_CHECKBOX = 4;
|
||||||
|
static const int IDC_FILE_TYPE_CHECKBOX = IDC_FILE_CUSTOM_CHECKBOX + 1;
|
||||||
|
|
||||||
// Returns a first extension from the extension specification string.
|
// Returns a first extension from the extension specification string.
|
||||||
// Multiple extensions are separated with ';'.
|
// Multiple extensions are separated with ';'.
|
||||||
// Example: input - ".c;.cpp;.h", output - ".c"
|
// Example: input - ".c;.cpp;.h", output - ".c"
|
||||||
|
@ -151,12 +154,15 @@ namespace // anonymous
|
||||||
generic_string getDialogFileName(IFileDialog* dialog)
|
generic_string getDialogFileName(IFileDialog* dialog)
|
||||||
{
|
{
|
||||||
generic_string fileName;
|
generic_string fileName;
|
||||||
PWSTR pszFilePath = nullptr;
|
if (dialog)
|
||||||
HRESULT hr = dialog->GetFileName(&pszFilePath);
|
|
||||||
if (SUCCEEDED(hr) && pszFilePath)
|
|
||||||
{
|
{
|
||||||
fileName = pszFilePath;
|
PWSTR pszFilePath = nullptr;
|
||||||
CoTaskMemFree(pszFilePath);
|
HRESULT hr = dialog->GetFileName(&pszFilePath);
|
||||||
|
if (SUCCEEDED(hr) && pszFilePath)
|
||||||
|
{
|
||||||
|
fileName = pszFilePath;
|
||||||
|
CoTaskMemFree(pszFilePath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return fileName;
|
return fileName;
|
||||||
}
|
}
|
||||||
|
@ -170,7 +176,7 @@ namespace // anonymous
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Backups the current directory in constructor and restores it in destructor.
|
// Backs up the current directory in constructor and restores it in destructor.
|
||||||
// This is needed in case dialog changes the current directory.
|
// This is needed in case dialog changes the current directory.
|
||||||
class CurrentDirBackup
|
class CurrentDirBackup
|
||||||
{
|
{
|
||||||
|
@ -197,13 +203,15 @@ namespace // anonymous
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class FileDialogEventHandler : public IFileDialogEvents
|
class FileDialogEventHandler : public IFileDialogEvents, public IFileDialogControlEvents
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static HRESULT createInstance(const std::vector<Filter>& filterSpec, REFIID riid, void **ppv)
|
static HRESULT createInstance(IFileDialog* dlg, const std::vector<Filter>& filterSpec,
|
||||||
|
int fileIndex, int wildcardIndex, REFIID riid, void **ppv)
|
||||||
{
|
{
|
||||||
*ppv = nullptr;
|
*ppv = nullptr;
|
||||||
FileDialogEventHandler *pDialogEventHandler = new (std::nothrow) FileDialogEventHandler(filterSpec);
|
FileDialogEventHandler* pDialogEventHandler =
|
||||||
|
new (std::nothrow) FileDialogEventHandler(dlg, filterSpec, fileIndex, wildcardIndex);
|
||||||
HRESULT hr = pDialogEventHandler ? S_OK : E_OUTOFMEMORY;
|
HRESULT hr = pDialogEventHandler ? S_OK : E_OUTOFMEMORY;
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
|
@ -228,6 +236,13 @@ public:
|
||||||
AddRef();
|
AddRef();
|
||||||
return NOERROR;
|
return NOERROR;
|
||||||
}
|
}
|
||||||
|
else if (riid == __uuidof(IFileDialogControlEvents))
|
||||||
|
{
|
||||||
|
// Increment the reference count and return the pointer.
|
||||||
|
*ppv = static_cast<IFileDialogControlEvents*>(this);
|
||||||
|
AddRef();
|
||||||
|
return NOERROR;
|
||||||
|
}
|
||||||
return E_NOINTERFACE;
|
return E_NOINTERFACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,34 +275,91 @@ public:
|
||||||
// First launch order: 2. Buttons are added, correct window title.
|
// First launch order: 2. Buttons are added, correct window title.
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
IFACEMETHODIMP OnSelectionChange(IFileDialog* dlg) override
|
IFACEMETHODIMP OnSelectionChange(IFileDialog*) override
|
||||||
{
|
{
|
||||||
// First launch order: 4. Main window is shown.
|
// First launch order: 4. Main window is shown.
|
||||||
if (!_dialog)
|
if (shouldInitControls())
|
||||||
initDialog(dlg);
|
initControls();
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
IFACEMETHODIMP OnShareViolation(IFileDialog*, IShellItem*, FDE_SHAREVIOLATION_RESPONSE*) override
|
IFACEMETHODIMP OnShareViolation(IFileDialog*, IShellItem*, FDE_SHAREVIOLATION_RESPONSE*) override
|
||||||
{
|
{
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
IFACEMETHODIMP OnTypeChange(IFileDialog* dlg) override
|
IFACEMETHODIMP OnTypeChange(IFileDialog*) override
|
||||||
{
|
{
|
||||||
// First launch order: 1. Inactive, window title might be wrong.
|
// First launch order: 1. Inactive, window title might be wrong.
|
||||||
generic_string name = getDialogFileName(dlg);
|
UINT dialogIndex = 0;
|
||||||
if (changeExt(name, dlg))
|
if (SUCCEEDED(_dialog->GetFileTypeIndex(&dialogIndex)))
|
||||||
dlg->SetFileName(name.c_str());
|
{
|
||||||
|
// Enable checkbox if type was changed.
|
||||||
|
if (OnTypeChange(dialogIndex))
|
||||||
|
_customize->SetCheckButtonState(IDC_FILE_TYPE_CHECKBOX, TRUE);
|
||||||
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OnTypeChange(UINT dialogIndex)
|
||||||
|
{
|
||||||
|
if (dialogIndex == 0)
|
||||||
|
return false;
|
||||||
|
generic_string name = getDialogFileName(_dialog);
|
||||||
|
if (changeExt(name, dialogIndex - 1))
|
||||||
|
return SUCCEEDED(_dialog->SetFileName(name.c_str()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
IFACEMETHODIMP OnOverwrite(IFileDialog*, IShellItem*, FDE_OVERWRITE_RESPONSE*) override
|
IFACEMETHODIMP OnOverwrite(IFileDialog*, IShellItem*, FDE_OVERWRITE_RESPONSE*) override
|
||||||
{
|
{
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IFileDialogControlEvents methods
|
||||||
|
|
||||||
|
IFACEMETHODIMP OnItemSelected(IFileDialogCustomize*, DWORD, DWORD) override
|
||||||
|
{
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
IFACEMETHODIMP OnButtonClicked(IFileDialogCustomize*, DWORD) override
|
||||||
|
{
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
IFACEMETHODIMP OnCheckButtonToggled(IFileDialogCustomize*, DWORD id, BOOL bChecked) override
|
||||||
|
{
|
||||||
|
if (id == IDC_FILE_TYPE_CHECKBOX)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
if (bChecked)
|
||||||
|
{
|
||||||
|
ok = SUCCEEDED(_dialog->SetFileTypeIndex(_lastSelectedType));
|
||||||
|
ok &= OnTypeChange(_lastSelectedType);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UINT currentIndex = 0;
|
||||||
|
ok = SUCCEEDED(_dialog->GetFileTypeIndex(¤tIndex));
|
||||||
|
if (ok && currentIndex != 0 && currentIndex != _wildcardType)
|
||||||
|
_lastSelectedType = currentIndex;
|
||||||
|
ok &= SUCCEEDED(_dialog->SetFileTypeIndex(_wildcardType));
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
IFACEMETHODIMP OnControlActivating(IFileDialogCustomize*, DWORD) override
|
||||||
|
{
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Use createInstance() instead
|
// Use createInstance() instead
|
||||||
FileDialogEventHandler(const std::vector<Filter>& filterSpec) : _cRef(1), _filterSpec(filterSpec)
|
FileDialogEventHandler(IFileDialog* dlg, const std::vector<Filter>& filterSpec, int fileIndex, int wildcardIndex)
|
||||||
|
: _cRef(1), _dialog(dlg), _customize(dlg), _filterSpec(filterSpec), _lastSelectedType(fileIndex + 1),
|
||||||
|
_wildcardType(wildcardIndex >= 0 ? wildcardIndex + 1 : 0)
|
||||||
{
|
{
|
||||||
_staticThis = this;
|
_staticThis = this;
|
||||||
}
|
}
|
||||||
|
@ -300,14 +372,13 @@ private:
|
||||||
FileDialogEventHandler(FileDialogEventHandler&&) = delete;
|
FileDialogEventHandler(FileDialogEventHandler&&) = delete;
|
||||||
FileDialogEventHandler& operator=(FileDialogEventHandler&&) = delete;
|
FileDialogEventHandler& operator=(FileDialogEventHandler&&) = delete;
|
||||||
|
|
||||||
// Inits dialog pointer and overrides window procedures for file name edit and ok button.
|
// Overrides window procedures for file name edit and ok button.
|
||||||
// Call this as late as possible to ensure all the controls of the dialog are created.
|
// Call this as late as possible to ensure all the controls of the dialog are created.
|
||||||
void initDialog(IFileDialog * d)
|
void initControls()
|
||||||
{
|
{
|
||||||
assert(!_dialog);
|
|
||||||
_dialog = d;
|
|
||||||
_okButtonProc = nullptr;
|
_okButtonProc = nullptr;
|
||||||
_fileNameProc = nullptr;
|
_fileNameProc = nullptr;
|
||||||
|
assert(_dialog);
|
||||||
com_ptr<IOleWindow> pOleWnd = _dialog;
|
com_ptr<IOleWindow> pOleWnd = _dialog;
|
||||||
if (pOleWnd)
|
if (pOleWnd)
|
||||||
{
|
{
|
||||||
|
@ -320,16 +391,27 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Changes the name extension according to currently selected file type index.
|
bool shouldInitControls() const
|
||||||
bool changeExt(generic_string& name, IFileDialog* dlg)
|
|
||||||
{
|
{
|
||||||
UINT typeIndex = 0;
|
return !_okButtonProc && !_fileNameProc;
|
||||||
if (FAILED(dlg->GetFileTypeIndex(&typeIndex)))
|
}
|
||||||
|
|
||||||
|
// Changes the name extension according to currently selected file type index.
|
||||||
|
bool changeExt(generic_string& name)
|
||||||
|
{
|
||||||
|
if (!_dialog)
|
||||||
return false;
|
return false;
|
||||||
// Index starts from 1
|
UINT dialogIndex = 0;
|
||||||
if (typeIndex > 0 && typeIndex - 1 < _filterSpec.size())
|
if (FAILED(_dialog->GetFileTypeIndex(&dialogIndex)) || dialogIndex == 0)
|
||||||
|
return false;
|
||||||
|
return changeExt(name, dialogIndex - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool changeExt(generic_string& name, size_t extIndex)
|
||||||
|
{
|
||||||
|
if (extIndex >= 0 && extIndex < _filterSpec.size())
|
||||||
{
|
{
|
||||||
const generic_string ext = get1stExt(_filterSpec[typeIndex - 1].ext);
|
const generic_string ext = get1stExt(_filterSpec[extIndex].ext);
|
||||||
if (!endsWith(ext, _T(".*")))
|
if (!endsWith(ext, _T(".*")))
|
||||||
return replaceExt(name, ext);
|
return replaceExt(name, ext);
|
||||||
}
|
}
|
||||||
|
@ -365,7 +447,7 @@ private:
|
||||||
// Name is a file path.
|
// Name is a file path.
|
||||||
// Add file extension if missing.
|
// Add file extension if missing.
|
||||||
if (!hasExt(fileName))
|
if (!hasExt(fileName))
|
||||||
nameChanged |= changeExt(fileName, _dialog);
|
nameChanged |= changeExt(fileName);
|
||||||
}
|
}
|
||||||
// Update the edit box text.
|
// Update the edit box text.
|
||||||
// It will update the address if the path is a directory.
|
// It will update the address if the path is a directory.
|
||||||
|
@ -487,10 +569,13 @@ private:
|
||||||
static FileDialogEventHandler* _staticThis;
|
static FileDialogEventHandler* _staticThis;
|
||||||
|
|
||||||
long _cRef;
|
long _cRef;
|
||||||
IFileDialog* _dialog = nullptr;
|
com_ptr<IFileDialog> _dialog;
|
||||||
|
com_ptr<IFileDialogCustomize> _customize;
|
||||||
const std::vector<Filter> _filterSpec;
|
const std::vector<Filter> _filterSpec;
|
||||||
HWND _hwndNameEdit = nullptr;
|
HWND _hwndNameEdit = nullptr;
|
||||||
bool _monitorKeyboard = true;
|
bool _monitorKeyboard = true;
|
||||||
|
UINT _lastSelectedType = 0;
|
||||||
|
UINT _wildcardType = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
WNDPROC FileDialogEventHandler::_okButtonProc;
|
WNDPROC FileDialogEventHandler::_okButtonProc;
|
||||||
|
@ -520,6 +605,16 @@ public:
|
||||||
NULL,
|
NULL,
|
||||||
CLSCTX_INPROC_SERVER,
|
CLSCTX_INPROC_SERVER,
|
||||||
IID_PPV_ARGS(&_dialog));
|
IID_PPV_ARGS(&_dialog));
|
||||||
|
_customize = _dialog;
|
||||||
|
|
||||||
|
// Init the event handler.
|
||||||
|
// Pass the initially selected file type.
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
hr = FileDialogEventHandler::createInstance(_dialog, _filterSpec, _fileTypeIndex, _wildcardIndex, IID_PPV_ARGS(&_events));
|
||||||
|
|
||||||
|
// If "assign type" is OFF, then change the file type to *.*
|
||||||
|
if (_enableFileTypeCheckbox && !_fileTypeCheckboxValue && _wildcardIndex >= 0)
|
||||||
|
_fileTypeIndex = _wildcardIndex;
|
||||||
|
|
||||||
if (SUCCEEDED(hr) && _title)
|
if (SUCCEEDED(hr) && _title)
|
||||||
hr = _dialog->SetTitle(_title);
|
hr = _dialog->SetTitle(_title);
|
||||||
|
@ -564,7 +659,10 @@ public:
|
||||||
|
|
||||||
// The selected index should be set after the file types are set.
|
// The selected index should be set after the file types are set.
|
||||||
if (SUCCEEDED(hr) && _fileTypeIndex >= 0)
|
if (SUCCEEDED(hr) && _fileTypeIndex >= 0)
|
||||||
hr = _dialog->SetFileTypeIndex(_fileTypeIndex + 1); // This index is 1-based
|
hr = _dialog->SetFileTypeIndex(_fileTypeIndex + 1); // This index is 1-based.
|
||||||
|
|
||||||
|
if (_enableFileTypeCheckbox)
|
||||||
|
addCheckbox(IDC_FILE_TYPE_CHECKBOX, _fileTypeCheckboxLabel.c_str(), _fileTypeCheckboxValue);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
return addControls();
|
return addControls();
|
||||||
|
@ -595,47 +693,62 @@ public:
|
||||||
|
|
||||||
bool addControls()
|
bool addControls()
|
||||||
{
|
{
|
||||||
_customize = _dialog;
|
|
||||||
if (!_customize)
|
if (!_customize)
|
||||||
return false;
|
return false;
|
||||||
if (_checkboxLabel && _checkboxLabel[0] != '\0')
|
if (_checkboxLabel && _checkboxLabel[0] != '\0')
|
||||||
{
|
{
|
||||||
const BOOL isChecked = FALSE;
|
return addCheckbox(IDC_FILE_CUSTOM_CHECKBOX, _checkboxLabel, false, _isCheckboxActive);
|
||||||
HRESULT hr = _customize->AddCheckButton(IDC_FILE_CHECKBOX, _checkboxLabel, isChecked);
|
|
||||||
if (SUCCEEDED(hr) && !_isCheckboxActive)
|
|
||||||
{
|
|
||||||
hr = _customize->SetControlState(IDC_FILE_CHECKBOX, CDCS_INACTIVE | CDCS_VISIBLE);
|
|
||||||
return SUCCEEDED(hr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool addCheckbox(int id, const TCHAR* label, bool value, bool enabled = true)
|
||||||
|
{
|
||||||
|
if (!_customize)
|
||||||
|
return false;
|
||||||
|
HRESULT hr = _customize->AddCheckButton(id, label, value ? TRUE : FALSE);
|
||||||
|
if (SUCCEEDED(hr) && !enabled)
|
||||||
|
{
|
||||||
|
hr = _customize->SetControlState(id, CDCS_INACTIVE | CDCS_VISIBLE);
|
||||||
|
return SUCCEEDED(hr);
|
||||||
|
}
|
||||||
|
return SUCCEEDED(hr);
|
||||||
|
}
|
||||||
|
|
||||||
bool show()
|
bool show()
|
||||||
{
|
{
|
||||||
|
assert(_dialog);
|
||||||
|
if (!_dialog)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
DWORD dwCookie = 0;
|
||||||
|
if (_events)
|
||||||
|
{
|
||||||
|
hr = _dialog->Advise(_events, &dwCookie);
|
||||||
|
if (FAILED(hr))
|
||||||
|
_events.Release();
|
||||||
|
}
|
||||||
|
|
||||||
bool okPressed = false;
|
bool okPressed = false;
|
||||||
HRESULT hr = FileDialogEventHandler::createInstance(_filterSpec, IID_PPV_ARGS(&_events));
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
DWORD dwCookie;
|
hr = _dialog->Show(_hwndOwner);
|
||||||
hr = _dialog->Advise(_events, &dwCookie);
|
okPressed = SUCCEEDED(hr);
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = _dialog->Show(_hwndOwner);
|
|
||||||
okPressed = SUCCEEDED(hr);
|
|
||||||
|
|
||||||
_dialog->Unadvise(dwCookie);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_events)
|
||||||
|
_dialog->Unadvise(dwCookie);
|
||||||
|
|
||||||
return okPressed;
|
return okPressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL getCheckboxState() const
|
BOOL getCheckboxState(int id) const
|
||||||
{
|
{
|
||||||
if (_customize)
|
if (_customize)
|
||||||
{
|
{
|
||||||
BOOL bChecked = FALSE;
|
BOOL bChecked = FALSE;
|
||||||
HRESULT hr = _customize->GetCheckButtonState(IDC_FILE_CHECKBOX, &bChecked);
|
HRESULT hr = _customize->GetCheckButtonState(id, &bChecked);
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
return bChecked;
|
return bChecked;
|
||||||
}
|
}
|
||||||
|
@ -695,8 +808,6 @@ public:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const int IDC_FILE_CHECKBOX = 4;
|
|
||||||
|
|
||||||
HWND _hwndOwner = nullptr;
|
HWND _hwndOwner = nullptr;
|
||||||
const TCHAR* _title = nullptr;
|
const TCHAR* _title = nullptr;
|
||||||
const TCHAR* _defExt = nullptr;
|
const TCHAR* _defExt = nullptr;
|
||||||
|
@ -706,8 +817,12 @@ public:
|
||||||
const TCHAR* _initialFileName = nullptr;
|
const TCHAR* _initialFileName = nullptr;
|
||||||
bool _isCheckboxActive = true;
|
bool _isCheckboxActive = true;
|
||||||
std::vector<Filter> _filterSpec;
|
std::vector<Filter> _filterSpec;
|
||||||
int _fileTypeIndex = -1;
|
int _fileTypeIndex = -1; // preferred file type index
|
||||||
|
int _wildcardIndex = -1; // *.* file type index
|
||||||
bool _hasReadonly = false; // set during the result handling
|
bool _hasReadonly = false; // set during the result handling
|
||||||
|
bool _enableFileTypeCheckbox = false;
|
||||||
|
bool _fileTypeCheckboxValue = false; // initial value
|
||||||
|
generic_string _fileTypeCheckboxLabel;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
com_ptr<IFileDialog> _dialog;
|
com_ptr<IFileDialog> _dialog;
|
||||||
|
@ -750,6 +865,9 @@ void CustomFileDialog::setExtFilter(const TCHAR *extText, const TCHAR *exts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (newExts.find(_T("*.*")) == 0)
|
||||||
|
_impl->_wildcardIndex = static_cast<int>(_impl->_filterSpec.size());
|
||||||
|
|
||||||
_impl->_filterSpec.push_back({ extText, newExts });
|
_impl->_filterSpec.push_back({ extText, newExts });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -793,7 +911,7 @@ void CustomFileDialog::setExtIndex(int extTypeIndex)
|
||||||
|
|
||||||
bool CustomFileDialog::getCheckboxState() const
|
bool CustomFileDialog::getCheckboxState() const
|
||||||
{
|
{
|
||||||
return _impl->getCheckboxState();
|
return _impl->getCheckboxState(IDC_FILE_CUSTOM_CHECKBOX);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CustomFileDialog::isReadOnly() const
|
bool CustomFileDialog::isReadOnly() const
|
||||||
|
@ -801,6 +919,22 @@ bool CustomFileDialog::isReadOnly() const
|
||||||
return _impl->_hasReadonly;
|
return _impl->_hasReadonly;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CustomFileDialog::enableFileTypeCheckbox(const generic_string& text, bool value)
|
||||||
|
{
|
||||||
|
assert(!text.empty());
|
||||||
|
if (!text.empty())
|
||||||
|
{
|
||||||
|
_impl->_fileTypeCheckboxLabel = text;
|
||||||
|
_impl->_enableFileTypeCheckbox = true;
|
||||||
|
_impl->_fileTypeCheckboxValue = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CustomFileDialog::getFileTypeCheckboxValue() const
|
||||||
|
{
|
||||||
|
return _impl->getCheckboxState(IDC_FILE_TYPE_CHECKBOX);
|
||||||
|
}
|
||||||
|
|
||||||
generic_string CustomFileDialog::doSaveDlg()
|
generic_string CustomFileDialog::doSaveDlg()
|
||||||
{
|
{
|
||||||
if (!_impl->initSave())
|
if (!_impl->initSave())
|
||||||
|
|
|
@ -38,6 +38,9 @@ public:
|
||||||
void setCheckbox(const TCHAR* text, bool isActive = true);
|
void setCheckbox(const TCHAR* text, bool isActive = true);
|
||||||
void setExtIndex(int extTypeIndex);
|
void setExtIndex(int extTypeIndex);
|
||||||
|
|
||||||
|
void enableFileTypeCheckbox(const generic_string& text, bool value);
|
||||||
|
bool getFileTypeCheckboxValue() const;
|
||||||
|
|
||||||
// Empty string is not a valid file name and may signal that the dialog was canceled.
|
// Empty string is not a valid file name and may signal that the dialog was canceled.
|
||||||
generic_string doSaveDlg();
|
generic_string doSaveDlg();
|
||||||
generic_string pickFolder();
|
generic_string pickFolder();
|
||||||
|
|
|
@ -426,9 +426,8 @@ BEGIN
|
||||||
CONTROL "Peek on document map",IDC_CHECK_ENABLEDOCPEEKONMAP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,269,71,140,10
|
CONTROL "Peek on document map",IDC_CHECK_ENABLEDOCPEEKONMAP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,269,71,140,10
|
||||||
|
|
||||||
// "Enable Notepad++ auto-updater" should be always the 1st item, because it'll be hidden if GUP.exe is absent
|
// "Enable Notepad++ auto-updater" should be always the 1st item, because it'll be hidden if GUP.exe is absent
|
||||||
CONTROL "Mute all sounds", IDC_CHECK_MUTE_SOUNDS, "Button", BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP, 37, 94, 217, 10
|
CONTROL "Enable Notepad++ auto-updater",IDC_CHECK_AUTOUPDATE,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP, 37, 94, 210, 10
|
||||||
CONTROL "Enable Notepad++ auto-updater",IDC_CHECK_AUTOUPDATE,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP, 37, 78, 210, 10
|
CONTROL "Mute all sounds", IDC_CHECK_MUTE_SOUNDS, "Button", BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP, 37, 109, 217, 10
|
||||||
CONTROL "Set Save dialog file extension filter to *.*",IDC_CHECK_SAVEDLGEXTFILTALLTYPES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,37,109,267,10
|
|
||||||
CONTROL "Autodetect character encoding",IDC_CHECK_DETECTENCODING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,37,124,217,10
|
CONTROL "Autodetect character encoding",IDC_CHECK_DETECTENCODING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,37,124,217,10
|
||||||
CONTROL "Minimize to system tray",IDC_CHECK_MIN2SYSTRAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,37,139,217,10
|
CONTROL "Minimize to system tray",IDC_CHECK_MIN2SYSTRAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,37,139,217,10
|
||||||
CONTROL "Show only filename in title bar",IDC_CHECK_SHORTTITLE,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,37,154,217,10
|
CONTROL "Show only filename in title bar",IDC_CHECK_SHORTTITLE,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,37,154,217,10
|
||||||
|
|
|
@ -1025,7 +1025,6 @@ INT_PTR CALLBACK MiscSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM)
|
||||||
::SendDlgItemMessage(_hSelf, IDC_CHECK_MIN2SYSTRAY, BM_SETCHECK, nppGUI._isMinimizedToTray, 0);
|
::SendDlgItemMessage(_hSelf, IDC_CHECK_MIN2SYSTRAY, BM_SETCHECK, nppGUI._isMinimizedToTray, 0);
|
||||||
::SendDlgItemMessage(_hSelf, IDC_CHECK_DETECTENCODING, BM_SETCHECK, nppGUI._detectEncoding, 0);
|
::SendDlgItemMessage(_hSelf, IDC_CHECK_DETECTENCODING, BM_SETCHECK, nppGUI._detectEncoding, 0);
|
||||||
::SendDlgItemMessage(_hSelf, IDC_CHECK_AUTOUPDATE, BM_SETCHECK, nppGUI._autoUpdateOpt._doAutoUpdate, 0);
|
::SendDlgItemMessage(_hSelf, IDC_CHECK_AUTOUPDATE, BM_SETCHECK, nppGUI._autoUpdateOpt._doAutoUpdate, 0);
|
||||||
::SendDlgItemMessage(_hSelf, IDC_CHECK_SAVEDLGEXTFILTALLTYPES, BM_SETCHECK, nppGUI._setSaveDlgExtFiltToAllTypes, 0);
|
|
||||||
::SendDlgItemMessage(_hSelf, IDC_CHECK_DIRECTWRITE_ENABLE, BM_SETCHECK, nppGUI._writeTechnologyEngine == directWriteTechnology, 0);
|
::SendDlgItemMessage(_hSelf, IDC_CHECK_DIRECTWRITE_ENABLE, BM_SETCHECK, nppGUI._writeTechnologyEngine == directWriteTechnology, 0);
|
||||||
::SendDlgItemMessage(_hSelf, IDC_CHECK_ENABLEDOCPEEKER, BM_SETCHECK, nppGUI._isDocPeekOnTab ? BST_CHECKED : BST_UNCHECKED, 0);
|
::SendDlgItemMessage(_hSelf, IDC_CHECK_ENABLEDOCPEEKER, BM_SETCHECK, nppGUI._isDocPeekOnTab ? BST_CHECKED : BST_UNCHECKED, 0);
|
||||||
::SendDlgItemMessage(_hSelf, IDC_CHECK_ENABLEDOCPEEKONMAP, BM_SETCHECK, nppGUI._isDocPeekOnMap ? BST_CHECKED : BST_UNCHECKED, 0);
|
::SendDlgItemMessage(_hSelf, IDC_CHECK_ENABLEDOCPEEKONMAP, BM_SETCHECK, nppGUI._isDocPeekOnMap ? BST_CHECKED : BST_UNCHECKED, 0);
|
||||||
|
@ -1103,10 +1102,6 @@ INT_PTR CALLBACK MiscSubDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM)
|
||||||
nppGUI._autoUpdateOpt._doAutoUpdate = isCheckedOrNot(static_cast<int32_t>(wParam));
|
nppGUI._autoUpdateOpt._doAutoUpdate = isCheckedOrNot(static_cast<int32_t>(wParam));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
case IDC_CHECK_SAVEDLGEXTFILTALLTYPES:
|
|
||||||
nppGUI._setSaveDlgExtFiltToAllTypes = isCheckedOrNot(static_cast<int32_t>(wParam));
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
case IDC_CHECK_MIN2SYSTRAY:
|
case IDC_CHECK_MIN2SYSTRAY:
|
||||||
nppGUI._isMinimizedToTray = isCheckedOrNot(static_cast<int32_t>(wParam));
|
nppGUI._isMinimizedToTray = isCheckedOrNot(static_cast<int32_t>(wParam));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
|
@ -198,7 +198,6 @@
|
||||||
#define IDC_CHECK_SMARTHILITEWHOLEWORDONLY (IDD_PREFERENCE_SUB_MISC + 38)
|
#define IDC_CHECK_SMARTHILITEWHOLEWORDONLY (IDD_PREFERENCE_SUB_MISC + 38)
|
||||||
#define IDC_CHECK_SMARTHILITEUSEFINDSETTINGS (IDD_PREFERENCE_SUB_MISC + 39)
|
#define IDC_CHECK_SMARTHILITEUSEFINDSETTINGS (IDD_PREFERENCE_SUB_MISC + 39)
|
||||||
#define IDC_CHECK_SMARTHILITEANOTHERRVIEW (IDD_PREFERENCE_SUB_MISC + 40)
|
#define IDC_CHECK_SMARTHILITEANOTHERRVIEW (IDD_PREFERENCE_SUB_MISC + 40)
|
||||||
#define IDC_CHECK_SAVEDLGEXTFILTALLTYPES (IDD_PREFERENCE_SUB_MISC + 51)
|
|
||||||
|
|
||||||
//-- xFileEditViewHistoryParameterGUI: Additional Checkbox for enabling the history for restoring the edit view per file.
|
//-- xFileEditViewHistoryParameterGUI: Additional Checkbox for enabling the history for restoring the edit view per file.
|
||||||
#define IDC_CHECK_REMEMBEREDITVIEWPERFILE (IDD_PREFERENCE_SUB_MISC + 41)
|
#define IDC_CHECK_REMEMBEREDITVIEWPERFILE (IDD_PREFERENCE_SUB_MISC + 41)
|
||||||
|
|
Loading…
Reference in New Issue