Využívání rozhraní API pomocí C++/WinRT

Toto téma ukazuje, jak používat rozhraní API C++/WinRT, ať už jsou součástí Windows, implementována dodavatelem komponent třetí strany, nebo implementována vámi.

Důležité

Proto, aby příklady kódu v tomto tématu byly krátké a snadno je můžete vyzkoušet, můžete je reprodukovat tak, že vytvoříte nový projekt konzolové aplikace Windows (C++/WinRT) a zkopírujete kód. Nemůžete ale tímto způsobem z nebalené aplikace používat libovolné vlastní typy prostředí Windows Runtime od třetích stran. Tímto způsobem můžete používat pouze typy systému Windows.

Pokud chcete využívat vlastní typy prostředí Windows Runtime (třetích stran) z konzolové aplikace, budete muset aplikaci poskytnout identitu balíčku, aby bylo možné vyřešit registraci spotřebovaných vlastních typů. Další informace najdete v článku Windows Application Packaging Project.

Alternativně můžete vytvořit nový projekt pomocí šablon projektů Prázdná aplikace, v balíčku (WinUI 3 pro desktop) pro C++ nebo Komponenta prostředí Windows Runtime (C++/WinRT). Tyto typy aplikací už mají identitu balíčku.

Pokud je rozhraní API v oboru názvů systému Windows

Toto je nejběžnější případ, kdy budete využívat rozhraní API prostředí Windows Runtime. Pro každý typ v oboru názvů Windows definovaném v metadatech definuje C++/WinRT ekvivalent C++, který je přátelský (označovaný jako projektovaný typ). Promítnutý typ má stejný plně kvalifikovaný název jako typ systému Windows, ale je umístěn v oboru názvů C++ winrt s použitím syntaxe C++. Například Windows::Foundation::Uri se projektuje do C++/WinRT jako winrt::Windows::Foundation::Uri.

Tady je jednoduchý příklad kódu. Pokud chcete zkopírovat následující příklady kódu přímo do hlavního zdrojového souboru projektu konzolové aplikace Windows (C++/WinRT), pak nejprve ve vlastnostech projektu nastavte možnost Nepoužít předkompilované hlavičky.

// main.cpp
#include <winrt/Windows.Foundation.h>

using namespace winrt;
using namespace Windows::Foundation;

int main()
{
    winrt::init_apartment();
    Uri contosoUri{ L"http://www.contoso.com" };
    Uri combinedUri = contosoUri.CombineUri(L"products");
}

Zahrnutá hlavička winrt/Windows.Foundation.h je součástí sady SDK, která se nachází uvnitř složky %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt\. Hlavičky v této složce obsahují typy z oborů názvů Windows promítnuté do C++/WinRT. V tomto příkladu winrt/Windows.Foundation.h obsahuje winrt::Windows::Foundation::Uri, což je projektovaný typ pro třídu runtime Windows::Foundation::Uri.

Návod

Kdykoli chcete použít typ z oboru názvů Windows, zahrňte hlavičku C++/WinRT odpovídající danému oboru názvů. Direktivy using namespace jsou volitelné, ale pohodlné.

Ve výše uvedeném příkladu kódu po inicializaci C++/WinRT alokujeme na zásobníku hodnotu promítaného typu winrt::Windows::Foundation::Uri pomocí jednoho z jeho veřejně zdokumentovaných konstruktorů (Uri(String) v tomto příkladu). V tomto nejběžnějším případě použití obvykle stačí udělat jen tohle. Jakmile máte projektovanou hodnotu typu C++/WinRT, můžete ji považovat za instanci skutečného typu prostředí Windows Runtime, protože má všechny stejné členy.

Ve skutečnosti je projektovaná hodnota proxy; je to v podstatě jen inteligentní ukazatel na záložní objekt. Konstruktory projektované hodnoty volají RoActivateInstance k vytvoření instance podkladové třídy prostředí prostředí Windows Runtime (Windows.Foundation.Uri v tomto případě) a ukládají výchozí rozhraní tohoto objektu do nové projektované hodnoty. Jak je znázorněno níže, vaše volání členů promítané hodnoty jsou ve skutečnosti prostřednictvím inteligentního ukazatele předávána podkladovému objektu, kde dochází ke změnám stavu.

Projektovaný typ Windows::Foundation::Uri

Když hodnota contosoUri opustí rozsah platnosti, dojde k její destrukci a uvolní svou referenci na výchozí rozhraní. Pokud je tento odkaz posledním odkazem na podkladový objekt prostředí Windows Runtime Windows.Foundation.Uri, podkladový objekt se také zničí.

Návod

Projektovaný typ je obálka nad typem prostředí Windows Runtime pro účely využívání jeho rozhraní API. Například promítnuté rozhraní je obal nad rozhraním prostředí Windows Runtime.

Projekční hlavičky C++/WinRT

Chcete-li z C++/WinRT využívat rozhraní API oboru názvů systému Windows, zahrňte hlavičkové soubory ze složky %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt. Musíte zahrnout hlavičky odpovídající každému používanému oboru názvů.

Například pro Windows::Security::Cryptography::Certificates obor názvů, ekvivalentní definice typu C++/WinRT jsou umístěny v winrt/Windows.Security.Cryptography.Certificates.h. Zahrnutím této hlavičky získáte přístup ke všem typům v oboru názvů Windows::Security::Cryptography::Certificates.

Někdy bude jedna hlavička oboru názvů obsahovat části souvisejících hlaviček oboru názvů, ale neměli byste se spoléhat na tuto implementaci. Explicitně uveďte hlavičkové soubory pro obory názvů, které používáte.

Například Metoda Certificate::GetCertificateBlob vrátí Windows::Storage::Streams::IBuffer rozhraní. Před voláním metody Certificate::GetCertificateBlob musíte zahrnout soubor záhlaví oboru názvů winrt/Windows.Storage.Streams.h, aby bylo možné přijmout vrácený objekt Windows::Storage::Streams::IBuffer a pracovat s ním.

Zapomenutí zahrnout požadované hlavičkové soubory oboru názvů před použitím typů z daného oboru názvů je běžným zdrojem chyb při sestavení.

Přístup ke členům prostřednictvím objektu, přes rozhraní nebo prostřednictvím ABI

S projekcí C++/WinRT není běhová reprezentace třídy prostředí Windows Runtime ničím jiným než podkladovými rozhraními ABI. Pro usnadnění ale můžete kódovat proti třídám způsobem, který jejich autor zamýšlel. Můžete například volat metodu ToString objektu Uri, jako by to byla metoda třídy (ve skutečnosti je interně metodou samostatného rozhraní IStringable).

WINRT_ASSERT je definice makra a rozbalí se na _ASSERTE.

Uri contosoUri{ L"http://www.contoso.com" };
WINRT_ASSERT(contosoUri.ToString() == L"http://www.contoso.com/"); // QueryInterface is called at this point.

Toto pohodlí se dosahuje prostřednictvím dotazu pro příslušné rozhraní. Ale vždy jste pod kontrolou. Můžete se rozhodnout obětovat část tohoto pohodlí výměnou za o něco vyšší výkon tím, že si sami získáte rozhraní IStringable a použijete je přímo. V následujícím příkladu kódu získáte skutečný ukazatel rozhraní IStringable za běhu (prostřednictvím jednorázového dotazu). Potom je vaše volání ToString přímé a zabrání dalšímu volání QueryInterface.

...
IStringable stringable = contosoUri; // One-off QueryInterface.
WINRT_ASSERT(stringable.ToString() == L"http://www.contoso.com/");

Tuto techniku můžete použít, pokud víte, že budete volat několik metod v rámci téhož rozhraní.

Mimochodem, pokud chcete přistupovat k členům na úrovni ABI, můžete. Následující příklad kódu ukazuje, jak a existují další podrobnosti a příklady kódu v interoperabilitě mezi C++/WinRT a ABI.

#include <Windows.Foundation.h>
#include <unknwn.h>
#include <winrt/Windows.Foundation.h>
using namespace winrt::Windows::Foundation;

int main()
{
    winrt::init_apartment();
    Uri contosoUri{ L"http://www.contoso.com" };

    int port{ contosoUri.Port() }; // Access the Port "property" accessor via C++/WinRT.

    winrt::com_ptr<ABI::Windows::Foundation::IUriRuntimeClass> abiUri{
        contosoUri.as<ABI::Windows::Foundation::IUriRuntimeClass>() };
    HRESULT hr = abiUri->get_Port(&port); // Access the get_Port ABI function.
}

Zpožděná inicializace

V jazyce C++/WinRT má každý projektovaný typ speciální konstruktor C++/WinRT std::nullptr_t . S výjimkou tohoto jediného všechny konstruktory promítaného typu – včetně výchozího konstruktoru – způsobí vytvoření podkladového objektu prostředí Windows Runtime a poskytnou vám na něj inteligentní ukazatel. Toto pravidlo se tedy použije všude, kde se používá výchozí konstruktor, například neinicializované místní proměnné, neinicializované globální proměnné a neinicializované členské proměnné.

Pokud na druhé straně chcete vytvořit proměnnou projektovaného typu, aniž byste vytvořili záložní prostředí Windows Runtime objekt (abyste mohli tuto práci pozdržet až později), můžete to udělat. Deklarujte proměnnou nebo pole pomocí speciálního konstruktoru C++/WinRT std::nullptr_t (který projekce C++/WinRT vloží do každé třídy modulu runtime). Tento speciální konstruktor používáme s m_gamerPicBuffer v následujícím příkladu kódu.

#include <winrt/Windows.Storage.Streams.h>
using namespace winrt::Windows::Storage::Streams;

#define MAX_IMAGE_SIZE 1024

struct Sample
{
    void DelayedInit()
    {
        // Allocate the actual buffer.
        m_gamerPicBuffer = Buffer(MAX_IMAGE_SIZE);
    }

private:
    Buffer m_gamerPicBuffer{ nullptr };
};

int main()
{
    winrt::init_apartment();
    Sample s;
    // ...
    s.DelayedInit();
}

Všechny konstruktory u promítaného typu s výjimkou konstruktoru std::nullptr_t vedou k vytvoření podkladového objektu prostředí Windows Runtime. Konstruktor std::nullptr_t v podstatě neprovádí žádnou operaci. Očekává, že se projektovaný objekt v další době inicializuje. Takže bez ohledu na to, zda třída modulu runtime má výchozí konstruktor, nebo ne, můžete tuto techniku použít k efektivní zpožděné inicializaci.

To má vliv na další místa, kde vyvoláváte výchozí konstruktor, jako jsou vektory a mapy. Podívejte se na tento příklad kódu, k němuž budete potřebovat projekt Blank App, Packaged (WinUI 3 in Desktop) v jazyce C++.

std::map<int, TextBlock> lookup;
lookup[2] = value;

Přiřazení vytvoří nový TextBlock a pak jej okamžitě přepíše pomocí value. Tady je náprava.

std::map<int, TextBlock> lookup;
lookup.insert_or_assign(2, value);

Podívejte se také , jak výchozí konstruktor ovlivňuje kolekce.

Nepoužívejte omylem odloženou inicializaci

Dávejte pozor, abyste omylem nevolali konstruktoru std::nullptr_t. Řešení konfliktů v kompilátoru mu dává přednost před továrními konstruktory. Představte si například tyto dvě definice tříd modulu runtime.

// GiftBox.idl
runtimeclass GiftBox
{
    GiftBox();
}

// Gift.idl
runtimeclass Gift
{
    Gift(GiftBox giftBox); // You can create a gift inside a box.
}

Řekněme, že chceme vytvořit dárek , který není uvnitř krabice ( dárek vytvořený pomocí neinicializované dárkové schránky). Nejprve se podíváme na nesprávný způsob, jak to udělat. Víme, že existuje konstruktor Gift, který přijímá GiftBox. Pokud ale budeme v pokušení předat hodnotu null typu GiftBox (tedy při volání konstruktoru Gift pomocí jednotné inicializace, jak to děláme níže), nedosáhneme požadovaného výsledku.

// These are *not* what you intended. Doing it in one of these two ways
// actually *doesn't* create the intended backing Windows Runtime Gift object;
// only an empty smart pointer.

Gift gift{ nullptr };
auto gift{ Gift(nullptr) };

Co tady získáte, je neinicializovaný dárek. Nedostanete dárek z neinicializovaného GiftBoxu. Tady je správný způsob, jak to udělat.

// Doing it in one of these two ways creates an initialized
// Gift with an uninitialized GiftBox.

Gift gift{ GiftBox{ nullptr } };
auto gift{ Gift(GiftBox{ nullptr }) };

V chybném příkladu se předání literálu nullptr vyhodnotí ve prospěch konstruktoru pro odloženou inicializaci. Chcete-li vyřešit ve prospěch konstruktoru továrny, typ parametru musí být GiftBox. Stále máte možnost předat explicitně odložení inicializace GiftBoxu, jak je znázorněno ve správném příkladu.

Tento další příklad je také správný, protože parametr má typ GiftBox, a ne std::nullptr_t.

GiftBox giftBox{ nullptr };
Gift gift{ giftBox }; // Calls factory constructor.

K nejednoznačnosti dojde pouze tehdy, když předáte literál nullptr.

Nevytvářejte omylem objekt pomocí kopírovacího konstruktoru.

Toto upozornění je podobné tomu, které je popsáno ve výše uvedené části Neprovádějte omylem opožděnou inicializaci.

Kromě konstruktoru pro odloženou inicializaci projekce C++/WinRT také vkládá kopírovací konstruktor do každé běhové třídy. Jedná se o konstruktor s jedním parametrem, který přijímá stejný typ jako objekt, který se vytváří. Výsledný inteligentní ukazatel ukazuje na tentýž podkladový objekt prostředí prostředí Windows Runtime jako ten, na který ukazuje jeho parametr konstruktoru. Výsledkem jsou dva objekty inteligentního ukazatele ukazující na stejný záložní objekt.

Tady je definice třídy runtime, kterou použijeme v příkladech kódu.

// GiftBox.idl
runtimeclass GiftBox
{
    GiftBox(GiftBox biggerBox); // You can place a box inside a bigger box.
}

Řekněme, že chceme vytvořit GiftBox uvnitř většího GiftBox.

GiftBox bigBox{ ... };

// These are *not* what you intended. Doing it in one of these two ways
// copies bigBox's backing-object-pointer into smallBox.
// The result is that smallBox == bigBox.

GiftBox smallBox{ bigBox };
auto smallBox{ GiftBox(bigBox) };

Správný postup, jak to udělat, spočívá v explicitním volání aktivační továrny.

GiftBox bigBox{ ... };

// These two ways call the activation factory explicitly.

GiftBox smallBox{
    winrt::get_activation_factory<GiftBox, IGiftBoxFactory>().CreateInstance(bigBox) };
auto smallBox{
    winrt::get_activation_factory<GiftBox, IGiftBoxFactory>().CreateInstance(bigBox) };

Pokud je rozhraní API implementované v komponentě prostředí Windows Runtime

Tato část se týká toho, jestli jste komponentu vytvořili sami, nebo pochází od dodavatele.

Note

Informace o instalaci a použití rozšíření C++/WinRT Visual Studio (VSIX) a balíčku NuGet (které společně poskytují podporu šablony projektu a sestavení) najdete v tématu Visual Studio podpora pro C++/WinRT.

Ve svém projektu aplikace přidejte odkaz na soubor metadat prostředí Windows Runtime (.winmd) komponenty prostředí Windows Runtime a projekt sestavte. Během sestavování nástroj cppwinrt.exe generuje standardní knihovnu C++, která plně popisuje – nebo promítá – rozhraní API komponenty. Jinými slovy, vygenerovaná knihovna obsahuje pro komponentu projektované typy.

Poté, stejně jako u typu v oboru názvů Windows, zahrnete soubor záhlaví a vytvoříte projektovaný typ pomocí některého z jeho konstruktorů. Spouštěcí kód projektu aplikace registruje třídu runtime a konstruktor projektu projektu volá RoActivateInstance k aktivaci třídy runtime z odkazované komponenty.

#include <winrt/ThermometerWRC.h>

struct App : AppT<App>
{
    ThermometerWRC::Thermometer thermometer;
    ...
};

Další podrobnosti, kód a podrobný postup používání rozhraní API implementovaných v komponentě prostředí Windows Runtime najdete v tématech Komponenty prostředí Windows Runtime s C++/WinRT a Vytváření událostí v C++/WinRT.

Pokud je rozhraní API implementováno v projektu, který API využívá

Příklad kódu v této části pochází z tématu Ovládací prvky XAML; vazba na vlastnost C++/WinRT. V tomto tématu najdete další podrobnosti, kód a názorný postup využívání třídy runtime implementované ve stejném projektu, který ho využívá.

Typ, který se používá v uživatelském rozhraní XAML, musí být třídou modulu Runtime, i když je ve stejném projektu jako XAML. V tomto scénáři vygenerujete projektovaný typ z metadat třídy modulu runtime prostředí Windows Runtime (.winmd). Znovu zahrnete hlavičku, ale pak máte na výběr mezi C++/WinRT verze 1.0 nebo verze 2.0 způsoby vytvoření instance třídy runtime. Metoda verze 1.0 používá winrt::make; Metoda verze 2.0 se označuje jako jednotná konstrukce. Pojďme se na ně podívat.

Vytváření pomocí winrt::make

Začněme výchozí metodou (C++/WinRT verze 1.0), protože je vhodné se s tímto vzorem alespoň seznámit. Projektovaný typ vytvoříte pomocí jeho konstruktoru std::nullptr_t . Tento konstruktor neprovádí žádné inicializace, takže je nutné instanci přiřadit hodnotu prostřednictvím winrt::make pomocné funkce a předat všechny nezbytné argumenty konstruktoru. Třídu runtime implementovanou ve stejném projektu jako kód, který ji používá, není nutné registrovat ani vytvářet její instanci prostřednictvím aktivace prostředí Windows Runtime/COM.

Podrobný postup najdete v článku Ovládací prvky XAML; vazba na vlastnost C++/WinRT. Tato část ukazuje extrakce z tohoto názorného postupu.

// MainPage.idl
import "BookstoreViewModel.idl";
namespace Bookstore
{
    runtimeclass MainPage : Microsoft.UI.Xaml.Controls.Page
    {
        BookstoreViewModel MainViewModel{ get; };
    }
}

// MainPage.h
...
struct MainPage : MainPageT<MainPage>
{
    ...
    private:
        Bookstore::BookstoreViewModel m_mainViewModel{ nullptr };
};
...

// MainPage.cpp
...
#include "BookstoreViewModel.h"

MainPage::MainPage()
{
    m_mainViewModel = winrt::make<Bookstore::implementation::BookstoreViewModel>();
    ...
}

Jednotná konstrukce

S C++/WinRT verze 2.0 a novější je k dispozici optimalizovaná forma konstrukce, která se označuje jako jednotná konstrukce (viz Novinky a změny v C++/WinRT 2.0).

Úplný podrobný postup najdete v článku Ovládací prvky XAML; vazba na vlastnost C++/WinRT. Tato část obsahuje výňatky z tohoto podrobného návodu.

Pokud chcete místo winrt::make použít jednotnou konstrukci, budete potřebovat aktivační továrnu. Dobrým způsobem, jak ho vygenerovat, je přidat konstruktor do vašeho IDL.

// MainPage.idl
import "BookstoreViewModel.idl";
namespace Bookstore
{
    runtimeclass MainPage : Microsoft.UI.Xaml.Controls.Page
    {
        MainPage();
        BookstoreViewModel MainViewModel{ get; };
    }
}

Pak deklarujte MainPage.h a inicializujete m_mainViewModel v jednom kroku, jak je znázorněno níže.

// MainPage.h
...
struct MainPage : MainPageT<MainPage>
{
    ...
    private:
        Bookstore::BookstoreViewModel m_mainViewModel;
        ...
    };
}
...

A pak v konstruktoru MainPage v MainPage.cpp není potřeba uvádět kód m_mainViewModel = winrt::make<Bookstore::implementation::BookstoreViewModel>();.

Další informace o sjednocené konstrukci a ukázky kódu najdete v tématu Přihlášení ke sjednocené konstrukci a přímému přístupu k implementaci.

Vytváření instancí a vracení projektovaných typů a rozhraní

Tady je příklad toho, jak můžou projektované typy a rozhraní vypadat ve vašem náročném projektu. Mějte na paměti, že projektovaný typ (například ten v tomto příkladu) je vygenerovaný nástrojem a není to něco, co byste sami vytvořili.

struct MyRuntimeClass : MyProject::IMyRuntimeClass, impl::require<MyRuntimeClass,
    Windows::Foundation::IStringable, Windows::Foundation::IClosable>

MyRuntimeClass je promítaný typ; mezi promítaná rozhraní patří IMyRuntimeClass, IStringable a IClosable. Tato část ukázala různé způsoby, jak můžete vytvořit instanci promítnutého typu. Tady je připomenutí a souhrn s použitím třídy MyRuntimeClass jako příklad.

// The runtime class is implemented in another compilation unit (it's either a Windows API,
// or it's implemented in a second- or third-party component).
MyProject::MyRuntimeClass myrc1;

// The runtime class is implemented in the same compilation unit.
MyProject::MyRuntimeClass myrc2{ nullptr };
myrc2 = winrt::make<MyProject::implementation::MyRuntimeClass>();
  • Můžete přistupovat ke členům všech rozhraní promítaného typu.
  • Projektovaný typ můžete vrátit volajícímu.
  • Projektované typy a rozhraní jsou odvozeny od winrt::Windows::Foundation::IUnknown. Můžete tedy volat IUnknown::as u projektovaného typu nebo rozhraní k dotazování na jiná projektovaná rozhraní, která pak můžete buď použít, nebo vrátit volajícímu. Členská funkce as funguje podobně jako QueryInterface.
void f(MyProject::MyRuntimeClass const& myrc)
{
    myrc.ToString();
    myrc.Close();
    IClosable iclosable = myrc.as<IClosable>();
    iclosable.Close();
}

Aktivační továrny

Pohodlný, přímý způsob vytvoření objektu C++/WinRT je následující.

using namespace winrt::Windows::Globalization::NumberFormatting;
...
CurrencyFormatter currency{ L"USD" };

Může se ale stát, že budete chtít vytvořit aktivační továrnu sami a pak z ní vytvářet objekty podle potřeby. Zde je několik příkladů, které ukazují, jak použít šablonu funkce winrt::get_activation_factory.

using namespace winrt::Windows::Globalization::NumberFormatting;
...
auto factory = winrt::get_activation_factory<CurrencyFormatter, ICurrencyFormatterFactory>();
CurrencyFormatter currency = factory.CreateCurrencyFormatterCode(L"USD");
using namespace winrt::Windows::Foundation;
...
auto factory = winrt::get_activation_factory<Uri, IUriRuntimeClassFactory>();
Uri uri = factory.CreateUri(L"http://www.contoso.com");

Třídy ve dvou výše uvedených příkladech pocházejí z oboru názvů Windows. V tomto dalším příkladu je teploměrWRC::Teploměr vlastní typ implementovaný v prostředí Windows Runtime komponentě.

auto factory = winrt::get_activation_factory<ThermometerWRC::Thermometer>();
ThermometerWRC::Thermometer thermometer = factory.ActivateInstance<ThermometerWRC::Thermometer>();

Nejednoznačnosti člena/typu

Pokud má členská funkce stejný název jako typ, existuje nejednoznačnost. Pravidla vyhledávání nekvalifikovaných názvů v jazyce C++ ve členských funkcích způsobují, že se před hledáním v oblastech názvů nejprve prohledává třída. Pravidlo selhání substituce není chybou (SFINAE) se nepoužije (uplatňuje se při rozhodování o přetížení funkčních šablon). Takže pokud název uvnitř třídy nemá smysl, kompilátor nebude dál hledat lepší shodu – jednoduše hlásí chybu.

struct MyPage : Page
{
    void DoWork()
    {
        // This doesn't compile. You get the error
        // "'winrt::Windows::Foundation::IUnknown::as':
        // no matching overloaded function found".
        auto style{ Application::Current().Resources().
            Lookup(L"MyStyle").as<Style>() };
    }
}

Výše si kompilátor myslí, že předáváte FrameworkElement.Style() (což je v jazyce C++/WinRT členská funkce) jako parametr šablony IUnknown::as. Řešením je vynutit, aby se název Style interpretoval jako typ Microsoft::UI::Xaml::Style.

struct MyPage : Page
{
    void DoWork()
    {
        // One option is to fully-qualify it.
        auto style{ Application::Current().Resources().
            Lookup(L"MyStyle").as<Microsoft::UI::Xaml::Style>() };

        // Another is to force it to be interpreted as a struct name.
        auto style{ Application::Current().Resources().
            Lookup(L"MyStyle").as<struct Style>() };

        // If you have "using namespace Windows::UI;", then this is sufficient.
        auto style{ Application::Current().Resources().
            Lookup(L"MyStyle").as<Xaml::Style>() };

        // Or you can force it to be resolved in the global namespace (into which
        // you imported the Microsoft::UI::Xaml namespace when you did
        // "using namespace Microsoft::UI::Xaml;".
        auto style = Application::Current().Resources().
            Lookup(L"MyStyle").as<::Style>();
    }
}

Nekvalifikované vyhledávání názvů má zvláštní výjimku v případě, že název následuje ::, v takovém případě ignoruje funkce, proměnné a výčtové hodnoty. To vám umožní dělat takové věci.

struct MyPage : Page
{
    void DoSomething()
    {
        Visibility(Visibility::Collapsed); // No ambiguity here (special exception).
    }
}

Volání funkce Visibility() se překládá na název členské funkce UIElement.Visibility. Ale parametr Visibility::Collapsed následuje za slovem Visibility s ::, a proto je název metody ignorován a kompilátor tak najde enum class.

Důležitá rozhraní API