Processamento da cadeia de caracteres em C++/WinRTString handling in C++/WinRT

Com o C++/WinRT é possível chamar APIs do Windows Runtime usando tipos de cadeia de caracteres longa da Biblioteca padrão de C++, como std::wstring (observação: mas não com tipos de cadeia de caracteres curta, como std::string).With C++/WinRT, you can call Windows Runtime APIs using C++ Standard Library wide string types such as std::wstring (note: not with narrow string types such as std::string). O C++/WinRT tem um tipo de cadeia de caracteres personalizado chamado winrt::hstring (definido na biblioteca de C++/WinRT, que é %WindowsSdkDir%Include\<WindowsTargetPlatformVersion>\cppwinrt\winrt\base.h).C++/WinRT does have a custom string type called winrt::hstring (defined in the C++/WinRT base library, which is %WindowsSdkDir%Include\<WindowsTargetPlatformVersion>\cppwinrt\winrt\base.h). Esse é o tipo de cadeia de caracteres que construtores, funções e propriedades do Windows Runtime podem usar e retornar.And that's the string type that Windows Runtime constructors, functions, and properties actually take and return. Porém, em muitos casos, graças aos construtores e operadores de conversão de hstring, é possível optar se deseja ou não estar ciente de hstring no código cliente.But in many cases—thanks to hstring's conversion constructors and conversion operators—you can choose whether or not to be aware of hstring in your client code. Se você estiver criando APIs, provavelmente precisará saber sobre a existência de hstring.If you're authoring APIs, then you're more likely to need to know about hstring.

Existem muitos tipos de cadeia de caracteres em C++.There are many string types in C++. Existem variantes em muitas bibliotecas além de std::basic_string na Biblioteca padrão de C++.Variants exist in many libraries in addition to std::basic_string from the C++ Standard Library. O C++17 tem utilitários de conversão de cadeia de caracteres e std::basic_string_view para preencher a lacuna entre todos os tipos de cadeia de caracteres.C++17 has string conversion utilities, and std::basic_string_view, to bridge the gaps between all of the string types. winrt::hstring fornece conversibilidade com std::wstring_view para fornecer a interoperabilidade para a qual std::basic_string_view foi projetado.winrt::hstring provides convertibility with std::wstring_view to provide the interoperability that std::basic_string_view was designed for.

Usar std::wstring (e, opcionalmente, winrt::hstring) com UriUsing std::wstring (and optionally winrt::hstring) with Uri

Windows::Foundation::Uri é construído a partir de um winrt::hstring.Windows::Foundation::Uri is constructed from a winrt::hstring.

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

Entretanto, hstring tem construtores de conversão que permitem usá-lo sem precisar estar ciente dele.But hstring has conversion constructors that let you work with it without needing to be aware of it. Este é um exemplo de código que mostra como criar um Uri a partir de um literal de cadeia de caracteres longa, de um modo de exibição de cadeia de caracteres longa e de um std::wstring.Here's a code example showing how to make a Uri from a wide string literal, from a wide string view, and from a 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 };
}

O acessador de propriedade Uri::Domain é do tipo hstring.The property accessor Uri::Domain is of type hstring.

public:
    winrt::hstring Domain();

Lembrando que estar ciente desse detalhe é opcional, graças ao operador de conversão de hstring para std::wstring_view.But, again, being aware of that detail is optional thanks to hstring's conversion operator to 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"

Da mesma forma, IStringable::ToString retorna hstring.Similarly, IStringable::ToString returns hstring.

public:
    hstring ToString() const;

Uri implementa a interface IStringable.Uri implements the 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/"

Use a função hstring::c_str para obter uma cadeia de caracteres longa padrão a partir de um hstring (assim como se faz em um std::wstring).You can use the hstring::c_str function to get a standard wide string from an hstring (just as you can from a std::wstring).

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

Se houver um hstring,será possível criar um Uri a partir dele.If you have an hstring then you can make a Uri from it.

Uri awUriFromHstring{ tostringHstring };

Considere um método que use um hstring.Consider a method that takes an hstring.

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

Todas as opções que você acabou de ver também se aplicam a esses casos.All of the options you've just seen also apply in such cases.

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

hstring tem um operador de conversão std::wstring_view de membro; a conversão é realizada sem custo adicional.hstring has a member std::wstring_view conversion operator, and the conversion is achieved at no cost.

void legacy_print(std::wstring_view view);

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

Operadores e funções winrt::hstringwinrt::hstring functions and operators

Uma série de construtores, operadores, funções e iteradores são implementados para winrt::hstring.A host of constructors, operators, functions, and iterators are implemented for winrt::hstring.

Um hstring é um intervalo, portanto, use-o com for baseado em intervalo ou com std::for_each.An hstring is a range, so you can use it with range-based for, or with std::for_each. Ele também fornece operadores de comparação para fazer uma comparação com naturalidade e eficiência de seus equivalentes na Biblioteca padrão do C++.It also provides comparison operators for naturally and efficiently comparing against its counterparts in the C++ Standard Library. Ele contém tudo o que você precisa para usar o hstring como uma chave para contêineres associativos.And it includes everything you need to use hstring as a key for associative containers.

Reconhecemos que várias bibliotecas do C++ usam std::string e trabalham exclusivamente com textos em UTF-8.We recognize that many C++ libraries use std::string, and work exclusively with UTF-8 text. Como uma conveniência, fornecemos auxiliares, como winrt::to_string e winrt::to_hstring, para converter em ambas as direções.As a convenience, we provide helpers, such as winrt::to_string and winrt::to_hstring, for converting back and forth.

WINRT_ASSERT é uma definição de macro e se expande para _ASSERTE.WINRT_ASSERT is a macro definition, and it expands to _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!");

Para obter mais exemplos e saber mais sobre funções e operadores de hstring, confira o tópico de referência de API winrt::hstring.For more examples and info about hstring functions and operators, see the winrt::hstring API reference topic.

A lógica de winrt::hstring e winrt::param::hstringThe rationale for winrt::hstring and winrt::param::hstring

O Windows Runtime é implementado em termos de caracteres wchar_t, mas a Interface Binária de Aplicativo (ABI) do Windows Runtime não é um subconjunto do que std::wstring ou std::wstring_view fornece.The Windows Runtime is implemented in terms of wchar_t characters, but the Windows Runtime's Application Binary Interface (ABI) is not a subset of what either std::wstring or std::wstring_view provide. O uso deles resultaria em uma ineficiência significativa.Using those would lead to significant inefficiency. Ao invés disso, o C++/WinRT fornece winrt::hstring, que representa uma cadeia de caracteres imutável consistente com o HSTRING subjacente e implementado por trás de uma interface semelhante à de std::wstring.Instead, C++/WinRT provides winrt::hstring, which represents an immutable string consistent with the underlying HSTRING, and implemented behind an interface similar to that of std::wstring.

Você pode perceber que os parâmetros de entrada do C++/WinRT que logicamente devem aceitar winrt::hstring esperam, na verdade, winrt::param::hstring.You may notice that C++/WinRT input parameters that should logically accept winrt::hstring actually expect winrt::param::hstring. O namespace param contém um conjunto de tipos usado exclusivamente para otimizar os parâmetros de entrada a fim de fazer a associação natural a tipos da Biblioteca padrão do C++ e evitar cópias e outras ineficiências.The param namespace contains a set of types used exclusively to optimize input parameters to naturally bind to C++ Standard Library types and avoid copies and other inefficiencies. Não se deve usar esses tipos diretamente.You shouldn't use these types directly. Se você quiser usar uma otimização para suas próprias funções, use std::wstring_view.If you want to use an optimization for your own functions then use std::wstring_view. Confira também Passagem de parâmetros para o limite do ABI.Also see Passing parameters into the ABI boundary.

O resultado é que, na maioria das vezes, é possível ignorar as especificidades do gerenciamento de cadeias de caracteres do Windows Runtime e trabalhar com eficiência com o que você sabe.The upshot is that you can largely ignore the specifics of Windows Runtime string management, and just work with efficiency with what you know. E isso é importante, considerando até que ponto as cadeias de caracteres são usadas no Windows Runtime.And that's important, given how heavily strings are used in the Windows Runtime.

Formatar cadeias de caracteresFormatting strings

Uma opção para a formatação de cadeias de caracteres é std::wostringstream.One option for string-formatting is std::wostringstream. Este é um exemplo que formata e exibe uma mensagem simples de rastreamento de depuração.Here's an example that formats and displays a simple debug trace message.

#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());
}

A maneira correta de definir uma propriedadeThe correct way to set a property

Uma propriedade é definida passando um valor para uma função setter.You set a property by passing a value to a setter function. Aqui está um exemplo.Here's an example.

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

O código a seguir está incorreto.The code below is incorrect. Ele é compilado, mas tudo o que faz é modificar a winrt::hstring temporária retornada pela função de acessador Text() e, em seguida, descartar o resultado.It compiles, but all it does is to modify the temporary winrt::hstring returned by the Text() accessor function, and then to throw the result away.

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

APIs importantesImportant APIs