Anzeigen von WinRT UI-Objekten, die von CoreWindow abhängig sind

Bestimmte Auswahlsteuerelemente, Popups, Dialogfelder und andere WinRT-Objekte (Windows-Runtime) sind von einem CoreWindow-Element abhängig. In der Regel wird eine Benutzeroberfläche (UI) angezeigt. Obwohl CoreWindow in Desktop-Apps nicht unterstützt wird (siehe Nicht unterstützte Core-Klassen), können Sie weiterhin viele dieser WinRT-Klassen in Ihrer Desktop-App verwenden, indem Sie ein wenig Interoperationscode hinzufügen.

Ihre Desktop-App kann Windows UI Library (WinUI) 3,Windows Presentation Foundation (WPF)- oder Windows Forms-Apps (WinForms) sein. Codebeispiele werden in C# und C++/WinRT vorgestellt.

Festlegen des Besitzerfensterhandles (HWND) für ein WinRT-UI-Objekt

Für Klassen, die die IInitializeWithWindow-Schnittstelle (oder die entsprechende IDataTransferManagerInterop-Schnittstelle) implementieren, können Sie diese Schnittstelle verwenden, um ein Besitzerfenster für das Objekt festzulegen, bevor Sie es anzeigen. Dies ist ein zweistufiger Prozess.

  1. Entscheiden Sie, welches Fenster der Besitzer des ANZUZEIGENden UI-Objekts ist, und rufen Sie den HWND des Fensters ab. Weitere Details und Codebeispiele für diesen Schritt finden Sie unter Abrufen eines Fensterhandles (HWND).
  2. Rufen Sie dann die entsprechende Interoperatierbarkeits-API (für C# oder C++/WinRT) auf, um ein Besitzerfensterhandle (HWND) für das WinRT-UI-Objekt festzulegen.

Für Klassen, die IInitializeWithWindow implementieren

Diese Klassen implementieren IInitializeWithWindow:

Hinweis

Die oben aufgeführte Liste ist notwendigerweise unvollständig – verweisen Sie auf die Dokumentation eines Typs , um festzustellen, ob IInitializeWithWindow (oder eine entsprechende Interopschnittstelle) implementiert wird.

Die nächsten Abschnitte enthalten Codebeispiele zum Anzeigen eines FolderPicker.The next sections contain code examples to display a FolderPicker. Es ist jedoch dieselbe Technik, eine der oben aufgeführten APIs anzuzeigen.

WinUI 3 mit C# (auch WPF/WinForms mit .NET 6 oder höher)

Hinweis

Die Codebeispiele in diesem Abschnitt verwenden die Interop.WindowNative C#-Interopklasse "WinRT.Interop.WindowNative C#". Wenn Sie .NET 6 oder höher als Ziel verwenden, können Sie diese Klasse in einem WPF- oder WinForms-Projekt verwenden. Informationen zum Einrichten Ihres Projekts hierzu finden Sie unter Aufrufen von Interoperabilitäts-APIs aus einer .NET-App.

Der folgende C#-Code erwartet, dass Sie bereits das muster verwendet haben, das in "Abrufen eines Fensterhandles (HWND)" dokumentiert ist. Um dann das Besitzerfenster für das anzuzeigende UI-Objekt festzulegen, ruft der Code die Initialize-Methode für die Interopklasse WinRT.Interop.InitializeWithWindow C# auf. Weitere Informationen zu den C#-Interoperabilitätsklassen finden Sie unter Aufrufen von Interop-APIs aus einer .NET-App.

// 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 mit C++

Der folgende C++/WinRT-Code erwartet, dass Sie bereits das muster verwendet haben, das in "Abrufen eines Fensterhandles (HWND)" dokumentiert ist. Um dann das Besitzerfenster für das anzuzeigende UI-Objekt festzulegen, ruft der Code die Interoperatability-Methode IInitializeWithWindow::Initialize auf.

// 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() };
}

Für Klassen, die IDataTransferManagerInterop implementieren

Die Windows.ApplicationModel.DataTransfer.DataTransferManager-Klasse implementiert die IDataTransferManagerInterop-Schnittstelle (mit der Sie wie IInitializeWithWindow ein Besitzerfenster festlegen können).

In einer Desktop-App rufen Sie anstelle der DataTransferManager.ShowShareUI-Methode IDataTransferManagerInterop::ShowShareUIForWindow auf, wie in den folgenden Codebeispielen gezeigt.

WinUI 3 mit C# (auch WPF/WinForms mit .NET 6 oder höher)

// 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 mit 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);
}
...

Für Klassen, die IUserConsentVerifierInterop implementieren

Die Windows.Security.Credentials.UI.UserConsentVerifier-Klasse implementiert die IUserConsentVerifierInterop-Schnittstelle (mit der Sie wie IInitializeWithWindow ein Besitzerfenster festlegen können).

In einer Desktop-App statt die UserConsentVerifier.RequestVerificationAsync-Methode aufzurufen:

Weitere Informationen und Codebeispiele finden Sie unter UserConsentVerifier.

Für Klassen, die andere Interopschnittstellen implementieren

Diese Schnittstellen verfügen über XxxForWindow-Methoden , mit denen Sie ein Besitzerfensterhandle (HWND) festlegen können. Sie können diese Schnittstellen direkt aus C++/WinRT verwenden. Versionen der Schnittstellen sind auch in Form von C#-Klassen vorhanden. Weitere Informationen finden Sie unter Aufrufen von Interop-APIs aus einer .NET-App.