在mfc应用程序中显示文本文件时滚动

在mfc应用程序中显示文本文件时滚动,mfc,cview,Mfc,Cview,我有一个mfc应用程序,其中我必须显示文本。每当我使用滚动条时,都会调用OnDraw()函数。这是我的OnDraw()函数: CString fileText = pDoc->GetFileText(); //get text from file CRect rect; GetClientRect(&rect); pDC->DrawText(fileText.GetString(), &rect, DT_LEFT|DT_NOCLIP); 这似乎效率很低,因为滚

我有一个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函数只重新绘制所需的内容。有人能给我一些关于如何进行的建议吗


谢谢。

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

CRect rcUpdate;
GetClipBox(rcUpdate);
pDC->BitBlt(rcUpdate.left, rcUpdate.top, rcUpdate.Width(), rcUpdate.Height(),
                        m_pMemDC, rcUpdate.left, rcUpdate.top, SRCCOPY);
这将只是复制屏幕的更新部分,并将大大提高您的性能


在前面的问题中,我发布了一些代码来帮助使用双缓冲区,这可能会有所帮助。这还包括您实际上不需要的GDI+代码,您可以忽略它。

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

CRect rcUpdate;
GetClipBox(rcUpdate);
pDC->BitBlt(rcUpdate.left, rcUpdate.top, rcUpdate.Width(), rcUpdate.Height(),
                        m_pMemDC, rcUpdate.left, rcUpdate.top, SRCCOPY);
这将只是复制屏幕的更新部分,并将大大提高您的性能


在前面的问题中,我发布了一些代码来帮助使用双缓冲区,这可能会有所帮助。这还包括您实际上不需要且可以忽略的GDI+代码。

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

首先,如果每一行都有相同的高度,那就容易了10倍(我还假设你没有有趣的东西,比如行内图像、格式、段落间距等等)。基本上,您要做的是计算滚动条的总行数(假设您有1000行,滚动条为50%,这意味着您需要从第500行开始绘制)以及可以显示的文本行数(通过将控件的高度除以每条线的高度可以轻松计算)

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

现在仍然有很多细节需要处理,比如当你一直滚动到最后时显示什么,你是否允许半行可见,等等,但本质上,以上就是它的归结

此外,我希望您没有从每个OnDraw()上的文件中读取文本,因为这本身就可能导致速度减慢


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

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

首先,如果每一行都有相同的高度,这将使它变得容易10倍(我还假设你没有有趣的东西,如行内图像、格式、段落间距等)。基本上你要做的是计算滚动条的行数(假设您有1000行,滚动条为50%,这意味着您需要从第500行开始绘制)以及可以显示的文本行数(通过将控件的高度除以每行的高度来轻松计算)

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

现在仍然有很多细节需要处理,比如当你一直滚动到最后时显示什么,你是否允许半行可见,等等,但本质上,以上就是它的归结

此外,我希望您没有从每个OnDraw()上的文件中读取文本,因为这本身就可能导致速度减慢


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

谢谢你的回答。尝试了双缓冲。按照说明操作。它不起作用。事实上,更糟糕的是。我正在处理每个大约10mb的文本文件。GetClipBox()似乎是唯一的方法(据我所知)。但是,我不知道该怎么做。我很惊讶双缓冲速度较慢-我只能假设实现在某个地方有问题。但是,呈现如此大的文本文件可能需要不同的方法。您可能是对的,您需要使用GetClipBox()。然后,您需要找出哪些文本需要重新绘制才能获得正确的结果,并且只在屏幕上绘制该部分,而不是整个文档。我认为您需要将该字符串分解为子字符串,并维护一个错误列表,以便将其绘制出来,但其他人可能会建议更好的方法。此外,当我试着按照你提到的链接中的代码进行操作,我发现图形有一个错误。VS2010说它是一个未知的标识符。为什么?你不需要图形部件-那只是GDI+部件。要解决这个问题,你需要“使用名称空间Gdiplus”另外,请记住在启动应用程序时初始化GDI+。谢谢您的回答。尝试了双缓冲。按照说明操作。它不起作用。事实上,更糟。我