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). Même si CoreWindow n’est pas pris en charge dans les applications de bureau (voir classes Core non prises en charge), vous pouvez toujours utiliser la plupart de ces classes WinRT dans votre application de bureau en ajoutant un peu de code d’interopérabilité.

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

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

Pour les classes qui implémentent l’interface IInitializeWithWindow (ou l’interface IDataTransferManagerInterop équivalente), vous pouvez utiliser cette interface 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 le propriétaire de l’objet d’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é appropriée (pour C# ou C++/WinRT) pour 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 d’un 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 il s’agit de la même technique pour afficher l’une 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 version ultérieure, vous pouvez utiliser cette classe dans un projet WPF ou WinForms. Pour plus d’informations sur la configuration de votre projet pour ce faire, consultez les API d’interopérabilité des appels à 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 à afficher, le code appelle la méthode Initialize sur la classe Interop.WinRT.Interop.InitializeWithWindow C#. Pour plus d’informations sur les classes d’interopérabilité C#, consultez Les API d’interopérabilité d’appel à 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 illustré 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 plus d’informations et des exemples de code, 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. Les versions des interfaces existent également sous la forme de classes C#. Pour plus d’informations, consultez les API d’interopérabilité des appels à partir d’une application .NET.