You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MFC对话框垂直滚动回滚后控件消失问题求助

对话框垂直滚动回滚顶部时控件消失的问题

我正在适配小尺寸显示屏,部分用户使用这类设备,但对话框布局在小屏幕上有内容无法显示。我已在对话框添加垂直滚动条并映射到变量,但无法提供完整对话框资源。

以下是我编写的代码:

void CChristianLifeMinistryEditorDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    int nDelta;
    int nMaxPos = 100; // Maximum scroll position, adjust as needed

    switch (nSBCode)
    {
    case SB_LINEUP:
        nDelta = -10; // Scroll up by 10 units
        break;
    case SB_LINEDOWN:
        nDelta = 10; // Scroll down by 10 units
        break;
    case SB_PAGEUP:
        nDelta = -50; // Scroll up by a page (adjust as needed)
        break;
    case SB_PAGEDOWN:
        nDelta = 50; // Scroll down by a page (adjust as needed)
        break;
    case SB_THUMBTRACK:
        nDelta = nPos - m_nScrollPos;
        break;
    default:
        nDelta = 0;
    }

    // Calculate the new scroll position
    int nNewPos = m_nScrollPos + nDelta;
    nNewPos = max(0, min(nNewPos, nMaxPos));

    // If the position has changed, scroll the window
    if (nNewPos != m_nScrollPos)
    {
        ScrollPartialArea(0, m_nScrollPos - nNewPos);

        m_nScrollPos = nNewPos;
        SetScrollPos(SB_VERT, m_nScrollPos, TRUE);
    }

    __super::OnVScroll(nSBCode, nPos, pScrollBar);
}


// Function to scroll a part of the dialog
void CChristianLifeMinistryEditorDlg::ScrollPartialArea(int dx, int dy)
{
    // Define the scroll rectangle (portion of the client area to scroll)
    CRect rctScroll;
    CRect rctStatus;
    m_verticalScroll.GetWindowRect(rctScroll);
    m_StatusBar.GetWindowRect(rctStatus);
    ScreenToClient(rctScroll);
    ScreenToClient(rctStatus);
    const CRect scrollRect(0, 0,
        rctScroll.left - 2, rctStatus.top - 2);

    // Define the clipping rectangle (NULL means no clipping)
    CRect* prcClip = nullptr;

    // Region and rectangle for update region
    CRgn updateRgn;
    updateRgn.CreateRectRgn(0, 0, 0, 0);
    CRect rcUpdate;

    // Flags for scrolling
    const UINT flags = SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE;

    // Perform the scrolling
    const int result = ScrollWindowEx(
        dx,
        dy,
        &scrollRect,
        prcClip,
        &updateRgn,
        &rcUpdate,
        flags
    );

    // Check the result (0 if an error occurred, otherwise positive value)
    if (result == 0)
    {
        // Handle error (optional)
    }

    // Clean up
    updateRgn.DeleteObject();
}

程序运行时向下滚动功能正常:

  • 滚动前:
    滚动前界面
  • 滚动后:
    向下滚动后界面

但回滚到顶部时,所有原始控件消失:
回滚到顶部后界面


我尝试用DeferWindowPos修改代码如下:

void CChristianLifeMinistryEditorDlg::ScrollPartialArea(int dx, int dy)
{
    // Define the scroll rectangle (portion of the client area to scroll)
    CRect rctScroll;
    CRect rctStatus;
    m_verticalScroll.GetWindowRect(rctScroll);
    m_StatusBar.GetWindowRect(rctStatus);
    ScreenToClient(rctScroll);
    ScreenToClient(rctStatus);
    const CRect scrollRect(0, 0,
        rctScroll.left - 2, rctStatus.top - 2);

    // Assume you want to scroll the controls by (dx, dy) pixels.
    CWnd* pWnd = GetWindow(GW_CHILD); // Get the first child control
    if (!pWnd)
        return;

    // Determine the number of child windows
    int count = 0;
    while (pWnd)
    {
        CRect rctControl;
        pWnd->GetWindowRect(rctControl);
        ScreenToClient(rctControl);
        if (scrollRect.PtInRect(rctControl.CenterPoint()))
        {
            count++;
        }
        pWnd = pWnd->GetNextWindow();
    }

    // Begin the defer window position operation
    HDWP hDWP = BeginDeferWindowPos(count);
    if (!hDWP)
        return;

    pWnd = GetWindow(GW_CHILD); // Reset to the first child control
    while (pWnd)
    {
        CRect rect;
        pWnd->GetWindowRect(&rect);
        ScreenToClient(&rect);
        if (scrollRect.PtInRect(rect.CenterPoint()))
        {
            // Adjust the position by the scroll offset (dx, dy)
            rect.OffsetRect(dx, dy);

            // Add this control to the batch of window position changes
                hDWP = DeferWindowPos(hDWP, pWnd->GetSafeHwnd(), nullptr, rect.left, rect.top,
                    rect.Width(), rect.Height(), SWP_NOZORDER | SWP_NOACTIVATE);
        }

        // Move to the next child control
        pWnd = pWnd->GetNextWindow();
    }

    // Apply all the changes
    EndDeferWindowPos(hDWP);
}

修改后回滚到顶部时布局异常:
使用DeferWindowPos后回滚界面

实际滚动超过左右箭头后逐步回滚,会出现如下情况:
逐步回滚后的界面


我找到一篇使用ScrollWindow实现滚动对话框的方案,效果不错,仅存在轻微残影问题(该问题将另行咨询)。

内容的提问来源于stack exchange,提问作者Andrew Truckle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 21:59:53