1

我有一个 mfc 应用程序,我必须在其中显示文本。每当我使用滚动条时,都会调用 OnDraw() 函数。这是我的 OnDraw() 函数:

CString fileText = pDoc->GetFileText();   //get text from file
CRect rect;
GetClientRect(&rect);

pDC->DrawText(fileText.GetString(), &rect, DT_LEFT|DT_NOCLIP);

这似乎效率低下,因为滚动需要永远。问题是我正在重新绘制整个文本文件。我想使用 GetClipBox 函数仅重绘所需的内容。谁能给我有关如何进行的建议?

谢谢。

4

2 回答 2

1

双缓冲在这里对您没有帮助,因为您仍在将整个字符串绘制到屏幕外位图。您想要的是仅绘制实际显示的字符串部分,这说起来容易做起来难。

首先,如果每行具有相同的高度,那么它会变得容易 10 倍(我还假设您没有有趣的东西,例如内嵌图像、格式、段落间距等)。基本上你想要做的是推导出滚动条的总行数(假设你有 1000 行,滚动条为 50%,这意味着你需要从第 500 行开始绘制)和您可以显示多少行文本(通过将控件的高度除以每行的高度很容易计算)。

然后,从字符串中提取这些行,然后只将它们传递给 DrawText()。最简单的方法是不将总文本存储为一个字符串,而是存储为字符串向量,每个条目中一行。

现在还有很多细节需要解决,比如当你一直滚动到最后时要显示什么,你是否允许半行可见等等,但基本上以上就是它归结为的内容。

此外,我希望您不要在每个 OnDraw() 上从文件中读取文本,因为仅此一项可能会导致速度变慢。

GetClipBox() 在这里并不真正相关,因为无论如何您都想重绘内容窗口的全部内容,即使您只滚动 1 个像素。关键是要减少要绘制的东西的数量(传递给 DrawText()),而不是限制要绘制的屏幕空间的数量。

于 2012-07-04T15:17:18.217 回答
0

我认为解决您的问题的最佳方法可能是双缓冲。基本上,对屏幕外位图进行绘画,然后在调用 OnPaint() 时,只需调用

CRect rcUpdate;
GetClipBox(rcUpdate);
pDC->BitBlt(rcUpdate.left, rcUpdate.top, rcUpdate.Width(), rcUpdate.Height(),
                        m_pMemDC, rcUpdate.left, rcUpdate.top, SRCCOPY);

这只会复制屏幕的更新部分,并且应该会大大提高您的性能。

我在这里的上一个问题中发布了一些代码来帮助处理双缓冲区,这可能会有所帮助。这还包括您实际上不需要并且可以省略的 GDI+ 代码。

于 2012-07-04T07:37:38.680 回答