diff --git a/build.bat b/build.bat index 335b7c3..9f9dfc1 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 /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 /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 1d820be..ed521fe 100644 --- a/examples/ui/main.c +++ b/examples/ui/main.c @@ -407,8 +407,6 @@ int main() widget_view("Buttons") { ui_button("Button 1"); - ui_button("Button 2"); - ui_button("Button 3"); if(ui_button("Test Dialog").clicked) { @@ -423,6 +421,12 @@ int main() printf("no options selected\n"); } } + + if(ui_button("Open").clicked) + { + str8 file = mp_open_dialog(mem_scratch(), "Open File", 0, 0, 0, true); + printf("selected file %.*s\n", (int)file.len, file.ptr); + } } ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 0.5}, diff --git a/src/win32_app.c b/src/win32_app.c index 1656280..a0d9ff0 100644 --- a/src/win32_app.c +++ b/src/win32_app.c @@ -1087,12 +1087,62 @@ str8 mp_app_get_resource_path(mem_arena* arena, const char* name) //TODO: GetOpenFileName() doesn't seem to support selecting folders, and // requires filters which pair a "descriptive" name with an extension + +#define interface struct +#include +#undef interface + MP_API str8 mp_open_dialog(mem_arena* arena, const char* title, const char* defaultPath, int filterCount, const char** filters, - bool directory); + bool directory) +{ + str8 res = {0}; + HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); + if(SUCCEEDED(hr)) + { + IFileOpenDialog* dialog = 0; + hr = CoCreateInstance(&CLSID_FileOpenDialog, NULL, CLSCTX_ALL, &IID_IFileOpenDialog, (void**)&dialog); + if(SUCCEEDED(hr)) + { + if(directory) + { + FILEOPENDIALOGOPTIONS opt; + dialog->lpVtbl->GetOptions(dialog, &opt); + dialog->lpVtbl->SetOptions(dialog, opt | FOS_PICKFOLDERS); + } + + hr = dialog->lpVtbl->Show(dialog, NULL); + if(SUCCEEDED(hr)) + { + IShellItem* item; + hr = dialog->lpVtbl->GetResult(dialog, &item); + if(SUCCEEDED(hr)) + { + PWSTR filePath; + hr = item->lpVtbl->GetDisplayName(item, SIGDN_FILESYSPATH, &filePath); + + if(SUCCEEDED(hr)) + { + int utf8Size = WideCharToMultiByte(CP_UTF8, 0, filePath, -1, NULL, 0, NULL, NULL); + if(utf8Size > 0) + { + res.ptr = mem_arena_alloc(arena, utf8Size); + res.len = utf8Size-1; + WideCharToMultiByte(CP_UTF8, 0, filePath, -1, res.ptr, utf8Size, NULL, NULL); + } + CoTaskMemFree(filePath); + } + item->lpVtbl->Release(item); + } + } + } + } + CoUninitialize(); + return(res); +} MP_API str8 mp_save_dialog(mem_arena* arena, const char* title,