Verwerking van tekenreeksen in C++/WinRT

Met C++/WinRT kunt u Windows Runtime API's aanroepen met C++ Standard Library wide string types, zoals std::wstring (opmerking: niet met smalle tekenreekstypen zoals std::string). C++/WinRT heeft inderdaad een aangepast stringtype genaamd winrt::hstring (gedefinieerd in de C++/WinRT-basisbibliotheek, namelijk %WindowsSdkDir%Include\<WindowsTargetPlatformVersion>\cppwinrt\winrt\base.h). En dat is het tekenreekstype dat Windows Runtime constructors, functies en eigenschappen daadwerkelijk overnemen en retourneren. Maar in veel gevallen, dankzij de conversieconstructors en conversieoperators van hstring, kunt u kiezen of u al dan niet op de hoogte wilt zijn van hstring in uw clientcode. Als u API's ontwerpt , moet u waarschijnlijk meer weten over hstring.

Er zijn veel tekenreekstypen in C++. Er bestaan varianten in veel bibliotheken naast std::basic_string uit de C++-standaardbibliotheek. C++17 heeft hulpprogramma's voor tekenreeksconversie en std::basic_string_view om de hiaten tussen alle tekenreekstypen te overbruggen. winrt::hstring biedt conversiemogelijkheden met std::wstring_view om de interoperabiliteit te bieden waarvoor std::basic_string_view is ontworpen.

Std::wstring gebruiken (en optioneel winrt::hstring) met Uri

Windows::Foundation::Uri wordt samengesteld op basis van een winrt::hstring.

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

Maar hstring heeft conversieconstructeurs waarmee u ermee kunt werken zonder dat u zich daar bewust van hoeft te zijn. Hier volgt een codevoorbeeld waarin wordt getoond hoe u een URI maakt op basis van een letterlijke tekenreeks, vanuit een brede tekenreeksweergave en vanuit een 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 };
}

De eigenschapstoegangsfunctie Uri::D omain is van het type hstring.

public:
    winrt::hstring Domain();

Maar nogmaals, het is niet nodig om van dat detail op de hoogte te zijn dankzij de conversieoperator van hstring naar 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"

Op dezelfde manier retourneert IStringable::ToString de hstring .

public:
    hstring ToString() const;

Uri implementeert de IStringable-interface .

// 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/"

U kunt de functie hstring::c_str gebruiken om een standaard brede tekenreeks op te halen uit een hstring (net zoals u dat kunt met een std::wstring).

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

Als u een hstring hebt, kunt u er een URI van maken.

Uri awUriFromHstring{ tostringHstring };

Overweeg een methode die een hstring gebruikt.

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

Alle opties die u zojuist hebt gezien, zijn ook van toepassing in dergelijke gevallen.

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

hstring heeft een lid std::wstring_view conversieoperator en de conversie wordt zonder kosten bereikt.

void legacy_print(std::wstring_view view);

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

functies en operatoren van winrt::hstring

Een host van constructors, operators, functies en iterators worden geïmplementeerd voor winrt::hstring.

Een hstring is een range, dus u kunt deze gebruiken in een op ranges gebaseerde for, of met std::for_each. Het biedt ook vergelijkingsoperatoren voor natuurlijke en efficiënte vergelijkingen met de tegenhangers in de C++ Standard-bibliotheek. En het bevat alles wat u nodig hebt om hstring te gebruiken als sleutel voor associatieve containers.

We herkennen dat veel C++-bibliotheken gebruikmaken van std::string en exclusief werken met UTF-8-tekst. Als gemak bieden we helpers, zoals winrt::to_string en winrt::to_hstring, om heen en weer te converteren.

WINRT_ASSERT is een macrodefinitie en wordt uitgebreid naar _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!");

Zie het naslagonderwerp winrt::hstring-API voor meer voorbeelden en informatie over hstring-functies en operators.

De beweegreden achter winrt::hstring en winrt::param::hstring

De Windows Runtime wordt geïmplementeerd in termen van wchar_t tekens, maar de ABI (Application Binary Interface) van de Windows Runtime is geen subset van wat std::wstring of std::wstring_view bieden. Het gebruik van deze zou leiden tot aanzienlijke inefficiëntie. In plaats daarvan biedt C++/WinRT winrt::hstring, die een onveranderbare tekenreeks vertegenwoordigt die consistent is met de onderliggende HSTRING, en die wordt geïmplementeerd achter een interface die vergelijkbaar is met die van std::wstring.

Het valt u misschien op dat C++/WinRT-invoerparameters die logischerwijs winrt::hstring zouden moeten accepteren, in werkelijkheid winrt::param::hstring verwachten. De parameternaamruimte bevat een set typen die uitsluitend worden gebruikt om invoerparameters te optimaliseren om op natuurlijke wijze te binden aan C++ Standaardbibliotheektypen en kopieën en andere inefficiënties te voorkomen. U mag deze typen niet rechtstreeks gebruiken. Als u een optimalisatie wilt gebruiken voor uw eigen functies, gebruikt u std::wstring_view. Zie ook Parameters doorgeven over de ABI-grens.

Kortom, je kunt de specifieke details van het beheer van tekenreeksen in Windows Runtime grotendeels negeren en gewoon efficiënt werken met wat je al kent. En dat is belangrijk, gezien hoe veelvuldig tekenreeksen worden gebruikt in de Windows Runtime.

Opmaak van tekenreeksen

Eén optie voor tekenreeksopmaak is std::wostringstream. Hier is een voorbeeld dat een eenvoudig foutopsporingsbericht opmaakt en weergeeft.

#include <sstream>
#include <winrt/Microsoft.UI.Input.h>
#include <winrt/Microsoft.UI.Xaml.Input.h>
...
void MainPage::OnPointerPressed(winrt::Microsoft::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());
}

De juiste manier om een eigenschap in te stellen

U stelt een eigenschap in door een waarde door te geven aan een setterfunctie. Dit is een voorbeeld.

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

De onderstaande code is onjuist. Het compileert, maar het enige wat het doet is om de tijdelijke winrt::hstring te wijzigen die wordt geretourneerd door de functie Text() accessor en vervolgens het resultaat weg te gooien.

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

Belangrijke API's