c++ - 包装对话过程

标签 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;

如果放弃虚拟对话过程,把static改成这样可以吗:

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->_dlg,0) 只适用于 WM_CLOSE?我还需要像这样从 thisPtr 分配 _dlg 吗:thisPtr->_dlg = dlg?

感谢您提供的任何帮助。

最佳答案

这会降低您的灵 active - 最好从虚拟对话过程调用事件处理程序,从而允许您覆盖各个子类的行为。如果您希望默认情况下为 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

关于c++ - 包装对话过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5519767/

相关文章:

javascript - 如何使用模式在同一页面上添加多个幻灯片?

c++ - 如何在 QComboBox 上设置不可选择的默认文本?

c++ - 如何在 win32 中更改工具栏按钮的位图?

c++ - Win32 exe 找不到在 .lib 中编译的资源

javascript - 如何使用 Zurb Foundation 显示打开、打开、关闭、关闭回调函数?

java - 为什么在模式对话框关闭之前不调用 done()?

c++ - mem_fn & bind 的一些实际用途

c++ - CudaMalloc 分配内存时失败

c++ - 使用 std::tuple 从 map 中输出

c++ - 如何使用Win32线程池API?