summaryrefslogtreecommitdiff
path: root/ui/IFileDialog_Vista/ifile_dialog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ui/IFileDialog_Vista/ifile_dialog.cpp')
-rw-r--r--ui/IFileDialog_Vista/ifile_dialog.cpp98
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;
+}
bgstack15