Why do you need to use bitmap in the first place?For scrolling, you should use ScrollDC and then just repaint the newly exposed window.Why do you want to write another editor?
I've read some of your code. The basic scrolling code is:ScrollDC(GetDC()->m_hDC, 0, ScrollLines * GetLineHeight(), &mClientRect, NULL, NULL, &rect); InvalidateRect(&rect, TRUE); UpdateWindow();I do not need bitmaps being used.1) How slow is your current code? Measure it. 2) How fast do you want your code to be? 100% faster, 200% faster. 3) Measure now much time is spent on ScrollDC. You have no way to improve it, except to minimize its area. 4) Check whether rect returned by ScollDC is right 5) UpdateWindow should call your OnDraw routine eventually. A faster ways is just call OnDraw, or functions called by it directly. 6) Check if the parameters passed to OnDraw is optimal. 7) Measure how much time is spent within OnDraw, check how can you reduce the area, how can you improve speed.BTW, what is the design goal of your code? Do you want it to be able to print? If so, you should avoid using DrawText.
could you give me your whole project? i'm interested in such problem... [email protected]
to:nlstone(天外流星) 完整的工程实在不方便给出,视图类部分的代码可以给你一份。
> 这个问题真的那么难吗?这么多牛人都解决不了Do not expect other people to tell you which line to change. You have to do your own investigation. What have you done after I gave you a list of things to do?
人气咋就这么低啊
===============帮忙UP
不为求分
在OnEraseBkgnd中使用PatBlt处理背景自画并return TRUE;
在OnPaint不做任何处理
在OnDraw中BitBlt你的事先准备好的内存DC
我现在已经是只绘制需要绘制的部分,而没有重绘整个客户区
我就是在拖动滚动条时候刷新实在无法忍受,特别是滚动大片区域的时候,非常明显的闪烁。你的意思是开多线程来避免闪烁?
to:jiangsheng(蒋晟.MSMVP2004Jan)
谢谢,我看看试一试
2 如果你要实现滚动的平滑,就不要在滚动条消息中不停地重绘,而是要把内存DC里的位图做大一些,譬如三个显示区域高,这样,在三个显示
2 如果你要实现滚动的平滑,就不要在滚动条消息中不停地重绘,而是要把内存DC里的位图做大一些,譬如三个显示区域高,这样,在三个显示区域内的滚动就无须重绘,而只是调整bitblt贴图的位置,这样是不会有闪烁的.若超出此范围,则进行一次重绘另,既然屏幕上的东东都是位图贴出来的,是不应该有"闪烁"的问题,充其量你重绘过于频繁造成移动不平滑,有迟滞感.如果是"闪烁"的话,还是要检查你自己的代码了...
2.我现在的局部重绘,也是调整BitBlt贴图的位置,就是有非常明显的闪烁(大块区域),如果是一行高度的话,闪烁并不明显,但是还是看的出来,使用两种颜色就很明显,(意思就是一个视图分割为2块,一块区域填充一种颜色,另外一块区域填充为白色,这样当滚动一行的时候,就可以比较明显的看到闪烁!
在拖动滚动条的时候并不存在"局部重绘"的情况...
你可以把你的具体方案说一下,你的描述还不足以看清问题的本质另,2D显示要追求效率的极致,在win32下还是要用到DDraw/OpenGL,但在你的需求中,似乎还不必出此绝招
当滚动条滚动一行内容的时候,就是一个明显的局部重绘了阿,我只BitBlt一行文本高度宽度的兼容位图给设备DC阿
我觉得UltraEdit没有用到DirectDraw技术!以GDI的能力我觉得完全可以轻松的完成平滑滚动文本这样的需求,只是我现在还没有找到一个好的办法来解决而已!我相信一定是可以的
那么应该把兼容位图选入到兼容DC中,但是要把兼容DC的内容传递给设备DC还是需要经过一次BitBlt才行,而不能经过ScrollWindow来进行滚动阿
2. 滚动的时候使用 ScrollWindow 函数
因为我使用了DrawText来绘制文本到设备DC上的效果和使用双缓冲后的效果差别不大,但是我觉得使用DrawText的速度还是比BitBlt的速度快一些,因为闪烁感没有那么强烈。
袁大哥ScrollDC这个API是滚动DC用的,那么我用它直接滚动设备DC是否有效呢?我现在的代码写了很多了,不知道如何下手去修改这些代码了。敬请指教!
因为Windows自带的Edit和RichEdit不能满足我的需求,所以我才下定决心自己写一个Editor的
2) Measure the performance of your code.
3) Setup a goal on how fast do you want it to be.
void xxxx::ScrollToLine(int nNewLineOffset, bool bNoSmoothScroll /*= false*/, bool bTrackScrollBar /*=true*/)
{
if (nNewLineOffset != nTopLine)
{
if (bNoSmoothScroll || !bSmoothScroll) {
int ScrollLines = nTopLine - nNewLineOffset; //滚动多少行
nTopLine = nNewLineOffset;
CRect rect;
ScrollDC(GetDC()->m_hDC, 0, ScrollLines * GetLineHeight(),
&mClientRect, NULL, NULL, &rect);
InvalidateRect(&rect, TRUE);
UpdateWindow();
}
{
int nLineHeight = GetLineHeight(); //得到行高度
if (nTopLine > nNewLineOffset)
{
int nIncrement = (nTopLine - nNewLineOffset) /
SMOOTH_SCROLL_FACTOR;
nIncrement += 1;
while (nTopLine > nNewLineOffset)
{
int TopLine = nTopLine - nIncrement;
if (nTopLine < nNewLineOffset)
nTopLine = nNewLineOffset;
int ScrollLines = TopLine - nTopLine;
nTopLine = TopLine;
ScrollDC(GetDC()->m_hDC, 0, -nLineHeight *
ScrollLines, NULL, NULL, NULL, NULL);
UpdateWindow();
if (bTrackScrollBar)
RecalcVertScrollBar(true);
}
}
else //if (nTopLine <= nNewLineOffset)
{
int nIncrement = (nNewLineOffset - nTopLine) /
SMOOTH_SCROLL_FACTOR ;
nIncrement += 1;
while (nTopLine < nNewLineOffset)
{
int TopLine = nTopLine + nIncrement;
if (nTopLine > nNewLineOffset)
nTopLine = nNewLineOffset;
int nScrollLines = TopLine - nTopLine;
//µ±ËüֵΪ¸ºÊýµÄʱºò,±íÃ÷´ÓÉÏÍùϹö¶¯,·´Ö®ÔòÊÇ´ÓÏÂÍùÉϹö¶¯
//mnNeedRepaintLine = nScrollLines;
nTopLine = TopLine;
//ScrollWindow(0, -nLineHeight * nScrollLines);
ScrollDC(GetDC()->m_hDC, 0, -nLineHeight * nScrollLines, NULL, NULL, NULL, NULL);
UpdateWindow();
if (bTrackScrollBar)
RecalcVertScrollBar(true);
}
}
{
CRect rcLine;
if (mrcNeedRepaint.IsRectNull() == FALSE)
rcLine = mrcNeedRepaint;
else
rcLine = mClientRect;
rcLine.top = rcLine.top - rcLine.top % nLineHeight;
rcLine.bottom = rcLine.bottom - rcLine.bottom % nLineHeight; unsigned int uiCurrentLine = nTopLine;
unsigned int uiDrawEndLine = 0;
unsigned int uiCurrentChar = nOffsetChar;
unsigned int uiDrawEndChar = 0;
int iMarginWidth = GetMarginWidth();
if ((bShowSideColumn) && (mrcNeedRepaint.left / nCharWidth))
{
uiCurrentChar += (mrcNeedRepaint.left - iMarginWidth) / nCharWidth;
uiDrawEndChar = ((mrcNeedRepaint.right - iMarginWidth) / nCharWidth) + nOffsetChar;
}
else
{
uiCurrentChar += mrcNeedRepaint.left / nCharWidth;
uiDrawEndChar += mrcNeedRepaint.right / nCharWidth + nOffsetChar;
} uiCurrentLine += (mrcNeedRepaint.top - mClientRect.top) / nLineHeight;
uiDrawEndLine = ((mrcNeedRepaint.bottom - mrcNeedRepaint.top) / nLineHeight) + uiCurrentLine;
if (uiDrawEndLine > nLineCount)
uiDrawEndLine = nLineCount;
CRect rcSideColumn(0, rcLine.top, GetMarginWidth(), rcLine.top + nLineHeight);
CRect rcCacheLine(GetMarginWidth(), rcLine.top, rcLine.Width(), rcLine.top + nLineHeight);
CFont *pOldFont = pDC->SelectObject(fCurFont); while(rcLine.top < mClientRect.bottom)
{
if(uiCurrentLine < uiDrawEndLine)
{
if (bShowSideColumn)
{
DrawMargin(pDC, rcSideColumn, uiCurrentLine);
}
DrawSingleLine(pDC, rcCacheLine, uiCurrentLine, uiCurrentChar, uiDrawEndChar);
}
else
{
if ((mClientRect.bottom % nLineHeight != 0) && (uiCurrentLine <= uiDrawEndLine))
{
if (uiCurrentLine < uiDrawEndLine)
{
rcSideColumn.top = mClientRect.bottom - mClientRect.bottom % nLineHeight;
rcSideColumn.bottom = mClientRect.bottom;
rcCacheLine.top = rcSideColumn.top ;
rcCacheLine.bottom = rcSideColumn.bottom ;
} if (bShowSideColumn)
{
DrawMargin(pDC, rcSideColumn, uiCurrentLine, true);
}
DrawSingleLine(pDC, rcCacheLine, uiCurrentLine, uiCurrentChar, uiDrawEndChar, true);
}
else
{
if (bShowSideColumn)
{
DrawMargin(pDC, rcSideColumn, -1);
}
DrawSingleLine(pDC, rcCacheLine, -1, 0, 0);
}
}
++uiCurrentLine;
rcLine.OffsetRect(0, nLineHeight);
rcSideColumn.OffsetRect(0, nLineHeight);
rcCacheLine.OffsetRect(0, nLineHeight);
}
//VERIFY(pDC->BitBlt(mrcNeedRepaint.left, mrcNeedRepaint.top, mrcNeedRepaint.Width(),
// mrcNeedRepaint.Height(), pCacheDC, mrcNeedRepaint.left, mrcNeedRepaint.top, SRCCOPY));
//pCacheDC->SelectObject(pOldFont);
pDC->SelectObject(pOldFont);
}这段代码是重绘行使用的代码
InvalidateRect(&rect, TRUE);
UpdateWindow();I do not need bitmaps being used.1) How slow is your current code? Measure it.
2) How fast do you want your code to be? 100% faster, 200% faster.
3) Measure now much time is spent on ScrollDC. You have no way to improve it, except to minimize its area.
4) Check whether rect returned by ScollDC is right
5) UpdateWindow should call your OnDraw routine eventually. A faster ways is just call OnDraw, or functions called by it directly.
6) Check if the parameters passed to OnDraw is optimal.
7) Measure how much time is spent within OnDraw, check how can you reduce the area, how can you improve speed.BTW, what is the design goal of your code? Do you want it to be able to print? If so, you should avoid using DrawText.
不过贴出的代码部分也未看到涉及到绘图性能的关键部分。
[email protected]
完整的工程实在不方便给出,视图类部分的代码可以给你一份。
拙才认为:一次把所有要显示的都画到ScrollDC上(当然不能很大,用全部绘制,局部绘制还是会有闪烁的),只有滚动条滚动到要超出该页的显示范围时才再次BitBlt。
这个方法就是我现在用的方法,效率不能接受
我真的觉的好奇怪。
又不是啥3D动画之类的。怎么会让人觉的闪?
实现windows记事本的效果并不困难啊!!你说的大块区域,到底有多大?2M?
那我可以肯定的说,拖来拖去,记事本也闪的。(不过俺的显卡集成的才1M显存,别人的不知道)
to:gameboy999(-'_'-)
我已经重载了OnEraseBkgnd并且直接返回TRUE但是没有什么作用啊
我也想写过类似的代码ps:其实如果文本多的话
windows的记事本显示也很慢 可以 看着它是一大块 一大块的刷的