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.
Belangrijk
Zie API's gebruiken met C++/WinRT en Author API's met C++/WinRT voor essentiële concepten en termen die ondersteuning bieden voor uw begrip van het gebruiken en schrijven van runtimeklassen met C++/WinRT.
Een van de krachtigste functies van de Windows App SDK is de flexibiliteit die de gebruikersinterfacestack (UI) biedt om aangepaste besturingselementen te maken op basis van het XAML-besturingselementtype. Het XAML UI-framework biedt functies zoals aangepaste afhankelijkheidseigenschappen en gekoppelde eigenschappen en besturingssjablonen, waarmee u eenvoudig functies met uitgebreide en aanpasbare besturingselementen kunt maken. In dit onderwerp wordt u begeleid bij de stappen voor het maken van een aangepast (sjabloon) besturingselement met C++/WinRT.
Een lege app maken (BgLabelControlApp)
Begin met het maken van een nieuw project in Microsoft Visual Studio. Maak een Lege app, verpakt (WinUI 3 voor desktop) voor een C++-project, stel de naam in op BgLabelControlApp en zorg ervoor (zodat uw mapstructuur overeenkomt met de stapsgewijze handleiding) dat Plaats oplossing en project in dezelfde map niet is aangevinkt. Richt u op de meest recente algemeen beschikbare (dus niet preview)-versie van de Windows SDK.
Later in dit onderwerp wordt u gevraagd uw project te bouwen (maar bouw het niet vóór die tijd).
Note
Zie Visual Studio support for C++/WinRT voor informatie over het configureren van Visual Studio voor C++/WinRT-ontwikkeling, waaronder het installeren en gebruiken van de C++/WinRT Visual Studio-extensie (VSIX) en het NuGet-pakket (die samen projectsjablonen en ondersteuning voor builds bieden).
We gaan een nieuwe klasse maken om een aangepast (sjabloon) besturingselement weer te geven. We ontwerpen en gebruiken de klasse binnen dezelfde compilatie-eenheid. Maar we willen deze klasse kunnen instantiëren vanuit XAML-markeringen en daarom wordt het een runtimeklasse. En we gaan C++/WinRT gebruiken om het te schrijven en te gebruiken.
De eerste stap bij het ontwerpen van een nieuwe runtimeklasse is het toevoegen van een nieuw Midl File-item (.idl) aan het project. Geef deze de naam BgLabelControl.idl. Verwijder de standaardinhoud van BgLabelControl.idl, en plak vervolgens deze declaratie van de runtimeklasse.
// BgLabelControl.idl
namespace BgLabelControlApp
{
runtimeclass BgLabelControl : Microsoft.UI.Xaml.Controls.Control
{
BgLabelControl();
static Microsoft.UI.Xaml.DependencyProperty LabelProperty{ get; };
String Label;
}
}
In de bovenstaande lijst ziet u het patroon dat u volgt bij het declareren van een afhankelijkheidseigenschap (DP). Er zijn twee onderdelen van elke DP. Eerst definieert u een alleen-leesbare statische eigenschap van het type DependencyProperty. Deze heeft de naam van uw DP plus eigenschap. U gebruikt deze statische eigenschap in uw implementatie. Ten tweede declareert u een instantie-eigenschap voor lezen en schrijven met het type en de naam van uw DP. Als u een gekoppelde eigenschap wilt maken (in plaats van een DP), raadpleegt u de codevoorbeelden in aangepaste gekoppelde eigenschappen.
Note
Als u een DP met een drijvende-kommatype wilt, maakt u deze double (Double in MIDL 3.0). Het declareren en implementeren van een DP van het type float (Single in MIDL), en vervolgens het instellen van een waarde voor die DP in XAML-opmaak, leidt tot de fout Kan geen 'Windows.Foundation.Single' maken op basis van de tekst '<NUMBER>'.
Sla het bestand op. Het project wordt momenteel niet gebouwd om te worden voltooid, maar het bouwen nu is handig omdat hiermee de broncodebestanden worden gegenereerd waarin u de BgLabelControl-runtimeklasse implementeert. Ga dus verder en bouw nu (de buildfouten die u in deze fase kunt verwachten, hebben te maken met een 'onopgeloste extern symbool').
Tijdens het buildproces wordt het midl.exe hulpprogramma uitgevoerd om een Windows Runtime metagegevensbestand (\BgLabelControlApp\Debug\BgLabelControlApp\Unmerged\BgLabelControl.winmd) te maken waarin de runtimeklasse wordt beschreven. Vervolgens wordt het hulpprogramma uitgevoerd om broncodebestanden te genereren die u ondersteunen bij het cppwinrt.exe ontwerpen en gebruiken van uw runtimeklasse. Deze bestanden bevatten stubs om u op weg te helpen met het implementeren van de BgLabelControl-runtimeklasse die u hebt gedeclareerd in uw IDL. Die stubs zijn \BgLabelControlApp\BgLabelControlApp\Generated Files\sources\BgLabelControl.h en BgLabelControl.cpp.
Kopieer de stub-bestanden BgLabelControl.h en BgLabelControl.cpp van \BgLabelControlApp\BgLabelControlApp\Generated Files\sources\ daaruit naar de projectmap.\BgLabelControlApp\BgLabelControlApp\ Zorg ervoor dat Alle bestanden weergeven is ingeschakeld in Solution Explorer. Klik met de rechtermuisknop op de stub-bestanden die u hebt gekopieerd en klik op Include In Project.
Boven aan BgLabelControl.h en BgLabelControl.cpp ziet u een static_assert, die u moet verwijderen. Nu wordt het project gebouwd.
De aangepaste besturingselementklasse BgLabelControl implementeren
Nu gaan we onze runtimeklasse openen \BgLabelControlApp\BgLabelControlApp\BgLabelControl.h en BgLabelControl.cpp implementeren. Wijzig BgLabelControl.hde constructor om de standaardstijlsleutel in te stellen, Label en LabelProperty te implementeren, een statische gebeurtenishandler met de naam OnLabelChanged toe te voegen om wijzigingen in de waarde van de afhankelijkheidseigenschap te verwerken en voeg een privélid toe om het back-upveld voor LabelProperty op te slaan.
Nadat u die hebt toegevoegd, ziet uw BgLabelControl.h er zo uit. U kunt dit codefragment kopiëren en plakken om de inhoud van BgLabelControl.h te vervangen.
// BgLabelControl.h
#pragma once
#include "BgLabelControl.g.h"
namespace winrt::BgLabelControlApp::implementation
{
struct BgLabelControl : BgLabelControlT<BgLabelControl>
{
BgLabelControl() { DefaultStyleKey(winrt::box_value(L"BgLabelControlApp.BgLabelControl")); }
winrt::hstring Label()
{
return winrt::unbox_value<winrt::hstring>(GetValue(m_labelProperty));
}
void Label(winrt::hstring const& value)
{
SetValue(m_labelProperty, winrt::box_value(value));
}
static Microsoft::UI::Xaml::DependencyProperty LabelProperty() { return m_labelProperty; }
static void OnLabelChanged(Microsoft::UI::Xaml::DependencyObject const&, Microsoft::UI::Xaml::DependencyPropertyChangedEventArgs const&);
private:
static Microsoft::UI::Xaml::DependencyProperty m_labelProperty;
};
}
namespace winrt::BgLabelControlApp::factory_implementation
{
struct BgLabelControl : BgLabelControlT<BgLabelControl, implementation::BgLabelControl>
{
};
}
Definieer in BgLabelControl.cpp de statische leden als volgt. U kunt dit codefragment kopiëren en plakken om de inhoud van BgLabelControl.cpp te vervangen.
// BgLabelControl.cpp
#include "pch.h"
#include "BgLabelControl.h"
#include "BgLabelControl.g.cpp"
namespace winrt::BgLabelControlApp::implementation
{
Microsoft::UI::Xaml::DependencyProperty BgLabelControl::m_labelProperty =
Microsoft::UI::Xaml::DependencyProperty::Register(
L"Label",
winrt::xaml_typename<winrt::hstring>(),
winrt::xaml_typename<BgLabelControlApp::BgLabelControl>(),
Microsoft::UI::Xaml::PropertyMetadata{ winrt::box_value(L"default label"), Microsoft::UI::Xaml::PropertyChangedCallback{ &BgLabelControl::OnLabelChanged } }
);
void BgLabelControl::OnLabelChanged(Microsoft::UI::Xaml::DependencyObject const& d, Microsoft::UI::Xaml::DependencyPropertyChangedEventArgs const& /* e */)
{
if (BgLabelControlApp::BgLabelControl theControl{ d.try_as<BgLabelControlApp::BgLabelControl>() })
{
// Call members of the projected type via theControl.
BgLabelControlApp::implementation::BgLabelControl* ptr{ winrt::get_self<BgLabelControlApp::implementation::BgLabelControl>(theControl) };
// Call members of the implementation type via ptr.
}
}
}
In deze procedure gebruiken we OnLabelChanged niet. Maar het staat er zodat u kunt zien hoe u een afhankelijkheidseigenschap registreert met een callback voor eigenschapswijzigingen. De implementatie van OnLabelChanged laat ook zien hoe u een afgeleid projected type kunt verkrijgen van een geprojecteerd basistype (het geprojecteerde basistype is DependencyObject, in dit geval). En het laat zien hoe u vervolgens een aanwijzer kunt verkrijgen naar het type dat het verwachte type implementeert. Deze tweede bewerking is natuurlijk alleen mogelijk in het project dat het verwachte type implementeert (dat wil gezegd het project dat de runtimeklasse implementeert).
Note
Als u de Windows SDK-versie 10.0.17763.0 (Windows 10, versie 1809), of een latere versie, niet hebt geïnstalleerd, moet u winrt::from_abi aanroepen in de eventhandler voor wijzigingen van de afhankelijkheidseigenschap hierboven, in plaats van winrt::get_self.
De standaardstijl voor BgLabelControl ontwerpen
In zijn constructor stelt BgLabelControl een standaard stijlsleutel voor zichzelf in. Maar wat is een standaardstijl? Een aangepast (sjabloon) besturingselement moet een standaardstijl hebben, die een standaardsjabloon voor besturingselementen bevat, die kan worden gebruikt om zichzelf weer te geven als de consument van het besturingselement geen stijl en/of sjabloon instelt. In deze sectie voegen we een opmaakbestand toe aan het project met de standaardstijl.
Zorg ervoor dat Alle bestanden weergeven nog steeds is ingeschakeld (in Solution Explorer). Maak onder het projectknooppunt een nieuwe map (niet een filter, maar een map) en geef deze de naam Thema's. Voeg onder ThemesEen nieuw item van het type Visual C++>XAML XAML-weergave> toe en geef het de naam 'Generic.xaml'. De map- en bestandsnamen moeten zo zijn, zodat het XAML-framework de standaardstijl voor een aangepast besturingselement kan vinden. Verwijder de standaardinhoud van Generic.xamlen plak de onderstaande markeringen.
<!-- \Themes\Generic.xaml -->
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:BgLabelControlApp">
<Style TargetType="local:BgLabelControl" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:BgLabelControl">
<Grid Width="100" Height="100" Background="{TemplateBinding Background}">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{TemplateBinding Label}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
In dit geval is de besturingssjabloon de enige eigenschap die door de standaardstijl wordt ingesteld. De sjabloon bestaat uit een vierkant (waarvan de achtergrond is gebonden aan de eigenschap Achtergrond die alle exemplaren van het type XAML-besturingselement hebben) en een tekstelement (waarvan de tekst is gebonden aan de eigenschap BgLabelControl::Labelafhankelijkheid).
Een exemplaar van BgLabelControl toevoegen aan de hoofdpagina van de gebruikersinterface
Open MainPage.xaml, die de XAML-opmaak voor onze hoofdgebruikersinterfacepagina bevat. Voeg direct na het -knop-element (in het StackPanel) de volgende markupcode toe.
<local:BgLabelControl Background="Red" Label="Hello, World!"/>
Voeg ook de volgende include-instructie toe aan MainPage.h, zodat het type MainPage (een combinatie van gecompileerde XAML-opmaak en imperatieve code) bekend is met het aangepaste besturingselement BgLabelControl. Als u BgLabelControl- wilt gebruiken vanaf een andere XAML-pagina, voegt u deze instructie ook toe aan het headerbestand voor die pagina. U kunt ook een enkele insluitingsrichtlijn in uw vooraf gecompileerde headerbestand plaatsen.
// MainPage.h
...
#include "BgLabelControl.h"
...
Bouw nu het project en voer het uit. U ziet dat de standaardsjabloon voor besturingselementen is gekoppeld aan het achtergrondpenseel en aan het label van de BgLabelControl instantie in de mark-up.
In deze stapsgewijze uitleg werd een eenvoudig voorbeeld getoond van een aangepast besturingselement op basis van een sjabloon in C++/WinRT. U kunt uw eigen aangepaste besturingselementen willekeurig uitgebreid en volledig maken. Een aangepast besturingselement kan bijvoorbeeld de vorm aannemen van iets dat zo ingewikkeld is als een bewerkbaar gegevensraster, een videospeler of een visualisatie van 3D-geometrie.
Overschrijfbare methoden implementeren, zoals MeasureOverride en OnApplyTemplate
Zie de sectie in Bellen en overschrijven van uw basistype met C++/WinRT.
Belangrijke API's
Verwante onderwerpen
Windows developer