Freigeben über


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

Bestimmte Auswahlelemente, Popups, Dialogfelder und andere Windows-Runtime-Objekte (WinRT) sind von einem CoreWindow-abhängig, typischerweise um eine Benutzeroberfläche (UI) anzuzeigen. 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 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. Es 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 Fenstergriffs (HWND).
  2. Rufen Sie dann die entsprechende Interoperabilitäts-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 – lesen Sie die Dokumentation eines Typs, um zu ermitteln, ob er IInitializeWithWindow (oder eine entsprechende Interop-Schnittstelle) implementiert.

Die nächsten Abschnitte enthalten Codebeispiele zum Anzeigen eines 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 WinRT.Interop.WindowNative-Interopklasse in 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 Interop-APIs aus einer .NET-App.

Der folgende C#-Code erwartet, dass Sie das in Abrufen eines Fensterhandles (HWND) dokumentierte Muster bereits verwendet haben. Um das Besitzerfenster für das UI-Objekt, das angezeigt werden soll, festzulegen, ruft der Code die Initialize-Methode der WinRT.Interop.InitializeWithWindow C#-Interop-Klasse 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 unten stehende C++/WinRT-Code setzt voraus, dass Sie bereits das Muster verwendet haben, das in Abrufen eines Fenstergriffs (HWND)dokumentiert ist. Um dann das Besitzerfenster für das anzuzeigende UI-Objekt festzulegen, ruft der Code die Interoperabilitätsmethode 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 (die es Ihnen wie bei IInitializeWithWindowermöglicht, ein Besitzerfenster festzulegen).

In einer Desktop-App verwenden Sie anstelle der DataTransferManager.ShowShareUI--Methode die Methode IDataTransferManagerInterop::ShowShareUIForWindow, 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 IInitializeWithWindowein Besitzerfenster festlegen können).

Rufen Sie in einer Desktop-App nicht die UserConsentVerifier.RequestVerificationAsync-Methode auf:

Weitere Informationen und Codebeispiele finden Sie unter UserConsentVerifier.

Für Klassen, die andere Interopschnittstellen implementieren

Diese Schnittstellen verfügen über Methoden wie XxxForWindow, mit denen Sie ein Besitzerfenster-Handle (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.