パスワードを忘れた? アカウント作成
15595175 journal
Windows

route127の日記: Unicode版Autohotkeyから敢えてMessageBoxAを使う 2

日記 by route127

以前PerlでUnicode::String::utf8($text)->utf16leとか試した覚えがあったがあれはTextOutAだった。

Unicode版のAutohotkey(AutohotkeyU64.exe)ではメッセージボックスを利用するのには組み込みのMsgBoxを用いて

str:="あいう"
MsgBox, %str%

とすれば自動的にMessageBoxWが選択されるようでうまく表示されるのだが、ここで敢えてDllCallでMessageBoxAを呼び出そうとすると文字列の符号化方式をCP932に変更する必要があり、その準備としてメモリ確保等の手数が増す。
(手間を減らすためのスクリプトで結局メモリ管理が必要になる)

str:="あいう"
len:=StrLen(str)
buf:=(len+1)*2
 
VarSetCapacity(str2, buf, 0)
StrPut(str, &str2, buf, "CP932")
MsgBox, %str2%    ;CP932で符号化した文字列がMessageBoxWで表示されるので化ける
DllCall("MessageBoxA", "Uint", 0, "Str", str2, "Str", "title", "Int", 0)

バッファのサイズbufは文字数×2バイト文字とヌル終端でlen*2+1のような気がしてきたが上手くいっているのでヨシ!
また今回CP932への変換はahk組込みのStrPutのオプションを利用したがWin32APIのMultiByteToWideCharとWideCharToMultiByteの2つを組合せて行う方法もあるらしい。
ahkでの例もあったがCP指定の所を65001から932に変えて使っても上手くMessageBoxAで表示させられなかった。

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
  • autohotkeyはよくわからないが

    str:="あいう"

    これが UTF-16 なら、 WideCharToMultiByte だけでよい。

    DllCall("WideCharToMultiByte", "uint", 0, "int", 0, "uint", &str
                                                                  , "int", -1, "str", str2, "uint", BufSize
                                                                  , "int", 0, "int", 0)

    これが UTF-8 なら、ahkでの例 のやつで、MultiByteToWideChar・WideCharToMultiByteの呼び出しが、下記のよーな感じとなる、と思う。(元の例が、SJISからUTF-8への変換であることに注意)

    DllCall("MultiByteToWideChar", "uint", 65001, "int", 0, "str", str
                                                                  , "int", -1, "uint", &Buf1, "uint", RawLen + 1)
        DllCall("WideCharToMultiByte", "uint", 0, "int", 0, "uint", &Buf1
                                                                  , "int", -1, "str", Buf2, "uint", BufSize
                                                                  , "int", 0, "int", 0)

    CodePage が 0 の指定で、Windowsの言語環境に応じたコードページを使用するとかそんなやつなので、元の例の 65001 を 932 に変えると、 str を CP932 とみなして UTF-16にし、その後 UTF-16 から CP932 にする動作になるので意図した動作をしない。

    --
    svn-init() {
      svnadmin create .svnrepo
      svn checkout file://$PWD/.svnrepo .
    }
  • by Anonymous Coward on 2022年03月14日 21時59分 (#4215586)

    〜Wを呼ぶ際の文字列はUTF-16≒Wide文字列。
    〜Aを呼ぶ際の文字列はOEMCP(日本語環境のデフォではANSIコードページ(0)≒OEMコードページ(1)≒コードページ932)。
    MultiByteToWideCharは第一引数のCPからWide文字列への変換。
    WideCharToMultiByteはWide文字列から第一引数のCPへの変換。

    「ahkでの例」で出してるコードは、ANSIコードページ→UTF-16→UTF-8。
    AHKの文字列の内部コードがUTF-16なのかその言語環境のコードページなマルチバイト文字列なのかはしらんけど、
    とりあえずリンク先の処理はその言語環境のコードページなマルチバイト文字列突っ込むとUTF-8で返す処理。
    日本語環境でそのコードの最終をCP932にして動かすって事は一回UTF-16にしてるだけの無変換だから意味ないね。
    多分だけど、このリンク先のコードはマルチバイト版用のコードな気がする。
    UTF-16環境で使うならWideCharToMultiByteで0か1か932を指定してのUTF-16→CP932変換だけで良い。

    というかそもそもMessageBoxAは内部的にMultiByteToWideCharしてMessageBoxWを呼ぶとかだった気がするから、
    わざわざMessageBoxAの方を呼ぶ意味がない。

typodupeerror

皆さんもソースを読むときに、行と行の間を読むような気持ちで見てほしい -- あるハッカー

読み込み中...