如何将控件封装在可放置在MFC中的对话框的窗口中?

时间:2017-12-03 03:15:13

标签: mfc

我希望有一个窗口放在一个可以包含另一个控件的对话框中。这样做的原因是我可以让封装控件超过对话框中已分配区域的大小,并具有独立的滚动条以查看完整控件。

这个描述听起来应该有一些已经为此做的事情。那是对的吗?如果是这样,它是什么?如果没有,我将如何做到这一点?

修改

等等,我看到了这个。带标签页。这些实际上创建了一个对话框,该对话框是主对话框的父级。如果页面太小,则会显示滚动条。所以这是可能的,只需要弄清楚如何。玩VS,有一个自定义控件可能正是我正在寻找的。

1 个答案:

答案 0 :(得分:1)

要将控件封装在对话框中以在对话框中使用,请执行以下操作:

  1. 创建对话框资源并将其清空(即删除其上的所有控件)并设置以下标志:

    • 外观

      • 边框: 精简
      • 风格: 儿童
      • 标题栏: 错误 //自动
    • 行为

      • 申请窗口: 错误 //自动
    • 其它
      • 控件: True
      • ID: IDD_CONTROL_WRAPPER (或任何您想要的内容)

    这将是包装器对话框。

  2. 为包装器对话框创建一个类(右键单击对话框并选择 Add Class ... ),我将把它称为CControlWrapper以获取这些指令。

  3. 在你的包装器对话框中,将你想要封装的控件添加到你的类中,并添加一个与它关联的变量(在我的例子中,我将使用一个id为IDC_WRAPPED_CTRL的列表框和成员变量名m_ctrl)。
  4. 使其成为控件占据对话框的整个空间:

    1. ON_WM_SIZE()消息添加到您的包装器对话框的消息映射中。
    2. 创建OnSize()功能。
    3. 或使用向导。您的OnSize()函数应如下所示:

      void CControlWrapper::OnSize(UINT nType, int cx, int cy)
      {
          CDialogEx::OnSize(nType, cx, cy);
          if (m_ctrl.m_hWnd)
              m_ctrl.SetWindowPos(nullptr, 0, 0, cx, cy, SWP_SHOWWINDOW);
      }
      

      您可以将控件的大小更改为您想要的任何值。使其变大只会使控件被剪裁。

    4. 如果您还没有这样做,请创建主对话框类。
    5. 将包装好的对话框控件作为变量添加到主对话框类中(在本例中,我称之为m_childDlg)。
    6. 在主对话框的OnInitDialog()功能中创建对话框。

      m_childDlg.Create(IDD_CONTROL_WRAPPER, this);
      
    7. 设置它的位置和大小:

      m_childDlg.SetWindowPos(0, 8, 8, 500, 500, SWP_SHOWWINDOW);
      
    8. 就是这样!

      以下是您可以做的一些选项。

      1. 为了使你可以使用对话框编辑器将控件放在主对话框上,你可以使它成为封装控件可以将自己放在你指定的控件上:

        void CControlWrapper::CreateOvertop(CWnd* pParent, int originalId)
        {
            CreateOvertop(pParent, pParent->GetDlgItem(originalId));
        }
        
        void CControlWrapper::CreateOvertop(CWnd* pParent, CWnd* pOrignalWnd)
        {
            // Create the control wrapper
            Create(IDD_CONTROL_WRAPPER, pParent);
        
            // This two lines makes it so that the drawing zorder is respected
            ModifyStyle(0, WS_CLIPSIBLINGS);
            // Also this line stops the original window from having a tab stop,
            // if not cleared in dialog editor.
            pOrignalWnd->ModifyStyle(WS_TABSTOP, WS_CLIPSIBLINGS);
        
            // Position the control wrapper dialog control over the old control
            CRect rect;
            pOrignalWnd->GetWindowRect(rect);
            pParent->ScreenToClient(rect);
            // position this control over old control less border
            SetWindowPos(pOrignalWnd->GetWindow(GW_HWNDPREV)
                , rect.left + 2, rect.top + 2, rect.Width() - 4, rect.Height() - 4
                , SWP_SHOWWINDOW);
        }
        

        然后,在主对话框的OnInitDialog()中,您可以调用其中一个函数而不是CControlWrapper::OnCreate(),并且您的控件将使用它正在替换的控件的边框。

      2. 添加WRAPPED_CTRL* CControlWrapper::operator->(),以便您可以轻松访问包装的对象。
      3. 天空是极限......:)