Sdílet prostřednictvím


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

Toto téma ukazuje, jak využívat rozhraní API C++/WinRT, ať už jsou součástí Windows, implementovaná dodavateli komponent třetích stran, nebo vámi.

Důležité

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

Pokud chcete využívat vlastní typy Windows Runtime (od třetích stran) z konzolové aplikace, budete muset aplikaci přiřadit identitu balíčku, aby bylo možné vyřešit registraci spotřebovaných vlastních typů. Další informace viz v tématu Windows Application Packaging Project.

Případně můžete vytvořit nový projekt z prázdné aplikace (C++/WinRT), základní aplikace (C++/WinRT)nebo Windows Runtime komponenty (C++/WinRT) šablony projektů. Tyto typy aplikací už mají identitu balíčku.

Pokud je rozhraní API v oboru názvů 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 vhodný pro C++ (nazývaný projektovaný typ ). Projektovaný typ má stejný plně kvalifikovaný název jako typ Windows, ale je umístěný v oboru názvů C++ `winrt` pomocí syntaxe jazyka C++. Například Windows::Foundation::Uri je projektován 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 systému Windows (C++/WinRT), pak nejprve nastavte nepoužít předkompilované hlavičky ve vlastnostech projektu.

// 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 oborů názvů Windows promítané do C++/WinRT. V tomto příkladu winrt/Windows.Foundation.h obsahuje winrt::Windows::Foundation::Uri, což je projektovaný typ třídy modulu runtime Windows::Foundation::Uri.

Návod

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

V příkladu kódu výše po inicializaci C++/WinRT přidělujeme na zásobníku hodnotu projektovaného typu winrt::Windows::Foundation::Uri prostřednictvím jednoho z veřejně zdokumentovaných konstruktorů (v tomto příkladuUri(String)). U tohoto nejběžnějšího případu použití je to obvykle vše, co musíte udělat. 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 zavoláním RoActivateInstance vytvoří instanci podkladové třídy Windows Runtime (Windows.Foundation.Uri, v tomto případě) a uloží výchozí rozhraní tohoto objektu do nové projektované hodnoty. Jak je znázorněno níže, vaše volání členů projektované hodnoty ve skutečnosti delegují pomocí inteligentního ukazatele na záložní objekt; kde dochází ke změnám stavu.

Očekávaný typ Windows::Foundation::Uri

Když využití hodnota contosoUri skončí, zničí se a uvolní svou referenci na výchozí rozhraní. Pokud je tento odkaz posledním odkazem na podkladový objekt Windows Runtime Windows.Foundation.Uri, pak se také podkladový objekt 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ítané rozhraní je obálkou pro rozhraní prostředí Windows Runtime.

Hlavičky projekce C++/WinRT

Pokud chcete využívat rozhraní API oboru názvů Windows z C++/WinRT, zahrnete hlavičky 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 v oboru názvů Windows::Security::Cryptography::Certificates se ekvivalentní definice typů C++/WinRT nacházejí 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ě zahrňte hlavičky pro používané obory názvů.

Například Metoda Certificate::GetCertificateBlob vrátí rozhraní Windows::Storage::Streams::IBuffer . Před voláním metody Certificate::GetCertificateBlob musíte zahrnout winrt/Windows.Storage.Streams.h hlavičkový soubor oboru názvů, abyste měli jistotu, že můžete přijímat a pracovat s vráceným rozhraním Windows::Storage::Streams::IBuffer.

Zapomenutí zahrnout požadované hlavičky oboru názvů před použitím typů v tomto oboru názvů je běžným zdrojem chyb při sestavování.

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

Při projekci C++/WinRT nepřekračuje reprezentace za běhu třídy Windows Runtime základní rozhraní 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 ToStringUri, jako by to byla metoda třídy (ve skutečnosti v zákulisí je to metoda na samostatném rozhraní IStringable).

WINRT_ASSERT je makro definice 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 trochu pohodlí pro získání trochu výkonu tím, že načtete rozhraní IStringable sami a použijete ho 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 volání ToString přímé a vyhýbá se dalšímu volání QueryInterface.

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

Tuto techniku můžete zvolit, pokud víte, že budete volat několik metod na stejném rozhraní.

Mimochodem, pokud chcete přistupovat k členům na úrovni ABI, můžete. Následující příklad kódu ukazuje, jak na to, a také další podrobnosti a příklady kódu najdete v o 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 jednoho všechny konstruktory s typovým projektováním – včetně výchozího konstruktoru – způsobí vytvoření podpůrného objektu 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 druhou stranu chcete vytvořit proměnnou projektovaného typu, aniž by se vytvořil záložní objekt prostředí Windows Runtime (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 projektovaného typu s výjimkou konstruktoru std::nullptr_t způsobují vytvoření podpůrného objektu Windows Runtime. Std::nullptr_t konstruktor je v podstatě no-op. 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. Vezměte v úvahu tento příklad kódu, pro který budete potřebovat prázdnou aplikaci (C++/WinRT) projektu.

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

Přiřazení vytvoří nový TextBlocka ihned ho valuepřepíše. 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.

Neprovádějte zpožděnou inicializaci omylem

Dávejte pozor, abyste omylem nevyvolali konstruktor std::nullptr_t. Řešení konfliktů kompilátoru ho upřednostňuje před konstruktory továrny. 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, který je vytvořen s neinicializovaným GiftBox). 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. Ale pokud budeme chtít předat null GiftBox (vyvolání konstruktoru dárek pomocí jednotné inicializace, jak je uvedeno níže), pak nebudeme získat výsledek, který chceme.

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

To, co zde dostanete, je neinicializovaný dar. Nedostanete dárkový s neinicializovanou dárkovou schránkou. 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 nesprávném příkladu vede předání literálu nullptr k upřednostnění konstruktoru se zpožděnou inicializací. Aby bylo stanoveno ve prospěch továrního konstruktoru, typ parametru musí být GiftBox. Stále máte možnost předat objekt GiftBox, který explicitně zpožďuje inicializaci, 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 nikoli std::nullptr_t.

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

Je to jen tehdy, když předáte hodnotu nullptr, že se objeví nejednoznačnost.

Nekopírujte ho omylem.

Toto upozornění je podobné tomu, které je popsáno v části Neodkládejte inicializaci omylem v horní části.

Kromě konstruktoru pro zpožděnou inicializaci také projekce C++/WinRT vkládá konstruktor kopírování do každé třídy za běhu. Jedná se o konstruktor s jedním parametrem, který přijímá stejný typ jako objekt, který se vytváří. Výsledný inteligentní ukazatel odkazuje na stejný záložní objekt prostředí Windows Runtime, na který odkazuje 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 dárkovou krabičku uvnitř větší dárkové krabičky.

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ý způsob, jak to udělat, je přímo volat továrnu na aktivaci.

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 implementováno v komponentě Windows Runtime

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

Poznámka:

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

V projektu aplikace odkažte na soubor komponenty Windows Runtime s metadaty prostředí Windows Runtime (.winmd) a sestavte. Během sestavování nástroj cppwinrt.exe generuje standardní knihovnu C++, která plně popisuje—nebo promítá—rozhraní API pro danou komponentu. Jinými slovy, vygenerovaná knihovna obsahuje pro komponentu projektované typy.

Poté, stejně jako u typu oboru názvů Windows, zahrnete hlavičku a vytvoříte projektovaný typ pomocí jednoho z jeho konstruktorů. Spouštěcí kód projektové aplikace registruje běhovou třídu a konstruktor promítnutého typu volá RoActivateInstance k aktivaci běhové třídy z odkazované komponenty.

#include <winrt/ThermometerWRC.h>

struct App : implements<App, IFrameworkViewSource, IFrameworkView>
{
    ThermometerWRC::Thermometer thermometer;
    ...
};

Další podrobnosti, kód a názorný postup využívání rozhraní API implementovaných v komponentě Prostředí Windows Runtime najdete v tématu součásti prostředí Windows Runtime s komponentami C++/WinRT a Author vC++/WinRT .

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

Příklad kódu v této části je převzat z tématu ovládací prvky XAML, přičemž se váže na vlastnost jazyka 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 využívá z uživatelského rozhraní XAML, musí být třída modulu runtime, i když je ve stejném projektu jako XAML. V tomto scénáři vygenerujete projektovaný typ z metadat prostředí Windows Runtime třídy modulu 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řída modulu runtime, která je implementována ve stejném projektu jako využívající kód, nemusí být zaregistrována ani vytvořena prostřednictvím aktivace Windows Runtime nebo COM.

Viz ovládací prvky XAML; vytvořte vazbu na vlastnost C++/WinRT pro úplný návod. Tato část ukazuje výňatky z tohoto názorného postupu.

// MainPage.idl
import "BookstoreViewModel.idl";
namespace Bookstore
{
    runtimeclass MainPage : Windows.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

Ve verzi C++/WinRT 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).

Viz ovládací prvky XAML; vytvořte vazbu na vlastnost C++/WinRT pro úplný návod. Tato část ukazuje výňatky z tohoto názorného postupu.

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 : Windows.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.cppnení potřeba kód m_mainViewModel = winrt::make<Bookstore::implementation::BookstoreViewModel>();.

Další informace o jednotných konstrukcích a příkladech kódu naleznete v tématu Přihlášení k jednotné konstrukci a přímý přístup k implementaci.

Vytváření instancí a návrat 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 projektovaný typ: projektované rozhraní zahrnují IMyRuntimeClass, IStringablea IClosable. Toto téma ukázalo různé způsoby, jak vytvořit instanci projekční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 mít přístup k členům všech rozhraní promítaného typu.
  • Promítnutý 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 na projektovaném typu nebo rozhraní, abyste se dotázali na jiná projektovaná rozhraní, která můžete také použít nebo vrátit volajícímu. v roli členské funkce působí 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. Tady je několik příkladů, které vám ukážou, 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 v předchozích dvou příkladech jsou typy z oboru názvů Systému Windows. V tomto dalším příkladu TeploměrWRC::Teploměr je vlastní typ implementovaný v komponentě Windows Runtime.

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

Nejasnosti v určení člena/typu

Pokud má členská funkce stejný název jako typ, existuje nejednoznačnost. Pravidla pro vyhledávání nekvalifikovaných jmen v jazyce C++ v metodách třídy způsobují, že se nejprve prohledá třída, než se hledá v prostorech jmen. Selhání při substituci není chybou podle pravidla (SFINAE), nepoužije se (použije se při řešení přetěžování šablon funkcí). 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>() };
    }
}

Kompilátor výše uvedený si myslí, že předáváte FrameworkElement.Style() (což je v jazyce C++/WinRT funkce člena) jako parametr šablony pro IUnknown::as. Řešením je vynutit, aby byl název Style interpretován jako typ Windows::UI::Xaml::Style.

struct MyPage : Page
{
    void DoWork()
    {
        // One option is to fully-qualify it.
        auto style{ Application::Current().Resources().
            Lookup(L"MyStyle").as<Windows::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 Windows::UI::Xaml namespace when you did
        // "using namespace Windows::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í Visibility() se přeloží na název členské funkce UIElement.Visibility. Ale parametr Visibility::Collapsed následuje za slovem Visibility s ::, a tak je název metody přehlížen a kompilátor najde výčtovou třídu.

Důležitá rozhraní API