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 nieuw Windows Console Application-project (C++/WinRT) te maken en code te kopiëren en plakken. U kunt echter niet zomaar willekeurige aangepaste Windows Runtime-typen van derden gebruiken vanuit een app zonder pakket. U kunt op die manier alleen typen uit Windows gebruiken.
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 Project voor meer informatie.
U kunt ook een nieuw project maken op basis van de projectsjablonen Blank App, Packaged (WinUI 3 in Desktop) voor C++ of Windows Runtime Component (C++/WinRT). 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++-beschrijvend equivalent (het verwachte type genoemd). 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 wilt kopiëren en plakken in het hoofdbroncodebestand van een Windows Console Application (C++/WinRT)-project, stelt u dan eerst Voorgecompileerde headers niet gebruiken in bij de projecteigenschappen.
// 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 meegeleverde 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, wat het geprojecteerde type is voor de runtimeklasse Windows::Foundation::Uri.
Hint
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 instructies zijn optioneel, maar handig.
In het bovenstaande codevoorbeeld plaatsen we, na het initialiseren van C++/WinRT, een waarde van het geprojecteerde type winrt::Windows::Foundation::Uri op de stack via een van de publiek gedocumenteerde constructors (Uri(String), in dit voorbeeld). Hiervoor, in dit meest voorkomende geval, is dat meestal alles wat u hoeft te doen. Zodra u een C++/WinRT-typewaarde hebt, kunt u deze behandelen alsof het een exemplaar van het werkelijke Windows Runtime type is, omdat deze 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(s) van de geprojecteerde waarde roepen RoActivateInstance aan om een exemplaar van de onderliggende 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 verwachte waarde daadwerkelijk gedelegeerd via de slimme aanwijzer naar het backing-object; dit is waar statuswijzigingen optreden.
Wanneer de contosoUri waarde buiten scope raakt, wordt deze vernietigd en geeft deze de verwijzing naar de standaardinterface vrij. Als die verwijzing de laatste verwijzing is naar het onderliggende Windows Runtime-object Windows.Foundation.Uri, wordt ook het onderliggende object vernietigd.
Hint
Een geprojecteerd type is een omhulsel rond een Windows Runtime-type om de API's ervan te gebruiken. Een geprojecteerde interface is bijvoorbeeld een wrapper om een Windows Runtime-interface.
C++/WinRT-projectieheaders
Als u Windows naamruimte-API's uit C++/WinRT wilt gebruiken, neemt u headers uit de %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt map op. 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. Inclusief deze header geeft u toegang tot alle typen in de Windows::Security::Cryptography::Certificates-naamruimte.
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 de vereiste naamruimteheaders toe te voegen voordat u typen in die naamruimte gebruikt, is een veelvoorkomende oorzaak van buildfouten.
Toegang krijgen tot leden 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 het gemak kunt u programmeren met klassen zoals de auteur het bedoeld heeft. U kunt bijvoorbeeld de ToString-methode van een URI aanroepen alsof dat een methode van de klasse was (in feite is het onder de dekking 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 verkrijgt u tijdens de uitvoering een daadwerkelijke IStringable-interfacepointer (via een eenmalige opvraging). Daarna is uw aanroep naar ToString direct en voorkomt u verdere aanroep van 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 en er meer details en codevoorbeelden zijn 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 die, zorgen alle projected-type constructors, inclusief de standaardconstructor, ervoor dat een back-up 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 hiermee een backing Windows Runtime object wordt gemaakt (zodat u dat werk tot later kunt vertragen), 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 van het geprojecteerde type behalve de std::nullptr_t-constructor leiden ertoe dat een onderliggend 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 het volgende codevoorbeeld; hiervoor hebt u een Blank App, Packaged (WinUI 3 op desktop)-project voor C++ nodig.
std::map<int, TextBlock> lookup;
lookup[2] = value;
De opdracht maakt een nieuw 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.
Initialiseer niet per ongeluk te laat
Wees voorzichtig dat u de std::nullptr_t constructor niet per ongeluk aanroept. De conflictoplossing van de compiler geeft daaraan voorrang 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 cadeau willen maken dat zich niet in een doos bevindt (een cadeau dat is samengesteld 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 als parameter neemt. Maar als we in de verleiding komen om een null-GiftBox door te geven (waarbij we de constructor van Gift aanroepen via uniforme initialisatie, zoals we hieronder doen), dan krijgen we niet het resultaat dat we willen.
// 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 cadeau. Je krijgt geen cadeau met een ongeïnitialiseerde GiftBox. 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 bij het doorgeven van een nullptr letterlijke waarde gekozen voor de constructor voor uitgestelde initialisatie. Om dit op te lossen ten gunste van de fabrieksconstructor, moet het type parameter een GiftBox zijn. U kunt nog steeds een expliciet vertraagd geïnitialiseerde GiftBox doorgeven, zoals in het juiste voorbeeld wordt getoond.
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 u een nullptr letterlijke waarde doorgeeft, ontstaat de dubbelzinnigheid.
Kopieconstrueer niet per ongeluk.
Deze waarschuwing is vergelijkbaar met de waarschuwing die hierboven is beschreven in de sectie Initialiseer niet per ongeluk te laat.
Naast de constructor voor uitgestelde initialisatie voegt de C++/WinRT-projectie ook een kopieerconstructor toe aan elke runtime-klasse. Het is een constructor met één parameter die hetzelfde type accepteert als het object dat wordt gemaakt. De resulterende slimme aanwijzer verwijst naar dezelfde 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 maken in 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 correcte manier om dit te doen is de activeringsfabriek 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.
Note
Zie Visual Studio support for C++/WinRT voor informatie over het installeren en gebruiken van de Visual Studio-extensie (VSIX) en het NuGet-pakket voor C++/WinRT, die samen projectsjablonen en ondersteuning voor builds bieden.
Raadpleeg in uw toepassingsproject het bestand Windows Runtime metagegevens (.winmd) van het Windows Runtime-onderdeel en bouw. Tijdens de build genereert het cppwinrt.exe hulpprogramma een standaard C++-bibliotheek die het API-gebied voor het onderdeel volledig beschrijft( of projecten). Met andere woorden, de gegenereerde bibliotheek bevat de verwachte typen voor het onderdeel.
Vervolgens neemt u, net als bij een type in een Windows-naamruimte, een headerbestand op en construeert u het geprojecteerde type via een van de 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 : AppT<App>
{
ThermometerWRC::Thermometer thermometer;
...
};
Zie Windows Runtime onderdelen met C++/WinRT en Author-gebeurtenissen in C++/WinRT voor meer informatie, code en een overzicht van het gebruik van API's die zijn geïmplementeerd in een Windows Runtime-onderdeel.
Als de API is geïmplementeerd in het verbruikende project
Het codevoorbeeld in deze sectie is afkomstig uit het onderwerp XAML-besturingselementen; bind met 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 geprojecteerd type uit de Windows Runtime-metadata (.winmd) van de runtimeklasse. Nogmaals, u neemt een headerbestand op, maar vervolgens hebt u de keuze tussen de manier van C++/WinRT versie 1.0 of die van versie 2.0 om een exemplaar van de runtime-klasse te construeren. 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.
Samenstellen met behulp 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 construeert het geprojecteerde type via de std::nullptr_t-constructor. Deze constructor voert geen initialisatie uit, dus u moet vervolgens een waarde aan het exemplaar toewijzen via de winrt::make helper-functie, waarbij eventuele benodigde constructorargumenten worden doorgegeven. Een runtimeklasse die is geïmplementeerd in hetzelfde project als de verbruikende code hoeft niet te worden geregistreerd en hoeft niet te worden geïnstantieerd via Windows Runtime/COM-activering.
Zie XAML-besturingselementen; bind aan een C++/WinRT-eigenschap voor een volledig overzicht. In dit gedeelte ziet u fragmenten uit die stapsgewijze handleiding.
// 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>();
...
}
Uniforme constructie
Met C++/WinRT versie 2.0 en hoger is er een geoptimaliseerde vorm van constructie beschikbaar voor u, bekend als uniforme constructie (zie Nieuws en wijzigingen, in C++/WinRT 2.0).
Zie XAML-besturingselementen; bind aan een C++/WinRT-eigenschap voor een volledig overzicht. In deze sectie worden fragmenten uit die stapsgewijze uitleg getoond.
Als u uniforme initialisatie wilt gebruiken in plaats van winrt::make, hebt u een activatiefactory 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 : Microsoft.UI.Xaml.Controls.Page
{
MainPage();
BookstoreViewModel MainViewModel{ get; };
}
}
MainPage.h Declareer en initialiseer vervolgens m_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 Aanmelden voor uniforme constructie en directe implementatietoegang voor 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, IStringable en IClosable. In dit onderwerp ziet u de verschillende manieren waarop u een geprojecteerd type kunt instantiëren. Hier volgt een herinnering en samenvatting, waarbij MyRuntimeClass als voorbeeld wordt gebruikt.
// 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 teruggeven aan de aanroeper.
- Geprojecteerde typen en interfaces zijn afgeleid van winrt::Windows::Foundation::IUnknown. Dus kunt u IUnknown::as aanroepen op een geprojecteerd type of een interface om andere geprojecteerde interfaces op te vragen, die u vervolgens kunt gebruiken of aan een aanroeper kunt retourneren. De functie as member 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 soms wilt u de activeringsfabriek zelf maken en er vervolgens objecten van 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 bovenstaande twee voorbeelden zijn typen uit een Windows naamruimte. In dit volgende voorbeeld is ThermometerWRC::Thermometer een aangepast type 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 lidfuncties van C++ zorgen ervoor dat eerst in de klasse wordt gezocht voordat in naamruimten wordt gezocht. De vervangingsfout is geen foutregel (SFINAE) is niet van toepassing (deze is van toepassing tijdens overbelastingsresolutie van functiesjablonen). 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() doorgeeft (die in C++/WinRT een lidfunctie is) als de sjabloonparameter voor IUnknown::as. De oplossing is om af te dwingen dat de naam Style wordt geïnterpreteerd als het type 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>();
}
}
Niet-gekwalificeerde naamzoekactie heeft een speciale uitzondering in het geval dat de naam wordt gevolgd door ::, in welk geval functies, variabelen en opsommingswaarden worden 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 lidfunctie UIElement.Visibility. Maar de parameter Visibility::Collapsed volgt het woord Visibility met ::, en dus wordt de methodenaam genegeerd, en de compiler vindt de enum-klasse.
Belangrijke API's
- QueryInterface-functie
- RoActivateInstance-functie
- Windows::Foundation::Uri-klasse
- winrt::get_activation_factory functiesjabloon
- winrt::functiesjabloon maken
- winrt::Windows::Foundation::IUnknown struct
Verwante onderwerpen
Windows developer