void WinPaint(HWND hWnd) { // 元の文字列の定義 std::u16string u16s = u"aあغ山👨👧經经"; ///////////////////////////// // ICUの設定 icu::UnicodeString usr(u16s.c_str()); UErrorCode err; icu::BreakIterator* bi = icu::BreakIterator::createCharacterInstance( icu::Locale::getDefault(),err); bi->setText(usr); //////////////////////////// //フォトの設定 HDC hdc; PAINTSTRUCT ps; hdc = BeginPaint(hWnd, &ps); SetTextColor(hdc, RGB(0, 0, 0)); //文字の色を設定 SetBkColor(hdc, RGB(230, 230, 230)); //文字の背景色を設定 HFONT backup = (HFONT)SelectObject(hdc, hFont1); //Step2 フォントを適応 TEXTMETRIC tm; GetTextMetrics(hdc, &tm); int TH = 10; //////////////////////////// //文字を一文字(書記素)ずつ表示
int32_t current = bi->first(); while (current != icu::BreakIterator::DONE) { // 文字の長さを知る必要があるので、 // 「現在の文字の位置」と「前の文字の位置」が必要 int32_t prev = current; current = bi->next(); if (current == UBRK_DONE) { break; } int32_t count = current - prev;//文字の長さ
TextOutW(hdc, 10, TH, (WCHAR*)& usr.getBuffer()[prev], count);//文字を書く
//改行 TH += tm.tmHeight+5; }
SelectObject(hdc, backup); EndPaint(hWnd, &ps); }
TextOutW(hdc, 10, TH, (WCHAR*)& usr.getBuffer()[prev], count);//文字を書く
icu::UnicodeString e; usr.extract(prev, count, e); // win32api のWCHARはutf16なのでただキャストするだけで変換できる TextOutW(hdc, 10, TH, (WCHAR*)e.getBuffer(), e.length());//文字を書く
// substr(現在位置,切り取る長さ) std::u16string sub = u16s.substr(prev, count); TextOutW(hdc, 10, TH, (WCHAR*)sub.data(), count);//文字を書く
なおなぜかWordpressのせいでサロゲートペアが入力できないのでサンプルから抜いている。
first(),next()で操作するのはchar16_tとしての配列の要素番号。なので+1移動で2Byte移動だが、サロゲートペアや結合文字があった場合はその限りではない。