dllfuncw と charset="iso-8859-1 の関係No.03314
misono さん 12/07/24 09:06
 
ユニコード版dll呼び出し dllfuncw で自作dllを使用しています。

charset="iso-8859-1" のメールを表示しているときに、マクロで
#n = dllfuncw("testfunc", $str);
という形で実行すると自作dll側はユニコードを期待しているのに
$strにはiso-8859-1 が入っています。
結果的に自作dll側で文字列の処理をしようとすると文字化けが発生します。
$str = "メール";
のように文字列を直接代入していても、そのようになるようです。

これは当然の話なのかもしれませんが、たとえば
message $str;
では画面上には文字化けせずに表示されます。

メールごとにこのように挙動が変わってしまうと自作dll側としては不都合なのですが、
これはどうにかできるものなのでしょうか?


[ ]
RE:03314 dllfuncw と charset="iso-8859-No.03315
秀まるお さん 12/07/24 11:35
 
 こちらで簡単にテストをした限りは、dllfuncwで呼び出した関数に渡される
パラメータは、たしかにユニコードになって渡ってるように思います。

 こちらでテストしたのは、とりあえずtkinfo.dllにテスト用の関数を1つ追加
しました。

extern "C" WCHAR* TestFuncW( WCHAR* pwsz ) {
    MessageBoxW( GetActiveWindow(), pwsz, L"Test", MB_OK );
    return pwsz;
}

 で、これを呼び出す用に、

    loaddll "tkinfo.dll";
    $text = dllfuncstr("CurrentHeader", "Content-Type");
    #n = dllfuncw("TestFuncW", $text);

 みたいなマクロを作成しました。

 それで、何か適当な欧文メールを選択して実行すると、例えば


    text/html; charset="iso-8859-1"

 のようなメッセージが出てきます。なのでうまく動いてるように思います。

 ちなみにですが、

    $text = dllfuncstr("CurrentHeader", "Subject");

 のようにして中国語のメールで実行した場合でも、一応正しく中国語の
Subjectが表示されるようです。なので一応うまく動作してるような気がします。

 何かこちらのサンプルと違う所があれば教えて欲しいです。

[ ]
RE:03315 dllfuncw と charset="iso-8859-No.03316
misono さん 12/07/24 14:05
 
>extern "C" WCHAR* TestFuncW( WCHAR* pwsz ) {
>    MessageBoxW( GetActiveWindow(), pwsz, L"Test", MB_OK );
>    return pwsz;
>}

同じテスト関数を作りました。

> で、これを呼び出す用に、
>
>    loaddll "tkinfo.dll";
>    $text = dllfuncstr("CurrentHeader", "Content-Type");
>    #n = dllfuncw("TestFuncW", $text);
>
> みたいなマクロを作成しました。
>
> それで、何か適当な欧文メールを選択して実行すると、例えば
>
>
>    text/html; charset="iso-8859-1"
>
> のようなメッセージが出てきます。なのでうまく動いてるように思います。
>
> ちなみにですが、
>
>    $text = dllfuncstr("CurrentHeader", "Subject");
>
> のようにして中国語のメールで実行した場合でも、一応正しく中国語の
>Subjectが表示されるようです。なので一応うまく動作してるような気がします。

はい、これは私の所も正常動作しています。

以下のようなサンプルマクロではいかがでしょうか。

    loaddll "tkinfo.dll";
    $text = "メールです";
    #n = dllfuncw("TestFuncW", $text);

この場合は、"メールです"が文字化けします。

[ ]
RE:03316 dllfuncw と charset="iso-8859-No.03317
秀まるお さん 12/07/24 15:13
 
 今テストしたら再現出来ました。たしかに化けました。

 実は、これの問題に対応させるために、秀丸エディタの方では、マクロを
Unicodeで保存してもらうとOKになるって仕様がありました。

 マクロ用のファイルをUnicode(UTF-16,BOMあり)で保存して実行すると、秀丸
エディタの方ではちゃんとマクロ内の文字列がユニコードで読み込まれて、
「テスト」の文字列がうまくdllに渡されます。

 秀丸メールでも、実はV5.75まではそういう仕様でしたが、V5.76β2で仕様変
更してしまいました。

 改版履歴:
      秀丸メール本体上でマクロ実行するときで、マクロファイル
      がユニコードの場合、表示してるメールのコードページに関
      係なく、常にコードページ=932としてマクロを読み込むよう
      にした。

 これは、根本的に秀丸マクロがかかえてる矛盾で、あちらを立てればこちらが
立たず的な、大変ややこしい問題になってしまいますが…。とりあえず一回元の
V5.75と同じ仕様に戻してもいいでしょうか。

 それで1回β版を出すということで…。


 とりあえずの回避策としては、マクロをUnicodeで保存するのと同時に、

    "テスト"

 の所を

    "\u30C6\u30B9\u30C8"

 のように、ユニコードの文字コードを直接記述すれば回避出来るようではあり
ますが、これではダメですかね。
 (この方法でなぜ回避出来てしまうのかはちょっと謎ですが)

[ ]
RE:03317 dllfuncw と charset="iso-8859-No.03318
秀まるお さん 12/07/24 15:24
 
 あと、実は現状のmessage文やquestion文は、マクロをユニコードで作成した
場合は逆に文字化けしてメッセージ表示されてしまうって仕様(?)になってい
たりします。

 これについては別途messagew文/questionw文でも追加したらいいんじゃないか
という話もあるにはあります。

 とりあえずの回避策としては、

    #objShell = createobject("WScript.Shell");
    callmethod #objShell, "PopUp", "テスト";

 のようにして回避する手段があるにはあります。

[ ]
RE:03317 dllfuncw と charset="iso-8859-No.03319
misono さん 12/07/24 17:00
 
> マクロ用のファイルをUnicode(UTF-16,BOMあり)で保存して実行すると、秀丸
>エディタの方ではちゃんとマクロ内の文字列がユニコードで読み込まれて、
>「テスト」の文字列がうまくdllに渡されます。

ああ、エディタの方ですね。
今メール本体ウインドウでテストしてて、あれ化けるなと思ってました。

> 秀丸メールでも、実はV5.75まではそういう仕様でしたが、V5.76β2で仕様変
>更してしまいました。
>
> 改版履歴:
>      秀丸メール本体上でマクロ実行するときで、マクロファイル
>      がユニコードの場合、表示してるメールのコードページに関
>      係なく、常にコードページ=932としてマクロを読み込むよう
>      にした。
>
> これは、根本的に秀丸マクロがかかえてる矛盾で、あちらを立てればこちらが
>立たず的な、大変ややこしい問題になってしまいますが…。とりあえず一回元の
>V5.75と同じ仕様に戻してもいいでしょうか。

エディタ側とメール側の仕様を合わせていただき、
前で述べたようなマクロとDLLの作り方で動作するようにしていただければと思
っています。
なので、そういう仕様で私はお願いしたいです。

> とりあえずの回避策としては、マクロをUnicodeで保存するのと同時に、
>
>    "テスト"
>
> の所を
>
>    "\u30C6\u30B9\u30C8"
>
> のように、ユニコードの文字コードを直接記述すれば回避出来るようではあり
>ますが、これではダメですかね。
文字列が決め打ちならいいのですが・・・そうでないことが多いので。
ちょっと現実的ではありません。

> (この方法でなぜ回避出来てしまうのかはちょっと謎ですが)

[ ]
RE:03319 dllfuncw と charset="iso-8859-No.03320
秀まるお さん 12/07/25 15:18
 
 昨日V5.79β1をアップロードしたのですが、実はこれに、message文/question
文のユニコード版関数も追加しました。

 Bypass_MessageBoxWって関数になります。

 マクロをUnicode(UTF-16)で作成すれば、外国語メール上であっても文字化
けせずにメッセージ表示出来ます。

 以下のマクロでの、例えば最初のメッセージは化けますが、2個目のメッセー
ジは化けないです。

    loaddll "tkinfo.dll";
    #n = dllfunc("Bypass_MessageBox", hidemaruhandle(0), "テスト", 0 );
    #n = dllfuncw("Bypass_MessageBoxW", hidemaruhandle(0), "テスト", 0 );

 tkinfo.dllのヘルプにも説明を追加しました。

[ ]
RE:03320 dllfuncw と charset="iso-8859-No.03321
misono さん 12/07/25 17:33
 
大変、大変ありがたいです。
今、動作を検証しまして、きちんと表示されることを確認しました。

ありがとうございます!

[ ]
RE:03316 dllfuncw と charset="iso-8859-No.03322
misono さん 12/07/26 09:21
 
すいません、もう少し直っていないようです。
以下のマクロだと文字化けを起こしています。

    loaddll "tkinfo.dll";
//    $text = dllfuncstr("CurrentHeader", "Content-Type");
    $text = dllfuncstr("CurrentFolder");
    #n = dllfuncw("TestFuncW", $text);

よろしくお願いします。

>>extern "C" WCHAR* TestFuncW( WCHAR* pwsz ) {
>>    MessageBoxW( GetActiveWindow(), pwsz, L"Test", MB_OK );
>>    return pwsz;
>>}

[ ]
RE:03322 dllfuncw と charset="iso-8859-No.03323
秀まるお さん 12/07/26 12:37
 
 実は、03317番発言で「あちらを立てればこちらが立たず」の件は、実はこの
ような問題があるから、だったような気がします。

 tkinfo.dllの返す値は、全部、日本語コードページ前提で返してしまってまし
て、コードページが欧文だと、文字化けしたような感じになってしまうようです。

 根本的な解決のためには、文字列を扱う関数にはすべてユニコード版も用意す
るか、またはコードページを判断して文字列を返すかって形になるんですが、後
者は、たぶん他のマクロでの互換性の問題が出る可能性が高いです。

 なので、ユニコード版を追加する形で対応させていただくしか無いように思い
ます。

 追加する予定の関数の例:

    $text = dllfuncstrw("CurrentFolderW");

 一回トライしてみていけそうかどうか判断して、またお返事させていただきま
す。

[ ]
RE:03323 dllfuncw と charset="iso-8859-No.03324
秀まるお さん 12/07/26 19:04
 
 CurrentFolderW関数などを追加するって形でトライしてみたんですが、いまい
ち問題解決にならないようでした。

 そもそもですが、マクロをユニコードで作成して、例えば欧文文字コードの
メールを対象にしてマクロが動き始めたとしても、そこから例えばNextMail関数
呼び出しで別のメールを選択すると、そのメールはまた別の言語になってること
があって、そうするとマクロで持ってる変数が全部文字化けしたようなことにな
ってしまいます。

 (これは秀丸エディタでもありえる、根本的なマクロの問題ではあります)

 それで、1ついい解決策を考えました。

    SetJapaneseCodePageMode

 って関数を追加します。これにパラメータに1を指定して呼び出すと、以後、
秀丸メール本体ウィンドウ上の秀丸エディタ相当部分は、常に日本語文字コード
であるかのごとく動作するようになります。

 例えばその状態で中国語のメールを選択すると、それは例えば秀丸エディタで
「エンコード=Shift-JISだけども中国語の漢字を入力した状態」って風になりま
す。

 そういう状態だと、とにかく基本すべて日本語ってことで計算出来て、ややこ
しい問題がすべてクリアになります。

 この場合、マクロはUnicodeじゃてくて、Shift-JISで保存する必要があります。
(この前と逆で申し訳ないですが)

 マクロを手直してしていただく点は、

 1.マクロの最初で

         #n = dllfunc("SetJapaneseCodePageMode", 1);

   を実行し、終了直前に

         #n = dllfunc("SetJapaneseCodePageMode", 0);

   を実行する。(終了直前の処理は無くても実害は無いけども)

 2.マクロをShift-JIS形式で保存し直す。


 だけの手はずになります。

 もうちょっとテストしてからまたβ版としてアップロードさせていただきます。

[ ]
RE:03324 dllfuncw と charset="iso-8859-No.03325
misono さん 12/07/27 10:00
 
とても、いいアイデアじゃないですか!
待ち遠しいです!
早くテストさせてください(笑い)。

[ ]
RE:03325 dllfuncw と charset="iso-8859-No.03326
秀まるお さん 12/07/27 11:24
 
 今アップロードしました。

 よろしくお願いします。

32bit版:
http://hide.maruo.co.jp/software/bin/hmmail579b2_signed.exe

64bit版:
http://hide.maruo.co.jp/software/bin/hmmail579b2_x64_signed.exe

 メールの内容書き換えとかもテストしたので一応大丈夫だと思います。

注意点としては…

 SetJapaneseCodePageMode関数を呼び出すとメール内容枠がリフレッシュされ
て、結果としてカーソル位置がリセットされたり範囲選択が解除されたりする欠
点があります。

[ ]
RE:03326 dllfuncw と charset="iso-8859-No.03327
misono さん 12/07/27 13:23
 
今テストをはじめたところですが、おおむね満足
しています。

これは、難しいようであればかまいませんが、以下のマクロがあるとき、
SetJapaneseCodePageMode(0) でコードページを解除しても
変数に代入されている文字コードを維持することは可能でしょうか。

たとえばSetJapaneseCodePageMode の第2パラメータで 保持する/破棄する が
設定できればと思ったのですが・・・。
複数DLLだと(コーディング次第ですが)、ちょっと取り回しが面倒かなと思いま
して。

ちなみに複数DLLの同時ロードの仕方は知っています。

loaddll "tkinfo.dll";
#n = dllfunc("SetJapaneseCodePageMode", 1);
$str = dllfuncstr("CurrentFolder");
#n = dllfunc("SetJapaneseCodePageMode", 1);
loaddll "testdll.dll";
#n = dllfuncw("TestFuncW", $str);

[ ]
RE:03327 dllfuncw と charset="iso-8859-No.03328
秀まるお さん 12/07/27 14:40
 
 変数の中に入っている文字列のコードページは、SetJapaneseCodePageModeで
パラメータに1を指定しても0を指定してもずっと変わらず、932のままです。

 マクロファイルをShift-JISで作成してる場合は、基本的に文字列変数の内容
は日本語932前提ってことになります。

 何を心配されてるのかちょっと分かりませんが、例えばloaddllで複数DLLを切
り替えてロードする時に、自動的に直前にロードしてたdllがfreeされてしまう
とまずいことがあるってことでしょうか。もしそうだとしたら、とりあえず
tkinfo.dllについてはfreeされてまずいことは何も無いので、それについては心
配はいらないです。

 書いていただいたサンプルマクロも意味がいまいとつ分かりませんが、
SetJapaneseCodePageMode関数呼び出しはマクロの先頭で1回実行したらいいだ
けでして、2回呼び出す必要は無いです。

loaddll "tkinfo.dll";
#n = dllfunc("SetJapaneseCodePageMode", 1);
$str = dllfuncstr("CurrentFolder");
#n = dllfunc("SetJapaneseCodePageMode", 1);          …2回目は不要

[ ]
RE:03328 dllfuncw と charset="iso-8859-No.03329
misono さん 12/07/27 15:00
 
> 何を心配されてるのかちょっと分かりませんが、例えばloaddllで複数DLLを切
>り替えてロードする時に、自動的に直前にロードしてたdllがfreeされてしまう
>とまずいことがあるってことでしょうか。もしそうだとしたら、とりあえず
>tkinfo.dllについてはfreeされてまずいことは何も無いので、それについては心
>配はいらないです。

説明不足ですいません。
マクロ終了直前に

>#n = dllfunc("SetJapaneseCodePageMode", 1);          …2回目は不要

を呼び出すことが気になっていまして、
実害はないと書かれていますので、そうなのだとは思いますが、

これを呼び出すタイミングについて
複数DLLをロードする場合で、それを loaddll 文で行う場合、
どのタイミングにするか・・・といった話です。

loaddll "tkinfo.dll";
#n = dllfunc("SetJapaneseCodePageMode", 1);
$str = dllfuncstr("CurrentFolder");
#n = dllfunc("SetJapaneseCodePageMode", 1);
loaddll "testdll.dll";
#n = dllfuncw("TestFuncW", $str);

TestFuncWが呼ばれた時点では文字列はiso-8859-1になっています。
(当たり前といえばそうですが)


すいません、ちょっと書いていて、この要望は、普通あり得ないなと思うように
なりました。


複数dllを扱うときは loaddll 関数で対応します。

[ ]
RE:03329 dllfuncw と charset="iso-8859-No.03330
秀まるお さん 12/07/27 15:14
 
> TestFuncWが呼ばれた時点では文字列はiso-8859-1になっています。
> (当たり前といえばそうですが)

 すみません。テストしたら状況理解出来ました。

 実は、$str自体はマルチバイト文字列(Shift-JIS前提)の文字列で内部的に
は保持してるんですが、dllfuncwやdllfuncstrwを呼び出す時は、その内部文字
列を、その呼び出しの瞬間にユニコードに変換します。

 この時、もしも秀丸エディタ相当部分が「エンコード種類=外国語」って状態
になっていると、実はShift-JISで入ってる文字列が外国語コードページの文字
列であるかのごとく解釈されて、結果としてdllfuncwに渡される文字列が化けま
す。

 なので、SetJapaneseCodePageModeでパラメータに0を渡すのは、マクロの一番
最後でないとまずいです。

 マクロが終了する時に読んで欲しいのは、パラメータに「0」を指定しての
SetJapaneseCodePageMode呼び出しでして、たとえば、

loaddll "tkinfo.dll";
#n = dllfunc("SetJapaneseCodePageMode", 1);
$str = dllfuncstr("CurrentFolder");
loaddll "testdll.dll";
#n = dllfuncw("TestFuncW", $str);
loaddll "tkinfo.dll";
#n = dllfunc("SetJapaneseCodePageMode", 0);

 みたいな形にすればいいです。(loaddllが多くてすみませんが)

[ ]
RE:03330 dllfuncw と charset="iso-8859-No.03331
秀まるお さん 12/07/27 15:21
 
 それと、マクロの最後に

    #n = dllfunc("SetJapaneseCodePageMode", 0);

 を実行して欲しいと書いてありますが、別にこれはやらなくても大した問題は
無いです。

 これを実行しないでおくと、日本語コードページのままで外国語メールを表示
したような状態に内部的になってしまってるということで、それで何か実害があ
るかというと、特にはありません。

 また、その状態で何か別のメールを選択すると、そのタイミングで自動的に
「コードページ=日本語固定のモード」はOFFに戻ります。

 とりあえずマクロの先頭で

    loaddll "tkinfo.dll";
    #n = dllfunc("SetJapaneseCodePageMode", 1);

 を実行してくれさえすれば問題無いです。この作戦でお願いします。

[ ]
RE:03331 dllfuncw と charset="iso-8859-No.03332
misono さん 12/07/27 15:30
 
OK です!!

丁寧にご対応くださりありがとうございます。
実害がないということの意味が理解できましたので、
自前のマクロではマクロ終了直前の方は書かないでおきたいと思います。
SetJapaneseCodePageMode "だけ" するためにloaddllするのは自前のマクロでは
必要ないので、

本当にありがとうございます。

[ ]