UTF-8文字列をAPI引数で使えるようになった

Windows10 の 1903 以降で、Windows API の -A 系列で、UTF-8 文字列を使えるようになったと記載を見かけたので試してみました。結論としては、「確かに使える!」です。条件が許せば、 UTF-8 と UTF-16 を考慮したプログラムで、Shift-JIS 文字を忘れることができるかもしれません。

Use the Windows UTF-8 code page - Windows apps
Use UTF-8 character encoding for optimal compatibility between web apps and other \*nix-based platforms (Unix, Linux, and variants), minimize localization bugs,...

設定方法

Visual Studio 2019 で、 C++ の Win32 プロジェクトを用いる場合で説明します。

必要になるのはマニフェストファイルで、以下の内容のテキストファイルを作成します。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
  <assemblyIdentity type="win32" name="..." version="6.0.0.0"/>
  <application>
    <windowsSettings>
      <activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>
    </windowsSettings>
  </application>
</assembly>

このファイルをプロジェクトに追加して、プロジェクトのプロパティを変更します。マニフェストツール / 入出力 を開いて、追加のマニフェストファイルに追加したファイルを設定します。

文字セットの設定は UNICODE、ANSI どちらでもうまく動作しました。ただし使用しているAPI セットはきちんと合わせることが必要です。DefWindowProc, GetMessage, DispatchMessageA あたりで変に混在状態だと以下のタイトル文字化けという症状が出ました。注意しましょう。

動作確認

CreateWindowA 関数を使ってみたところ、これでうまくタイトル文字列が表示されます!

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance;
   
   auto u8str = u8"日本語UTF8タイトル";

   HWND hWnd = CreateWindowA(
       szWindowClass, 
       u8str, 
       WS_OVERLAPPEDWINDOW,
       CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 
       nullptr, nullptr, hInstance, nullptr);

文字列の変換で、CP_ACP を使っている場合では、入力文字を Shift-JIS という解釈から UTF-8 解釈というようにモードが変わります。そのため以下のコードで UTF-8 から UTF-16 への変換ができます。

const auto stru8 = u8"日本語";
len = MultiByteToWideChar(CP_ACP, 0, stru8, -1, nullptr, 0);
wbuf.resize(len);
MultiByteToWideChar(CP_ACP, 0, stru8, -1, wbuf.data(), len);

しかし、 OutputDebugStringA でデバッグ出力に UTF-8 文字列を出力することはできませんでした。先ほどの、“日本語UTF8タイトル” という文字列をそのまま呼び出した結果が以下です。

ここでも UTF-8 文字列で受け取って表示してくれるととてもよかっただけに残念なポイントでした。

判定ができるか?

以下の GetACP 関数を用いることで一応の判定は可能かもしれません。この関数は現在のANSI コードページを返却します。上記で UTF-8 のコードページを設定している場合 65001 が返ってきます。なお、設定がない場合には日本語の Windows 環境では 932 が返ってきます。

   UINT value = GetACP();
GetACP function (winnls.h) - Win32 apps
Retrieves the current Windows ANSI code page identifier for the operating system.Caution  The ANSI API functions, for example, the ANSI version of TextOut, impl...
Code Page Identifiers - Win32 apps
The following table defines the available code page identifiers.

もっと簡単な設定方法

マニフェストファイルを追加のマニフェストファイルとして処理しなくても、リソースファイルに追加する方法でも可能なことが分かりました。ファイルを作成するところは同様で、単純にプロジェクトに追加するだけで済みます。

プログラミング
すらりんをフォローする
すらりん日記

コメント

タイトルとURLをコピーしました