高分求解!关于程序脱离VS后运行速度慢的问题

Sandrer 2012-10-30 02:25:01
做了一个触摸屏的图标滚动的界面模块(基于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 的问题?最后还是不是我自己的问题?
...全文
260 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
Sandrer 2012-11-02
  • 打赏
  • 举报
回复
网上查了一下, 说的是 GDI+ 初始化的代码必须放在调用这个 DLL 的程序里才行
试了一下, 的确可行, 但这样就破坏了连接库的封装性了, 所以这个办法被我否决

后来我是用多线程来管理画图这块, 每条线程管理10个图片~~~

结贴
Sandrer001 2012-11-02
  • 打赏
  • 举报
回复
插楼结帖!
Sandrer 2012-10-31
  • 打赏
  • 举报
回复
// 绘画按钮
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);
}
Sandrer 2012-10-31
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 的回复:]
把工程打包传上来, 大家来试试

可以加些日志或dbgstring, 记录看哪个函数耗时多
[/Quote]

就是我上面贴的那个函数,注释后就没问题了~
Yofoo 2012-10-31
  • 打赏
  • 举报
回复
把工程打包传上来, 大家来试试

可以加些日志或dbgstring, 记录看哪个函数耗时多
狂僧挥翰 2012-10-31
  • 打赏
  • 举报
回复
来学习学习.....
傻X 2012-10-31
  • 打赏
  • 举报
回复
如果怀疑是GDI+的问题的话,换成GDI试试可以用CDC画。或者CImage之类的库看看效果

库有问题还是比较少见的。
w_xei 2012-10-31
  • 打赏
  • 举报
回复
是不是GDI+加载库的时间问题,开始有没有加载
Sandrer 2012-10-31
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]
要不用TextureBrush看看
TextureBrush myBrush(bmp);
graphics.FillRectangle

这个效率比那个DrawImage高很多。尝试下吧
[/Quote]

也试了,还是一样~~~
从文件夹上直接运行程序的话,图标拖动过程会很"卡"
Sandrer 2012-10-31
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]
这个应该和GDI+没有关系,在其他机子上也会么
[/Quote]

问题是我把画图的代码注释后,无论程序在哪运行效率都一样~
所以我怀疑是不是我的 GDI+ 库有问题~
我自己在 C 盘搜索过,一共有3个版本的 GDI+ 库
Sandrer 2012-10-31
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
这个只能自己测试了,你可以先不用编绎成DLL通过其它程序来调用,直接编成一个程序试试,另外,看一下编绎选项,改变优化选项试试,等找出原因后再编绎成DLL
[/Quote]

已经测试过了,结果还是一样!
在IDE中按下"启动调试"后,程序的拖动过程会比直接在文件夹上运行要顺畅
Sandrer 2012-10-31
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 的回复:]
如果怀疑是GDI+的问题的话,换成GDI试试可以用CDC画。或者CImage之类的库看看效果

库有问题还是比较少见的。
[/Quote]

之前没用 GDI+ 前,所有图片都是BMP或者是ICO格式的文件
这些文件都是直接用 GDI 画上去,没有我说的问题

后来换了 PNG, 就用到了 GDI+, 速度就变慢了!
shen_wei 2012-10-30
  • 打赏
  • 举报
回复
用程序测试看看。。换一个程序测试看看!!
傻X 2012-10-30
  • 打赏
  • 举报
回复
最好上下调用CRollPanelWnd::DrawImage代码的地方和完整函数。

感觉那里有问题哦
supercllc 2012-10-30
  • 打赏
  • 举报
回复
是不是在不停的DrawImage啊
调试的时候可能2秒画一次

直接启动的时候就一秒画好几次了
傻X 2012-10-30
  • 打赏
  • 举报
回复
要不用TextureBrush看看
TextureBrush myBrush(bmp);
graphics.FillRectangle

这个效率比那个DrawImage高很多。尝试下吧
Ginie 2012-10-30
  • 打赏
  • 举报
回复
这个应该和GDI+没有关系,在其他机子上也会么
hdg3707 2012-10-30
  • 打赏
  • 举报
回复
这个只能自己测试了,你可以先不用编绎成DLL通过其它程序来调用,直接编成一个程序试试,另外,看一下编绎选项,改变优化选项试试,等找出原因后再编绎成DLL

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧