Windows アプリで UTF-8 コード ページを使用する

UTF-8 文字エンコードを使って Web アプリと他の *nix ベースのプラットフォーム (Unix、Linux など) との最適な互換性を確保し、ローカライズのバグを最小限に抑え、テストのオーバーヘッドを減らします。

UTF-8 は国際化のためのユニバーサル コード ページであり、Unicode 文字セット全体をエンコードすることができます。 Web では広く使われており、*nix ベースのプラットフォームではデフォルトとなっています。

プロセス コード ページを UTF-8 に設定する

Windows バージョン 1903 (2019 年 5 月の更新プログラム) 以降、パッケージ化されたアプリの場合は appx マニフェスト、パッケージ化されていないアプリの場合は fusion マニフェストの ActiveCodePage プロパティを使って、プロセスのコード ページとして UTF-8 を使うように強制できるようになりました。

Note

GDI は現在、プロセスごとの ActiveCodePage プロパティの設定をサポートしていません。 代わりに、GDI はデフォルトでアクティブなシステム コード ページに設定されます。 GDI 経由で UTF-8 テキストをレンダリングするようにアプリを構成するには、Windows の設定> 時刻と言語>言語と地域>管理言語設定>システム ロケールの変更 に移動し、 ベータ: 世界中の言語をサポートするには Unicode UTF-8 を使用します。 次に、変更を有効にするために PC を再起動します。

ActiveCodePage プロパティを宣言し、以前の Windows ビルドをターゲットにして実行することはできますが、レガシー コード ページの検出と変換は通常どおり処理する必要があります。 Windows バージョン 1903 の最小ターゲット バージョンの場合、プロセス コード ページは常に UTF-8 になるため、レガシ コード ページの検出と変換を回避することができます。

Note

エンコードされた文字は 1 から 4 バイトです。 UTF-8 では 6 バイトまでの長いバイト シーケンスをサポートしていますが、Unicode 6.0 の最大のコード ポイント (U+10FFFF) は 4 バイトしかありません。

パッケージ化されたアプリの場合は appx マニフェスト:

<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
         ...
         xmlns:uap7="http://schemas.microsoft.com/appx/manifest/uap/windows10/7"
         xmlns:uap8="http://schemas.microsoft.com/appx/manifest/uap/windows10/8"
         ...
         IgnorableNamespaces="... uap7 uap8 ...">

  <Applications>
    <Application ...>
      <uap7:Properties>
        <uap8:ActiveCodePage>UTF-8</uap8:ActiveCodePage>
      </uap7:Properties>
    </Application>
  </Applications>
</Package>

パッケージ化されていない Win32 アプリの場合は fusion マニフェスト:

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

Note

mt.exe -manifest <MANIFEST> -outputresource:<EXE>;#1 を使用して、コマンド ラインから既存の実行可能ファイルにマニフェストを追加します。

-A と -W API の比較

多くの場合、Win32 API は - A と - W の両方のバリアントをサポートしています。

-A バリアントの場合、システムに構成されている ANSI コード ページを認識することができ、char* をサポートします。一方、-W バリアントの場合、UTF-16 で動作し、WCHAR をサポートします。

最近まで、Windows では、-A API よりも「Unicode」の -W バリアントを重視してきました。 ただし、最近のリリースでは、アプリに UTF-8 サポートを導入する手段として、ANSI コード ページと -A API が使われています。 ANSI コード ページが UTF-8 用に構成されている場合、-A API は通常 UTF-8 で動作します。 このモデルには、-A API を使って構築した既存のコードを、コードを変更することなくサポートできるという利点があります。

コード ページ変換

Windows は UTF-16 (WCHAR) でネイティブに動作するので、場合によっては、Windows API と相互運用するために UTF-8 データを UTF-16 (またはその逆) に変換する必要があります。

MultiByteToWideCharWideCharToMultiByte を使うと、UTF-8 と UTF-16 (WCHAR) (およびその他のコード ページ) の間で変換できます。 これは、レガシ Win32 API が WCHAR しか理解しない場合に特に便利です。 これらの関数を使うと、UTF-8 の入力を WCHAR に変換して -W API に渡し、必要に応じて結果を変換して戻すことができます。

dwFlags0 に設定してこれらの機能を使用する場合は、MB_ERR_INVALID_CHARS または CodePage のいずれかの CP_UTF8 を使用します (そうでない場合は ERROR_INVALID_FLAGS が発生します)。

Note

CP_ACPCP_UTF8 と同じになるのは、Windows バージョン 1903 (2019 年 5 月の更新プログラム) 以降で動作し、前述の ActiveCodePage プロパティが UTF-8 に設定されている場合のみです。 それ以外の場合は、レガシ システムのコード ページが使用されます。 CP_UTF8 を明示的に使うことをお勧めします。