Вертикальная полоса прокрутки для диалогового окна в CPropertySheet не работает - PullRequest
0 голосов
/ 25 июня 2018

Я новичок в 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;
    }
}

Inв этом случае полоса прокрутки перемещается, но дочерние элементы управления не работают?

По-другому, я включил управление полосой прокрутки для листа свойств, как показано ниже в 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 голосов
/ 25 июня 2018

PropertySheet выберет самый большой диалог страницы и изменит свой размер, чтобы отобразились все диалоги страницы.Прокрутка не требуется, если не существует переопределения для размера PropertySheet, или в CMyPropertyPage::OnInitDialog

* 1003 были добавлены дополнительные элементы управления. Кроме того, экран конечного пользователя может иметь более низкое разрешение, и в этом случае части соответствующего листа будут скрыты,Вам просто нужно сделать страницы диалогов меньшего размера, не выше 1000 пикселей или около 300 точек диалога.

Код, показанный в вопросе, является попыткой обновления скроллера.В дополнение к обновлению скроллера, вы должны прокрутить само диалоговое окно.

Ссылка от @AndrewTruckle показывает, как использовать 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()
...