做了一个触摸屏的图标滚动的界面模块(基于PC的),使用 GDI+ 进行绘图,独立编译成 DLL。
同一工程下建立了一个测试用的程序在VS2005下,按下“启动调试”按钮运行后,界面图标滚动时运行流畅(无论是 DEBUG 或 RELEASE 下)
图标滚动时CPU占用只有14%左右但如果在文件夹下直接运行该程序的话,界面图标滚动时则非常“卡”
看过任务栏管理器中的数据,内存增加到一定量后不会在递增、GDI对象也维持不变,即内存泄露的可能性不大
但滚动图标时的CPU占用去到25%了
但如果将 GDI+ 绘制图标的代码注释掉,其它保持不变,那么无论是VS启动调试或在文件夹下直接运行,那么速度是一样的
调用GDI+绘图的代码就只有几行:void CRollPanelWnd::DrawImage(CDC *pDC, Image *pImg, const RECT &rect, BOOL bDefaultSize)
{
if (pImg == NULL || pImg->GetLastStatus() != Ok)
return; int cx = rect.right - rect.left;
int cy = rect.bottom - rect.top;
if (bDefaultSize)
{
cx = (int)pImg->GetWidth();
cy = (int)pImg->GetHeight();
} Graphics graphics(pDC->m_hDC);
graphics.DrawImage(pImg, rect.left, rect.top, cx, cy);
}pImg 是从按钮图标被创建起一直到按钮被删除都会一直保存的
究竟是什么原因?是 gdi+ 的库问题吗?还是 VS2005 的问题?最后还是不是我自己的问题?
同一工程下建立了一个测试用的程序在VS2005下,按下“启动调试”按钮运行后,界面图标滚动时运行流畅(无论是 DEBUG 或 RELEASE 下)
图标滚动时CPU占用只有14%左右但如果在文件夹下直接运行该程序的话,界面图标滚动时则非常“卡”
看过任务栏管理器中的数据,内存增加到一定量后不会在递增、GDI对象也维持不变,即内存泄露的可能性不大
但滚动图标时的CPU占用去到25%了
但如果将 GDI+ 绘制图标的代码注释掉,其它保持不变,那么无论是VS启动调试或在文件夹下直接运行,那么速度是一样的
调用GDI+绘图的代码就只有几行:void CRollPanelWnd::DrawImage(CDC *pDC, Image *pImg, const RECT &rect, BOOL bDefaultSize)
{
if (pImg == NULL || pImg->GetLastStatus() != Ok)
return; int cx = rect.right - rect.left;
int cy = rect.bottom - rect.top;
if (bDefaultSize)
{
cx = (int)pImg->GetWidth();
cy = (int)pImg->GetHeight();
} Graphics graphics(pDC->m_hDC);
graphics.DrawImage(pImg, rect.left, rect.top, cx, cy);
}pImg 是从按钮图标被创建起一直到按钮被删除都会一直保存的
究竟是什么原因?是 gdi+ 的库问题吗?还是 VS2005 的问题?最后还是不是我自己的问题?
解决方案 »
- deviceiocontrol 如何获取光盘信息?
- 什么是 Open Platform
- 如何判断键盘事件中 Ctrl+Enter 的情况
- 请问怎样实现向treectrl插入一个节点后,立即可以让用户编辑其文本呢
- 求在多文档中注册 多个菜单 多个工具栏的方法???
- raw_sock,能在windows xp 下使用嗎?
- 如何在COM接口中传递IDL基本类型的数组
- SOS,请问ADO的CommandText是否有长度限制?
- 如何实现按回车键时,处理某个函数
- 如何象WPS2000那样灌入各种数据库文件?
- 关于结构体的文本文件(txt)存储及读取的问题
- 50分求套 CCeSocket 类的h文件和cpp文件!
TextureBrush myBrush(bmp);
graphics.FillRectangle这个效率比那个DrawImage高很多。尝试下吧
调试的时候可能2秒画一次直接启动的时候就一秒画好几次了
已经测试过了,结果还是一样!
在IDE中按下"启动调试"后,程序的拖动过程会比直接在文件夹上运行要顺畅
问题是我把画图的代码注释后,无论程序在哪运行效率都一样~
所以我怀疑是不是我的 GDI+ 库有问题~
我自己在 C 盘搜索过,一共有3个版本的 GDI+ 库
void CRollPanelWnd::DrawButton(CDC *pDC, int nIndex, LPRECT lprc, BOOL *pbPress)
{
if (nIndex < 0 || nIndex >= m_lpPanelInfo->button.nButtonCount)
return; LPPANELBUTTON lpButton = &m_lpPanelInfo->button.lpButtons[nIndex];
if (lpButton == NULL || (pbPress != NULL && *pbPress == lpButton->bPress))
return; if (lprc == NULL) lprc = &lpButton->rect;
int cx = lprc->right - lprc->left;
int cy = lprc->bottom - lprc->top;
if (cx == 0 || cy == 0) return; CRect rcItem(lprc);
rcItem.OffsetRect(-lprc->left, -lprc->top); CBitmap bmp; bmp.CreateCompatibleBitmap(pDC, cx, cy);
CDC memDC; memDC.CreateCompatibleDC(pDC);
memDC.SelectObject(&bmp); CFont *pOldFont = memDC.SelectObject(&m_lpPanelInfo->button.fontText); if (m_lpPanelInfo->bkgnd.hDC != NULL)
memDC.BitBlt(0, 0, cx, cy, CDC::FromHandle(m_lpPanelInfo->bkgnd.hDC), lprc->left, lprc->top, SRCCOPY); CSize sizeText = memDC.GetTextExtent(_T("焯"), 1); CRect rcIcon(0, 0, 0, 0);
if (lpButton->pImg != NULL && lpButton->pImg->GetLastStatus() == Ok)
{
rcIcon.bottom = rcIcon.right = rcItem.Height(); if (rcIcon.bottom > rcIcon.right)
rcIcon.right = rcIcon.bottom = rcItem.Width(); if (!m_lpPanelInfo->button.bTile)
{
rcIcon.right = rcIcon.bottom = (rcIcon.Width() - (sizeText.cy + BUTTONTEXT_MARGIN));
rcIcon.OffsetRect((rcItem.Width() - rcIcon.Width()) / 2, 0);
}
} // 画高亮背景
if (pbPress == NULL) pbPress = &lpButton->bPress;
if (*pbPress)
{
CBitmap bmp; bmp.CreateCompatibleBitmap(pDC, cx, cy);
CDC dcMem; dcMem.CreateCompatibleDC(pDC);
dcMem.SelectObject(&bmp);
dcMem.BitBlt(0, 0, cx, cy, &memDC, 0, 0, SRCCOPY); CBrush br(RGB(0x7f, 0x9d, 0xb9));
dcMem.SelectObject(&br);
dcMem.RoundRect(0, 0, cx, cy, 10, 10); BLENDFUNCTION bf = { AC_SRC_OVER };
bf.SourceConstantAlpha = 0x4c;
memDC.AlphaBlend(0, 0, cx, cy, &dcMem, 0, 0, cx, cy, bf); if (!rcIcon.IsRectEmpty())
rcIcon.InflateRect(-5, -5);
} lpButton->bPress = *pbPress;
////////////////////////////////////////////
// 把这行注释掉之后, 就不会发生我说的情况了
DrawImage(&memDC, lpButton->pImg, rcIcon); if (lpButton->lpText != NULL)
{
memDC.SetBkMode(TRANSPARENT); CRect rcText(rcItem);
if (!m_lpPanelInfo->button.bTile)
{
rcText.InflateRect(-BUTTONTEXT_MARGIN, 0);
rcText.top = rcIcon.bottom + BUTTONTEXT_MARGIN;
if (!rcIcon.IsRectEmpty() && (*pbPress))
rcText.top += 5; rcText.OffsetRect(1, 1);
memDC.SetTextColor(RGB(0xcc, 0xcc, 0xcc));
memDC.DrawText(lpButton->lpText[0], -1, rcText, DT_VCENTER | DT_CENTER | DT_SINGLELINE | DT_END_ELLIPSIS); rcText.OffsetRect(-1, -1);
memDC.SetTextColor(0);
memDC.DrawText(lpButton->lpText[0], -1, rcText, DT_VCENTER | DT_CENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
}
else
{
rcText.left = rcIcon.right + 5;
if (!rcIcon.IsRectEmpty() && (*pbPress))
rcText.left += 5; int nTextCount = lpButton->nTextCount; // 计算按钮中可显示数量的文字行数
int nRowCount = ((rcText.Height() + BUTTONTEXT_MARGIN) / (sizeText.cy + BUTTONTEXT_MARGIN)); // 可显示数量
if (nRowCount > nTextCount) nRowCount = nTextCount; int nTextHeight = (sizeText.cy + BUTTONTEXT_MARGIN) * nRowCount - BUTTONTEXT_MARGIN; // 实际显示高度
rcText.top = (rcItem.Height() - nTextHeight) / 2;
rcText.bottom = rcText.top + nTextHeight; // 画文字阴影
rcText.OffsetRect(1, 1);
memDC.SetTextColor(RGB(0xcc, 0xcc, 0xcc));
memDC.DrawText(lpButton->lpText[0], -1, rcText, DT_LEFT | DT_TOP | DT_SINGLELINE | DT_END_ELLIPSIS); rcText.OffsetRect(-1, -1);
memDC.SetTextColor(0);
memDC.DrawText(lpButton->lpText[0], -1, rcText, DT_LEFT | DT_TOP | DT_SINGLELINE | DT_END_ELLIPSIS); memDC.SetTextColor(RGB(0x80, 0x80, 0x80));
int nOffsetY = sizeText.cy + BUTTONTEXT_MARGIN;
for (int i = 1; i < nRowCount; i++)
{
rcText.top += nOffsetY;
memDC.DrawText(lpButton->lpText[i], -1, rcText, DT_LEFT | DT_TOP | DT_SINGLELINE | DT_END_ELLIPSIS);
}
}
} memDC.SelectObject(pOldFont); pDC->BitBlt(lprc->left, lprc->top, cx, cy, &memDC, 0, 0, SRCCOPY);
}
之前没用 GDI+ 前,所有图片都是BMP或者是ICO格式的文件
这些文件都是直接用 GDI 画上去,没有我说的问题后来换了 PNG, 就用到了 GDI+, 速度就变慢了!
试了一下, 的确可行, 但这样就破坏了连接库的封装性了, 所以这个办法被我否决后来我是用多线程来管理画图这块, 每条线程管理10个图片~~~结贴