クラスのメンバーであるダイアログ プロシージャを使用するにはどうすればよいでしょうか。ウィンドウ ラッパー クラスを作成していCreateDialogParam
ますが、グローバル ダイアログ プロシージャが必要なので、次の回避策を試しました。
このトピックについて少し検索しました。私Dialog
はサブクラスCMainWnd
化してインスタンス化するクラスを作成しています。クラスには、Dialog
として定義されたメンバー関数がありますINT_PTR CALLBACK Dialog::cb_proc(HWND,UINT,WPARAM,LPARAM)
。これで、ウィンドウにはコールバック プロシージャとしてグローバル関数が必要であることがわかりました。
そこでstd::map<HWND,Dialog*> DlgProcs
、ダイアログ ウィンドウ ハンドルをその Dialog クラス ポインタに関連付けるマップを作成しました。
そして、INT_PTR CALLBACK DlgMainProc(HWND,UINT,WPARAM,LPARAM)
私はそれをに渡すことができましたCreateDialogParam()
。の本体で、パラメーターをDlgMainProc(...)
使用してマップを検索し、そのメンバーを見つけて返します。hWnd
Dialog*
cb_proc(..)
私の問題は、メッセージが処理されないことです。これは、Dialog
クラスのメンバープロシージャが呼び出されないためです。MessageBox()
ステートメントのDlgMainProc
中に aを入れるif (DlgProcs.find(hWnd) != DlgProcs.end()) {
と、Visual Studio 2008 からプログラムを中止しなければならなくなるまで、何度も何度もメッセージ ボックスが表示されhWnd
ます。奇妙なことは、その後のステートメントにそれを入れると、これも実行されることです。これは、マップでelse
が見つからないことを矛盾して伝えています。hWnd
メンバー関数にメッセージ ボックスを配置すると、cb_proc
まったく表示されません。しかし、この間、コンパイラ、リンカー、または実行時エラーが発生することはありません。そこからメッセージボックスを削除すると (プログラムを中止する必要がないため、デバッグ目的のためだけでした)、プログラムは実行されますが、メッセージは処理されず、X ボタンはプログラムを閉じず、ボタンのクリックは何もしません。
PasteBin コードは次のとおりです: http://pastebin.com/GsGUBpZU
ところで、これをサブクラス化しても問題ありません。ウィンドウは正常に作成され、メッセージは処理されず、cb_proc
呼び出されません。
編集:コードの関連部分は次のとおりです
map<HWND,Dialog*> g_DlgProcs;
INT_PTR CALLBACK g_MainDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
if (g_DlgProcs.find(hWnd) != g_DlgProcs.end()) {
Alert("blah"); // Gets executed repeatedly
return g_DlgProcs[hWnd]->cb_proc(hWnd, msg, wParam, lParam);
} else {
Alert("blah"); // Removing the above alert, this gets
// executed repeatedly, erm, as well.. O.o strange
return FALSE;
}
}
Dialog::Dialog(int id, HWND parent /* = HWND_DESKTOP */) {
_id = id;
_parent = parent;
// Tried this before CreateDialogParam
g_DlgProcs.insert(make_pair(_handle, this));
_handle = CreateDialogParam(
(HINSTANCE)GetModuleHandle(NULL),
MAKEINTRESOURCE(id), _parent,
(DLGPROC)g_MainDlgProc, NULL
);
// Then tried it after CreateDialogParam
g_DlgProcs.insert(make_pair(_handle, this));
}
INT_PTR CALLBACK Dialog::cb_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
Alert("blah"); // Never gets executed
bool handled = true;
switch (msg)
{
case WM_INITDIALOG:
OnInitialize();
break;
case WM_COMMAND:
if (HIWORD(wParam) == 0 || HIWORD(wParam) == 1) {
OnMenuCommand((HIWORD(wParam) == 1), (int)LOWORD(wParam));
} else {
OnCtrlCommand((int)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam);
}
break;
case WM_NOTIFY:
{
LPNMHDR head = (LPNMHDR)lParam;
OnNotification(head->code, head->idFrom, head->hwndFrom);
}
break;
case WM_CLOSE:
OnClose(); // DestroyWindow(_handle)
break;
case WM_DESTROY:
OnDestroy(); // PostQuitMessage(0)
default:
handled = ProcessMsg(msg, wParam, lParam);
}
// Convert bool to Windows BOOL enum
return ((handled == true) ? TRUE : FALSE);
}
なぜ呼び出されないのか誰か知っていますか?または、メンバー関数を DLGPROC として使用する別の方法を教えてください。