Afficher les objets d’interface utilisateur WinRT qui dépendent de CoreWindow

Certains sélecteurs, fenêtres contextuelles, boîtes de dialogue et autres objets Windows Runtime (WinRT) dépendent d’un CoreWindow, qui est en général utilisé pour afficher une interface utilisateur (IU). CoreWindow n’est pas pris en charge dans les applications de bureau (voir Principales classes non prises en charge), mais vous pouvez toujours utiliser un grand nombre de ces classes WinRT dans votre application de bureau en ajoutant quelques lignes de code d’interopérabilité.

Votre application de bureau peut être une application WinUI 3, Windows Presentation Foundation (WPF) ou Windows Forms (WinForms). Les exemples de code sont présentés en C# et en C++/WinRT.

Définir le handle de la fenêtre propriétaire (HWND) d'un objet d’interface utilisateur WinRT

Pour les classes qui implémentent l’interface IInitializeWithWindow (ou l’interface IDataTransferManagerInterop équivalente), vous pouvez utiliser celle-ci pour définir une fenêtre propriétaire sur l’objet avant de l’afficher. Ce processus comprend deux étapes.

  1. Déterminez la fenêtre qui sera propriétaire de l’objet de l’interface utilisateur que vous souhaitez afficher, et récupérez le HWND de cette fenêtre. Pour plus d’informations et des exemples de code pour cette étape, consultez Récupérer un handle de fenêtre (HWND).
  2. Appelez ensuite l’API d’interopérabilité correspondante (pour C# ou C++/WinRT) afin de définir un handle de fenêtre propriétaire (HWND) pour l’objet d’interface utilisateur WinRT.

Pour les classes qui implémentent IInitializeWithWindow

Ces classes implémentent IInitializeWithWindow :

Remarque

La liste ci-dessus est nécessairement incomplète : reportez-vous à la documentation de chaque type pour voir s'il implémente IInitializeWithWindow (ou une interface d’interopérabilité équivalente).

Les sections suivantes contiennent des exemples de code pour afficher un FolderPicker. Mais la technique est la même pour afficher n'importe laquelle des API répertoriées ci-dessus.

WinUI 3 avec C# (également WPF/WinForms avec .NET 6 ou version ultérieure)

Remarque

Les exemples de code de cette section utilisent la classe d'interopérabilité C# WinRT.Interop.WindowNative. Si vous ciblez .NET 6 ou une version ultérieure, vous pouvez utiliser cette classe dans un projet WPF ou WinForms. Pour plus d’informations sur la configuration de votre projet à cet effet, veuillez consulter Appeler des API d’interopérabilité à partir d’une application .NET.

Le code C# ci-dessous s’attend à ce que vous ayez déjà utilisé le modèle documenté dans Récupérer un handle de fenêtre (HWND). Ensuite, pour définir la fenêtre propriétaire de l’objet d’interface utilisateur que vous souhaitez afficher, le code appelle la méthode Initialize sur la classe d'interopérabilité C# WinRT.Interop.InitializeWithWindow. Pour plus d’informations sur les classes d’interopérabilité C#, consultez Appeler des API d’interopérabilité à partir d’une application .NET.

// MainWindow.xaml.cs
private async void ShowFolderPickerAsync(IntPtr hWnd)
{
    // Create a folder picker.
    var folderPicker = new Windows.Storage.Pickers.FolderPicker();

    // Initialize the folder picker with the window handle (HWND).
    WinRT.Interop.InitializeWithWindow.Initialize(folderPicker, hWnd);

    // Use the folder picker as usual.
    folderPicker.FileTypeFilter.Add("*");
    var folder = await folderPicker.PickSingleFolderAsync();
}

WinUI 3 avec C++

Le code C++/WinRT ci-dessous s’attend à ce que vous ayez déjà utilisé le modèle documenté dans Récupérer un handle de fenêtre (HWND). Ensuite, pour définir la fenêtre propriétaire de l’objet d’interface utilisateur que vous souhaitez afficher, le code appelle la méthode d'interopérabilité IInitializeWithWindow::Initialize.

// pch.h
...
#include <microsoft.ui.xaml.window.h>
#include <Shobjidl.h>
#include <winrt/Windows.Storage.Pickers.h>

// MainWindow.xaml.cpp
winrt::fire_and_forget ShowFolderPickerAsync(HWND hWnd)
{
    // Create a folder picker.
    Windows::Storage::Pickers::FolderPicker folderPicker;

    // Initialize the folder picker with the window handle (HWND).
    auto initializeWithWindow{ folderPicker.as<::IInitializeWithWindow>() };
    initializeWithWindow->Initialize(hWnd);

    // Use the folder picker as usual.
    folderPicker.FileTypeFilter().Append(L"*");
    auto folder{ co_await folderPicker.PickSingleFolderAsync() };
}

Pour les classes qui implémentent IDataTransferManagerInterop

La classe Windows.ApplicationModel.DataTransfer.DataTransferManager implémente l’interface IDataTransferManagerInterop (qui, comme IInitializeWithWindow, vous permet de définir une fenêtre propriétaire).

Dans une application de bureau, au lieu d’appeler la méthode DataTransferManager.ShowShareUI, vous appelez IDataTransferManagerInterop ::ShowShareUIForWindow, comme dans les exemples de code ci-dessous.

WinUI 3 avec C# (également WPF/WinForms avec .NET 6 ou version ultérieure)

// MainWindow.xaml.cs
...
public sealed partial class MainWindow : Window
{
    ...

    [System.Runtime.InteropServices.ComImport]
    [System.Runtime.InteropServices.Guid("3A3DCD6C-3EAB-43DC-BCDE-45671CE800C8")]
    [System.Runtime.InteropServices.InterfaceType(
        System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIUnknown)]
    interface IDataTransferManagerInterop
    {
        IntPtr GetForWindow([System.Runtime.InteropServices.In] IntPtr appWindow,
            [System.Runtime.InteropServices.In] ref Guid riid);
        void ShowShareUIForWindow(IntPtr appWindow);
    }

    static readonly Guid _dtm_iid = 
        new Guid(0xa5caee9b, 0x8708, 0x49d1, 0x8d, 0x36, 0x67, 0xd2, 0x5a, 0x8d, 0xa0, 0x0c);

    private void myButton_Click(object sender, RoutedEventArgs e)
    {
        // Retrieve the window handle (HWND) of the current WinUI 3 window.
        var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);

        IDataTransferManagerInterop interop =
        Windows.ApplicationModel.DataTransfer.DataTransferManager.As
            <IDataTransferManagerInterop>();

        IntPtr result = interop.GetForWindow(hWnd, _dtm_iid);
        var dataTransferManager = WinRT.MarshalInterface
            <Windows.ApplicationModel.DataTransfer.DataTransferManager>.FromAbi(result);

        dataTransferManager.DataRequested += (sender, args) =>
        {
            args.Request.Data.Properties.Title = "In a desktop app...";
            args.Request.Data.SetText("...display WinRT UI objects that depend on CoreWindow.");
            args.Request.Data.RequestedOperation = 
                Windows.ApplicationModel.DataTransfer.DataPackageOperation.Copy;
        };

        // Show the Share UI
        interop.ShowShareUIForWindow(hWnd);
    }
}
...

WinUI 3 avec C++

// pch.h in a Windows App SDK app
...
#include <shobjidl_core.h>
#include <microsoft.ui.xaml.window.h>
#include <winrt/Windows.ApplicationModel.DataTransfer.h>
...

// MainWindow.xaml.cpp
...
void MainWindow::myButton_Click(IInspectable const&, RoutedEventArgs const&)
{
    // Retrieve the window handle (HWND) of the current WinUI 3 window.
    auto windowNative{ this->m_inner.as<::IWindowNative>() };
    HWND hWnd{ 0 };
    windowNative->get_WindowHandle(&hWnd);

    winrt::com_ptr<IDataTransferManagerInterop> interop = 
        winrt::get_activation_factory<Windows::ApplicationModel::DataTransfer::DataTransferManager,
        IDataTransferManagerInterop>();

    winrt::guid _dtm_iid{ 0xa5caee9b, 0x8708, 0x49d1, { 0x8d, 0x36, 0x67, 0xd2, 0x5a, 0x8d, 0xa0, 0x0c } };
    Windows::ApplicationModel::DataTransfer::DataTransferManager dataTransferManager{ nullptr };
    interop->GetForWindow(hWnd, _dtm_iid, winrt::put_abi(dataTransferManager));

    dataTransferManager.DataRequested([](Windows::ApplicationModel::DataTransfer::DataTransferManager const& /* sender */,
        Windows::ApplicationModel::DataTransfer::DataRequestedEventArgs const& args)
    {
        args.Request().Data().Properties().Title(L"In a desktop app...");
        args.Request().Data().SetText(L"...display WinRT UI objects that depend on CoreWindow.");
        args.Request().Data().RequestedOperation(Windows::ApplicationModel::DataTransfer::DataPackageOperation::Copy);
    });

    interop->ShowShareUIForWindow(hWnd);
}
...

Pour les classes qui implémentent IUserConsentVerifierInterop

La classe Windows.Security.Credentials.UI.UserConsentVerifier implémente l’interface IUserConsentVerifierInterop (qui, comme IInitializeWithWindow, vous permet de définir une fenêtre propriétaire).

Dans une application de bureau, au lieu d’appeler la méthode UserConsentVerifier.RequestVerificationAsync :

Pour en savoir plus et obtenir des exemples supplémentaires, consultez UserConsentVerifier.

Pour les classes qui implémentent d’autres interfaces d’interopérabilité

Ces interfaces ont des méthodes XxxForWindow, qui vous permettent de définir un handle de fenêtre propriétaire (HWND). Vous pouvez utiliser ces interfaces directement à partir de C++/WinRT. Des versions des interfaces existent également sous la forme de classes C#. Pour plus d’informations, consultez Appeler des API d’interopérabilité à partir d’une application .NET.