共用方式為


C++/WinRT 中的字串處理

使用 C++/WinRT,您可以使用 C++ 標準程式庫的寬字元串類型呼叫 Windows Runtime API,例如 std::wstring(注意:不使用狹窄字元串類型如 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::Uri 是從 winrt::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();

但是,知道這個細節是可選的,這要歸功於 hstringstd::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"

同樣地,IStringable::ToString 會傳回 hstring。

public:
    hstring ToString() const;

URI 實作 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/"

您可以使用 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 是一個範圍,因此您可以將它與以範圍為基礎的 forstd::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::wstringstd::wstring_view 提供的子集。 使用這些會導致顯著的效率低下。 反之,C++/WinRT 會提供 winrt::hstring,代表與底層 HSTRING一致的不可變字串,並通過類似於 std::wstring的介面進行實作。

您可能會注意到,C++/WinRT 輸入參數應該以邏輯方式 接受 winrt::hstring 實際上期望 winrt::param::hstring參數 命名空間包含一組類型,專門用來優化輸入參數,使其自然地綁定到 C++ 標準函式庫的類型,從而避免複製操作和其他低效行為。 您不應該直接使用這些類型。 如果您要針對自己的函式使用優化,請使用 std::wstring_view。 請參閱 將參數傳遞到 ABI 邊界

結論是,您基本上可以忽略 Windows 執行階段字串管理的特定細節,並只利用您所知的內容來提高效率。 這很重要,因為在 Windows 執行階段中廣泛使用字串。

格式化字串

字串格式設定的其中一個選項是 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());
}

設定屬性的正確方式

您可以藉由將值傳遞至 setter 函式來設定屬性。 以下是範例。

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