はじめまして.けんじ と申します.
Windows プログラミングは初心者ですが,最近になって,Windows7 上で
VC++2010 Express を使用して,Win32 プログラムを書いています.
CreateDialog() でダイアログを生成しているのですが,あるソフトのプラグインで,
メッセージループに直接手を入れられないので,
http://support.microsoft.com/kb/233263/ja
を参考にしながら,
hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, NULL,
GetCurrentThreadId());
でフックして,TAB キーなどを拾うようにしています.
この状態で,生成したダイアログに貼り付けてあるエディットボックスに日本語を
入力すると,「あ」→「・」のような文字化けを起こしてしまいます.
SetWindowsHookEx() の呼び出しを止めると文字化けは起こしません.
マルチバイト文字セットでビルドしているのを Unicode 文字セットに切り替えれば,
大丈夫なことは分かったのですが,マルチバイト文字セットのままでは文字化けする
のは避けられないのでしょうか?
SetWindowsHookExが#defineであることは確認してみましたか。
この関数にはMBCS用とUnicode用の2つの実体があります。
winuser.hを参照してみてください。
さて、このようにMBCS用とUnicode用が用意されている関数は
直接実行することができ、それ用(MBCS/Unicode)の動作を
実行します。
これは、それが含まれるプロジェクトのオプションとは
独立しています。
仲澤@失業者 さん,アドバイスありがとうございます.
SetWindowsHookEx() がマクロだとは思っていませんでした.
確認したところ,現状は,MBCS でビルドしているので,
#define SetWindowsHookEx SetWindowsHookExA
側が採用されていました.
そこで,呼び出し側を明示的に SetWindowsHookExW() に変え
てみたのですが,「あ」→「B」のように化け方が変わったも
のの,正しい結果にはなりませんでした.
ANSI でも UNICODE でもなく,MBCS で使っているので上手く
いってないということは理解できたのですが,MBCS のまま,
解決する方法はあるのでしょうか?
何を応えてよいのかわかりませんが、
例えば、単にテキストボックスに文字を設定する場合は
SetWindowText( hWnd, 文字列);
となります。
説明の繰り返しになりますが、このSetWindowTextも
マクロなんですけど確認しましたでしょうか。
文字列の部分にCStringを使う場合も、それの実体
CStringAとCStringWのどちらかを選択できます。
てな感じなんですけど、どうでしょう。
仲澤@失業者 さん,ありがとうございます.
ポイントを上手く説明できておらず申し訳ないのですが,いまのところ,
(いろいろ削った結果) ダイアログボックスには,エディットボックスが
あるだけで,とくに処理はしていません.
タイプした日本語文字列が,そのままエディットボックスに表示されるだ
けで良いのですが,MBCS でビルドした場合には入力した文字列が化けて
しまう,という状況です.
キー入力したものをそのまま,表示したいだけで,SetWindowText() など
は使っていないのですが,どこかで暗黙的に呼ばれているのでしょうか?
コードは以下のようになっています.
--------
[test.cpp (抜粋)]
hdlg = CreateDialog(
(HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),
MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogProc);
/* .... */
BOOL CALLBACK DialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
switch (msg) {
case WM_INITDIALOG:
hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, NULL,
GetCurrentThreadId());
return TRUE;
case WM_CLOSE:
DestroyWindow(hdlg);
hdlg = NULL;
return TRUE;
}
return FALSE;
}
--------
[test.rc (全体)]
#include <windows.h>
#include resource.h
LANGUAGE LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN
IDD_DIALOG1 DIALOG 0, 0, 280, 28
STYLE DS_3DLOOK | DS_CENTER | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP
| WS_THICKFRAME | WS_SYSMENU
EXSTYLE WS_EX_WINDOWEDGE
CAPTION TEST
FONT 10, MS UI Gothic
{
EDITTEXT IDC_EDIT1, 5, 7, 270, 15, ES_AUTOHSCROLL, WS_EX_TRANSPARENT
}
--------
え~と、3回目になっちゃいますけど
CreateDialog()もマクロなんですね(vv;)。
つまり、ウインドウはMBCSとUnicodeにはっきりと分かれてしまうのです。
もう一回提案しますが、まに受けてくれることを祈っています(合掌)。
「winuser.hを開いて、使用しようとしている関数の定義を参照しましょう」
ところで、MBCSにしたい理由とは何でしょう。
UnicodeウインドウのコントロールはMBCSの実行ファイルでも可能ですが、
直接、又は間接的に文字列を使用している全ての部分にこれらの仕組みが
利いてくるのは、すでにお察しの通りです。
それは、大変に困難で見返りの少ない道だとの認識ですので
やや大変心配です。
×やや大変心配です。
○やや心配です。
・・・orz.
仲澤@失業者 さん,度々お付き合いいただき,ありがとうございます.
ご指摘いただいたように,マクロで隠蔽されているところを探していっ
たところ,無事解決することが出来ました.
結局,修正が必要だったのは,
・SetWindowsHookEx → SetWindowsHookExW
・(GetMsgProc 内の) IsDialogMessage → IsDialogMessageW
の2箇所でした.この変更により,文字化けせずに表示できるようになり
ました.
> ところで、MBCSにしたい理由とは何でしょう。
プラグイン用の SDK として提供されているユーティリティ関数群が MBCS
じゃないとビルドできない,というのが理由でした.ソースで提供され
ている部分なので,自分で Unicode 対応にしてしまえば良さそうではあ
るのですが,バグも入りそうですし,できれば余計なことはせずに MBCS
のまま通してしまいたかったので助かりました.
ありがとうございました.