GDI效率有关问题:DrawText调用1万次,慢的要命
GDI效率问题:DrawText调用1万次,慢的要命
需要调用 DrawText一万次,每次输出的数字不一样。
好慢。。。。
大伙可有好的效率优化办法?
------解决方案--------------------
可以事先判断一下,然后只绘制可见区域的文本
可以把需要缩放的图形绘制在一个DC不需要缩放的图形绘制在另一个DC,最后混合到窗口DC
------解决方案--------------------
可以把事先需要绘制的数据放在一个位图上,先在位图上重画数据已经改变的数据,然后一次性刷新图片到屏幕
------解决方案--------------------
在OnDraw的时候,最好只执行一次Bitblt
------解决方案--------------------
不是这么处理的,你要只绘制需要更新的区域。
// 我假设是MM_TEXT映射模式,其他模式自己处理。
void CMyView::OnDraw(CDC* pDC)
{
CRect rectUpdate;
switch (pDC->GetClipBox(&rectUpdate))
{
default:
break;
case ERROR:
case NULLREGION:
return;
}
CSize size = rectUpdate.Size();
CDC dcMem;
dcMem.CreateCompatableDC(pDC);
CBitmap bmp;
bmp.CreateCompatableBitmap(pDC, size.cx, size.cy);
dcMem.SaveDC();
dcMem.SelectObject(bmp);
dcMem.OffsetViewPort(-rectUpdate.left, -rectUpdate.top);
// draw....
// 最好根据坐标和行高等信息直接计算出第一个需要更新的行和最后一个需要更新的行。
CRect r;
if (r.IntersetRect(&TheRectToPaint, &rectUpdate))
{
// draw the string.....
}
dcMem.SetMapMode(MM_TEXT);
dcMem.SetViewPortOrg(0, 0);
pDC->BitBlt(...., &dcMem, 0, 0, SRCCOPY);
dcMem.RestoreDC(-1);
}
以上代码是我随手写的,没有检验过,但只是告诉你思路。
------解决方案--------------------
------解决方案--------------------
------解决方案--------------------
只画界面显示的,你判断超过区域的就别画,这样的话就画非常少,不会有你说的画10000次
------解决方案--------------------
需要调用 DrawText一万次,每次输出的数字不一样。
好慢。。。。
大伙可有好的效率优化办法?
------解决方案--------------------
可以事先判断一下,然后只绘制可见区域的文本
可以把需要缩放的图形绘制在一个DC不需要缩放的图形绘制在另一个DC,最后混合到窗口DC
------解决方案--------------------
可以把事先需要绘制的数据放在一个位图上,先在位图上重画数据已经改变的数据,然后一次性刷新图片到屏幕
------解决方案--------------------
在OnDraw的时候,最好只执行一次Bitblt
------解决方案--------------------
不是这么处理的,你要只绘制需要更新的区域。
// 我假设是MM_TEXT映射模式,其他模式自己处理。
void CMyView::OnDraw(CDC* pDC)
{
CRect rectUpdate;
switch (pDC->GetClipBox(&rectUpdate))
{
default:
break;
case ERROR:
case NULLREGION:
return;
}
CSize size = rectUpdate.Size();
CDC dcMem;
dcMem.CreateCompatableDC(pDC);
CBitmap bmp;
bmp.CreateCompatableBitmap(pDC, size.cx, size.cy);
dcMem.SaveDC();
dcMem.SelectObject(bmp);
dcMem.OffsetViewPort(-rectUpdate.left, -rectUpdate.top);
// draw....
// 最好根据坐标和行高等信息直接计算出第一个需要更新的行和最后一个需要更新的行。
CRect r;
if (r.IntersetRect(&TheRectToPaint, &rectUpdate))
{
// draw the string.....
}
dcMem.SetMapMode(MM_TEXT);
dcMem.SetViewPortOrg(0, 0);
pDC->BitBlt(...., &dcMem, 0, 0, SRCCOPY);
dcMem.RestoreDC(-1);
}
以上代码是我随手写的,没有检验过,但只是告诉你思路。
------解决方案--------------------
------解决方案--------------------
------解决方案--------------------
只画界面显示的,你判断超过区域的就别画,这样的话就画非常少,不会有你说的画10000次
------解决方案--------------------
- C/C++ code
// OnPaint的时候,只执行了bitblt。 void CMathCalc::OnPaint() { CPaintDC dc(this); // device context for painting // TODO: Add your message handler code here ::BitBlt( g____mathfun_canvasdc, g____mathfun_canvas_l, g____mathfun_canvas_t, g____mathfun_canvas_w, g____mathfun_canvas_h, g____mathfun_memdc, 0, 0, SRCCOPY ); // Do not call CDialog::OnPaint() for painting messages } // 按下右键,拖动图形 void CMathCalc::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default if( MK_RBUTTON == nFlags ) { if( m_bmove ) { int dx, dy; dx = m_x - point.x; dy = m_y - point.y; g____mathfun_cx -= dx; g____mathfun_cy -= dy; g____mathfun_draw(); m_x = point.x; m_y = point.y; } } CDialog::OnMouseMove(nFlags, point); } void g____mathfun_draw( void ) { int i; i = 0; myclear(); // 画图像的具体代码在这里,要优化的地方主要也在这里 ShowPic(); } // 清除背景为白色,本质就是一个bitblt void myclear( void ) { ::BitBlt( g____mathfun_memdc, 0, 0, g____mathfun_canvas_w, g____mathfun_canvas_h, g____mathfun_backdc, 0, 0, SRCCOPY ); } // 直接显示到屏幕上,可在任意地方直接调用,本例中在MouseMove中调用 void ShowPic( void ) { ::BitBlt( g____mathfun_canvasdc, g____mathfun_canvas_l, g____mathfun_canvas_t, g____mathfun_canvas_w, g____mathfun_canvas_h, g____mathfun_memdc, 0, 0, SRCCOPY ); }
------解决方案--------------------