VC中如何把一个内存设备环境中的位图复制到另一个内存设备环境中?

chiweiyong 2014-11-10 03:20:18
自制了一个倒计时窗口类控件,在OnPaint函数中使用GDI+的DrawImage函数绘制背景图。150毫秒通过Invalidate函数发送WM_PAINT消息刷新屏幕。但实际运行过程中发现,每次通过DrawImage函数绘制控件窗口的背景太占CPU(4%,电脑室4核芯片),于是定义了一个初始化函数Init,在初始化函数中将背景预先绘制到一个内存设备区域,然后在OnPaint中将该内存设备环境中的内容复制到当前的内存设备环境中。但无法实现。求指教。

void CCountDClock::Init()
{
m_pDc = new CDC;//m_pDC是控件类CCountDClock的成员变量,类型为CDC*
m_pDc->CreateCompatibleDC(NULL);
CBitmap bmp;
bmp.CreateCompatibleBitmap(m_pDc, rect.Width(), rect.Height());
m_pDc->SelectObject(&bmp);
Graphics graphics(m_pDc->GetSafeHdc());
Image image_bckground(TEXT(".\\res\\student_background.png"));
graphics.SetSmoothingMode(SmoothingModeAntiAlias);

bmp.DeleteObject();
}

void CCountDClock::OnPaint()
{
// TODO: Add your message handler code here
// Do not call CWnd::OnPaint() for painting messages
CPaintDC dc(this);
CDC memdc;
CBitmap bmp;
CRect rc;
int nWidth, nHeight;
CFont m_font1;
CFont m_font2;
memdc.CreateCompatibleDC(&dc);
GetClientRect(&rc);
nWidth = rc.Width();nHeight = rc.Height();
int nClock_width, nClock_height,nClockcenter_width, nClockcenter_height;
bmp.CreateCompatibleBitmap(&dc, nWidth, nHeight);
memdc.SelectObject(&bmp);
memdc.FillSolidRect(rc,RGB(0,0,0));
memdc.SetBkMode(TRANSPARENT);

Graphics graphics(memdc.GetSafeHdc());

// Image image_bckground(TEXT(".\\res\\student_background.png"));

memdc.BitBlt(0, 0, rc.Width(), rc.Height(), m_pDc, 0, 0, SRCCOPY);//此处想把之前的m_pDC指向的内存设备复制到memdc中,但没有成功
Image image_clockframe(TEXT(".\\res\\alarm_empty.png"));
nClock_width = image_clockframe.GetWidth();
nClock_height = image_clockframe.GetHeight();
// graphics.SetSmoothingMode(SmoothingModeAntiAlias);
// graphics.DrawImage(&image_bckground, 0, 0, nWidth, nHeight);//原来的绘图函数由于绘制频率较高,太占用CPU
.................................
}

...全文
440 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
chiweiyong 2014-11-12
  • 打赏
  • 举报
回复
最后还是定义了一个成员变量来解决,感谢hubo86915531给的思路。
sumos 2014-11-10
  • 打赏
  • 举报
回复
要不要这么麻烦,原因在于Image的加载慢导致 定义一个成员变量 shared_ptr<Image> im; 在Init中加载 im.reset(Image::FromFile(...)); 在Paint中双缓存就够了
chiweiyong 2014-11-10
  • 打赏
  • 举报
回复
第一次发帖,技术也是菜鸟入门,还望给位大哥见谅,给点耐心
chiweiyong 2014-11-10
  • 打赏
  • 举报
回复
引用 8 楼 hubo86915531 的回复:
[quote=引用 7 楼 chiweiyong 的回复:] [quote=引用 5 楼 hubo86915531 的回复:] [quote=引用 3 楼 hubo86915531 的回复:] 定义为成员变量 CBitmap m_bmp; CDC m_pDC; 初始化 m_pDC = NULL;

CPaintDC dc(this);
CRect rc;
int nWidth, nHeight;
GetClientRect(&rc);
 nWidth = rc.Width();nHeight = rc.Height();
if(m_pDC ==NULL)
{
m_pDC = new CDC;
m_bmp.CreateCompatibleBitmap(&dc, nWidth, nHeight);
m_pDC.CreateCompatibleDC(&dc);
}
CBrush brush(RGB(255,255,255));	
CBitmap* pold=m_pDC->SelectObject(&m_bmp);
m_pDC->FillRect(&rc&brush);
//这里自己写函数对内存DC操作 传参数为m_pDC;
dc.->BitBlt(0,0,nWidth,nHeight,m_pDC,0,0,SRCCOPY);
m_pDC->SelectObject(pold);
最后记得释放内存m_pDC和m_bmp资源
CDC* m_pDC; m_pDC->CreateCompatibleDC(&dc); dc.BitBlt(0,0,nWidth,nHeight,m_pDC,0,0,SRCCOPY);[/quote] 目前我已经实现了时钟功能,绘图是没有问题的,但原先直接在OnPaint函数中直接使用DrawImage进行背景图的绘制占用CPU,所以想在控件类中定义一个成员变量CDC* m_pDc,将背景图预先画在这个内存设备环境的位图中,然后在OnPaint函数中直接复制给当前的用于绘图的内存设备环境的位图,本想用Bitblt函数实现,但是不行。其实问题的本质就是:如何复制内存设备环境中的位图到另一个内存设备环境。[/quote] …………你试过我给你写的代码没有?上面就是从一个内存DC拷贝到另一个DC[/quote] 这个我有试过,我想我可能没解释清楚:OnPaint函数每次绘制两个部分:不随时间变化的背景图片(GDI+的DrawImage函数实现)以及随时间变化需要刷新显示的时间显示(GDI的DrawText实现)。我在OnPaint函数里定义了一个局部的CDC类型的变量和CBitmap变量,如下:

 	CDC memdc;
 	CBitmap bmp;
	CRect rc;
	int nWidth, nHeight;
	CFont m_font1;
	CFont m_font2;
	memdc.CreateCompatibleDC(&dc);
	GetClientRect(&rc);
	nWidth = rc.Width();nHeight = rc.Height();
	int nClock_width, nClock_height,nClockcenter_width, nClockcenter_height;
	bmp.CreateCompatibleBitmap(&dc, nWidth, nHeight);
	memdc.SelectObject(&bmp);
然后绘制背景图:

	Graphics graphics(memdc.GetSafeHdc());
	Image image_bckground(TEXT(".\\res\\student_background.png"));
	graphics.SetSmoothingMode(SmoothingModeAntiAlias);
	graphics.DrawImage(&image_bckground, 0, 0, nWidth, nHeight);
现在我不想每次在OnPaint函数中通过graphics.DrawImage(&image_bckground, 0, 0, nWidth, nHeight);来绘制背景图,而是想定义一个全局的CDC变量,在窗口创建的时候讲背景图先绘制在这个内存设备环境的位图上,然后每次OnPaint函数中通过bitblt将背景图绘制到现在的设备环境的位图上,再在这幅位图上进行其他部件的绘制。也就是说我需要调用两次BITBLT函数,一次是复制背景图,一次是将背景图以及在此基础上全部绘制好的整个画面复制到实际的DC中。两次调用bitblt函数的对象不同,一个是CDC memdc.bitblt(),一次是CPaintDC dc.bitblt。 表达能力比较差,还望见谅。
hubo86915531 2014-11-10
  • 打赏
  • 举报
回复
引用 7 楼 chiweiyong 的回复:
[quote=引用 5 楼 hubo86915531 的回复:] [quote=引用 3 楼 hubo86915531 的回复:] 定义为成员变量 CBitmap m_bmp; CDC m_pDC; 初始化 m_pDC = NULL;

CPaintDC dc(this);
CRect rc;
int nWidth, nHeight;
GetClientRect(&rc);
 nWidth = rc.Width();nHeight = rc.Height();
if(m_pDC ==NULL)
{
m_pDC = new CDC;
m_bmp.CreateCompatibleBitmap(&dc, nWidth, nHeight);
m_pDC.CreateCompatibleDC(&dc);
}
CBrush brush(RGB(255,255,255));	
CBitmap* pold=m_pDC->SelectObject(&m_bmp);
m_pDC->FillRect(&rc&brush);
//这里自己写函数对内存DC操作 传参数为m_pDC;
dc.->BitBlt(0,0,nWidth,nHeight,m_pDC,0,0,SRCCOPY);
m_pDC->SelectObject(pold);
最后记得释放内存m_pDC和m_bmp资源
CDC* m_pDC; m_pDC->CreateCompatibleDC(&dc); dc.BitBlt(0,0,nWidth,nHeight,m_pDC,0,0,SRCCOPY);[/quote] 目前我已经实现了时钟功能,绘图是没有问题的,但原先直接在OnPaint函数中直接使用DrawImage进行背景图的绘制占用CPU,所以想在控件类中定义一个成员变量CDC* m_pDc,将背景图预先画在这个内存设备环境的位图中,然后在OnPaint函数中直接复制给当前的用于绘图的内存设备环境的位图,本想用Bitblt函数实现,但是不行。其实问题的本质就是:如何复制内存设备环境中的位图到另一个内存设备环境。[/quote] …………你试过我给你写的代码没有?上面就是从一个内存DC拷贝到另一个DC
chiweiyong 2014-11-10
  • 打赏
  • 举报
回复
引用 5 楼 hubo86915531 的回复:
[quote=引用 3 楼 hubo86915531 的回复:] 定义为成员变量 CBitmap m_bmp; CDC m_pDC; 初始化 m_pDC = NULL;

CPaintDC dc(this);
CRect rc;
int nWidth, nHeight;
GetClientRect(&rc);
 nWidth = rc.Width();nHeight = rc.Height();
if(m_pDC ==NULL)
{
m_pDC = new CDC;
m_bmp.CreateCompatibleBitmap(&dc, nWidth, nHeight);
m_pDC.CreateCompatibleDC(&dc);
}
CBrush brush(RGB(255,255,255));	
CBitmap* pold=m_pDC->SelectObject(&m_bmp);
m_pDC->FillRect(&rc&brush);
//这里自己写函数对内存DC操作 传参数为m_pDC;
dc.->BitBlt(0,0,nWidth,nHeight,m_pDC,0,0,SRCCOPY);
m_pDC->SelectObject(pold);
最后记得释放内存m_pDC和m_bmp资源
CDC* m_pDC; m_pDC->CreateCompatibleDC(&dc); dc.BitBlt(0,0,nWidth,nHeight,m_pDC,0,0,SRCCOPY);[/quote] 目前我已经实现了时钟功能,绘图是没有问题的,但原先直接在OnPaint函数中直接使用DrawImage进行背景图的绘制占用CPU,所以想在控件类中定义一个成员变量CDC* m_pDc,将背景图预先画在这个内存设备环境的位图中,然后在OnPaint函数中直接复制给当前的用于绘图的内存设备环境的位图,本想用Bitblt函数实现,但是不行。其实问题的本质就是:如何复制内存设备环境中的位图到另一个内存设备环境。
lx624909677 2014-11-10
  • 打赏
  • 举报
回复
试试粘贴板,共享内存方式中的一种
hubo86915531 2014-11-10
  • 打赏
  • 举报
回复
引用 3 楼 hubo86915531 的回复:
定义为成员变量 CBitmap m_bmp; CDC m_pDC; 初始化 m_pDC = NULL;

CPaintDC dc(this);
CRect rc;
int nWidth, nHeight;
GetClientRect(&rc);
 nWidth = rc.Width();nHeight = rc.Height();
if(m_pDC ==NULL)
{
m_pDC = new CDC;
m_bmp.CreateCompatibleBitmap(&dc, nWidth, nHeight);
m_pDC.CreateCompatibleDC(&dc);
}
CBrush brush(RGB(255,255,255));	
CBitmap* pold=m_pDC->SelectObject(&m_bmp);
m_pDC->FillRect(&rc&brush);
//这里自己写函数对内存DC操作 传参数为m_pDC;
dc.->BitBlt(0,0,nWidth,nHeight,m_pDC,0,0,SRCCOPY);
m_pDC->SelectObject(pold);
最后记得释放内存m_pDC和m_bmp资源
CDC* m_pDC; m_pDC->CreateCompatibleDC(&dc); dc.BitBlt(0,0,nWidth,nHeight,m_pDC,0,0,SRCCOPY);
hubo86915531 2014-11-10
  • 打赏
  • 举报
回复
引用 3 楼 hubo86915531 的回复:
定义为成员变量 CBitmap m_bmp; CDC m_pDC; 初始化 m_pDC = NULL;

CPaintDC dc(this);
CRect rc;
int nWidth, nHeight;
GetClientRect(&rc);
 nWidth = rc.Width();nHeight = rc.Height();
if(m_pDC ==NULL)
{
m_pDC = new CDC;
m_bmp.CreateCompatibleBitmap(&dc, nWidth, nHeight);
m_pDC.CreateCompatibleDC(&dc);
}
CBrush brush(RGB(255,255,255));	
CBitmap* pold=m_pDC->SelectObject(&m_bmp);
m_pDC->FillRect(&rc&brush);
//这里自己写函数对内存DC操作 传参数为m_pDC;
dc.->BitBlt(0,0,nWidth,nHeight,m_pDC,0,0,SRCCOPY);
m_pDC->SelectObject(pold);
最后记得释放内存m_pDC和m_bmp资源
CDC* m_pDC; dc.BitBlt(0,0,nWidth,nHeight,m_pDC,0,0,SRCCOPY); 两个地方写错
hubo86915531 2014-11-10
  • 打赏
  • 举报
回复
定义为成员变量 CBitmap m_bmp; CDC m_pDC; 初始化 m_pDC = NULL;

CPaintDC dc(this);
CRect rc;
int nWidth, nHeight;
GetClientRect(&rc);
 nWidth = rc.Width();nHeight = rc.Height();
if(m_pDC ==NULL)
{
m_pDC = new CDC;
m_bmp.CreateCompatibleBitmap(&dc, nWidth, nHeight);
m_pDC.CreateCompatibleDC(&dc);
}
CBrush brush(RGB(255,255,255));	
CBitmap* pold=m_pDC->SelectObject(&m_bmp);
m_pDC->FillRect(&rc&brush);
//这里自己写函数对内存DC操作 传参数为m_pDC;
dc.->BitBlt(0,0,nWidth,nHeight,m_pDC,0,0,SRCCOPY);
m_pDC->SelectObject(pold);
最后记得释放内存m_pDC和m_bmp资源
绿茶加咖啡 2014-11-10
  • 打赏
  • 举报
回复
曾经看到过一个PNG时钟小程序,你下一个看看有没有帮助……
chiweiyong 2014-11-10
  • 打赏
  • 举报
回复
求大虾回复啊

15,976

社区成员

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

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