diff --git a/Windows/W32Util/ShellUtil.cpp b/Windows/W32Util/ShellUtil.cpp index c0f3af4a49..24b26a8639 100644 --- a/Windows/W32Util/ShellUtil.cpp +++ b/Windows/W32Util/ShellUtil.cpp @@ -10,15 +10,65 @@ #include "Common/Data/Format/PNGLoad.h" #include "ShellUtil.h" +#include // For IFileDialog and related interfaces #include #include #include namespace W32Util { - std::string BrowseForFolder(HWND parent, std::string_view title, std::string_view initialPath) { - std::wstring titleString = ConvertUTF8ToWString(title); - return BrowseForFolder(parent, titleString.c_str(), initialPath); + +std::string BrowseForFolder2(HWND parent, std::string_view title, std::string_view initialPath) { + const std::wstring wtitle = ConvertUTF8ToWString(title); + const std::wstring initialDir = ConvertUTF8ToWString(initialPath); + + std::wstring selectedFolder; + + // Create the FileOpenDialog object + IFileDialog* pFileDialog = nullptr; + HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pFileDialog)); + if (!SUCCEEDED(hr)) { + return ""; } + // Set the options to select folders instead of files + DWORD dwOptions; + hr = pFileDialog->GetOptions(&dwOptions); + if (SUCCEEDED(hr)) { + hr = pFileDialog->SetOptions(dwOptions | FOS_PICKFOLDERS); + } else { + return ""; + } + + // Set the initial directory + if (!initialDir.empty()) { + IShellItem* pShellItem = nullptr; + hr = SHCreateItemFromParsingName(initialDir.c_str(), nullptr, IID_PPV_ARGS(&pShellItem)); + if (SUCCEEDED(hr)) { + hr = pFileDialog->SetFolder(pShellItem); + pShellItem->Release(); + } + } + pFileDialog->SetTitle(wtitle.c_str()); + + // Show the dialog + hr = pFileDialog->Show(parent); + if (SUCCEEDED(hr)) { + // Get the selected folder + IShellItem* pShellItem = nullptr; + hr = pFileDialog->GetResult(&pShellItem); + if (SUCCEEDED(hr)) { + PWSTR pszFilePath = nullptr; + hr = pShellItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath); + if (SUCCEEDED(hr)) { + selectedFolder = pszFilePath; + CoTaskMemFree(pszFilePath); + } + pShellItem->Release(); + } + } + + pFileDialog->Release(); + return ConvertWStringToUTF8(selectedFolder); +} static int CALLBACK BrowseFolderCallback(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData) { if (uMsg == BFFM_INITIALIZED) { @@ -72,6 +122,12 @@ namespace W32Util { return result; } + std::string BrowseForFolder(HWND parent, std::string_view title, std::string_view initialPath) { + std::wstring titleString = ConvertUTF8ToWString(title); + return BrowseForFolder(parent, titleString.c_str(), initialPath); + } + + bool BrowseForFileName(bool _bLoad, HWND _hParent, const wchar_t *_pTitle, const wchar_t *_pInitialFolder, const wchar_t *_pFilter, const wchar_t *_pExtension, std::string &_strFileName) { @@ -333,4 +389,4 @@ bool CreateICOFromPNGData(const uint8_t *imageData, size_t imageDataSize, const return true; } -} // namespace +} // namespace W32Util diff --git a/Windows/W32Util/ShellUtil.h b/Windows/W32Util/ShellUtil.h index 8201ae691b..a983d4a219 100644 --- a/Windows/W32Util/ShellUtil.h +++ b/Windows/W32Util/ShellUtil.h @@ -7,11 +7,14 @@ class Path; -namespace W32Util -{ +namespace W32Util { + // Can't make initialPath a string_view, need the null so might as well require it. std::string BrowseForFolder(HWND parent, std::string_view title, std::string_view initialPath); std::string BrowseForFolder(HWND parent, const wchar_t *title, std::string_view initialPath); +// Modern dialog +std::string BrowseForFolder2(HWND parent, std::string_view title, std::string_view initialPath); + bool BrowseForFileName(bool _bLoad, HWND _hParent, const wchar_t*_pTitle, const wchar_t *_pInitialFolder, const wchar_t *_pFilter, const wchar_t*_pExtension, std::string& _strFileName); diff --git a/Windows/main.cpp b/Windows/main.cpp index 4f80b64659..707abe6808 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -626,7 +626,7 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string case SystemRequestType::BROWSE_FOR_FOLDER: { std::thread([=] { - std::string folder = W32Util::BrowseForFolder(MainWindow::GetHWND(), param1, param2); + std::string folder = W32Util::BrowseForFolder2(MainWindow::GetHWND(), param1, param2); if (folder.size()) { g_requestManager.PostSystemSuccess(requestId, folder.c_str()); } else { @@ -843,7 +843,11 @@ static void InitMemstickDirectory() { } static void WinMainInit() { - CoInitializeEx(NULL, COINIT_MULTITHREADED); + HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); + if (FAILED(hr)) { + _dbg_assert_(false); + } + net::Init(); // This needs to happen before we load the config. So on Windows we also run it in Main. It's fine to call multiple times. // Windows, API init stuff @@ -859,11 +863,6 @@ static void WinMainInit() { #endif PROFILE_INIT(); -#if PPSSPP_ARCH(AMD64) && defined(_MSC_VER) && _MSC_VER < 1900 - // FMA3 support in the 2013 CRT is broken on Vista and Windows 7 RTM (fixed in SP1). Just disable it. - _set_FMA3_enable(0); -#endif - InitDarkMode(); }