Windows11 外字の問題(WIn32 API TextOutW)

平井 0 評価のポイント
2025-08-12T00:35:33.86+00:00

Windows11(バージョン24H2 ビルド26100.4652)とWindows10(バージョン22H2 ビルド19045.6036)で外字の表示(Win32 API TextOutWの描画)に違いがあります。

手順:

  1. 外字エディタで、MS明朝用にUnicode 0xE849(私用領域)の外字を登録する。
  2. テキストエディタ(おそらくWin32 APIを使用)に外字1文字と、外字以外の全角文字+外字を入力する。
  3. Windows11の場合、外字1文字では正常に外字が表示されるが、外字以外の全角を含む行では外字が別の文字に置換される。
  4. Windows10の場合、外字1文字と、外字以外の全角文字+外字、どちらも正常に外字が表示される。

Win32 APIではなく、Direct2Dでは問題が発生しないようです。

何か解決方法はありますでしょうか?

↓Windows10Windows10-22H2(Build19045.6036) Windows11↓Windows11-24H2(26100.4652)

開発者テクノロジ | C++
{count} 件の投票

1 件の回答

並べ替え方法: 最も役に立つ
  1. motosan 2,220 評価のポイント
    2025-08-13T14:23:42.5233333+00:00

    U+E849 のコードを問題なく使用することは難しいようです。

    WordなどはUnicodeの私用領域をフォントファイルから取り込まず、外字ファイルからだけ取り込むようにしているようです。

    一部のアプリは、フォントファイルに無い場合だけ外字ファイルから取り込むようにしているようです。(もう少し複雑かもしれません)

    以下のような対応が考えられます。

    方法1)

      Unicodeで使える文字がないか調べて使う。(IMEパッドの手書き入力)

    方法2)

      私用領域の文字未登録のコードで外字を登録する。

    以上の方法は既存の文書の文字コードの書き換えが必要になります。

    ■ 表示できないアプリがあることを許容してU+E849 のコードを使う。

    方法3)

      質問にあるように Direct2D を使用するようにプログラムを修正する。

    方法4)

      外字ファイルのフォントで TextOutW で出力する。

      外字ファイルにないコードはシステムのデフォルトフォントが使用されるので、フォントを指定できない。

    描画部分のコード例(Copilotに聞きました)

        case WM_PAINT: {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            // 外字フォントファイルをロード
            const TCHAR* fontPath = L"C:\\Windows\\FONTS\\EUDC.TTE";
            if (AddFontResourceEx(fontPath, FR_PRIVATE, NULL) == 0) {
                MessageBox(hWnd, L"フォントのロードに失敗しました", L"エラー", 
                           MB_OK | MB_ICONERROR);
                return -1;
            }
            // 描画するテキスト(外字を含む)
            TCHAR text[]  = L"あ\uE849";
            // EUDCフォントを作成
            HFONT hFont = CreateFont(
                24, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
                DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
                DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"EUDC");
            // フォントを選択
            HFONT hOldFont = (HFONT)SelectObject(hdc, hFont);
            // テキストを描画
            TextOut(hdc, 100, 50, text, ARRAYSIZE(text));
            // フォントを元に戻す
            SelectObject(hdc, hOldFont);
            DeleteObject(hFont);
            ReleaseDC(hWnd, hdc);
            // 外字フォントファイルをメモリから削除
            RemoveFontResourceEx(fontPath, FR_PRIVATE, NULL);
            EndPaint(hWnd, &ps);
        } break;
    

    ※ (参考).Net の FormattedText では下記のようにフォントと外字ファイルを同時に指定できます。

    new FontFamily("MS ゴシック, C:\\Windows\\Fonts\\EUDC.tte#EUDC"),
    

    外字についての資料が少ないので、とりあえず、考え付いたことです。

    ご参考になれば幸いです。


お客様の回答

回答は、質問作成者が [承諾された回答] としてマークできます。これは、ユーザーが回答が作成者の問題を解決したことを知るのに役立ちます。