Use class member as WNDPROC/DLGPROC with or without global

自闭症网瘾萝莉.ら 提交于 2019-11-28 02:18:01

I tried your code and it worked: cb_proc gets called. You will miss any messages (e.g. WM_INITDIALOG) that get sent before CreateDialogParam returns.

You can fix the latter problem by adding the window handle and the object to the map in g_MainDlgProc. If you get a message for an unknown window, you know it belongs to the window you're creating; put the object in a global and you can add the handle/object to the map.

The standard solution is to pass your this pointer as the last parameter to Create,DialogParam, stash it in DWLP_USER in your WM_INITDIALOG handler, and retrieve it from DWLP_USER thereafter. Basically you use DWLP_USER as your map.

I'm just adding this here in case someone finds it useful; using the magic of C++11 lambdas and templates you can have a simple wrapper template that means you don't have to continually rewrite the boiler-plate code for saving and loading userdata in window and dialog box procedures.

Here's an example for the DialogBoxParam function, but the same technique can be applied to CreateDialogParam and CreateWindowEx as well.

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));
}

You would use it like this:

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);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!