Sdílet prostřednictvím


Zpracování řetězců v C++/WinRT

Pomocí C++/WinRTmůžete volat Windows Runtime API pomocí typů širokých řetězců standardní knihovny C++, jako je std::wstring (poznámka: ne s úzkými typy řetězců, jako je std::string). C++/WinRT má vlastní typ řetězce s názvem winrt::hstring (definovaný v základní knihovně C++/WinRT, což je %WindowsSdkDir%Include\<WindowsTargetPlatformVersion>\cppwinrt\winrt\base.h). A to je typ řetězce, který ve skutečnosti přebírají a vrací konstruktory, funkce a vlastnosti prostředí Windows Runtime. "Díky konverzním konstruktorům a konverzním operátorům hstringse ale mnoho případů můžete rozhodnout, zda chcete být povědomi o hstring ve vašem klientském kódu." Pokud rozhraní API pro vytváření, budete pravděpodobně potřebovat vědět o hstring.

V jazyce C++ existuje mnoho typů řetězců. Varianty existují v mnoha knihovnách kromě std::basic_string ze standardní knihovny C++. C++17 má nástroje pro převod řetězců, jako je std::basic_string_view, aby překonaly rozdíly mezi všemi typy řetězců. winrt::hstring poskytuje konvertibilitu s std::wstring_view, což umožňuje interoperabilitu, pro kterou byla std::basic_string_view navržena.

Použití std::wstring (a volitelně winrt::hstring) s identifikátorem URI

Windows::Foundation::Uri je vytvořen z winrt::hstring.

public:
    Uri(winrt::hstring uri) const;

Ale hstringkonverzní konstruktory, které vám umožňují s ním pracovat, aniž byste si toho museli být vědomi. Tady je příklad kódu, který ukazuje, jak vytvořit identifikátor URI ze širokého řetězcového literálu, ze širokého zobrazení řetězců a z std::wstring.

#include <winrt/Windows.Foundation.h>
#include <string_view>

using namespace winrt;
using namespace Windows::Foundation;

int main()
{
    using namespace std::literals;

    winrt::init_apartment();

    // You can make a Uri from a wide string literal.
    Uri contosoUri{ L"http://www.contoso.com" };

    // Or from a wide string view.
    Uri contosoSVUri{ L"http://www.contoso.com"sv };

    // Or from a std::wstring.
    std::wstring wideString{ L"http://www.adventure-works.com" };
    Uri awUri{ wideString };
}

Přístupový objekt vlastnosti Uri::Domain je typu hstring.

public:
    winrt::hstring Domain();

Ale opět si uvědomte, že podrobnosti jsou volitelné díky hstringoperátor převodu na std::wstring_view.

// Access a property of type hstring, via a conversion operator to a standard type.
std::wstring domainWstring{ contosoUri.Domain() }; // L"contoso.com"
domainWstring = awUri.Domain(); // L"adventure-works.com"

// Or, you can choose to keep the hstring unconverted.
hstring domainHstring{ contosoUri.Domain() }; // L"contoso.com"
domainHstring = awUri.Domain(); // L"adventure-works.com"

Podobně IStringable::ToString vrátí hstring .

public:
    hstring ToString() const;

identifikátor URI implementuje rozhraní IStringable.

// Access hstring's IStringable::ToString, via a conversion operator to a standard type.
std::wstring tostringWstring{ contosoUri.ToString() }; // L"http://www.contoso.com/"
tostringWstring = awUri.ToString(); // L"http://www.adventure-works.com/"

// Or you can choose to keep the hstring unconverted.
hstring tostringHstring{ contosoUri.ToString() }; // L"http://www.contoso.com/"
tostringHstring = awUri.ToString(); // L"http://www.adventure-works.com/"

Pomocí funkce hstring::c_str můžete získat standardní široký řetězec z hstring (stejně jako z std::wstring).

#include <iostream>
std::wcout << tostringHstring.c_str() << std::endl;

Pokud máte hstring, můžete z něj vytvořit identifikátor URI.

Uri awUriFromHstring{ tostringHstring };

Zvažte metodu, která přebírá hstring.

public:
    Uri CombineUri(winrt::hstring relativeUri) const;

Všechny možnosti, které jste právě viděli, platí i v takových případech.

std::wstring contact{ L"contact" };
contosoUri = contosoUri.CombineUri(contact);
    
std::wcout << contosoUri.ToString().c_str() << std::endl;

operátor převodu std::wstring_view člen a převod se dosahuje bez nákladů.

void legacy_print(std::wstring_view view);

void Print(winrt::hstring const& hstring)
{
    legacy_print(hstring);
}

winrt::hstring funkce a operátory

Množství konstruktorů, operátorů, funkcí a iterátorů je implementováno pro winrt::hstring.

hstring je rozsah, takže ho můžete použít s rozsahově založenými fornebo s std::for_each. Poskytuje také relační operátory pro přirozené a efektivní porovnávání se svými protějšky ve standardní knihovně C++. A to zahrnuje vše, co potřebujete použít hstring jako klíč pro asociativní kontejnery.

Uvědomujeme si, že mnoho knihoven C++ používá std::string a pracuje výhradně s textem UTF-8. Jako usnadnění poskytujeme pomocné rutiny, jako jsou winrt::to_string a winrt::to_hstring, pro převod tam a zpět.

WINRT_ASSERT je makro definice a rozbalí se na _ASSERTE.

winrt::hstring w{ L"Hello, World!" };

std::string c = winrt::to_string(w);
WINRT_ASSERT(c == "Hello, World!");

w = winrt::to_hstring(c);
WINRT_ASSERT(w == L"Hello, World!");

Další příklady a informace o funkcích a operátorech hstring najdete v referenčním tématu k rozhraní API winrt::hstring .

Odůvodnění winrt::hstring a winrt::param::hstring

Prostředí Windows Runtime se implementuje z hlediska wchar_t znaků, ale binární rozhraní ABI (Application Binary Interface) prostředí Windows Runtime není podmnožinou toho, co poskytují buď std::wstring nebo std::wstring_view. Použití těch by vedlo k významné neefektivitě. Místo toho jazyk C++/WinRT poskytuje winrt::hstring, který představuje neměnný řetězec konzistentní s podkladovým HSTRINGa implementovaný prostřednictvím rozhraní podobným rozhraní jako je std::wstring.

Můžete si všimnout, že vstupní parametry C++/WinRT, které by měly logicky přijímat winrt::hstring, skutečně očekávají winrt::param::hstring. param jmenný prostor obsahuje sadu typů používaných výhradně k optimalizaci vstupních parametrů, aby se přirozeně vazovaly na typy standardní knihovny C++ a zabránilo se kopiím a dalším neefektivnostem. Tyto typy byste neměli používat přímo. Pokud chcete použít optimalizaci pro vlastní funkce, použijte std::wstring_view. Viz také Předávání parametrů do rozhraní ABI.

Výsledek je ten, že můžete do značné míry ignorovat specifika správy řetězců ve Windows Runtime a efektivně pracovat s tím, co znáte. A to je důležité, vzhledem k tomu, jak silně se řetězce používají v prostředí Windows Runtime.

Formátování řetězců

Jednou z možností pro formátování řetězců je std::wostringstream. Tady je příklad, který formátuje a zobrazuje jednoduchou zprávu trasování ladění.

#include <sstream>
#include <winrt/Windows.UI.Input.h>
#include <winrt/Windows.UI.Xaml.Input.h>
...
void MainPage::OnPointerPressed(winrt::Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e)
{
    winrt::Windows::Foundation::Point const point{ e.GetCurrentPoint(nullptr).Position() };
    std::wostringstream wostringstream;
    wostringstream << L"Pointer pressed at (" << point.X << L"," << point.Y << L")" << std::endl;
    ::OutputDebugString(wostringstream.str().c_str());
}

Správný způsob nastavení vlastnosti

Vlastnost nastavíte předáním hodnoty funkci setter. Tady je příklad.

// The right way to set the Text property.
myTextBlock.Text(L"Hello!");

Níže uvedený kód je nesprávný. Kompiluje se, ale vše, co dělá, je upravit dočasnou winrt::hstring vrácenou přístupovou funkcí Text(), a pak výsledek vyhodit.

// *Not* the right way to set the Text property.
myTextBlock.Text() = L"Hello!";

Důležitá rozhraní API