绑定对话框过程作为自定义类的方法

时间:2015-07-19 18:46:48

标签: c++ winapi

我正在尝试绕过WINAPI来实现无模式Dialog窗口的过程作为自定义类的成员。我不确定这是可能的,但我希望有人知道。目标是让一个过程可以访问自定义类

的成员变量

我知道可以使用普通的窗户。 示例

//MyClass.h
class MyClass
{
    public:
    bool init( ... )
    static LRESULT CALLBACK    redirect(HWND hWnd, UINT msg,
                                          LPARAM lParam, WPARAM wParam);
    LRESULT myWndProc(HWND hWnd, UINT msg,
                      LPARAM lParam, WPARAM wParam);

    private:
    HWND m_MainHwnd;
}

通过定义将指针重定向到非静态实际过程处理的静态成员函数,该过程可以是成员函数:

//MyClass.cpp
MyClass::init( ... )
{
    //Create the window class for the main Window//
    m_windowed = windowed;
    WNDCLASSEX wc;  //Create a new extended windows class

    wc.cbSize = sizeof(WNDCLASSEX); //Size of our windows class
    wc.style = CS_HREDRAW | CS_VREDRAW; //class styles
    wc.lpfnWndProc = MyClass::redirect; //Default windows procedure function
    wc.cbClsExtra = NULL;   //Extra bytes after our wc structure
    wc.cbWndExtra = NULL;   //Extra bytes after our windows instance
    wc.hInstance = hInstance;   //Instance to current application
    wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); //Title bar Icon
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);   //Default mouse Icon
    wc.hbrBackground = CreateSolidBrush(0xFFFFFF);  //Window bg color
    wc.lpszMenuName = NULL; //Name of the menu attached to our window
    wc.lpszClassName = m_windowName;    //Name of our windows class
    wc.hIconSm = LoadIcon(NULL, IDI_WINLOGO); //Icon in your taskbar

    if (!RegisterClassEx(&wc))  //Register our windows class
    {
        //if registration failed, display error
        MessageBox(NULL, "Error registering Main Window class",
            "Error", MB_OK | MB_ICONERROR);
        return false;
    }

    m_MainHwnd = CreateWindowEx(    //Create our Extended Window
        NULL,   //Extended style
        m_windowName,   //Name of our windows class
        m_windowName,   //Name in the title bar of our window
        WS_OVERLAPPEDWINDOW | WS_VISIBLE,   //style of our window | Make it              visible on showWindow cmd
        30, 30, //Top left corner of window
        width,  //Width of our window
        height, //Height of our window
        NULL,   //Handle to parent window
        NULL,   //Handle to a Menu
        hInstance,  //Specifies instance of current program
        this    //used for an MDI client window
    );
}

请参阅WNDCLASSEX设置中的行: wc.lpfnWndProc = MyClass :: redirect; ?这是有效的,因为以下实现了重定向静态函数:

MyClass::redirect(HWND hwnd, UINT msg, LPARAM lParam, WPARAM wParam)
{
    if (msg == WM_CREATE)  SetWindowLongPtr(hwnd, GWL_USERDATA, (LONG_PTR)((CREATESTRUCT FAR *)lParam)->lpCreateParams);
    MyClass * pObject = (MyClass*)((LONG_PTR)GetWindowLongPtr(hwnd, GWL_USERDATA));
    if (pObject) return pObject->MyWndProc(hwnd, msg, wParam, lParam);

    //return the message for windows to handle it
    return DefWindowProc(hwnd,
        msg,
        wParam,
        lParam);
};

这使您可以像任何其他成员方法一样实现MyWndProc(...)。

现在!我真的希望能够对我的无模式对话框执行相同的操作 - 因为它知道“MyClass”的成员变量非常重要。另外 - 我喜欢我可以设计它并按照我的喜好重新设计它(如果我必须使用普通的窗口 - 在代码中设计它是很乏味的。)

有可能吗?

提前谢谢!

1 个答案:

答案 0 :(得分:2)

是的,可以在对话框中使用此方法,方式大致相同。

而不是使用WM_CREATE存储this指针,而是使用WM_INITDIALOG。请注意,用户数据会传递到WM_INITDIALOG本身的lParam - 没有与WM_CREATE一样的解除引用结构。

您可以将指针存储在DWLP_USER中,这是对话框所有者可用的指针大小窗口数据槽。

如果数据指针尚未分配,则最终的差异只是返回FALSE - 您不会从对话程序中调用DefWindowProc

class MyClass
{
public:
        static INT_PTR CALLBACK dlgRedirect(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
        LRESULT myDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
}

//...
HWND hwndDlg = DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_MYDIALOG), hwndParent,
    MyClass::dlgRedirect, reinterpret_cast<LPARAM>(this));

//...
INT_PTR CALLBACK MyClass::dlgRedirect(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    if (uMsg == WM_INITDIALOG) SetWindowLongPtr(hWnd, DWLP_USER, lParam);
    MyClass* pThis = reinterpret_class<MyClass*>(GetWindowLongPtr(hWnd, DWLP_USER));
    if (pThis) return pThis->myDlgProc(hWnd, uMsg, wParam, lParam);
    return FALSE;
}

INT_PTR MyClass::myDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    // real dialog procedure here
}