ICUライブラリで文字を一文字ずつ切り出したい。しかし切り出した結果をコンソール出力するのはもろもろの事情で難しく、ファイル出力は確認がめんどくさいのでウィンドウに描画する。
#include <windows.h> #include <unicode/ucnv.h> #include <unicode/brkiter.h> // 要リンク #pragma comment(lib, "icuuc.lib") // 以下のdllを要求される // icudt69.dll // icuuc69.dll LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); WCHAR szClassName[] = L"MY_ICU_TEST"; //ウィンドウクラス LPCWSTR fontname = L"MS P ゴシック"; HFONT hFont1; 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); //フォントを適応 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;//文字の長さ //win32api のWCHARはutf16なのでただキャストするだけで変換できる TextOutW(hdc, 10, TH, (WCHAR*)(&u16s.data()[prev]), count);//文字を書く // こっちでもいい substr(現在位置,切り取る長さ) // std::u16string sub = u16s.substr(prev, count); // TextOutW(hdc, 10, TH, (WCHAR*)sub.data(), count);//文字を書く //改行 TH += tm.tmHeight+5; } SelectObject(hdc, backup); EndPaint(hWnd, &ps); }
//////////////////////////////////// //////////////////////////////////// // 表示用 //////////////////////////////////// //////////////////////////////////// int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; BOOL bRet; WNDCLASSEX wc; HWND hWnd; ATOM atom; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hCurInst; wc.hIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); wc.hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = (LPCWSTR)szClassName; wc.hIconSm = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); if ((atom = RegisterClassEx(&wc)) == 0)return FALSE; hWnd = CreateWindow( MAKEINTATOM(atom), L"icu test", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 200, 500, // ウィンドウのサイズ NULL, NULL, hCurInst, NULL); if (!hWnd)return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) { if (bRet == -1) { break; } else { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int)msg.wParam; } LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { switch (msg) { case WM_CREATE: //Step1 フォント作成 hFont1 = CreateFont( 50, 0, //高さ, 幅 0, 0, FW_BOLD, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, VARIABLE_PITCH | FF_ROMAN, fontname); break; case WM_PAINT: WinPaint(hWnd); break; case WM_DESTROY: DeleteObject(hFont1); //Step4. HFONTオブジェクトを破棄 PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }