Bagikan melalui


Penanganan string di C++/WinRT

Dengan C++/WinRT, Anda dapat memanggil WINDOWS Runtime API menggunakan jenis string lebar Pustaka Standar C++ seperti std::wstring (catatan: tidak dengan jenis string sempit seperti std::string). C++/WinRT memang memiliki jenis string kustom yang disebut winrt::hstring (didefinisikan dalam pustaka dasar C++/WinRT, yaitu %WindowsSdkDir%Include\<WindowsTargetPlatformVersion>\cppwinrt\winrt\base.h). Dan itulah jenis string yang benar-benar diambil dan dikembalikan oleh konstruktor, fungsi, dan properti Windows Runtime. Tetapi dalam banyak kasus—berkat konstring konversi dan operator konversi hstring—Anda dapat memilih apakah akan mengetahui hstring dalam kode klien Anda atau tidak. Jika Anda menulis API, maka Anda lebih mungkin perlu mengetahui tentang hstring.

Ada banyak jenis string di C++. Varian ada di banyak pustaka selain std::basic_string dari Pustaka Standar C++. C++17 memiliki utilitas konversi string, dan std::basic_string_view, untuk menjenjangkan kesenjangan di antara semua jenis string. winrt::hstring memberikan konvertibilitas dengan std::wstring_view untuk memberikan interoperabilitas yang dirancang untuk std::basic_string_view .

Menggunakan std::wstring (dan opsional winrt::hstring) dengan Uri

Windows::Foundation::Uri dibangun dari winrt::hstring.

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

Tetapi hstring memiliki konstruktor konversi yang memungkinkan Anda bekerja dengannya tanpa perlu menyadarinya. Berikut adalah contoh kode yang menunjukkan cara membuat Uri dari literal string lebar, dari tampilan string yang luas, dan dari 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 };
}

Aksesor properti Uri::D omain berjenis hstring.

public:
    winrt::hstring Domain();

Tapi, sekali lagi, menyadari bahwa detail bersifat opsional berkat operator konversi hstring ke 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"

Demikian pula, IStringable::ToString mengembalikan hstring.

public:
    hstring ToString() const;

Uri mengimplementasikan antarmuka 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/"

Anda dapat menggunakan fungsi hstring::c_str untuk mendapatkan string lebar standar dari hstring (seperti yang Anda bisa dari std::wstring).

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

Jika Anda memiliki hstring maka Anda dapat membuat Uri darinya.

Uri awUriFromHstring{ tostringHstring };

Pertimbangkan metode yang mengambil hstring.

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

Semua opsi yang baru saja Anda lihat juga berlaku dalam kasus seperti itu.

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

hstring memiliki operator konversi anggota std::wstring_view , dan konversi dicapai tanpa biaya.

void legacy_print(std::wstring_view view);

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

winrt::hstring functions and operators

Sejumlah konstruktor, operator, fungsi, dan iterator diimplementasikan untuk winrt::hstring.

Hstring adalah rentang, sehingga Anda dapat menggunakannya dengan berbasis forrentang , atau dengan std::for_each. Ini juga menyediakan operator perbandingan untuk membandingkan secara alami dan efisien dengan rekan-rekannya di Pustaka Standar C++. Dan itu termasuk semua yang Anda butuhkan untuk menggunakan hstring sebagai kunci untuk kontainer asosiatif.

Kami mengenali bahwa banyak pustaka C++ menggunakan std::string, dan bekerja secara eksklusif dengan teks UTF-8. Sebagai kenyamanan, kami menyediakan pembantu, seperti winrt::to_string dan winrt::to_hstring, untuk mengonversi bolak-balik.

WINRT_ASSERT adalah definisi makro, dan meluas ke _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!");

Untuk contoh dan info selengkapnya tentang fungsi dan operator hstring, lihat topik referensi API winrt::hstring.

Alasan untuk winrt::hstring dan winrt::p aram::hstring

Windows Runtime diimplementasikan dalam hal karakter wchar_t , tetapi Application Binary Interface (ABI) Windows Runtime bukanlah subset dari apa yang disediakan std::wstring atau std::wstring_view . Menggunakannya akan menyebabkan inefisiensi yang signifikan. Sebagai gantinya, C++/WinRT menyediakan winrt::hstring, yang mewakili string yang tidak dapat diubah yang konsisten dengan HSTRING yang mendasar, dan diimplementasikan di belakang antarmuka yang mirip dengan std::wstring.

Anda mungkin melihat bahwa parameter input C++/WinRT yang harus secara logis menerima winrt::hstring benar-benar mengharapkan winrt::p aram::hstring. Namespace layanan param berisi sekumpulan jenis yang digunakan secara eksklusif untuk mengoptimalkan parameter input untuk secara alami mengikat jenis Pustaka Standar C++ dan menghindari salinan dan inefisiensi lainnya. Anda tidak boleh menggunakan jenis ini secara langsung. Jika Anda ingin menggunakan pengoptimalan untuk fungsi Anda sendiri, gunakan std::wstring_view. Lihat juga Meneruskan parameter ke dalam batas ABI.

Upshotnya adalah Anda sebagian besar dapat mengabaikan spesifik manajemen string Windows Runtime, dan hanya bekerja dengan efisiensi dengan apa yang Anda ketahui. Dan itu penting, mengingat bagaimana string berat digunakan dalam Windows Runtime.

Memformat string

Salah satu opsi untuk pemformatan string adalah std::wostringstream. Berikut adalah contoh yang memformat dan menampilkan pesan pelacakan debug sederhana.

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

Cara yang benar untuk mengatur properti

Anda mengatur properti dengan meneruskan nilai ke fungsi setter. Berikut adalah contoh.

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

Kode di bawah ini salah. Ini mengkompilasi, tetapi yang dilakukannya adalah memodifikasi winrt sementara ::hstring yang dikembalikan oleh fungsi aksesor Text(), dan kemudian untuk membuang hasilnya.

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

API penting