From db0dadd12860fd72ad440e5823ccb1a5a2138904 Mon Sep 17 00:00:00 2001 From: martinfouilleul Date: Tue, 23 May 2023 17:24:38 +0200 Subject: [PATCH] [win32] allow specifying start folder in open/save dialogs --- build.bat | 2 +- examples/ui/main.c | 4 ++-- src/win32_app.c | 38 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/build.bat b/build.bat index 9f9dfc1..9d1c053 100644 --- a/build.bat +++ b/build.bat @@ -6,6 +6,6 @@ set glsl_shaders=src\glsl_shaders\common.glsl src\glsl_shaders\blit_vertex.glsl call python3 scripts\embed_text.py %glsl_shaders% --prefix=glsl_ --output src\glsl_shaders.h set INCLUDES=/I src /I src/util /I src/platform /I ext /I ext/angle_headers -set LIBS=user32.lib opengl32.lib gdi32.lib shcore.lib delayimp.lib dwmapi.lib comctl32.lib ole32.lib /LIBPATH:./bin libEGL.dll.lib libGLESv2.dll.lib /DELAYLOAD:libEGL.dll /DELAYLOAD:libGLESv2.dll +set LIBS=user32.lib opengl32.lib gdi32.lib shcore.lib delayimp.lib dwmapi.lib comctl32.lib ole32.lib shell32.lib /LIBPATH:./bin libEGL.dll.lib libGLESv2.dll.lib /DELAYLOAD:libEGL.dll /DELAYLOAD:libGLESv2.dll cl /we4013 /Zi /Zc:preprocessor /DMP_BUILD_DLL /std:c11 %INCLUDES% src/milepost.c /Fo:bin/milepost.o /LD /link /MANIFEST:EMBED /MANIFESTINPUT:src/win32_manifest.xml %LIBS% /OUT:bin/milepost.dll /IMPLIB:bin/milepost.dll.lib diff --git a/examples/ui/main.c b/examples/ui/main.c index 8529a40..fa63e87 100644 --- a/examples/ui/main.c +++ b/examples/ui/main.c @@ -423,13 +423,13 @@ int main() if(ui_button("Open").clicked) { char* filters[] = {"md"}; - str8 file = mp_open_dialog(mem_scratch(), "Open File", 0, 1, filters, false); + str8 file = mp_open_dialog(mem_scratch(), "Open File", "C:\\Users", 1, filters, false); printf("selected file %.*s\n", (int)file.len, file.ptr); } if(ui_button("Save").clicked) { - str8 file = mp_save_dialog(mem_scratch(), "Save File", 0, 0, 0); + str8 file = mp_save_dialog(mem_scratch(), "Save File", "C:\\Users", 0, 0); printf("selected file %.*s\n", (int)file.len, file.ptr); } } diff --git a/src/win32_app.c b/src/win32_app.c index f45764f..d9991cd 100644 --- a/src/win32_app.c +++ b/src/win32_app.c @@ -1128,7 +1128,7 @@ MP_API str8 mp_open_dialog(mem_arena* arena, str8 filter = str8_list_join(arena, list); int filterWideSize = 1 + MultiByteToWideChar(CP_UTF8, 0, filter.ptr, filter.len, NULL, 0); - filterSpecs[i].pszSpec = mem_arena_alloc(arena, filterWideSize); + filterSpecs[i].pszSpec = mem_arena_alloc_array(arena, wchar_t, filterWideSize); MultiByteToWideChar(CP_UTF8, 0, filter.ptr, filter.len, (LPWSTR)filterSpecs[i].pszSpec, filterWideSize); ((LPWSTR)(filterSpecs[i].pszSpec))[filterWideSize-1] = 0; @@ -1140,6 +1140,23 @@ MP_API str8 mp_open_dialog(mem_arena* arena, mem_arena_clear_to(arena, mark); } + if(defaultPath) + { + mem_arena_marker mark = mem_arena_mark(arena); + int pathWideSize = MultiByteToWideChar(CP_UTF8, 0, defaultPath, -1, NULL, 0); + LPWSTR pathWide = mem_arena_alloc_array(arena, wchar_t, pathWideSize); + MultiByteToWideChar(CP_UTF8, 0, defaultPath, -1, pathWide, pathWideSize); + + IShellItem* item = 0; + hr = SHCreateItemFromParsingName(pathWide, NULL, &IID_IShellItem, (void**)&item); + if(SUCCEEDED(hr)) + { + hr = dialog->lpVtbl->SetFolder(dialog, item); + item->lpVtbl->Release(item); + } + mem_arena_clear_to(arena, mark); + } + hr = dialog->lpVtbl->Show(dialog, NULL); if(SUCCEEDED(hr)) { @@ -1196,7 +1213,7 @@ MP_API str8 mp_save_dialog(mem_arena* arena, str8 filter = str8_list_join(arena, list); int filterWideSize = 1 + MultiByteToWideChar(CP_UTF8, 0, filter.ptr, filter.len, NULL, 0); - filterSpecs[i].pszSpec = mem_arena_alloc(arena, filterWideSize); + filterSpecs[i].pszSpec = mem_arena_alloc_array(arena, wchar_t, filterWideSize); MultiByteToWideChar(CP_UTF8, 0, filter.ptr, filter.len, (LPWSTR)filterSpecs[i].pszSpec, filterWideSize); ((LPWSTR)(filterSpecs[i].pszSpec))[filterWideSize-1] = 0; @@ -1208,6 +1225,23 @@ MP_API str8 mp_save_dialog(mem_arena* arena, mem_arena_clear_to(arena, mark); } + if(defaultPath) + { + mem_arena_marker mark = mem_arena_mark(arena); + int pathWideSize = MultiByteToWideChar(CP_UTF8, 0, defaultPath, -1, NULL, 0); + LPWSTR pathWide = mem_arena_alloc_array(arena, wchar_t, pathWideSize); + MultiByteToWideChar(CP_UTF8, 0, defaultPath, -1, pathWide, pathWideSize); + + IShellItem* item = 0; + hr = SHCreateItemFromParsingName(pathWide, NULL, &IID_IShellItem, (void**)&item); + if(SUCCEEDED(hr)) + { + hr = dialog->lpVtbl->SetFolder(dialog, item); + item->lpVtbl->Release(item); + } + mem_arena_clear_to(arena, mark); + } + hr = dialog->lpVtbl->Show(dialog, NULL); if(SUCCEEDED(hr)) {