Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
In dit onderwerp wordt beschreven hoe u C++/WinRT API's gebruikt, ongeacht of ze deel uitmaken van Windows, worden geïmplementeerd door een externe leverancier van onderdelen of door uzelf zijn geïmplementeerd.
Belangrijk
Zodat de codevoorbeelden in dit onderwerp kort en eenvoudig zijn om uit te proberen, kunt u deze reproduceren door een nieuwe Windows-consoletoepassing (C++/WinRT) project te maken en code te kopiëren/plakken. U kunt echter geen willekeurige aangepaste Windows Runtime-typen (van derden) gebruiken vanuit een uitgepakte app. U kunt op die manier alleen Windows typen benutten.
Als u aangepaste (externe) Windows Runtime-typen van een console-app wilt gebruiken, moet u de app een pakketidentiteit geven, zodat deze de registratie van de verbruikte aangepaste typen kan oplossen. Zie Windows Application Packaging Projectvoor meer informatie.
U kunt ook een nieuw project maken op basis van de Lege app (C++/WinRT), Core App (C++/WinRT)of Windows Runtime Component (C++/WinRT) projectsjablonen. Deze app-typen hebben al een pakketidentiteit.
Als de API zich in een Windows-naamruimte bevindt
Dit is het meest voorkomende geval waarin u een Windows Runtime-API gebruikt. Voor elk type in een Windows-naamruimte die is gedefinieerd in metagegevens, definieert C++/WinRT een C++-vriendelijk equivalent (het geprojecteerd type). Een geprojecteerd type heeft dezelfde volledig gekwalificeerde naam als het Windows-type, maar wordt in de C++-winrt- naamruimte geplaatst met behulp van de C++-syntaxis. Bijvoorbeeld, Windows::Foundation::Uri wordt geprojecteerd in C++/WinRT als winrt::Windows::Foundation::Uri.
Hier volgt een eenvoudig codevoorbeeld. Als u de volgende codevoorbeelden rechtstreeks in het hoofdcodebestand van een Windows-consoletoepassing (C++/WinRT) project wilt plakken, stelt u eerst Precompiled Headers niet gebruiken in projecteigenschappen in.
// 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");
}
De opgenomen header winrt/Windows.Foundation.h maakt deel uit van de SDK, die zich in de map %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt\bevindt. De headers in die map bevatten Windows-naamruimtetypen die in C++/WinRT worden geprojecteerd. In dit voorbeeld bevat winrt/Windows.Foundation.hwinrt::Windows::Foundation::Uri, het verwachte type voor de runtimeklasse Windows::Foundation::Uri.
Aanbeveling
Wanneer u een type uit een Windows-naamruimte wilt gebruiken, moet u de C++/WinRT-header opnemen die overeenkomt met die naamruimte. De using namespace richtlijnen zijn optioneel, maar handig.
In het bovenstaande codevoorbeeld stapelalloceren we, na het initialiseren van C++/WinRT, een waarde van het winrt::Windows::Foundation::Uri geprojecteerde type via één van de openbaar gedocumenteerde constructors (Uri(String), in dit voorbeeld). Voor deze meest voorkomende gebruikssituatie is dat meestal alles wat u hoeft te doen. Zodra u een C++/WinRT-geprojecteerde typewaarde hebt, kunt u deze behandelen alsof het een exemplaar is van een werkelijk Windows Runtime-type, omdat het dezelfde leden heeft.
In feite is die verwachte waarde een proxy; Het is in wezen alleen een slimme aanwijzer naar een backing-object. De constructor(en) van de geprojecteerde waarde roepen RoActivateInstance aan om een instantie van de Windows Runtime-klasse (Windows.Foundation.Uri, in dit geval) te maken, en slaan de standaardinterface van dat object op in de nieuwe geprojecteerde waarde. Zoals hieronder wordt geïllustreerd, worden uw aanroepen naar de leden van de geprojecteerde waarde daadwerkelijk via de smart pointer gedelegeerd naar het ondersteunende object, waar statuswijzigingen optreden.
Wanneer de contosoUri waarde buiten scope valt, wordt deze vernietigd en wordt de verwijzing naar de standaardinterface vrijgegeven. Als deze verwijzing de laatste verwijzing is naar het achterliggende Windows Runtime Windows.Foundation.Uri-object, wordt het achterliggende object ook verwijderd.
Aanbeveling
Een geprojecteerd type is een wrapper voor een Windows Runtime-type om de API's te gebruiken. Een geprojecteerde interface is bijvoorbeeld een wrapper over een Windows Runtime-interface.
C++/WinRT-projectieheaders
Als u Windows-naamruimte-API's uit C++/WinRT wilt gebruiken, neemt u headers op uit de map %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt. U moet de headers opnemen die overeenkomen met elke naamruimte die u gebruikt.
Voor de Windows::Security::Cryptography::Certificates naamruimte bevinden de equivalente C++/WinRT-typedefinities zich bijvoorbeeld in winrt/Windows.Security.Cryptography.Certificates.h. Door deze header op te nemen, krijgt u toegang tot alle typen in de naamruimte Windows::Security::Cryptography::Certificates.
Soms bevat één naamruimteheader gedeelten van gerelateerde naamruimteheaders, maar u moet niet vertrouwen op deze implementatiedetails. Neem expliciet de headers op voor de naamruimten die u gebruikt.
De methode Certificate::GetCertificateBlob retourneert bijvoorbeeld een Windows::Storage::Streams::IBuffer-interface .
Voordat u de methode Certificate::GetCertificateBlob aanroept, moet u het headerbestand voor de winrt/Windows.Storage.Streams.h naamruimte opnemen om ervoor te zorgen dat u de geretourneerde Windows::Storage::Streams::IBuffer kunt ontvangen en gebruiken.
Het vergeten om de vereiste naamruimteheaders op te nemen voordat u typen in die naamruimte gebruikt, is een veelvoorkomende bron van buildfouten.
Leden openen via het object, via een interface of via de ABI
Met de C++/WinRT-projectie is de runtimeweergave van een Windows Runtime-klasse niet meer dan de onderliggende ABI-interfaces. Maar voor uw gemak kunt u code schrijven tegen klassen, zoals de auteur het bedoeld heeft. U kunt bijvoorbeeld de ToString-methode van een Uri- aanroepen alsof dit een methode van de klasse is (in feite is het achter de schermen een methode op de afzonderlijke IStringable interface).
WINRT_ASSERT is een macrodefinitie en wordt uitgebreid naar _ASSERTE.
Uri contosoUri{ L"http://www.contoso.com" };
WINRT_ASSERT(contosoUri.ToString() == L"http://www.contoso.com/"); // QueryInterface is called at this point.
Dit gemak wordt bereikt via een query voor de juiste interface. Maar je bent altijd in de controle. U kunt ervoor kiezen om een beetje van dat gemak weg te geven voor een beetje prestaties door de IStringable-interface zelf op te halen en deze rechtstreeks te gebruiken. In het onderstaande codevoorbeeld krijgt u een werkelijke IStringable-interfaceaanwijzer tijdens runtime (via een eenmalige query). Daarna is uw aanroep naar ToString direct en vermijdt u elke verdere aanroep naar QueryInterface.
...
IStringable stringable = contosoUri; // One-off QueryInterface.
WINRT_ASSERT(stringable.ToString() == L"http://www.contoso.com/");
U kunt deze techniek kiezen als u weet dat u verschillende methoden op dezelfde interface aanroept.
Als u echter wel toegang wilt tot leden op ABI-niveau, kunt u dat doen. In het onderstaande codevoorbeeld ziet u hoe het werkt, en er zijn meer details en codevoorbeelden te vinden in Interop tussen C++/WinRT en de 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.
}
Vertraagde initialisatie
In C++/WinRT heeft elk projecttype een speciale C++/WinRT-std::nullptr_t constructor. Met uitzondering van deze, zorgen alle projected-type constructors, inclusief de standaardconstructor, ervoor dat een Backing Windows Runtime-object wordt gemaakt en u een slimme aanwijzer krijgt. Deze regel wordt dus overal toegepast waarop de standaardconstructor wordt gebruikt, zoals niet-geïnitialiseerde lokale variabelen, niet-geïnitialiseerde globale variabelen en niet-geïnitialiseerde lidvariabelen.
Als u daarentegen een variabele van een geprojecteerd type wilt maken zonder dat u op zijn beurt een Backing Windows Runtime-object bouwt (zodat u dat werk tot later kunt uitstellen), kunt u dat doen. Declareer uw variabele of veld met behulp van die speciale C++/WinRT-std::nullptr_t constructor (die de C++/WinRT-projectie in elke runtimeklasse injecteert). We gebruiken die speciale constructor met m_gamerPicBuffer in het onderstaande codevoorbeeld.
#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();
}
Alle constructors op het projected type behalve de std::nullptr_t constructor zorgen ervoor dat er een back-up van het Windows Runtime-object wordt gemaakt. De std::nullptr_t constructor is in wezen een no-op. Er wordt verwacht dat het verwachte object op een later tijdstip wordt geïnitialiseerd. Dus, of een runtime-klasse een standaardconstructor heeft of niet, u kunt deze techniek gebruiken voor efficiënte vertraagde initialisatie.
Deze overweging is van invloed op andere plaatsen waar u de standaardconstructor aanroept, zoals in vectoren en kaarten. Bekijk dit codevoorbeeld, waarvoor u een lege app (C++/WinRT) project nodig hebt.
std::map<int, TextBlock> lookup;
lookup[2] = value;
De opdracht maakt een nieuwe TextBlock-en overschrijft deze onmiddellijk met value. Hier is de remedie.
std::map<int, TextBlock> lookup;
lookup.insert_or_assign(2, value);
Zie ook Hoe de standaardconstructor van invloed is op verzamelingen.
Zorg dat je niet per ongeluk vertraagd initialiseert
Wees voorzichtig dat u de std::nullptr_t constructor niet per ongeluk aanroept. De conflictoplossing van de compiler geeft deze de voorkeur boven de factory constructors. Denk bijvoorbeeld aan deze twee runtimeklassedefinities.
// GiftBox.idl
runtimeclass GiftBox
{
GiftBox();
}
// Gift.idl
runtimeclass Gift
{
Gift(GiftBox giftBox); // You can create a gift inside a box.
}
Stel dat we een Gift willen maken die niet in een doos zit (een Gift dat is geconstrueerd met een niet-geïnitialiseerde GiftBox). Laten we eerst eens kijken naar de verkeerde manier om dat te doen. We weten dat er een Gift constructor is die een GiftBox. Maar als we geneigd zijn om een null-GiftBox- door te geven (het aanroepen van de Gift constructor via uniforme initialisatie, zoals hieronder wordt gedaan), het gewenste resultaat niet krijgen.
// 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) };
Wat je hier krijgt, is een niet-geïnitialiseerd Geschenk. U krijgt geen Cadeau met een niet-geïnitialiseerde Cadeaudoos. Dit is de juiste manier om dat te doen.
// 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 }) };
In het onjuiste voorbeeld wordt het doorgeven van een nullptr literal ten gunste van de uitstel-initialisatieconstructor opgelost. Om dit op te lossen ten gunste van de fabrieksconstructor, moet het type parameter een GiftBoxzijn. U hebt nog steeds de mogelijkheid om een GiftBoxdoor te geven die expliciet met vertraging wordt geïnitieerd, zoals wordt weergegeven in het juiste voorbeeld.
Dit volgende voorbeeld is ook juist, omdat de parameter het type GiftBox heeft en niet std::nullptr_t.
GiftBox giftBox{ nullptr };
Gift gift{ giftBox }; // Calls factory constructor.
Pas wanneer je een nullptr-literal doorgeeft, ontstaat er dubbelzinnigheid.
Voorkom het per ongeluk maken van een kopie.
Deze waarschuwing is vergelijkbaar met de beschreven waarschuwing in de 'Niet per ongeluk vertraagde initialisatie' sectie hierboven.
Naast de vertragingsinitialiseerde constructor injecteert de C++/WinRT-projectie ook een kopieerconstructor in elke runtimeklasse. Het is een constructor met één parameter die hetzelfde type accepteert als het object dat wordt gemaakt. De resulterende slimme aanwijzer verwijst naar hetzelfde Backing Windows Runtime-object als waarnaar wordt verwezen door de constructorparameter. Het resultaat is twee slimme aanwijzerobjecten die naar hetzelfde backingobject wijzen.
Hier volgt een runtimeklassedefinitie die we gaan gebruiken in de codevoorbeelden.
// GiftBox.idl
runtimeclass GiftBox
{
GiftBox(GiftBox biggerBox); // You can place a box inside a bigger box.
}
Stel dat we een GiftBox willen construeren binnen een grotere 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) };
De juiste manier om dit te doen, is door de activatiefabriek expliciet aan te roepen.
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) };
Als de API is geïmplementeerd in een Windows Runtime-onderdeel
Deze sectie is van toepassing, ongeacht of u het onderdeel zelf hebt gemaakt of dat het afkomstig is van een leverancier.
Opmerking
Zie voor informatie over het installeren en gebruiken van de C++/WinRT Visual Studio-extensie (VSIX) en het NuGet-pakket (dat samen projectsjabloon en build-ondersteuning biedt), Visual Studio-ondersteuning voor C++/WinRT-.
Raadpleeg in het project van uw applicatie het Windows Runtime-metadata-bestand (.winmd) van het Windows Runtime-onderdeel en compileer. Tijdens de build genereert het hulpprogramma cppwinrt.exe een standaard-C++-bibliotheek die volledig wordt beschreven( of projecten), het API-gebied voor het onderdeel. Met andere woorden, de gegenereerde bibliotheek bevat de verwachte typen voor het onderdeel.
Net als voor een Windows-naamruimtetyp neemt u een header op en maakt u het geprojecteerde type aan via een van zijn constructors. De opstartcode van uw toepassingsproject registreert de runtimeklasse en de constructor van het projecttype roept RoActivateInstance aan om de runtimeklasse te activeren vanuit het onderdeel waarnaar wordt verwezen.
#include <winrt/ThermometerWRC.h>
struct App : implements<App, IFrameworkViewSource, IFrameworkView>
{
ThermometerWRC::Thermometer thermometer;
...
};
Zie voor meer informatie, code en een uitleg over het gebruik van API's die zijn geïmplementeerd in een Windows Runtime-onderdeel de secties Windows Runtime-onderdelen met C++/WinRT en Gebeurtenissen aanmaken in C++/WinRT.
Als de API is geïmplementeerd in het verbruikende project
Het codevoorbeeld in deze sectie is afkomstig uit het onderwerp XAML-besturingselementen; binden aan een C++/WinRT-eigenschap. Zie dat onderwerp voor meer informatie, code en een overzicht van het gebruik van een runtimeklasse die is geïmplementeerd in hetzelfde project dat het gebruikt.
Een type dat wordt gebruikt vanuit de XAML-gebruikersinterface, moet een runtimeklasse zijn, zelfs als het zich in hetzelfde project bevindt als de XAML. Voor dit scenario genereert u een projected type op basis van de Windows Runtime-metagegevens van de runtimeklasse (.winmd). Nogmaals, u neemt een header op, waarna u kunt kiezen tussen de manier waarop een instantie van de runtime-klasse wordt geconstrueerd met C++/WinRT versie 1.0 of versie 2.0. De methode versie 1.0 maakt gebruik van winrt::make; de methode versie 2.0 wordt uniforme constructie genoemd. Laten we elk op hun beurt eens bekijken.
Bouwen door gebruik te maken van winrt::make
Laten we beginnen met de standaardmethode (C++/WinRT versie 1.0), omdat het een goed idee is om ten minste bekend te zijn met dat patroon. U maakt het geprojecteerde type via de bijbehorende std::nullptr_t constructor. Deze constructor voert geen initialisatie uit, dus u moet vervolgens een waarde aan het exemplaar toewijzen via de winrt::make helperfunctie, waarbij u eventuele benodigde constructorargumenten doorgeeft. Een runtimeklasse die in hetzelfde project is geïmplementeerd als de verbruikende code, hoeft niet te worden geregistreerd of geïnstantieerd via Windows Runtime/COM-activering.
Zie XAML-besturingselementen; binden aan een C++/WinRT-eigenschap voor een volledig overzicht. In deze sectie ziet u extracten uit die rondleiding.
// 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>();
...
}
Uniforme constructie
Met C++/WinRT versie 2.0 en hoger is er een geoptimaliseerde vorm van constructie beschikbaar voor u, ook wel bekend als uniforme constructie (zie Nieuws en wijzigingen, in C++/WinRT 2.0).
Zie XAML-besturingselementen; binden aan een C++/WinRT-eigenschap voor een volledig overzicht. In deze sectie ziet u extracten uit die rondleiding.
Als u een uniforme constructie wilt gebruiken in plaats van winrt::make, hebt u een activatiefabriek nodig. Een goede manier om er een te genereren, is door een constructor toe te voegen aan uw IDL.
// MainPage.idl
import "BookstoreViewModel.idl";
namespace Bookstore
{
runtimeclass MainPage : Windows.UI.Xaml.Controls.Page
{
MainPage();
BookstoreViewModel MainViewModel{ get; };
}
}
Vervolgens declareert en initialiseert u in MainPage.hm_mainViewModel in slechts één stap, zoals hieronder wordt weergegeven.
// MainPage.h
...
struct MainPage : MainPageT<MainPage>
{
...
private:
Bookstore::BookstoreViewModel m_mainViewModel;
...
};
}
...
En in de MainPage constructor in MainPage.cppis de code m_mainViewModel = winrt::make<Bookstore::implementation::BookstoreViewModel>();niet nodig.
Zie Opt in to uniform construction, and direct implementation accessvoor meer informatie over uniforme constructie en codevoorbeelden.
Geprojecteerde typen en interfaces instantiëren en retourneren
Hier volgt een voorbeeld van hoe geprojecteerde typen en interfaces eruit kunnen zien in uw verbruikende project. Houd er rekening mee dat een geprojecteerd type (zoals het type in dit voorbeeld) wordt gegenereerd door een hulpprogramma en niet iets is dat u zelf zou ontwerpen.
struct MyRuntimeClass : MyProject::IMyRuntimeClass, impl::require<MyRuntimeClass,
Windows::Foundation::IStringable, Windows::Foundation::IClosable>
MyRuntimeClass is een geprojecteerd type; geprojecteerde interfaces omvatten IMyRuntimeClass, IStringableen IClosable. In dit onderwerp ziet u de verschillende manieren waarop u een geprojecteerd type kunt instantiëren. Hier volgt een herinnering en samenvatting, met behulp van MyRuntimeClass als voorbeeld.
// 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>();
- U hebt toegang tot de leden van alle interfaces van een geprojecteerd type.
- U kunt een geprojecteerd type retourneren aan een aanroeper.
- Projecttypen en interfaces zijn afgeleid van winrt::Windows::Foundation::IUnknown. U kunt dus IUnknown::as op een geprojecteerd type of interface aanroepen om andere geprojecteerde interfaces op te vragen, die u ook kunt gebruiken of aan een beller kunt teruggeven. De als lidfunctie werkt als QueryInterface.
void f(MyProject::MyRuntimeClass const& myrc)
{
myrc.ToString();
myrc.Close();
IClosable iclosable = myrc.as<IClosable>();
iclosable.Close();
}
Activeringsfabrieken
De handige, directe manier om een C++/WinRT-object te maken is als volgt.
using namespace winrt::Windows::Globalization::NumberFormatting;
...
CurrencyFormatter currency{ L"USD" };
Maar het kan voorkomen dat u zelf de activeringsfabriek wilt maken en vervolgens objecten wilt maken wanneer het u uitkomt. Hier volgen enkele voorbeelden die laten zien hoe u de functiesjabloon winrt::get_activation_factory gebruikt.
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");
De klassen in de twee bovenstaande voorbeelden zijn typen uit een Windows-naamruimte. In dit volgende voorbeeld is ThermometerWRC::Thermometer een aangepast type dat is geïmplementeerd in een Windows Runtime-onderdeel.
auto factory = winrt::get_activation_factory<ThermometerWRC::Thermometer>();
ThermometerWRC::Thermometer thermometer = factory.ActivateInstance<ThermometerWRC::Thermometer>();
Dubbelzinnigheid van lid/type
Wanneer een lidfunctie dezelfde naam heeft als een type, is er dubbelzinnigheid. De regels voor het opzoeken van niet-gekwalificeerde namen in C++-lidfuncties zorgen ervoor dat eerst de klasse wordt doorzocht voordat de naamruimte wordt onderzocht. De vervangingsfout is geen fout; de (SFINAE)-regel is niet van toepassing (deze regel is van toepassing tijdens de overbelastingsresolutie van functie-templates). Dus als de naam in de klasse niet zinvol is, blijft de compiler niet op zoek naar een betere overeenkomst. Er wordt gewoon een fout gerapporteerd.
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>() };
}
}
Hierboven denkt de compiler dat u FrameworkElement.Style() (die in C++/WinRT een lidfunctie is) doorgeeft als de sjabloonparameter voor IUnknown::as. De oplossing is om af te dwingen dat de naam Style wordt geïnterpreteerd als het type 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>();
}
}
Het opzoeken van niet-gekwalificeerde namen heeft een speciale uitzondering in het geval dat de naam wordt gevolgd door ::. In dat geval worden functies, variabelen en opsommingswaarden genegeerd. Hiermee kunt u dingen als deze doen.
struct MyPage : Page
{
void DoSomething()
{
Visibility(Visibility::Collapsed); // No ambiguity here (special exception).
}
}
De aanroep van Visibility() wordt omgezet in de naam van de UIElement.Visibility lidfunctie. Maar de parameter Visibility::Collapsed volgt het woord Visibility met ::, zodat de naam van de methode wordt genegeerd en de compiler de enumklasse vindt.
Belangrijke API's
- QueryInterface-functie
- functie RoActivateInstance
- Windows::Foundation::Uri-klasse
- winrt::get_activation_factory functiesjabloon
- winrt::functiesjabloon maken
- winrt::Windows::Foundation::IUnknown struct