This is a follow-on question to Guarang Dave’s question. With @Simon_Mourier’s help, he figured it out, but I still haven’t. Here’s my code with a few different options that haven’t worked commented out:
fire_and_forget MainWindow::FileOpenClickHandler(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&)
{
auto lifetime = get_strong();
// ref: /questions/75436438/how-to-get-main-window-handle-on-page-in-winui-3-using-c
//auto hWnd = GetProcessFirstWindowHandle(); // invalid window handle
// ref: CoPilot, possibly based on /questions/71432263/how-to-retrieve-the-window-handle-of-the-current-winui-3-mainwindow-from-a-page/71440820#71440820
//auto hWnd = App().MainWindow().as<::IWindowNative>()->WindowHandle(); // invalid window handle
// ref: https://learn.microsoft.com/en-us/windows/windows-app-sdk/api/win32/microsoft.ui.xaml.window/nf-microsoft-ui-xaml-window-iwindownative-get_windowhandle
auto window = MainWindow::Current();
auto windowNative{ window.as<::IWindowNative>() };
HWND hWnd{ 0 };
windowNative->get_WindowHandle(&hWnd); // invalid window handle
// Create the file picker
auto picker = winrt::Windows::Storage::Pickers::FileOpenPicker();
picker.SuggestedStartLocation(winrt::Windows::Storage::Pickers::PickerLocationId::DocumentsLibrary);
picker.FileTypeFilter().Append(L"*");
// Simplest option: Get the IInitializeWithWindow interface
//auto initializeWithWindow{ picker.as<IInitializeWithWindow>() };
// Option 2: Query for the IInitializeWithWindow interface
winrt::com_ptr<IUnknown> unknownPicker = picker.as<IUnknown>();
winrt::com_ptr<IInitializeWithWindow> initializeWithWindow;
unknownPicker->QueryInterface(IID_PPV_ARGS(&initializeWithWindow));
// Initialize the file picker with the window handle
initializeWithWindow->Initialize(hWnd);
// Open the file picker
try {
auto file = co_await picker.PickSingleFileAsync();
if (file != nullptr)
{
path = file.Path();
// read the file
}
else
{
// The user did not pick a file
}
}
catch (winrt::hresult_error const& ex)
{
// Open a window to show the error message
winrt::Microsoft::UI::Xaml::Controls::ContentDialog dialog;
dialog.Title(winrt::box_value(L"Error"));
dialog.Content(winrt::box_value(ex.message().c_str()));
dialog.CloseButtonText(L"OK");
dialog.XamlRoot(rootPanel().XamlRoot());
dialog.ShowAsync();
}
}
So far, everything I’ve tried leads to an “invalid window handle” exception on the first line of the try block. One thing that’s still totally opaque to me is Simon’s reminder that the FileOpenPicker must run on the UI thread. I have not intentionally created any other threads, so is any MainWindow::function on the UI thread or not? The main question is, of course, how do I get a valid window handle?