0

Related to a previous question in which a for loop wouldn't work, I 'm trying to replace a MessageBox() call to a WinUI content dialog, which means that the call must block for the caller.

After some hours of trying, I eventually created this one:

ContentDialogResult MainPage::ShowDialogBlocking(winrt::Microsoft::UI::Xaml::Window const& mainWindow)
{
    auto top = Content().as<Panel>();
    auto dialog = top.FindName(L"ProgressDialog").as<ContentDialog>();
    auto dispatcherQueue = mainWindow.DispatcherQueue();

    bool completed = false;
    ContentDialogResult result = {};


    auto as = dialog.ShowAsync();
    as.Completed([&](auto const& sender, auto)
        {
            auto s2 = sender.as< winrt::Windows::Foundation::IAsyncOperation<ContentDialogResult>>();
            auto top = Content().as<Panel>();
            auto dialog = top.FindName(L"ProgressDialog").as<ContentDialog>();
            result = s2.GetResults();
            completed = true;
            dispatcherQueue.EnqueueEventLoopExit();
        });

    dispatcherQueue.RunEventLoop();
    return result;
}

This works in a way that it actually blocks and when EnqueueEventLoopExit is called, the RunEventLoop returns.

However at this point the application crashes with an access violation. What could be the problem? It seems that with "EnqueueEventLoopExit" the dispatcher fatally gets released?

Edit: The following seems to work but I'm not sure it is reliable.

    void MainPage::ShowDialogBlocking()
    {
        auto dialog = ... // ContentDialog
        ContentDialogResult res;
        bool Completed = 0;
        auto as = dialog.ShowAsync();
        as.Completed([&](auto const& sender, auto)
            {
                res = sender.as<winrt::Windows::Foundation::IAsyncOperation<ContentDialogResult>>().GetResults(); 
                Completed = 1;
                

            });

        while (!Completed)
        {
            MSG msg;
            if (GetMessage(&msg, 0,0,0))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
    }
}
3
  • A contentDialog is not a Win32 window (no HWND), so I'm not sure you'll get to somewhere like this. Commented Mar 18 at 8:13
  • To properly exit the event loop, call DispatcherQueue.EnqueueEventLoopExit. In a WinUI Desktop app, you might want your code to keep running even after all the XAML windows on the thread have closed. To accomplish this, you can set the DispatcherShutdownMode property to OnExplicitShutdown. Commented Mar 18 at 8:32
  • @SimonMourier it is not, but I have a map of HWNDs mapped to Top level windows so a call to my own MessageBox will find the WinUI Window that has the ContentDialog inside. Commented Mar 18 at 8:38

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.