Freigeben über


Anzeigen von WinRT-UI-Objekten, die von CoreWindow abhängen

Bestimmte Auswahlprogramme, Popups, Dialogfelder und andere Windows-Runtime-Objekte (WinRT) sind von einem CoreWindow abhängig; in der Regel zum Anzeigen einer Benutzeroberfläche (UI). 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 das anzuzeigende UI-Objekt besitzen soll und holen Sie das HWND dieses Fensters ein. Weitere Details und Codebeispiele für diesen Schritt finden Sie unter Abrufen eines Fensterhandles (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 – 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. Die nächsten Abschnitte enthalten Codebeispiele zur Anzeige 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 C#-Interopklasse WinRT.Interop.WindowNative. 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 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 (mit der Sie wie IInitializeWithWindow ein Besitzerfenster festlegen können).

In einer Desktop-App rufen Sie anstelle der DataTransferManager.ShowShareUI-MethodeIDataTransferManagerInterop::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.