gpt4 book ai didi

c++ - CScrollView 只滚动大面积的部分区域

转载 作者:行者123 更新时间:2023-11-30 05:25:26 29 4
gpt4 key购买 nike

我在 CScrollView 中滚动大面积时遇到问题。当从上到下缓慢移动滚动条时,行为如下:起初滚动工作正常。在某些时候,进一步滚动不会做任何事情,而是显示该区域的顶部。在某个时候再次从顶部开始滚动。

这是一个小例子。我使用文档 View 模型创建了一个新的 MFC 项目,并使用 CScrollView 作为 View 类。我添加了以下代码来创建一个大区域并添加一些文本来显示,当前显示的是哪一部分:

void CScrollViewTest2View::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();

CSize sizeTotal;
// TODO: calculate the total size of this view
sizeTotal.cx = sizeTotal.cy = 100*1000;
SetScrollSizes(MM_TEXT, sizeTotal);

for(int i = 0; i < 1000; i++)
{
CStatic* label = new CStatic();
label->Create(NULL, WS_CHILD | WS_VISIBLE, CRect(10,10 + i*100,100,30 + i*100), this);
CString text;
text.Format(L"%d",i);
label->SetWindowText(text);
}
}

如果我添加以下代码,我会看到在滚动过程中“nPos”值似乎环绕。这可以解释这种行为。但我不知道如何解决这个问题。

BOOL CScrollViewTest2View::OnScroll(UINT nScrollCode, UINT nPos, BOOL bDoScroll )
{
CString msg;
msg.Format(L"nPos = %u\n",nPos);
TRACE(msg);
return CScrollView::OnScroll(nScrollCode, nPos, bDoScroll);
}

这是停止滚动时的输出:

nPos = 27826
nPos = 29190
nPos = 30281
nPos = 31372
nPos = 31645
nPos = 32464
nPos = 4294938588
nPos = 4294939134
nPos = 4294939407
nPos = 4294939680
nPos = 4294940225
nPos = 4294940771

那么有没有办法用CScrollView实现大面积完全向下滚动呢?

可以找到示例项目的代码here .

最佳答案

静态控件没有放置在您期望的位置。要查看问题,请运行以下代码:

static CStatic test;
CRect r(0, 0, 100, 30);
r.MoveToY(40000);
test.Create(0, WS_CHILD | WS_VISIBLE, r, this);

test.GetWindowRect(r);

TRACE("%d\n", r.top);

r.top 应该是 32767。这是因为 Windows 中的 16 位限制。所有 x/y 位置超过此限制的控件都将被推回此位置。

OnScroll 函数也有类似的问题,不过这可以通过使用 GetScrollInfo

来解决

ON_WM_VSCROLL 添加到消息映射并将以下 OnVScroll 覆盖到您的类

void CScrollViewTest2View::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
CView::OnVScroll(nSBCode, nPos, pScrollBar);
SCROLLINFO info;
GetScrollInfo(SB_VERT, &info, SIF_ALL);

int pos = info.nPos;
int save = pos;
switch (nSBCode)
{
case SB_LEFT: pos = info.nMin; break;
case SB_RIGHT: pos = info.nMax; break;
case SB_LINELEFT: pos--; break;
case SB_LINERIGHT: pos++; break;
case SB_PAGELEFT: pos -= info.nPage; break;
case SB_PAGERIGHT: pos += info.nPage; break;
case SB_THUMBPOSITION: pos = info.nTrackPos; break;
case SB_THUMBTRACK: pos = info.nTrackPos; break;
}

//make sure the new position is within range
if (pos < info.nMin) pos = info.nMin;
int max = info.nMax - info.nPage + 1;
if (pos > max) pos = max;

OnScrollBy(CSize(0, pos - save), 1);

//EDIT: moved this line after OnScrollBy and added condition
if (info.nPos != pos)
{
info.nPos = pos;
SetScrollInfo(SB_VERT, &info, FALSE);
}
UpdateWindow();
}

这不会解决 x/y 位置大于 32,000 的 Windows 控件的问题,但至少它会按预期滚动 DC。

为了测试,删除静态控件。您可以使用下面的绘制函数来测试绘画:

void CScrollViewTest2View::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();
CSize sizeTotal(0, 100 * 1000);
SetScrollSizes(MM_TEXT, sizeTotal);
}

void CScrollViewTest2View::OnDraw(CDC* pDC)
{
for (int i = 0; i < 1000; i++)
{
int y = i * 100;
CString s;
s.Format(L"%d ", y);
pDC->TextOutW(200, y, s);
}
}

关于c++ - CScrollView 只滚动大面积的部分区域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38241534/

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