C++ 包装对话框过程

C++ 包装对话框过程,c++,winapi,modal-dialog,C++,Winapi,Modal Dialog,我一直在使用包装对话框过程的标准方法,在类中使用静态对话框过程,以及以后派生的纯虚拟对话框过程。这很好,但我有一些设计问题。考虑我的静态对话过程的定义: INT_PTR __stdcall ModalDialog::router(HWND dlg, UINT msg, WPARAM wp, LPARAM lp) { ModalDialog *thisPtr = 0; if (msg == WM_INITDIALOG) { thisPtr = reinte

我一直在使用包装对话框过程的标准方法,在类中使用静态对话框过程,以及以后派生的纯虚拟对话框过程。这很好,但我有一些设计问题。考虑我的静态对话过程的定义:

INT_PTR __stdcall ModalDialog::router(HWND dlg, UINT msg, WPARAM wp, LPARAM lp)
{
    ModalDialog *thisPtr = 0;

    if (msg == WM_INITDIALOG)
    {
        thisPtr = reinterpret_cast< ModalDialog *>(lp);

        ::SetWindowLongPtr(dlg, DWLP_USER, reinterpret_cast< LONG_PTR >(thisPtr));

        thisPtr->_dlg = dlg;

        return static_cast< INT_PTR >(TRUE);
    }
    else
        thisPtr = reinterpret_cast< ModalDialog *>(::GetWindowLongPtr(dlg, DWLP_USER));

    if (thisPtr)
        //the virtual procedure from which to derive from
        return thisPtr->proc(msg, wp, lp);
    else
        //return false when not processing a message, look we should
        return static_cast< INT_PTR >(FALSE);
}
如果我放弃虚拟对话框过程,并像这样更改静态,是否可以:

INT_PTR __stdcall ModalDialog::router(HWND dlg, UINT msg, WPARAM wp, LPARAM lp)
{
    ModalDialog *thisPtr = 0;

    if (msg == WM_INITDIALOG)
    {
        thisPtr = reinterpret_cast< ModalDialog *>(lp);

        ::SetWindowLongPtr(dlg, DWLP_USER, reinterpret_cast< LONG_PTR >(thisPtr));

        thisPtr->_dlg = dlg;

        //ADDED
        onInitDialog(dlg);

        return static_cast< INT_PTR >(TRUE);
    }
    else
        thisPtr = reinterpret_cast< ModalDialog *>(::GetWindowLongPtr(dlg, DWLP_USER));

    //ADDED
    switch (msg)
    {
    case WM_COMMAND:
        if (thisPtr && thisPtr->onCommand(dlg, HIWORD(wp), LOWORD(lp)))
            return static_cast< INT_PTR >(TRUE);
        break;
    case WM_CLOSE:
        if (thisPtr && thisPtr->onClose(dlg))
            return static_cast< INT_PTR >(TRUE);
        break;
    defualt:
        return static_cast< INT_PTR >(FALSE);

    //if (thisPtr)
    //    return thisPtr->proc(msg, wp, lp);
    //else
    //    return static_cast< INT_PTR >(FALSE);
}
INT\u PTR\u stdcall ModalDialog::router(HWND dlg、UINT msg、WPARAM wp、LPARAM lp)
{
ModalDialog*thisPtr=0;
if(msg==WM_INITDIALOG)
{
该PTR=重新解释铸造(lp);
::SetWindowLongPtr(dlg、DWLP_用户、重新解释_cast(thisPtr));
这个ptr->_dlg=dlg;
//增加
onInitDialog(dlg);
返回static_cast(TRUE);
}
其他的
thisPtr=reinterpret_cast(::GetWindowLongPtr(dlg,DWLP_用户));
//增加
开关(msg)
{
case WM_命令:
if(thisPtr&&thisPtr->onCommand(dlg、HIWORD(wp)、LOWORD(lp)))
返回static_cast(TRUE);
打破
案例WM_结束:
if(thisPtr&&thisPtr->onClose(dlg))
返回static_cast(TRUE);
打破
解散:
返回静态\u cast(假);
//如果(本PTR)
//返回此PTR->proc(消息、wp、lp);
//否则
//返回静态\u cast(假);
}
这样,在基类中,我只需要重新定义虚拟的“on…”命令?我还注意到::EndDialog(thisPtr->\u dlg,0)只在WM_CLOSE上工作?我是否仍然需要像这样分配thisPtr中的_dlg:thisPtr->\u dlg=dlg


感谢您提供的任何帮助。

这会降低灵活性-最好从虚拟对话框过程调用事件处理程序,允许您覆盖单个子类的行为。如果您需要这些“事件处理程序”要在默认情况下为ModalDialog的所有子类调用,只需不要使虚拟对话框过程纯虚拟-也为ModalDialog实现它,并从子类显式调用它

ModalDialog::dialogProc(...) {
  switch (...) {
  case ...: onInitDialog(...); break;
  }
}

ModalDialogSubClass::dialogProc(...) {
  switch (...) {
  case ...: break;
  default: return ModalDialog::dialogProc(...);
}
在这种情况下,您可以决定在该基类的
dialogProc
中不调用特定基类的
onInitDialog

通常,您希望在静态过程中执行的操作很简单:

if (is first message) {
  SetWindowLong...
}
((ModalDialog *) GetWindowLong())->dialogProc(); // Also for the initial message

是的,我也是这样做的,总是调用
GetWindowLongPtr
,如果为空,则调用
SetWindowLongPtr
,无论第一条消息是什么。但是,这对我来说很有效,因为我是新的(std::nothrow)类实例在内部,而不是通过LPRAM传递,这可能不适用于rem45acp的方法,因为他似乎在外部创建类并传入指针,并且收到的第一条消息可能不是WM_INITDIALOG,它具有来自CreateDialogParam的数据指针。
if (is first message) {
  SetWindowLong...
}
((ModalDialog *) GetWindowLong())->dialogProc(); // Also for the initial message