質問

I have an mfc application in which i have to display text. Whenever I use the scrollbar , the OnDraw() function is called. This is my OnDraw() function:

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

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

This seems to be inefficient because scrolling is taking forever. The problem is that I am repainting the entire textfile again. I want to use the GetClipBox function to redraw only that which is required. Can anyone give me suggestions on how to proceed?

Thanks.

役に立ちましたか?

解決

Double buffering won't help you here since you're still drawing the whole string to the off-screen bitmap. What you want is to only draw the part of the string that is actually being shown, which is easier said than done.

First, if each line has the same height, that makes it 10 times easier (I'm also assuming you don't have funny stuff like in-line images, formatting, paragraph spacing, etc). Basically what you want to do is derive how far along the total amount of lines your scroll bar is (let's say you have 1000 lines, and your scrollbar is at 50%, that means you need to start drawing from the 500th line onwards) and how many lines of text you can display (easily calculated by dividing the height of the control by the height of each line).

Then, your extract those lines from the string, and you only pass those to DrawText(). The easiest way to do this is to store the total text not as one string, but as a vector of strings, one line in each entry.

Now there are still a bunch of details to get right such as what to display when you scroll all the way to the end, do you allow half lines to be visible, etc., but essentially the above is what it boils down to.

Furthermore, I hope you're not reading the text from a file on each OnDraw(), because that alone might cause the slowdown.

GetClipBox() isn't really relevant here, since you'll want to redraw the whole content of your content window anyway, even if you only scroll 1 pixel. The point is to reduce the amount of things to draw (that you pass to DrawText()), not to limit the amount of screen space that is being drawn to.

他のヒント

I think the best solution to your problem is probably double buffering. Basically, do your painting to an off-screen bitmap, then when OnPaint() is called, just call

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

Which will just copy the updated section of the screen and should improve your performance considerably.

I posted some code to help with the double buffer in a previous question here which might help. That also includes GDI+ code which you don't actually need and can just omit.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top