Win32 file dialog: Prefill the filename when saving

This commit is contained in:
Henrik Rydgård
2026-03-06 13:18:31 +01:00
parent 66b8e866fb
commit 9a7241708c
7 changed files with 30 additions and 37 deletions
+1 -1
View File
@@ -1315,7 +1315,7 @@ void CtrlDisAsmView::disassembleToFile() {
}
std::string filename;
if (W32Util::BrowseForFileName(false, nullptr, L"Save Disassembly As...", nullptr, L"All Files\0*.*\0\0", nullptr, filename)) {
if (W32Util::BrowseForFileName(false, nullptr, L"Save Disassembly As...", nullptr, nullptr, L"All Files\0*.*\0\0", nullptr, filename)) {
std::wstring fileName = ConvertUTF8ToWString(filename);
FILE *output = _wfopen(fileName.c_str(), L"wb");
if (output == nullptr) {
+1 -1
View File
@@ -20,7 +20,7 @@ void DumpMemoryWindow::HandleBrowseClick(HWND hwnd) {
GetWindowTextW(filenameWnd, &buffer[0], (int)buffer.size());
std::string fn = ConvertWStringToUTF8(buffer);
bool result = W32Util::BrowseForFileName(false, hwnd, L"Select filename", NULL, NULL, NULL, fn);
bool result = W32Util::BrowseForFileName(false, hwnd, L"Select filename", nullptr, L"dump.bin", nullptr, nullptr, fn);
if (result) {
filenameChosen_ = true;
buffer = ConvertUTF8ToWString(fn);
+1 -1
View File
@@ -439,7 +439,7 @@ void CGEDebugger::DescribeSecondPreview(const GPUgstate &state, char desc[256])
void CGEDebugger::PreviewExport(const GPUDebugBuffer *dbgBuffer) {
constexpr const wchar_t *filter = L"PNG Image (*.png)\0*.png\0JPEG Image (*.jpg)\0*.jpg\0All files\0*.*\0\0";
std::string fn;
if (W32Util::BrowseForFileName(false, GetDlgHandle(), L"Save Preview Image...", nullptr, filter, L"png", fn)) {
if (W32Util::BrowseForFileName(false, GetDlgHandle(), L"Save Preview Image...", nullptr, L"preview.png", filter, L"png", fn)) {
ScreenshotFormat fmt = fn.find(".jpg") != fn.npos ? ScreenshotFormat::JPG : ScreenshotFormat::PNG;
Path filename(fn);
+9 -7
View File
@@ -558,7 +558,7 @@ namespace MainWindow {
case ID_FILE_LOADSTATEFILE:
if (!Achievements::WarnUserIfHardcoreModeActive(false) && !NetworkWarnUserIfOnlineAndCantSavestate()) {
if (W32Util::BrowseForFileName(true, hWnd, L"Load state", 0, L"Save States (*.ppst)\0*.ppst\0All files\0*.*\0\0", L"ppst", fn)) {
if (W32Util::BrowseForFileName(true, hWnd, L"Load state", nullptr, nullptr, L"Save States (*.ppst)\0*.ppst\0All files\0*.*\0\0", L"ppst", fn)) {
SetCursor(LoadCursor(0, IDC_WAIT));
SaveState::Load(Path(fn), -1, SaveStateActionFinished);
}
@@ -566,7 +566,7 @@ namespace MainWindow {
break;
case ID_FILE_SAVESTATEFILE:
if (!Achievements::WarnUserIfHardcoreModeActive(true) && !NetworkWarnUserIfOnlineAndCantSavestate()) {
if (W32Util::BrowseForFileName(false, hWnd, L"Save state", 0, L"Save States (*.ppst)\0*.ppst\0All files\0*.*\0\0", L"ppst", fn)) {
if (W32Util::BrowseForFileName(false, hWnd, L"Save state", nullptr, L"state.ppst", L"Save States (*.ppst)\0*.ppst\0All files\0*.*\0\0", L"ppst", fn)) {
SetCursor(LoadCursor(0, IDC_WAIT));
SaveState::Save(Path(fn), -1, SaveStateActionFinished);
}
@@ -773,27 +773,29 @@ namespace MainWindow {
}
case ID_DEBUG_LOADMAPFILE:
if (W32Util::BrowseForFileName(true, hWnd, L"Load .ppmap", 0, L"Maps\0*.ppmap\0All files\0*.*\0\0", L"ppmap", fn)) {
if (W32Util::BrowseForFileName(true, hWnd, L"Load .ppmap", nullptr, nullptr, L"Maps\0*.ppmap\0All files\0*.*\0\0", L"ppmap", fn)) {
g_symbolMap->LoadSymbolMap(Path(fn));
NotifyDebuggerMapLoaded();
}
break;
case ID_DEBUG_SAVEMAPFILE:
if (W32Util::BrowseForFileName(false, hWnd, L"Save .ppmap", 0, L"Maps\0*.ppmap\0All files\0*.*\0\0", L"ppmap", fn))
if (W32Util::BrowseForFileName(false, hWnd, L"Save .ppmap", nullptr, L"map.ppmap", L"Maps\0*.ppmap\0All files\0*.*\0\0", L"ppmap", fn)) {
g_symbolMap->SaveSymbolMap(Path(fn));
}
break;
case ID_DEBUG_LOADSYMFILE:
if (W32Util::BrowseForFileName(true, hWnd, L"Load .sym", 0, L"Symbols\0*.sym\0All files\0*.*\0\0", L"sym", fn)) {
if (W32Util::BrowseForFileName(true, hWnd, L"Load .sym", nullptr, nullptr, L"Symbols\0*.sym\0All files\0*.*\0\0", L"sym", fn)) {
g_symbolMap->LoadNocashSym(Path(fn));
NotifyDebuggerMapLoaded();
}
break;
case ID_DEBUG_SAVESYMFILE:
if (W32Util::BrowseForFileName(false, hWnd, L"Save .sym", 0, L"Symbols\0*.sym\0All files\0*.*\0\0", L"sym", fn))
if (W32Util::BrowseForFileName(false, hWnd, L"Save .sym", nullptr, L"symbols.sym", L"Symbols\0*.sym\0All files\0*.*\0\0", L"sym", fn)) {
g_symbolMap->SaveNocashSym(Path(fn));
}
break;
case ID_DEBUG_RESETSYMBOLTABLE:
@@ -845,7 +847,7 @@ namespace MainWindow {
MessageBox(hWnd, L"File does not exist.", L"Sorry", 0);
} else if (info.type == FILETYPE_DIRECTORY) {
MessageBox(hWnd, L"Cannot extract directories.", L"Sorry", 0);
} else if (W32Util::BrowseForFileName(false, hWnd, L"Save file as...", 0, L"All files\0*.*\0\0", L"", fn)) {
} else if (W32Util::BrowseForFileName(false, hWnd, L"Save file as...", nullptr, nullptr, L"All files\0*.*\0\0", L"", fn)) {
const u32 handle = pspFileSystem.OpenFile(filename, FILEACCESS_READ, "");
// Note: len may be in blocks.
size_t len = pspFileSystem.SeekFile(handle, 0, FILEMOVE_END);
+11 -21
View File
@@ -114,40 +114,30 @@ std::string BrowseForFolder2(HWND parent, std::string_view title, std::string_vi
}
bool BrowseForFileName(bool _bLoad, HWND _hParent, const wchar_t *_pTitle,
const wchar_t *_pInitialFolder, const wchar_t *_pFilter, const wchar_t *_pExtension,
const wchar_t *_pInitialFolder, const wchar_t *initialFilename, const wchar_t *_pFilter, const wchar_t *_pExtension,
std::string &_strFileName) {
// Let's hope this is large enough, don't want to trigger the dialog twice...
std::wstring filenameBuffer(32768 * 10, '\0');
wchar_t fileBuffer[2048]{};
wchar_t fileNameBuffer[2048]{};
if (initialFilename) {
wcscpy_s(fileBuffer, initialFilename);
}
OPENFILENAME ofn{ sizeof(OPENFILENAME) };
auto resetFileBuffer = [&] {
ofn.nMaxFile = (DWORD)filenameBuffer.size();
ofn.lpstrFile = &filenameBuffer[0];
if (!_strFileName.empty())
wcsncpy(ofn.lpstrFile, ConvertUTF8ToWString(_strFileName).c_str(), filenameBuffer.size() - 1);
};
resetFileBuffer();
ofn.lpstrInitialDir = _pInitialFolder;
ofn.lpstrFilter = _pFilter;
ofn.lpstrFileTitle = nullptr;
ofn.nMaxFileTitle = 0;
ofn.lpstrFileTitle = fileNameBuffer;
ofn.nMaxFileTitle = ARRAY_SIZE(fileNameBuffer);
ofn.lpstrDefExt = _pExtension;
ofn.hwndOwner = _hParent;
ofn.lpstrFile = fileBuffer;
ofn.nMaxFile = ARRAY_SIZE(fileBuffer);
ofn.Flags = OFN_NOCHANGEDIR | OFN_EXPLORER;
if (!_bLoad)
ofn.Flags |= OFN_HIDEREADONLY;
int success = _bLoad ? GetOpenFileName(&ofn) : GetSaveFileName(&ofn);
if (success == 0 && CommDlgExtendedError() == FNERR_BUFFERTOOSMALL) {
size_t sz = *(unsigned short *)&filenameBuffer[0];
// Documentation is unclear if this is WCHARs to CHARs.
filenameBuffer.resize(filenameBuffer.size() + sz * 2);
resetFileBuffer();
success = _bLoad ? GetOpenFileName(&ofn) : GetSaveFileName(&ofn);
}
if (success) {
_strFileName = ConvertWStringToUTF8(ofn.lpstrFile);
return true;
+1 -1
View File
@@ -11,7 +11,7 @@ namespace W32Util {
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,
const wchar_t *_pInitialFolder, const wchar_t *initialFilename, const wchar_t *_pFilter, const wchar_t*_pExtension,
std::string& _strFileName);
std::vector<std::string> BrowseForFileNameMultiSelect(bool _bLoad, HWND _hParent, const wchar_t*_pTitle,
const wchar_t*_pInitialFolder, const wchar_t*_pFilter, const wchar_t*_pExtension);
+6 -5
View File
@@ -686,7 +686,7 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string
std::thread([=] {
SetCurrentThreadName("BrowseForImage");
std::string out;
if (W32Util::BrowseForFileName(true, MainWindow::GetHWND(), ConvertUTF8ToWString(param1).c_str(), nullptr,
if (W32Util::BrowseForFileName(true, MainWindow::GetHWND(), ConvertUTF8ToWString(param1).c_str(), nullptr, nullptr,
FinalizeFilter(L"All supported images (*.jpg *.jpeg *.png)|*.jpg;*.jpeg;*.png|All files (*.*)|*.*||").c_str(), L"jpg", out)) {
g_requestManager.PostSystemSuccess(requestId, out.c_str());
} else {
@@ -699,16 +699,17 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string
{
const BrowseFileType browseType = (BrowseFileType)param3;
std::wstring filter = MakeWindowsFilter(browseType);
std::wstring initialFilename = ConvertUTF8ToWString(param2); // TODO: Plumb through
std::string initialFilename = param2;
if (filter.empty()) {
// Unsupported.
return false;
}
const bool load = type == SystemRequestType::BROWSE_FOR_FILE;
std::thread([=] {
std::thread([load, param1, initialFilename, filter, requestId] {
SetCurrentThreadName("BrowseForFile");
std::string out;
if (W32Util::BrowseForFileName(load, MainWindow::GetHWND(), ConvertUTF8ToWString(param1).c_str(), nullptr, filter.c_str(), L"", out)) {
std::string out = initialFilename;
std::wstring wInitial = ConvertUTF8ToWString(initialFilename);
if (W32Util::BrowseForFileName(load, MainWindow::GetHWND(), ConvertUTF8ToWString(param1).c_str(), nullptr, wInitial.c_str(), filter.c_str(), L"", out)) {
g_requestManager.PostSystemSuccess(requestId, out.c_str());
} else {
g_requestManager.PostSystemFailure(requestId);