次の方法で共有


C++/WinRT での文字列処理

C++/WinRT では、std::wstring などの C++ 標準ライブラリのワイド文字列型を使用して Windows ランタイム API を呼び出すことができます (注: std::string などの狭い文字列型では呼び出しません)。 C++/WinRT には 、winrt::hstring という名前のカスタム文字列型があります (C++/WinRT 基本ライブラリで定義され、 %WindowsSdkDir%Include\<WindowsTargetPlatformVersion>\cppwinrt\winrt\base.h)。 これは、Windows ランタイムのコンストラクター、関数、プロパティが実際に受け取って返す文字列型です。 ただし、多くの場合、 hstring の変換コンストラクターと変換演算子のおかげで、クライアント コードで hstring を認識するかどうかを選択できます。 API 作成 場合は、hstring知る必要がある可能性が高くなります。

C++ には多くの文字列型があります。 バリアントは、C++ 標準ライブラリの std::basic_string に加えて、多くのライブラリに存在します。 C++17 には、すべての文字列型間のギャップを埋めるために、文字列変換ユーティリティと std::basic_string_view があります。 winrt::hstring は、std::wstring_view との変換性を提供し、std::basic_string_view が設計された相互運用性 提供します。

std::wstring (および必要に応じて winrt::hstring) を Uri と共に使用する

Windows::Foundation::Uriwinrt::hstring から構築されます。

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

ただし 、hstring には 変換コンストラクター があり、これを認識する必要なく操作できます。 ワイド文字列リテラル、ワイド文字列ビュー、std::wstring から URI を作成する方法を示すコード例を次に示します。

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

プロパティ アクセサー Uri::Domain は、hstring型です。

public:
    winrt::hstring Domain();

しかし、ここでも、その詳細を認識することは、std::wstring_viewを するhstringの 変換演算子 のおかげで省略可能です。

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

同様に、 IStringable::ToString は hstring を返します。

public:
    hstring ToString() const;

UriIStringable インターフェイスを実装します。

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

hstring::c_str 関数を使用して、hstring から標準のワイド文字列を取得できます (std::wstring の場合と同様)。

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

hstring がある場合は、そこから URI を作成できます。

Uri awUriFromHstring{ tostringHstring };

hstring を受け取るメソッドを考えてみましょう。

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

今見たすべてのオプションは、このような場合にも適用されます。

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

hstring にはメンバー std::wstring_view 変換演算子があり、変換はコストなしで実現されます。

void legacy_print(std::wstring_view view);

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

winrt::hstring 関数と演算子

多くのコンストラクター、演算子、関数、そしてイテレーターが、winrt::hstring に実装されています。

hstring は範囲であるため、範囲ベースのforまたはstd::for_eachで使用できます。 また、C++ 標準ライブラリの対応する演算子と自然かつ効率的に比較するための比較演算子も提供します。 また、関連付けられたコンテナーのキーとして hstring を使用するために必要なものがすべて含まれています。

多くの C++ ライブラリが std::string を使用し、UTF-8 テキストのみで動作することを認識しています。 便宜上、winrt::to_stringwinrt::to_hstringなどのヘルパーを提供し、前後に変換します。

WINRT_ASSERT はマクロ定義であり、_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!");

hstring の例や の関数と演算子に関する情報については、winrt::hstring API リファレンス トピックを参照してください。

winrt::hstringwinrt::param::hstring の根拠

Windows ランタイムは wchar_t 文字の観点から実装されますが、Windows ランタイムのアプリケーション バイナリ インターフェイス (ABI) は、std::wstring 、または std::wstring_view が提供 サブセットではありません。 これらを使用すると、重大な非効率性につながります。 代わりに、C++/WinRT は winrt::hstring を提供します。これは、基になる HSTRING と一致する不変の文字列を表し、 std::wstring と同様のインターフェイスの背後に実装されます。

winrt::hstring を論理的に受け入れる必要がある C++/WinRT 入力パラメーターは、実際には winrt::param::hstringを想定している場合があります。 param 名前空間には、C++ 標準ライブラリ型に自然にバインドし、コピーやその他の非効率性を回避するために入力パラメーターを最適化するために排他的に使用される型のセットが含まれています。 これらの型は直接使用しないでください。 独自の関数に最適化を使用する場合は、 std::wstring_view を使用します。 ABI 境界にパラメーターを渡す も参照してください。

結論としては、Windows ランタイムの文字列管理の詳細をそれほど気にせず、知識を活かして効率よく作業できるということです。 また、Windows ランタイムで文字列がどれだけ頻繁に使用されているかを考えると、これは重要です。

文字列の書式設定

文字列形式の 1 つのオプションは std::wostringstream です。 単純なデバッグ トレース メッセージを書式設定して表示する例を次に示します。

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

プロパティを正しく設定する方法

プロパティを設定するには、セッター関数に値を渡します。 例を次に示します。

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

次のコードが正しくありません。 コンパイルされますが、Text() アクセサー関数によって返される一時的な winrt::hstring を変更して、その結果を捨てるだけです。

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

重要な API