我将继续对此进行总结,如何使用作为类成员的对话程序?我正在创建一个窗口包装类,但是CreateDialogParam
需要一个全局对话框程序,所以我尝试了这个解决方法:
我已经对这个话题进行了一些搜索。我正在创建一个Dialog
类,我将其子类化为CMainWnd
,然后实例化它。在Dialog
类中,我有一个定义为INT_PTR CALLBACK Dialog::cb_proc(HWND,UINT,WPARAM,LPARAM)
的成员函数。现在,我知道windows必须具有全局函数作为回调过程。
所以我创建了一个std::map<HWND,Dialog*> DlgProcs
映射来将对话框窗口句柄与其Dialog类指针相关联。
INT_PTR CALLBACK DlgMainProc(HWND,UINT,WPARAM,LPARAM)
我可以将其传递给CreateDialogParam()
。在DlgMainProc(...)
正文中,我搜索地图以使用hWnd
参数查找Dialog*
并返回其cb_proc(..)
成员。
我的问题是没有处理任何消息,这是因为我的Dialog
类中的成员过程永远不会被调用。即使当我在MessageBox()
语句中放置DlgMainProc
时,也会一遍又一遍地显示消息框,直到我不得不从Visual Studio 2008中止该程序。这告诉我它正在我的地图中找到if (DlgProcs.find(hWnd) != DlgProcs.end()) {
。奇怪的是,如果我把它放在hWnd
语句之后也会这样做,这反过来告诉我它没有在地图中找到else
。
如果我在hWnd
成员函数中放置了一个消息框,则根本不会显示它。但在此期间,我从未得到任何编译器,链接器或运行时错误。当我从中删除消息框(因为不必中止程序,它只是为了调试目的)程序运行但没有消息得到处理,X按钮不关闭程序,按钮点击什么都不做。
以下是PasteBin代码:http://pastebin.com/GsGUBpZU
顺便说一句,我没有问题继承这个,我的窗口创建得很好,只是没有处理任何消息,cb_proc
永远不会被调用。
编辑:以下是代码的相关部分
cb_proc
有人知道为什么它永远不会被召唤?或者只是引导我使用成员函数作为DLGPROC的另一种方式?
答案 0 :(得分:3)
标准解决方案是将您的this
指针作为最后一个参数传递给Create,DialogParam
,将其存储在DWLP_USER
处理程序的WM_INITDIALOG
中,并从{{{{}}中检索它之后1}}。基本上你使用DWLP_USER
作为地图。
答案 1 :(得分:2)
我尝试了你的代码并且它有效:cb_proc
被调用。您将错过在WM_INITDIALOG
返回之前发送的所有邮件(例如CreateDialogParam
)。
您可以通过在g_MainDlgProc
中将窗口句柄和对象添加到地图来解决后一个问题。如果您收到未知窗口的消息,则表示它属于您正在创建的窗口;将对象放在全局中,您可以将句柄/对象添加到地图中。
答案 2 :(得分:0)
我只是在这里添加它,以防有人发现它有用;使用C ++ 11 lambda和模板的魔力,你可以有一个简单的包装模板,这意味着你不必不断重写样板代码,以便在窗口和对话框程序中保存和加载用户数据。
以下是DialogBoxParam
函数的示例,但同样的技术也适用于CreateDialogParam
和CreateWindowEx
。
template <typename T, INT_PTR (T::*P)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)>
INT_PTR DialogBoxThis(T* pThis, HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent)
{
return ::DialogBoxParam(hInstance, lpTemplateName, hWndParent, [](HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -> INT_PTR {
if (uMsg == WM_INITDIALOG) SetWindowLongPtr(hWnd, DWLP_USER, lParam);
T* pThis = reinterpret_cast<T*>(GetWindowLongPtr(hWnd, DWLP_USER));
return pThis ? (pThis->*P)(hWnd, uMsg, wParam, lParam) : FALSE;
}, reinterpret_cast<LPARAM>(pThis));
}
您可以这样使用它:
class MyClass
{
INT_PTR MyDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
};
// from inside MyClass, we can show a dialog that uses member function MyDlgProc as the dialog procedure
// note it is NOT a static function
DialogBoxThis<MyClass, &MyClass::MyDlgProc>(this, hInstance,
MAKEINTRESOURCE(IDD_MYDIALOG), hWndParent);