- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我已将 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/
我在 Cwnd 中实现了一个 CScrollBar,但是在滚动之后窗口上的控件消失了。我听说我可以通过某种方式使用 DeferWindowPos,但我不知道该怎么做。有什么想法吗? CPanel::C
我已将 CScrollBar 添加到名为 CPanel 的 Cwnd 中。但是当我滚动页面时,整个滚动条都会移动。知道我该如何解决这个问题吗?遗憾的是,将 CPanel 更改为 CScrollView
我是一名优秀的程序员,十分优秀!