Mfc 将垂直夹持器添加到对话框

Mfc 将垂直夹持器添加到对话框,mfc,Mfc,我不确定在这里向您显示什么代码。我的MFC应用程序中有一个CDialogEx派生资源: 它支持动态调整布局控件,因此用户可以调整窗口大小。但是我想添加一个垂直的抓取器(用红色表示),这样用户就可以使名称列的宽度变大 我对此做了一些研究,所有的文章都有近10年的历史,没有考虑到更新的动态调整控件 经过进一步研究,我发现“调整夹持器大小”一词并不是我的意思。这是右下角的图标。我不是这个意思 不过我相信你知道我的意思。有可能吗?添加自定义夹持器控件相对容易。请参见下面的CMySplittercla

我不确定在这里向您显示什么代码。我的MFC应用程序中有一个
CDialogEx
派生资源:

它支持动态调整布局控件,因此用户可以调整窗口大小。但是我想添加一个垂直的抓取器(用红色表示),这样用户就可以使名称列的宽度变大

我对此做了一些研究,所有的文章都有近10年的历史,没有考虑到更新的动态调整控件


经过进一步研究,我发现“调整夹持器大小”一词并不是我的意思。这是右下角的图标。我不是这个意思


不过我相信你知道我的意思。有可能吗?

添加自定义夹持器控件相对容易。请参见下面的
CMySplitter
class

但是,如果所有控件都在一个对话框中,则很难逐个重新定位/调整单个控件的大小

理想情况下,使用两个子对话框。在资源编辑器中为各个控件设置调整大小/重新定位属性。将夹点控件置于两个对话框之间,并相应调整大小

夹持器控制等级:

#include <functional>

class CMySplitter : public CStatic
{
public:
    class CPopup : public CWnd
    {
    public:
        CMySplitter *parent;
        int offset;
        void OnMouseMove(UINT flag, CPoint pt);
        void OnLButtonUp(UINT flag, CPoint pt);
        DECLARE_MESSAGE_MAP()
    };

    std::function<void(int)> callback;
    CRect boundary;
    CPopup popup;
    void OnLButtonDown(UINT flag, CPoint point);
    void PreSubclassWindow();
    void SetRange(int left, int right);
    DECLARE_MESSAGE_MAP()
};

//create splitter control from a static control in dialog
void CMySplitter::PreSubclassWindow()
{
    CStatic::PreSubclassWindow();

    //modify static control's style (must have SS_NOTIFY)
    SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_VISIBLE | SS_GRAYRECT | WS_CHILD | SS_NOTIFY);

    //create a popup window with transparency
    static CString classname =
        AfxRegisterWndClass(0, 0, (HBRUSH)GetStockObject(BLACK_BRUSH));
    popup.CreateEx(WS_EX_LAYERED | WS_EX_PALETTEWINDOW | WS_EX_NOACTIVATE,
        classname, NULL, WS_POPUP, CRect(0, 0, 0, 0), this, 0);

    popup.SetLayeredWindowAttributes(0, 128, LWA_ALPHA);
    popup.parent = this;
}

//when user click the static control, show a popup window
void CMySplitter::OnLButtonDown(UINT flag, CPoint pt)
{
    CStatic::OnLButtonDown(flag, pt);

    GetCursorPos(&pt);

    CRect rc;
    GetWindowRect(&rc);

    popup.offset = pt.x - rc.left;
    popup.SetWindowPos(NULL, rc.left, rc.top, rc.Width(), rc.Height(), SWP_SHOWWINDOW);
    popup.SetCapture();
}

//how far to the left and right the splitter can go
void CMySplitter::SetRange(int left_, int right_)
{
    CRect rc;
    GetParent()->GetWindowRect(&rc);
    boundary.left = rc.left + left_;
    boundary.right = rc.right - right_;
}

//move this popup window
void CMySplitter::CPopup::OnMouseMove(UINT flag, CPoint pt)
{
    CWnd::OnMouseMove(flag, pt);
    GetCursorPos(&pt);
    CRect rc;
    GetWindowRect(&rc);

    int x = pt.x - offset;
    if (x > parent->boundary.left && x < parent->boundary.right)
        SetWindowPos(NULL, x, rc.top, 0, 0, SWP_NOSIZE);
}

//hide popup window, let the parent dialog know
void CMySplitter::CPopup::OnLButtonUp(UINT flag, CPoint pt)
{
    CWnd::OnLButtonUp(flag, pt);
    ReleaseCapture();
    ShowWindow(SW_HIDE);

    CRect rc;
    GetWindowRect(&rc);
    parent->callback(rc.left);
}

BEGIN_MESSAGE_MAP(CMySplitter::CPopup, CWnd)
    ON_WM_CREATE()
    ON_WM_LBUTTONDOWN()
    ON_WM_LBUTTONUP()
    ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()

BEGIN_MESSAGE_MAP(CMySplitter, CWnd)
    ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()

您要查找的术语是a,传统上在CFrameWnd应用程序中通过a使用,而不是在CDialog中使用。
CSplitterWnd
是一种方法,但是如果您已经完成了对话框,并且想要添加调整大小/夹持器,则必须创建自己的控件。您需要将对话框分成两个子对话框,夹持器告诉子对话框调整大小。@BarmakShemirani OK。看起来工作太多了。我想我会离开的。好啊谢谢但我不知道如何添加两个子对话框,这可能会破坏我已有的所有代码。拥有子对话框涉及到什么?是的,你必须将对话框分成三部分。一个带有菜单的主对话框和两个子对话框。我更改了
CMyDialog
以显示一个示例。大多数对话框没有这种功能,它可能不值得增加复杂性。为了回答,我加了一个答案。
class CMyDialog : public CDialogEx
{
public:
    class CChild1 : public CDialogEx
    {
    };

    class CChild2 : public CDialogEx
    {
    };

    CChild1 child1;
    CChild1 child2;

    //respond to gripper resize
    void respond(int position)
    {
        CRect rs;
        m_splitter.GetWindowRect(&rs);
        rs.MoveToX(position);
        ScreenToClient(&rs);

        CRect rc;
        GetClientRect(&rc);

        CRect r1(0, 0, rs.left, rc.bottom);
        CRect r2(rs.right, 0, rc.right, rc.bottom);

        child1.MoveWindow(r1, TRUE);
        child2.MoveWindow(r2, TRUE);
        m_splitter.MoveWindow(rs, TRUE);

        m_splitter.Invalidate(TRUE);
    }

    CMySplitter m_splitter;
    BOOL OnInitDialog()
    {
        CDialogEx::OnInitDialog();
        child1.Create(IDD_PAGE1, this);
        child2.Create(IDD_PAGE2, this);

        m_splitter.SubclassDlgItem(IDC_STATIC1, this);
        m_splitter.SetRange(50, 50);
        m_splitter.callback = std::bind(&CMyDialog::respond, this, std::placeholders::_1);

        //width for splitter
        int dx = 10;

        CRect rc;
        GetClientRect(&rc);
        CRect r1(0, 0, 200, rc.bottom);
        CRect r2(r1.right + dx, 0, rc.right, rc.bottom);
        CRect rs(r1.right, 10, r2.left, rc.bottom - 10);

        child1.MoveWindow(r1);
        child2.MoveWindow(r2);
        m_splitter.MoveWindow(rs);

        child1.ShowWindow(SW_SHOW);
        child2.ShowWindow(SW_SHOW);

        return TRUE;
    }
    ...
};