包装对话程序

时间:2011-04-01 23:02:21

标签: 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 = 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);
}

假设我想将以下虚拟方法添加到ModalDialog基类:

virtual bool onInitDialog(HWND dlg) = 0;
virtual bool onCommand(HWND dlg, int high_word, int low_word) = 0;
virtual bool onClose(HWND dlg) = 0;

如果我放弃了虚拟对话框程序,并且像这样更改了静态,那会没事吗:

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

在基类中我只需重新定义虚拟“on ...”命令?我还注意到:: EndDialog(thisPtr-&gt; _dlg,0)仅适用于WM_CLOSE?我还需要像这样从thisPtr分配_dlg:thisPtr-&gt; _dlg = dlg?

感谢您提供任何帮助。

1 个答案:

答案 0 :(得分:2)

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

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

ModalDialogSubClass::dialogProc(...) {
  switch (...) {
  case ...: break;
  default: return ModalDialog::dialogProc(...);
}

鉴于这种情况,您可以决定调用onInitDialog,以获取该基类的dialogProc中的特定基类。

通常,您希望在静态过程中执行的操作只是:

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