Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Důležité
Základní koncepty a termíny, které podporují pochopení toho, jak využívat a vytvářet třídy modulu runtime pomocí C++/WinRT, najdete v tématu Využívání rozhraní API s rozhraními C++/WinRT a Author API s C++/WinRT.
Jednou z nejvýkonnějších funkcí Windows App SDK je flexibilita, kterou sada uživatelského rozhraní (UI) poskytuje k vytváření vlastních ovládacích prvků na základě typu ovládacího prvku XAML. Architektura uživatelského rozhraní XAML poskytuje funkce, jako jsou vlastní vlastnosti závislostí a připojené vlastnosti, a šablony ovládacích prvků, které usnadňují vytváření ovládacích prvků s bohatými funkcemi a přizpůsobitelnými ovládacími prvky. Toto téma vás provede postupem vytvoření vlastního ovládacího prvku (v šabloně) pomocí C++/WinRT.
Vytvoření prázdné aplikace (BgLabelControlApp)
Začněte vytvořením nového project v Microsoft Visual Studio. Vytvořte prázdnou aplikaci, zabalenou (WinUI 3 v desktopové verzi) pro projekt C++, nastavte jeho název na BgLabelControlApp a (aby struktura složek odpovídala návodu), ujistěte se, že je nezaškrtnuté políčko Umístit řešení a projekt do stejného adresáře . Cilte na nejnovější běžně dostupnou verzi sady Windows SDK (tedy ne ve verzi Preview).
V další části tohoto tématu budete vyzváni, abyste projekt sestavili (ale do té doby ho nesestavujte).
Note
Informace o nastavení Visual Studio pro vývoj pro C++/WinRT – včetně instalace a použití rozšíření C++/WinRT Visual Studio (VSIX) a balíčku NuGet (který společně poskytuje podporu šablony projektu a sestavení) – viz Visual Studio podpora pro C++/WinRT.
Vytvoříme novou třídu, která bude představovat vlastní (šablonovaný) ovládací prvek. Třídu vytvoříme a spotřebováváme ve stejné kompilační jednotce. Chceme ale mít možnost vytvořit instanci této třídy z kódu XAML a z tohoto důvodu to bude třída modulu runtime. A k jeho vytvoření a využití použijeme C++/WinRT.
Prvním krokem při vytváření nové třídy modulu runtime je přidání nové položky souboru Midl (.idl) do projektu. Pojmenujte ho BgLabelControl.idl. Odstraňte výchozí obsah BgLabelControl.idl a vložte tuto deklaraci runtime třídy.
// BgLabelControl.idl
namespace BgLabelControlApp
{
runtimeclass BgLabelControl : Microsoft.UI.Xaml.Controls.Control
{
BgLabelControl();
static Microsoft.UI.Xaml.DependencyProperty LabelProperty{ get; };
String Label;
}
}
Výše uvedený seznam ukazuje vzor, který sledujete při deklarování vlastnosti závislosti (DP). Každý DP má dvě části. Nejprve deklarujete statickou vlastnost jen pro čtení typu DependencyProperty. Má název vašeho DP a Property. Tuto statickou vlastnost použijete ve své implementaci. Zadruhé deklarujete vlastnost instance pro čtení i zápis s typem a názvem vašeho DP. Pokud chcete vytvořit připojenou vlastnost (nikoli DP), podívejte se na příklady kódu ve vlastních připojených vlastnostech.
Note
Pokud chcete DP typu s plovoucí desetinnou čárkou, nastavte jej jako double (Double v MIDL 3.0). Deklarace a implementace DP typu float (Single v MIDL) a následné nastavení hodnoty tohoto DP ve značkách XAML má za následek chybu Nepodařilo se vytvořit prvek typu Windows.Foundation.Single z textu '<NUMBER>'.
Uložte soubor. Projekt nyní nelze úspěšně sestavit až do konce, ale přesto je užitečné ho nyní sestavit, protože se tím vygenerují soubory zdrojového kódu, ve kterých budete implementovat běhovou třídu BgLabelControl. Takže pokračujte a nyní spusťte sestavení (chyby sestavení, které můžete v této fázi očekávat, souvisejí s „unresolved external symbol“).
Během procesu sestavení se midl.exe nástroj spustí a vytvoří soubor metadat prostředí Windows Runtime (\BgLabelControlApp\Debug\BgLabelControlApp\Unmerged\BgLabelControl.winmd) popisující třídu modulu runtime. Pak se cppwinrt.exe nástroj spustí a vygeneruje soubory zdrojového kódu, které vám pomůžou s vytvářením a využíváním třídy runtime. Tyto soubory obsahují stuby, které vám pomohou začít s implementací běhové třídy BgLabelControl, kterou jste deklarovali ve svém IDL. Ty stuby jsou \BgLabelControlApp\BgLabelControlApp\Generated Files\sources\BgLabelControl.h a BgLabelControl.cpp.
Zkopírujte soubory stub BgLabelControl.h a BgLabelControl.cpp z \BgLabelControlApp\BgLabelControlApp\Generated Files\sources\ do složky projektu, tedy \BgLabelControlApp\BgLabelControlApp\. V Průzkumník řešení se ujistěte, že je zapnutá možnost Zobrazit všechny soubory. Klikněte pravým tlačítkem myši na zástupné soubory, které jste zkopírovali, a vyberte Zahrnout do projektu.
V horní části BgLabelControl.h a BgLabelControl.cpp uvidíte static_assert, které budete muset odstranit. Projekt se teď sestaví.
Implementace vlastní třídy ovládacích prvků BgLabelControl
Teď pojďme otevřít \BgLabelControlApp\BgLabelControlApp\BgLabelControl.h a BgLabelControl.cpp a implementovat naši runtime třídu. V BgLabelControl.h změňte konstruktor tak, aby nastavoval výchozí klíč stylu, implementujte Label a LabelProperty, přidejte statickou obslužnou rutinu události s názvem OnLabelChanged pro zpracování změn hodnoty vlastnosti závislosti a přidejte privátní člen pro uložení podkladového pole pro LabelProperty.
Po jejich přidání vypadá váš BgLabelControl.h takto. Tento výpis kódu můžete zkopírovat a vložit, abyste nahradili obsah souboru BgLabelControl.h.
// 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>
{
};
}
V BgLabelControl.cpp definujte statické členy takto. Tento výpis kódu můžete zkopírovat a vložit, abyste nahradili obsah souboru BgLabelControl.cpp.
// 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.
}
}
}
V tomto názorném postupu nebudeme používat OnLabelChanged. Ale je to tam proto, abyste viděli, jak zaregistrovat závislou vlastnost se zpětným voláním při změně vlastnosti. Implementace OnLabelChanged také ukazuje, jak získat odvozený projektovaný typ ze základního projektovaného typu (základní projektovaný typ je DependencyObject, v tomto případě). Ukazuje, jak pak získat ukazatel na typ, který implementuje projektovaný typ. Tato druhá operace bude přirozeně možná pouze v projektu, který implementuje projektovaný typ (to znamená projekt, který implementuje třídu runtime).
Note
Pokud nemáte nainstalovanou sadu SDK pro Windows ve verzi 10.0.17763.0 (Windows 10, verze 1809) nebo novější, musíte ve výše uvedené obsluze události změny vlastnosti závislosti volat winrt::from_abi namísto winrt::get_self.
Návrh výchozího stylu pro BgLabelControl
Ve svém konstruktoru BgLabelControl nastaví výchozí klíč stylu sobě samému. Co je ale výchozí styl? Vlastní ovládací prvek (šablonovaný) musí mít výchozí styl obsahující výchozí šablonu ovládacího prvku, kterou může použít k vykreslení v případě, že příjemce ovládacího prvku nenastaví styl nebo šablonu. V této části přidáme do projektu soubor značek obsahující náš výchozí styl.
Ujistěte se, že je Show All Files stále zapnutý (v Průzkumník řešení). V uzlu projektu vytvořte novou složku (ne filtr, ale složku) a pojmenujte ji Motivy. V části ThemesPřidejte novou položku typu Visual C++>XAML XAML>View a pojmenujte ji Generic.xaml. Názvy složek a souborů musí být podobné, aby architektura XAML našla výchozí styl vlastního ovládacího prvku. Odstraňte výchozí obsah souboru Generic.xamla vložte níže uvedené značky.
<!-- \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>
V tomto případě jedinou vlastností, kterou výchozí sady stylů nastaví, je šablona ovládacího prvku. Šablona se skládá ze čtverce (jehož pozadí je vázáno na vlastnost Background, kterou mají všechny instance typu XAML Control) a textového prvku (jehož text je vázán na vlastnost závislosti BgLabelControl::Label).
Přidání instance BgLabelControl na hlavní stránku uživatelského rozhraní
Otevřete MainPage.xaml, který obsahuje kód XAML pro naši hlavní stránku uživatelského rozhraní. Bezprostředně za button element (uvnitř StackPanel) přidejte následující kód.
<local:BgLabelControl Background="Red" Label="Hello, World!"/>
Přidejte také do MainPage.h následující direktivu include, aby typ MainPage (kombinace kompilovaného značkování XAML a imperativního kódu) rozpoznal typ vlastního ovládacího prvku BgLabelControl. Pokud chcete použít BgLabelControl z jiné stránky XAML, přidejte tuto stejnou direktivu include také do souboru záhlaví této stránky. Případně stačí do předkompilovaného hlavičkového souboru vložit jedinou direktivu include.
// MainPage.h
...
#include "BgLabelControl.h"
...
Nyní sestavte a spusťte projekt. Uvidíte, že výchozí šablona ovládacího prvku je vázána k štětci pozadí a k popisku instance BgLabelControl v markupu.
Tento názorný postup ukázal jednoduchý příklad vlastního ovládacího prvku (v šabloně) v jazyce C++/WinRT. Můžete vytvářet vlastní ovládací prvky na míru, které mohou být libovolně propracované a plně vybavené. Například vlastní ovládací prvek může mít podobu něčeho tak složitého jako upravitelná datová mřížka, přehrávač videa nebo vizualizér 3D geometrie.
Implementace přepisovatelných metod, jako jsou MeasureOverride a OnApplyTemplate
Viz část Volání a přepisování bázového typu pomocí C++/WinRT.
Důležitá rozhraní API
Příbuzná témata
Windows developer