diff options
Diffstat (limited to 'ui/IFileDialog_Vista/ifile_dialog.cpp')
-rw-r--r-- | ui/IFileDialog_Vista/ifile_dialog.cpp | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/ui/IFileDialog_Vista/ifile_dialog.cpp b/ui/IFileDialog_Vista/ifile_dialog.cpp new file mode 100644 index 00000000..dd2bc7c8 --- /dev/null +++ b/ui/IFileDialog_Vista/ifile_dialog.cpp @@ -0,0 +1,98 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) ZenJu (zenju AT gmx DOT de) - All Rights Reserved * +// ************************************************************************** + +#include "ifile_dialog.h" +#define WIN32_LEAN_AND_MEAN +#include <zen/com_error.h> +#include <zen/com_ptr.h> +#include <Shobjidl.h> +#include <zen/scope_guard.h> +#include <string> + +using namespace zen; + + +namespace +{ +bool showFolderPickerImpl(HWND ownerWindow, //throw ComError; return "false" if cancelled by user + const wchar_t* defaultFolder, //optional! + std::wstring& selectedFolder) +{ + ComPtr<IFileDialog> fileDlg; + ZEN_CHECK_COM(::CoCreateInstance(CLSID_FileOpenDialog, //throw ComError + nullptr, + CLSCTX_ALL, + IID_PPV_ARGS(fileDlg.init()))); + + FILEOPENDIALOGOPTIONS dlgOptions = 0; + ZEN_CHECK_COM(fileDlg->GetOptions(&dlgOptions)); //throw ComError + ZEN_CHECK_COM(fileDlg->SetOptions(dlgOptions | FOS_PICKFOLDERS | FOS_NOVALIDATE | FOS_FORCEFILESYSTEM)); + + if (defaultFolder) //show last selection instead of top level if no default available + { + ComPtr<IShellItem> folderItem; + ZEN_CHECK_COM(::SHCreateItemFromParsingName(defaultFolder, + nullptr, + IID_PPV_ARGS(folderItem.init()))); + ZEN_CHECK_COM(fileDlg->SetFolder(folderItem.get())); + } + + try + { + ZEN_CHECK_COM(fileDlg->Show(ownerWindow)); //may fail with: HRESULT_FROM_WIN32(ERROR_CANCELLED) + } + catch (const ComError&) { return false; } + + ComPtr<IShellItem> folderItem; + ZEN_CHECK_COM(fileDlg->GetResult(folderItem.init())); + + LPWSTR folderPath = nullptr; + ZEN_CHECK_COM(folderItem->GetDisplayName(SIGDN_FILESYSPATH, &folderPath)); + ZEN_ON_SCOPE_EXIT(::CoTaskMemFree(folderPath)); + + selectedFolder = folderPath; + return true; +} + +const wchar_t* allocString(const std::wstring& msg) //ownership passed +{ + auto tmp = new wchar_t [msg.size() + 1]; //bad_alloc ? + ::wmemcpy(tmp, msg.c_str(), msg.size() + 1); //include 0-termination + return tmp; +} +} + +//################################################################################################## + +void ifile::showFolderPicker(void* ownerWindow, + const wchar_t* defaultFolder, + const wchar_t*& selectedFolder, + bool& cancelled, + const wchar_t*& errorMsg) +{ + selectedFolder = nullptr; + cancelled = false; + errorMsg = nullptr; + + try + { + std::wstring folderPath; + if (showFolderPickerImpl(static_cast<HWND>(ownerWindow), defaultFolder, folderPath)) //throw ComError + selectedFolder = allocString(folderPath); + else + cancelled = true; + } + catch (const ComError& e) + { + errorMsg = allocString(e.toString()); + } +} + + +void ifile::freeString(const wchar_t* str) +{ + delete [] str; +} |