c++ - 将对话框过程作为方法绑定(bind)到自定义类

标签 c++ winapi

<分区>

我正在尝试围绕 WINAPI 工作,以将无模式对话框窗口的过程作为自定义类的成员来实现。我不确定这是否可能,但我希望有人知道一种方法。目标是有一个过程可以访问自定义类的成员变量

我知道可以使用普通窗口。 示例:

//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”的成员变量是相当重要的。另外 - 我喜欢我可以设计它并按照我喜欢的方式重新设计它(如果我必须使用普通窗口 - 在代码中设计它会很乏味。)

这可能吗?

提前致谢!

最佳答案

是的,可以以大致相同的方式将此方法用于对话框。

不是使用 WM_CREATE 来存储 this 指针,而是使用 WM_INITDIALOG。请注意,用户数据在 lParam 本身中传递给 WM_INITDIALOG - 没有像 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
}

关于c++ - 将对话框过程作为方法绑定(bind)到自定义类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31504685/

相关文章:

c++ - 使用 jsoncpp 从 JSON 中获取节点的问题

c++ - 练习 : calculate the variance using arrays

c++ - 从宏生成和保存代码

winapi - windows API函数在哪里定义的?

c++ - 链接某些 Windows API 时出现链接器错误

c++ - 使用 libcurl 下载功能,但它不完整

c# - Powershell 使用来自 Add-Type 的 C# 代码使 shell 崩溃 (SystemParamtersInfo)

c++ - C++ pi 近似的不同输出

windows - 除了 "flags"参数外,ChildWindowFromPointEx 和 ChildWindowFromPoint 有何不同?

c++ - Opencv张量积