CPropertySheet中对话框的垂直滚动条不起作用

时间:2018-06-25 11:10:22

标签: mfc scrollbar propertysheet

我是MFC的初学者。我在属性表中嵌入了一个对话框。 由于对话框大于属性表,因此某些部分会被裁剪。

因此,我计划添加一个垂直滚动条。我尝试了两种方法。

  1. 在对话框本身的工具箱中添加了滚动条控件。

创建一个控制变量。

DDX_Control(pDX, IDC_SCROLLBAR, m_ctlScrollBar);

添加的消息映射如下:

ON_WM_VSCROLL(IDC_SCROLLBAR,OnVScroll)

OnInitDialog()中添加了以下代码:

SCROLLINFO ScrollInfo;
ScrollInfo.cbSize = sizeof(ScrollInfo);     
ScrollInfo.fMask = SIF_ALL;                 
ScrollInfo.nMin = 0;                        
ScrollInfo.nMax = 100;                      
ScrollInfo.nPage = 40;                      
ScrollInfo.nPos = 50;                       
ScrollInfo.nTrackPos = 0;                   
m_ctlScrollBar.SetScrollInfo(&ScrollInfo,TRUE);

OnVScroll()功能如下:

void CFeesPage::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    SCROLLINFO ScrollInfo;
    m_ctlScrollBar.GetScrollInfo(&ScrollInfo); 

    switch (nSBCode)
    {
        case SB_BOTTOM:         //Scrolls to the lower right. 
        break;

        case SB_ENDSCROLL:      //Ends scroll. 
        break;

        case SB_LINEDOWN:       //Scrolls one line down. 
        m_ctlScrollBar.SetScrollPos(m_ctlScrollBar.GetScrollPos() + 1,TRUE);
        break;

        case SB_LINEUP:         //Scrolls one line up. 
        m_ctlScrollBar.SetScrollPos(m_ctlScrollBar.GetScrollPos() - 1,TRUE);
        break;

        case SB_PAGEDOWN:       //Scrolls one page down. 
        m_ctlScrollBar.SetScrollPos(m_ctlScrollBar.GetScrollPos() + ScrollInfo.nPage, TRUE);
        break;

        case SB_PAGEUP:         //Scrolls one page up. 
        m_ctlScrollBar.SetScrollPos(m_ctlScrollBar.GetScrollPos() - ScrollInfo.nPage, TRUE);
        break;

        case SB_THUMBPOSITION:
        break;

        case SB_THUMBTRACK:
        m_ctlScrollBar.SetScrollPos(nPos, TRUE);
        break;

        case SB_TOP:            //Scrolls to the upper left. 
        break;
    }
}

在这种情况下,滚动条会移动,但子控件不会移动?

  1. 以另一种方式,我在OnInitDialog中为属性表启用了滚动条控件:

    CScrollBar* test = this->GetScrollBarCtrl(SB_VERT);
    

    如上设置SCROLLINFO

OnVScroll编写如下:

void CSubTranSheet::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    SCROLLINFO ScrollInfo;
    GetScrollInfo(SB_VERT, &ScrollInfo); 

    switch (nSBCode)
    {
        case SB_BOTTOM:         //Scrolls to the lower right. 
            break;

        case SB_ENDSCROLL:      //Ends scroll. 
            break;

        case SB_LINEDOWN:       //Scrolls one line down. 
            SetScrollPos(SB_VERT, GetScrollPos(SB_VERT) + 1, TRUE);
            break;

        case SB_LINEUP:         //Scrolls one line up. 
            SetScrollPos(SB_VERT, GetScrollPos(SB_VERT) - 1, TRUE);
            break;

        case SB_PAGEDOWN:       //Scrolls one page down. 
            SetScrollPos(SB_VERT, GetScrollPos(SB_VERT) + ScrollInfo.nPage, TRUE);
            break;

        case SB_PAGEUP:         //Scrolls one page up. 
            SetScrollPos(SB_VERT, GetScrollPos(SB_VERT) - ScrollInfo.nPage, TRUE);
            break;

        case SB_THUMBPOSITION:  
            break;

        case SB_THUMBTRACK:    
            SetScrollPos(SB_VERT, nPos, TRUE);
            break;

        case SB_TOP:            //Scrolls to the upper left. 
            break;
    }
}

在这种情况下,滚动条也会移动,但子对话框不会移动?

请帮助我。我不确定哪种方法正确。预先感谢。

1 个答案:

答案 0 :(得分:2)

PropertySheet将选择最大的页面对话框,并将调整其自身大小,以便显示所有页面对话框。除非滚动覆盖PropertySheet的大小,或者在CMyPropertyPage::OnInitDialog

中添加了其他控件,否则不需要滚动

此外,最终用户的屏幕可能具有较低的分辨率,在这种情况下,属性表的某些部分将被遮盖。您只需要制作较小的对话框页面,不超过1000像素或大约300个对话框点即可。

有问题的代码是尝试更新滚动条的尝试。除了更新滚动条,还必须滚动对话框本身。

@AndrewTruckle的link显示了如何使用ScrollWindow来实现这一点。

或者,您可以手动移动所有子控件,如下所示。这有点容易,因为您可以调整对话框的大小并调整滚动范围,而不必担心子控件的对齐方式。

#include <map>

class CMyPropertyPage : public CPropertyPage
{
    std::map<CWnd*, CRect> rc_children;
    CRect rc_max;
    void OnSize(UINT flags, int cx, int cy);
    void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
    DECLARE_MESSAGE_MAP()
};

void CMyPropertyPage::OnSize(UINT flags, int cx, int cy)
{
    CPropertyPage::OnSize(flags, cx, cy);
    CRect rc;
    if(!rc_max.bottom)
    {
        //initialize once:
        for(CWnd *p = GetWindow(GW_CHILD); p; p = p->GetWindow(GW_HWNDNEXT))
        {
            //save the rectangles for all child controls
            p->GetWindowRect(&rc);
            ScreenToClient(&rc);
            rc_children[p] = rc;

            //find the lowest point in dialog
            if(rc.bottom > rc_max.bottom)
                rc_max.bottom = rc.bottom;
        }
    }

    GetClientRect(&rc);
    SCROLLINFO info = { sizeof(info) };
    info.fMask = SIF_ALL;
    info.nMin = 0;
    info.nMax = (rc_max.bottom + 100); //100 pixels below the lowest control
    info.nPage = rc.bottom;
    SetScrollInfo(SB_VERT, &info, TRUE);
}

void CMyPropertyPage::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    CPropertyPage::OnVScroll(nSBCode, nPos, pScrollBar);
    SCROLLINFO info = { sizeof(SCROLLINFO) };
    GetScrollInfo(SB_VERT, &info, SIF_ALL);

    //update scroller
    switch(nSBCode)
    {
    case SB_LEFT: info.nPos = info.nMin; break;
    case SB_RIGHT: info.nPos = info.nMax; break;
    case SB_LINELEFT: info.nPos--; break;
    case SB_LINERIGHT: info.nPos++;  break;
    case SB_PAGELEFT: info.nPos -= info.nPage; break;
    case SB_PAGERIGHT: info.nPos += info.nPage; break;
    case SB_THUMBPOSITION: info.nPos = info.nTrackPos; break;
    case SB_THUMBTRACK: info.nPos = info.nTrackPos; break;
    }
    SetScrollInfo(SB_VERT, &info, TRUE);

    if(info.nPos < 0 || info.nPos > rc_max.bottom)
        return;

    //find how many child controls we have
    int count = 0;
    for(CWnd *p = GetWindow(GW_CHILD); p; p = p->GetWindow(GW_HWNDNEXT))
        count++;

    //go through all child controls and move them:
    HDWP hdwp = BeginDeferWindowPos(count);
    for(CWnd *p = GetWindow(GW_CHILD); p; p = p->GetWindow(GW_HWNDNEXT))
    {
        CRect rc;
        p->GetWindowRect(&rc);
        ScreenToClient(&rc);
        if(rc_children.find(p) != rc_children.end())
        {
            int y = info.nPos - rc_children[p].top;
            DeferWindowPos(hdwp, p->m_hWnd, NULL, rc.left, -y, 0, 0,
                SWP_NOSIZE | SWP_NOACTIVATE);
        }
    }
    EndDeferWindowPos(hdwp);
}

BEGIN_MESSAGE_MAP(CMyPropertyPage, CPropertyPage)
    ON_WM_VSCROLL()
    ON_WM_SIZE()
END_MESSAGE_MAP()