Condividi tramite


Visualizzare gli oggetti dell'interfaccia utente WinRT che dipendono da CoreWindow

Alcuni selettori, popup, finestre di dialogo e altri oggetti di Windows Runtime (WinRT) dipendono da un CoreWindow, generalmente per visualizzare un'interfaccia utente (UI). Anche se CoreWindow non è supportato nelle app desktop (vedi Classi core non supportate), puoi comunque usare molte di queste classi WinRT nell'app desktop aggiungendo un po' di codice di interoperabilità.

L'app desktop può essere WinUI 3, Windows Presentation Foundation (WPF) o Windows Forms (WinForms). Gli esempi di codice vengono presentati in C# e C++/WinRT.

Impostare l'handle della finestra proprietario (HWND) per un oggetto dell'interfaccia utente WinRT

Per le classi che implementano l'interfaccia IInitializeWithWindow (o l'interfaccia IDataTransferManagerInterop equivalente), è possibile usare tale interfaccia per impostare una finestra proprietario sull'oggetto prima di visualizzarla. Si tratta di un processo in due passaggi.

  1. Decidi quale finestra sarà il proprietario dell'oggetto UI che vuoi visualizzare e ottieni l'HWND di quella finestra. Per altri dettagli ed esempi di codice per questo passaggio, vedere Recuperare un handle di finestra (HWND).
  2. Chiamare quindi l'API di interoperabilità appropriata (per C# o C++/WinRT) per impostare un handle di finestra del proprietario (HWND) per l'oggetto interfaccia utente WinRT.

Per le classi che implementano IInitializeWithWindow

Queste classi implementano IInitializeWithWindow:

Annotazioni

L'elenco precedente è necessariamente incompleto: fare riferimento alla documentazione di un tipo per verificare se implementa IInitializeWithWindow (o un'interfaccia di interoperabilità equivalente).

Le sezioni successive contengono esempi di codice per visualizzare folderPicker. Ma è la stessa tecnica per visualizzare una delle API elencate in precedenza.

WinUI 3 con C# (anche WPF/WinForms con .NET 6 o versione successiva)

Annotazioni

Gli esempi di codice in questa sezione usano la classe di interoperabilità C# WinRT.Interop.WindowNative C#. Se si usa .NET 6 o versione successiva, è possibile usare tale classe in un progetto WPF o WinForms. Per informazioni sulla configurazione del progetto a tale scopo, vedere Chiamare API di interoperabilità da un'app .NET.

Il codice C# seguente prevede che sia già stato usato il modello documentato in Recuperare un handle di finestra (HWND). Quindi, per impostare la finestra proprietaria per l'oggetto dell'interfaccia utente che si desidera visualizzare, il codice chiama il metodo Initialize sulla classe di interoperabilità WinRT.Interop.InitializeWithWindow in C#. Per altre informazioni sulle classi di interoperabilità C#, vedere Chiamare le API interop da un'app .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 con C++

Il codice C++/WinRT seguente prevede di aver già usato il modello documentato in Recuperare un handle di finestra (HWND). Quindi, per impostare la finestra del proprietario per l'oggetto dell'interfaccia utente da visualizzare, il codice chiama il metodo di interoperabilità 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() };
}

Per le classi che implementano IDataTransferManagerInterop

La classe Windows.ApplicationModel.DataTransfer.DataTransferManager implementa l'interfaccia IDataTransferManagerInterop (che, come IInitializeWithWindow, consente di impostare una finestra proprietaria).

In un'app desktop, invece di chiamare il metodo DataTransferManager.ShowShareUI , chiami IDataTransferManagerInterop::ShowShareUIForWindow, come illustrato negli esempi di codice seguenti.

WinUI 3 con C# (anche WPF/WinForms con .NET 6 o versione successiva)

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

Per le classi che implementano IUserConsentVerifierInterop

La classe Windows.Security.Credentials.UI.UserConsentVerifier implementa l'interfaccia IUserConsentVerifierInterop (che, come IInitializeWithWindow, consente di impostare una finestra proprietaria).

In un'app desktop, invece di chiamare il metodo UserConsentVerifier.RequestVerificationAsync:

Per altre info ed esempi di codice, vedi UserConsentVerifier.

Per le classi che implementano altre interfacce di interoperabilità

Queste interfacce hanno metodi XxxForWindow, che consentono di impostare un handle di finestra proprietario (HWND). È possibile usare queste interfacce direttamente da C++/WinRT. Le versioni delle interfacce esistono anche sotto forma di classi C#. Per altri dettagli, vedere Chiamare API di interoperabilità da un'app .NET.