From 4457bcf4a7625cbeb3350f87d8cdf9ad7857bce5 Mon Sep 17 00:00:00 2001 From: GoaLitiuM Date: Sun, 24 Jan 2021 02:33:08 +0200 Subject: [PATCH] Use more modern file dialog for browsing folders --- .../Platform/Windows/WindowsFileSystem.cpp | 64 +++++++++++-------- 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/Source/Engine/Platform/Windows/WindowsFileSystem.cpp b/Source/Engine/Platform/Windows/WindowsFileSystem.cpp index 7c6b04fef..e30747961 100644 --- a/Source/Engine/Platform/Windows/WindowsFileSystem.cpp +++ b/Source/Engine/Platform/Windows/WindowsFileSystem.cpp @@ -5,6 +5,7 @@ #include "WindowsFileSystem.h" #include "Engine/Platform/File.h" #include "Engine/Platform/Window.h" +#include "Engine/Platform/Windows/ComPtr.h" #include "Engine/Core/Types/StringView.h" #include "../Win32/IncludeWindowsHeaders.h" @@ -293,41 +294,50 @@ bool WindowsFileSystem::ShowBrowseFolderDialog(Window* parentWindow, const Strin { bool result = true; + // Randomly generated GUID used for storing the last location of this dialog + const Guid folderGuid(0x53890ed9, 0xa55e47ba, 0xa970bdae, 0x72acedff); + // Allocate memory for the filenames int32 maxPathSize = 2 * MAX_PATH; Array pathBuffer; - pathBuffer.Resize(maxPathSize); - pathBuffer[0] = 0; + pathBuffer.EnsureCapacity(maxPathSize); - // Setup description - BROWSEINFOW bi; - ZeroMemory(&bi, sizeof(bi)); - if (parentWindow) - bi.hwndOwner = static_cast(parentWindow->GetNativePtr()); - bi.lpszTitle = title.HasChars() ? title.Get() : nullptr; - bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE; - bi.lpfn = BrowseCallbackProc; - bi.lParam = (LPARAM)(initialDirectory.HasChars() ? initialDirectory.Get() : nullptr); - - LPITEMIDLIST pidl = SHBrowseForFolder(&bi); - - if (pidl != nullptr) + ComPtr fd; + if (SUCCEEDED(CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&fd)))) { - // Get the name of the folder and put it in path - SHGetPathFromIDList(pidl, pathBuffer.Get()); + DWORD options; + fd->GetOptions(&options); + fd->SetOptions(options | FOS_PICKFOLDERS | FOS_NOCHANGEDIR); - if (pathBuffer[0] != 0) - { - path = pathBuffer.Get(); - result = false; - } + if (title.HasChars()) + fd->SetTitle(title.Get()); - // Free memory used - IMalloc* imalloc = 0; - if (SUCCEEDED(SHGetMalloc(&imalloc))) + // Associate the last selected folder with this GUID instead of overwriting the global one + fd->SetClientGuid(*reinterpret_cast(&folderGuid)); + + ComPtr defaultFolder; + if (SUCCEEDED(SHCreateItemFromParsingName(initialDirectory.Get(), NULL, IID_PPV_ARGS(&defaultFolder)))) + fd->SetFolder(defaultFolder); + + if (SUCCEEDED(fd->Show(parentWindow->GetHWND()))) { - imalloc->Free(pidl); - imalloc->Release(); + ComPtr si; + if (SUCCEEDED(fd->GetResult(&si))) + { + LPWSTR resultPath; + if (SUCCEEDED(si->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING, &resultPath))) + { + int32 resultPathLength = StringUtils::Length(resultPath); + if (resultPathLength < pathBuffer.Capacity()) + { + StringUtils::Copy(pathBuffer.Get(), resultPath, resultPathLength); + CoTaskMemFree(resultPath); + + path = pathBuffer.Get(); + result = false; + } + } + } } }