windresでシフトJISとUTF-8とUNICODEと戯れてみる
先人たちの戦いの記録を見ると、windresで漢字の文字化けが激しく、回避策の連続の様だ。だがしかし、今は2013年だ。対策されているに違いない(ソースもあるし)と、言うわけで、しばらく書くつもりがなかったWindowsアプリ(と言ってもメニューバーがあるだけのもの)を書いてみることにした。
結果から言えば…
ちなみに今回使用しているのは、Windows7(64bit)上でwindres 2.23.1だ。
取りあえず何にも考えないMS932編
Hello Worldのサンプルをどっからか拾ってきて、WNDCLASS or WNDCLASSEXのlpszMenuNameにメニューバーのリソースを登録するだけなので、サンプル掲載は省略。
リソースファイル(rc)のサンプル(保存形式 ANSI=MS932)
#include "resource.h" IDM_MAINMENU MENU BEGIN POPUP "ファイル(&F)" BEGIN MENUITEM "終了(&X)", IDM_END END END
windresの出力形式を明示的に指定して-O coffとかしている人がいますが、拡張子から推測されるので指定しなくてもかまいません。
>windres resource.rc resource.o >gcc -mwindows a.c resource.o >a.exe
ふむ、問題なさそう。では、シフトJISの苦手な途中に\コードが混じる漢字を入れてみましょうか。
と言うわけで、「ファイル(&F)」を「ファイル構成(&F)」に変更して再実行。
>windres resource.rc resource.o resource.rc:5: unrecognized escape sequence
ダメじゃん。と言うわけで\コードが隠れている「構」の後に\文字を入れて、つまり「POPUP "ファイル構\成(&F)"」に修正して再々実行。
う〜ん、30年昔に戻ったようだ。結局のところロケールを意識できていないのか?
ソースとmakefileを覗くと、どうもロケールが使われていない…languageとかコードページとか以前の問題なので、この辺のオプションを使用しても無駄無駄無駄
- 結論
- \コードが隠れていない漢字を使う分にはOK。隠れていたら、その末尾に\文字を追加してあげれば良い(?)。
以外にソースを読み込んだUTF-8編
ソース類をUTF-8に変換し、まずは何も指定しないでトライ。
リソースファイル(rc)のサンプル(保存形式 UTF-8)
#include "resource.h" IDM_MAINMENU MENU BEGIN POPUP "ファイル構成(&F)" BEGIN MENUITEM "終了(&X)", IDM_END END END
ktkr!待ってたよ!
ソースを覗くとANSIコードページに無理矢理UTF-8のコードを載せているので、楽しい出力になっている模様。たぶん--codepage(-c)オプションを指定すれば大丈夫そう。ちなみに、下の「65001」はUTF-8のコードページを示しているのです。と言うわけでやってみよう。
>windres -c 65001 resource.rc resource.o >gcc -mwindows a.c resource.o >a.exe
ちっ、つまらん。だが、しかし、タダでは起きん。いちいち保存形式調べて、-c 65001なんて付けたり、消したりするなんて、面倒だ。何か方法はないのか〜
と、lex(flex?)で書かれたソースを眺めていたらありましたよ。「#pragma code_page(65001)」すばらしい!!
ついでに、日本語で書いていることを明記するためにLANGUAGEキーワードも使っちゃいましょう。
リソースファイル(rc)のサンプル(保存形式 UTF-8)
#include <windows.h> #include "resource.h" LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT #pragma code_page(65001) IDM_MAINMENU MENU BEGIN POPUP "ファイル構成(&F)" BEGIN MENUITEM "終了(&X)", IDM_END END END
>windres resource.rc resource.o >gcc -mwindows a.c resource.o >a.exe
Yes, Yes, Yes. これで邪魔なオプションとは、おさらば。
- 結論
- #pragma使えば余計なオプション覚えなくて、更にシフトJISの様な変なこともしなくても良いので、これがベスト(?)。
気が狂っているとしか思えないUNICODE編
ソース(コンパイラ?)がUNICODE(ワイド文字列)に対応していないのは、周知なので、リソースファイルだけUNICODEに変換して、トライ。
>windres resource.rc resource.o resource.rc:1:4: warning: null character(s) ignored [enabled by default] resource.rc:1:6: warning: null character(s) ignored [enabled by default] resource.rc:1:8: warning: null character(s) ignored [enabled by default] resource.rc:1:10: warning: null character(s) ignored [enabled by default] resource.rc:1:12: warning: null character(s) ignored [enabled by default] … windres: resource.rc:1: syntax error windres: preprocessing failed.
わははは、出わ、出わ。まあlex(flex?)で書かれたソースを読んでいたから予想はしていたが、windresはマルチバイト文字列のファイルしか受け付けないのだ。と、言うわけでUTF-8形式に戻して、やり直し、やり直し。
ちなみに、これもソースからの情報だが、"…"ではなくL"…"とした場合、マルチバイト→UNICODE変換されず、UNICODEとして扱われる様だ。と、言うわけで、取りあえずL付けてみようか。
リソースファイル(rc)のサンプル(保存形式 UTF-8)
#include <windows.h> #include "resource.h" LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT #pragma code_page(65001) IDM_MAINMENU MENU BEGIN POPUP L"ファイル(&F)" BEGIN MENUITEM "終了(&X)", IDM_END END END
ん〜、意に反して(結果が既に予想できているから)windres普通に通りますね。じゃあ実行。
わははは、何語じゃ、いったい。では、どうすれば良かったのか?簡単(?)だよUNICODEを書けば良いのだよ。って、ANSIやUTF-8で書いてるファイルの途中に、UNICODE書けるエディターなんて無いよ〜。
と、言うわけで、エスケープシーケンスで、しこしこUNICODEを書くのだ! 優しい事にASCIIは自動的に先頭\x00を自動付与してくれるから、そのままでOKだぞ(何の慰めにもならん)。
で、出来たのが下のリソースファイル。
リソースファイル(rc)のサンプル(保存形式 UTF-8)
#include <windows.h> #include "resource.h" LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT #pragma code_page(65001) IDM_MAINMENU MENU BEGIN POPUP L"\x30d5\x30a1\x30a4\x30eb(&F)" //ファイル(&F) BEGIN MENUITEM "終了(&X)", IDM_END END END
実行すれば、ほれ、この通り。
つまり、UNICODEを使いたい奴は、UNICODEのコード表を覚えろって事だ。そんな変人見たことないな。
- 結論
- 変人には変人にしか見えない道がある。