gpt4 book ai didi

c++ - 使用 SW_SCROLLCHILDREN 调用 ScrollWindowEx 时,整个滚动条在 CWnd 中移动

转载 作者:行者123 更新时间:2023-11-30 03:46:17 25 4
gpt4 key购买 nike

我已将 CScrollBar 添加到名为 CPanel 的 Cwnd 中。但是当我滚动页面时,整个滚动条都会移动。知道我该如何解决这个问题吗?遗憾的是,将 CPanel 更改为 CScrollView 或 CFormView 不是一种选择。

CPanel::CPanel()
{
CreateEx(WS_EX_CONTROLPARENT, _T("Static"), NULL, WS_CHILD | WS_TABSTOP | WS_BORDER, m_clRect, pwndParent, IDC_PANEL_FORM);
ScrollBarInit();
}

void CPanel::ScrollBarInit()
{

//Before this i calculate size of scrollbar and size of scrollarea
m_pclScrollBar = new CScrollBar();
m_pclScrollBar->Create(WS_CHILD | WS_VISIBLE | SBS_VERT | SBS_RIGHTALIGN, clRectScrollbar, this, IDC_SCROLLBAR_FORM);
m_pclScrollBar->SetScrollRange(VSCROLL_RANGE_MIN, VSCROLL_RANGE_MAX);
//After this I add scrollbar info

}

void CPanel::OnVScroll(UINT iSBCode, UINT iPos, CScrollBar* pclScrollBar)
{
switch(pclScrollBar->GetDlgCtrlID())
{
case IDC_SCROLLBAR_FORM:
ScrollBarScroll(iSBCode, iPos, pclScrollBar);
break;
}
}

void CPanel::ScrollBarScroll(UINT iSBCode, UINT iPos, CScrollBar *pclScrollBar)
{
int iScrollPositionPrevious;
int iScrollPosition;
int iScrollPositionOriginal;

iScrollPositionOriginal = m_pclScrollBar->GetScrollPos();
iScrollPosition = iScrollPositionOriginal;

if(m_pclScrollBar != NULL)
{
SCROLLINFO info = {sizeof( SCROLLINFO ), SIF_ALL};
pclScrollBar->GetScrollInfo(&info, SB_CTL);

pclScrollBar->GetScrollRange(&info.nMin, &info.nMax);
info.nPos = pclScrollBar->GetScrollPos();

iScrollPositionPrevious = info.nPos;

switch(iSBCode)
{
case SB_TOP: // Scroll to top
iScrollPosition = VSCROLL_RANGE_MIN;
break;

case SB_BOTTOM: // Scroll to bottom
iScrollPosition = VSCROLL_RANGE_MAX;
break;

case SB_ENDSCROLL: // End scroll
break;

case SB_LINEUP: // Scroll one line up
if(iScrollPosition - VSCROLL_LINE >= VSCROLL_RANGE_MIN)
iScrollPosition -= VSCROLL_LINE;
else
iScrollPosition = VSCROLL_RANGE_MIN;
break;

case SB_LINEDOWN: // Scroll one line down
if(iScrollPosition + VSCROLL_LINE <= VSCROLL_RANGE_MAX)
iScrollPosition += VSCROLL_LINE;
else
iScrollPosition = VSCROLL_RANGE_MAX;
break;

case SB_PAGEUP: // Scroll one page up
{
// Get the page size
SCROLLINFO scrollInfo;
m_pclScrollBar->GetScrollInfo(&scrollInfo, SIF_ALL);

if(iScrollPosition > VSCROLL_RANGE_MIN)
iScrollPosition = max(VSCROLL_RANGE_MIN, iScrollPosition - VSCROLL_PAGE);
break;
}

case SB_PAGEDOWN: // Scroll one page down
{
// Get the page size
SCROLLINFO scrollInfo;
m_pclScrollBar->GetScrollInfo(&scrollInfo, SIF_ALL);

if(iScrollPosition < VSCROLL_RANGE_MAX)
iScrollPosition = min(VSCROLL_RANGE_MAX, iScrollPosition + VSCROLL_PAGE);
break;
}

case SB_THUMBPOSITION: // Scroll to the absolute position. The current position is provided in nPos
case SB_THUMBTRACK: // Drag scroll box to specified position. The current position is provided in nPos
iScrollPosition = iPos;
break;

default:
break;
}

if(iScrollPositionOriginal != iScrollPosition)
{
m_pclScrollBar->SetScrollPos(iScrollPosition);

ScrollWindowEx(0, iScrollPositionOriginal - iScrollPosition, NULL, NULL, NULL, NULL, SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE);
}
}
}

最佳答案

由于您在对 ScrollWindowEx 的调用中指定了 SW_SCROLLCHILDREN (另请参阅 ScrollWindowEx 的 Windows API 文档;它通常比 MFC 的更好),并通过为 lpRectScroll 参数传递 NULL 来请求滚动整个客户区,系统就是这样做的。滚动条也是一个子窗口,因此它可以像所有其他子控件一样移动。

SW_SCROLLCHILDREN 的文档中暗示了解决方案:

Scrolls all child windows that intersect the rectangle pointed to by lpRectScroll by the number of pixels specified in dx and dy.

要防止滚动条与其他子窗口一起移动,它必须从作为 lpRectScroll 参数传递的矩形中排除。为此,查询客户区,并减去滚动条占用的区域。假设滚动条在右边并且覆盖了整个高度,下面的代码将解决你的问题:

if(iScrollPositionOriginal != iScrollPosition) {
m_pclScrollBar->SetScrollPos(iScrollPosition);

// Query the window's client area
CRect clientArea;
GetClientRect(clientArea);
// Find the area occupied by the scrollbar
CRect scrollbarArea;
m_pclScrollBar->GetWindowRect(scrollbarArea);
// Adjust the client area to exclude the scrollbar area
CRect scrollArea(clientArea);
scrollArea.DeflateRect(0, 0, scrollbarArea.Width(), 0);
ScrollWindowEx(0, iScrollPositionOriginal - iScrollPosition, scrollArea, NULL,
NULL, NULL, SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE);
}

还要记住关于使用 SW_SCROLLCHILDREN 标志的注释:

If the SW_SCROLLCHILDREN flag is specified, Windows will not properly update the screen if part of a child window is scrolled. The part of the scrolled child window that lies outside the source rectangle will not be erased and will not be redrawn properly in its new destination. Use the DeferWindowPos Windows function to move child windows that do not lie completely within the lpRectScroll rectangle.

由于您无法控制用户滚动的像素数量,因此有时屏幕无法正确更新。要解决此问题,请按照上面引用中概述的过程实现解决方案:将对 ScrollWindowEx 的调用替换为对 DeferWindowPos 的一系列调用,手动重新定位所有子窗口。

关于c++ - 使用 SW_SCROLLCHILDREN 调用 ScrollWindowEx 时,整个滚动条在 CWnd 中移动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34150884/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com