add file open dialog (WinUI3) newapi

Wed, 31 Jan 2024 19:15:41 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Wed, 31 Jan 2024 19:15:41 +0100
branch
newapi
changeset 242
4ff7361dce95
parent 241
c51dd0e9ecb7
child 243
9f66c31a27ed

add file open dialog (WinUI3)

ui/ui/window.h file | annotate | diff | comparison | revisions
ui/winui/pch.h file | annotate | diff | comparison | revisions
ui/winui/window.cpp file | annotate | diff | comparison | revisions
--- a/ui/ui/window.h	Tue Jan 30 13:10:16 2024 +0100
+++ b/ui/ui/window.h	Wed Jan 31 19:15:41 2024 +0100
@@ -35,13 +35,22 @@
 extern "C" {
 #endif
 
+#define UI_FILEDIALOG_SELECT_SINGLE       0
+#define UI_FILEDIALOG_SELECT_MULTI        1
+#define UI_FILEDIALOG_SELECT_FOLDER       2
+
+typedef struct UiFileList {
+    char **files;
+    size_t nfiles;
+} UiFileList;
+
 UIEXPORT UiObject* ui_window(const char *title, void *window_data);
 UIEXPORT UiObject* ui_simplewindow(char *title, void *window_data);
 
 UIEXPORT void ui_window_size(UiObject *obj, int width, int height);
 
-char* ui_openfiledialog(UiObject *obj);
-char* ui_savefiledialog(UiObject *obj);
+UIEXPORT void ui_openfiledialog(UiObject *obj, unsigned int mode, ui_callback file_selected_callback, void *cbdata);
+UIEXPORT void ui_savefiledialog(UiObject *obj, unsigned int mode, ui_callback file_selected_callback, void *cbdata);
 
 #ifdef	__cplusplus
 }
--- a/ui/winui/pch.h	Tue Jan 30 13:10:16 2024 +0100
+++ b/ui/winui/pch.h	Wed Jan 31 19:15:41 2024 +0100
@@ -34,6 +34,12 @@
 #include <winrt/Microsoft.UI.Input.h>
 #include <winrt/Windows.UI.Core.h>
 #include <winrt/Windows.ApplicationModel.h>
+#include <winrt/Windows.Storage.Pickers.h>
+
 #include <winrt\Microsoft.UI.Dispatching.h>
 
 #include <winrt/Windows.Storage.Streams.h>
+
+#include <Microsoft.UI.Xaml.Window.h>
+
+#include <shobjidl_core.h>
--- a/ui/winui/window.cpp	Tue Jan 30 13:10:16 2024 +0100
+++ b/ui/winui/window.cpp	Wed Jan 31 19:15:41 2024 +0100
@@ -28,6 +28,7 @@
 
 #include "pch.h"
 
+
 #include "window.h"
 
 #include "appmenu.h"
@@ -52,6 +53,7 @@
 using namespace Microsoft::UI::Xaml::Markup;
 using namespace Windows::UI::Xaml::Interop;
 using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::Storage::Pickers;
 
 UiWindow::UiWindow(winrt::Microsoft::UI::Xaml::Window& win) : window(win) {}
 
@@ -185,3 +187,99 @@
 		win->window.AppWindow().Resize(wsize);
 	}
 }
+
+static void filedialog_callback(
+	UiObject *obj,
+	ui_callback file_selected_callback,
+	void *cbdata,
+	winrt::Windows::Foundation::Collections::IVectorView<winrt::Windows::Storage::StorageFile> result)
+{
+	UiFileList flist;
+	flist.nfiles = result.Size();
+	flist.files = new char*[flist.nfiles];
+
+	int i = 0;
+	for (auto const& file : result) {
+		winrt::hstring path = file.Path();
+		flist.files[i++] = wchar2utf8(path.c_str(), path.size());
+	}
+
+	UiEvent evt;
+	evt.obj = obj;
+	evt.document = obj->ctx->document;
+	evt.window = obj->window;
+	evt.eventdata = &flist;
+	evt.intval = 0;
+	file_selected_callback(&evt, cbdata);
+
+	for (int i = 0; i < flist.nfiles;i++) {
+		free(flist.files[i]);
+	}
+	delete[] flist.files;
+}
+
+static Windows::Foundation::IAsyncAction open_filedialog_async(UiObject *obj, unsigned int mode, ui_callback file_selected_callback, void *cbdata) {
+	FileOpenPicker openFileDialog = FileOpenPicker();
+	auto initializeWithWindow { openFileDialog.as<::IInitializeWithWindow>()
+	};
+
+	HWND hwnd{ nullptr };
+	winrt::check_hresult(obj->wobj->window.as<IWindowNative>()->get_WindowHandle(&hwnd));
+
+	initializeWithWindow->Initialize(hwnd);
+
+	openFileDialog.FileTypeFilter().Append(L"*");
+
+	if ((mode & UI_FILEDIALOG_SELECT_MULTI) == UI_FILEDIALOG_SELECT_MULTI) {
+		auto files = co_await openFileDialog.PickMultipleFilesAsync();
+		filedialog_callback(obj, file_selected_callback, cbdata, files);
+	} else {
+		auto file = co_await openFileDialog.PickSingleFileAsync();
+		auto files = single_threaded_vector<winrt::Windows::Storage::StorageFile>();
+		files.Append(file);
+		filedialog_callback(obj, file_selected_callback, cbdata, files.GetView());
+	}
+}
+
+static Windows::Foundation::IAsyncAction folderdialog_async(UiObject *obj, ui_callback file_selected_callback, void *cbdata) {
+	FolderPicker folderPicker = FolderPicker();
+	auto initializeWithWindow { folderPicker.as<::IInitializeWithWindow>()
+	};
+
+	HWND hwnd{ nullptr };
+	winrt::check_hresult(obj->wobj->window.as<IWindowNative>()->get_WindowHandle(&hwnd));
+
+	initializeWithWindow->Initialize(hwnd);
+
+	folderPicker.FileTypeFilter().Append(L"*");
+
+	auto folder = co_await folderPicker.PickSingleFolderAsync();
+	if (folder) {
+		winrt::hstring hpath = folder.Path();
+		char *cpath =  wchar2utf8(hpath.c_str(), hpath.size());
+		
+		UiFileList flist;
+		flist.nfiles = 1;
+		flist.files = &cpath;
+
+		UiEvent evt;
+		evt.obj = obj;
+		evt.document = obj->ctx->document;
+		evt.window = obj->window;
+		evt.eventdata = &flist;
+		evt.intval = 0;
+		file_selected_callback(&evt, cbdata);
+	}
+}
+
+UIEXPORT void ui_openfiledialog(UiObject *obj, unsigned int mode, ui_callback file_selected_callback, void *cbdata) {
+	if ((mode & UI_FILEDIALOG_SELECT_FOLDER) == UI_FILEDIALOG_SELECT_FOLDER) {
+		folderdialog_async(obj, file_selected_callback, cbdata);
+	} else {
+		open_filedialog_async(obj, mode, file_selected_callback, cbdata);
+	}
+}
+
+UIEXPORT void ui_savefiledialog(UiObject *obj, unsigned int mode, ui_callback file_selected_callback, void *cbdata) {
+
+}

mercurial