Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot use WinRT with MFC? #1396

Closed
wayneforrest opened this issue Mar 10, 2024 · 3 comments
Closed

Cannot use WinRT with MFC? #1396

wayneforrest opened this issue Mar 10, 2024 · 3 comments

Comments

@wayneforrest
Copy link

Version

C++/WinRT v2.0.220110.5

Summary

I am unable to use WinRT with MFC - "this function must be called from a UI thread"

Reproducible example

// here is the MFC OnInitDialog

BOOL MainDlg::OnInitDialog() {
     CDialogEx::OnInitDialog();
     HWND hwnd = GetSafeHwnd();

     winrt::init_apartment();
     CheckForAppUpdates(hwnd);
     // snip
}


winrt::fire_and_forget MainDlg::CheckForAppUpdates(HWND hWnd) {
try {
    // Capture the UI thread context
    // co_await winrt::resume_foreground(); // needs a Dispatcher.. which needs ?
    winrt::apartment_context ui_thread;
    // Switch to a background thread
    co_await winrt::resume_background();

    if (auto storeContext{ winrt::Windows::Services::Store::StoreContext::GetDefault() })
    {
        const auto updates =  co_await storeContext.GetAppAndOptionalStorePackageUpdatesAsync();

        if (updates) {
            const auto numUpdates = updates.Size();

            if (numUpdates > 0) {

                co_await ui_thread;
                // This method must be called on the UI thread. See docs..
                auto result = co_await storeContext.RequestDownloadAndInstallStorePackageUpdatesAsync(updates);

                auto overallState = result.OverallState();

                CString text;
                switch (overallState)
                {
                case StorePackageUpdateState::OtherError:
                    text = L"Updates: Other Error";
                    break;
                case StorePackageUpdateState::Downloading:
                    text = L"Updates: Downloading";
                    break;
                case StorePackageUpdateState::Pending:
                    text = L"Updates: Pending";
                    break;
                case StorePackageUpdateState::Canceled:
                    text = L"Updates: Cancelled";
                    break;
                case StorePackageUpdateState::Deploying:
                    text = L"Updates: Deploying";
                    break;
                default:
                    text.Format(L"Updates: %d", overallState);
                    break;
                }

                ::PostMessage(hWnd, WM_USER_APP_MSG, 0, (LPARAM)new CString(text));
                co_return;
            }
        }
    }
}
catch (winrt::hresult_error const& ex)
{
    // Handle WinRT exceptions
    ::PostMessage(hWnd, WM_USER_APP_MSG, 1, (LPARAM)new CString(ex.message().c_str()));
}
catch (std::exception const& ex)
{
    // Handle other exceptions
    ::PostMessage(hWnd, WM_USER_APP_MSG, 1, (LPARAM)new CString(ex.what()));
} 
}

Expected behavior

No response

Actual behavior

No response

Additional comments

This is not an actual bug, a simple example of MFC and WinRT would be helpful for me to use WinRT.

Thank you.

@wayneforrest wayneforrest changed the title Bug: Cannot use WinRT with MFC? Cannot use WinRT with MFC? Mar 10, 2024
@sylveon
Copy link
Contributor

sylveon commented Mar 10, 2024

In a desktop app, before using an instance of this class in a way that displays UI, you'll need to associate the object with its owner's window handle. For more info, and code examples, see Display WinRT UI objects that depend on CoreWindow.

https://learn.microsoft.com/en-us/uwp/api/windows.services.store.storecontext?view=winrt-22621

@wayneforrest
Copy link
Author

Hi @sylveon , I had a look at the examples you referred to and it appears it's for WinUI 3, and not for MFC.

Do you perhaps know of an MFC example I can refer to?

@sylveon
Copy link
Contributor

sylveon commented Mar 10, 2024

The example is pretty much the same without WinUI 3, you associate the StoreContext object to a window by querying it for IInitializeWithWindow (using storeContext.as<IInitializeWithWindow>()), then call Initialize on the returned object, passing in your HWND.

I don't know why they said this was for an example for WinUI 3 when it applies to all Win32 apps.

Also, your transition to a background thread isn't really needed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants