急,如何做到图片在界面上平滑移动,没有闪烁? 在程序需要在界面上移动一个汽车bmp图象,怎么才能做到汽车的无闪烁平滑移动?如何消除汽车移动后的尾巴?(界面背景可能是系统默认的灰色界面,也可能是一张图片,所以消除尾巴时需要恢复到汽车经过前的背景,这个该如何做到?) 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 void CCarElement::Display(UDT_State* pudt_State){ VERIFY(NULL != m_pDC); CDC memDC, backDC, newDC; backDC.CreateCompatibleDC(m_pDC); backDC.SelectObject(m_hBmp); newDC.CreateCompatibleDC(m_pDC); CBitmap* pBitmap = newDC.SelectObject(&m_Bmp); BITMAP bmp; m_Bmp.GetBitmap(&bmp); //恢复原来位置的背景 m_pDC->BitBlt(m_OldRECT.left, m_OldRECT.top, m_OldRECT.right - m_OldRECT.left, m_OldRECT.bottom - m_OldRECT.top, &backDC, 0, 0, SRCCOPY); if(m_rc.left > 0) { DeleteObject(m_hBmp); //保存新区域的背景 m_hBmp = CopyScreenToBitmap(m_pDC, &m_rc); } //绘图 m_pDC->StretchBlt(m_rc.left, m_rc.top, m_rc.right - m_rc.left, m_rc.top - m_rc.bottom, &newDC, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY); if(NULL != pBitmap) { newDC.SelectObject(pBitmap); pBitmap->DeleteObject(); } newDC.DeleteDC(); backDC.DeleteDC(); memDC.DeleteDC();}这是我的程序,可是还是达不到效果,请大虾指教!其中m_rc为图片新位置,m_OldRECT为前次图片位置,m_hBmp为保存的前次位置的背景,m_Bmp为图片对象 CopyScreenToBitmap的问题,m_hBmp应该是用CreateCompatibleBitmap创建出的内存位图,因为汽车的大小是一定的,所以只要创建一个就可以了 m_pDC->StretchBlt(m_rc.left, m_rc.top, m_rc.right - m_rc.left, m_rc.top - m_rc.bottom, &newDC, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);--好像反了,应该是m_rc.bottom - m_rc.top HBITMAP CCarElement::CopyScreenToBitmap(CDC* pDC, LPRECT lpRect){ HDC hScrDC, hMemDC; HBITMAP hBitmap, hOldBitmap; int nX, nY, nX2, nY2; int nWidth, nHeight; VERIFY(NULL != pDC); hScrDC = pDC->GetSafeHdc(); VERIFY(NULL != hScrDC); hMemDC = CreateCompatibleDC(hScrDC); VERIFY(NULL != hMemDC); nX = lpRect->left; nY = lpRect->top; nX2 = lpRect->right; nY2 = lpRect->bottom; nWidth = nX2 - nX; nHeight = nY2 - nY; if(nHeight < 0) nHeight *= -1; hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight); hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap); BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY); hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap); hScrDC = NULL; if(NULL != hMemDC) DeleteDC(hMemDC); if(NULL != hBitmap) DeleteObject(hBitmap); return hBitmap;}这是我的CopyScreenToBitmap函数的实现,m_hBmp是HBITMAP类型的我还是不太明白大虾的意思,我对图形这块真的不是很清楚,还望多指教!谢谢! to happyparrot(++++禽兽联盟主席-快乐鹦鹉+++++):因为我程序里用的是逻辑坐标,所以才这么需要反过来计算区域高度的 其中m_rc为图片新位置,m_OldRECT为前次图片位置,m_hBmp为保存的前次位置的背景,m_Bmp为图片对象_______________问题出在,你第一次把m_Bmp画在m_pDC上之后,每次保存背景和绘制新背景的时候,它都留在了上面。要保证m_hBmp上没有画上m_Bmp才能消除残像 hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);if(NULL != hBitmap) DeleteObject(hBitmap);返回的内存位图被你干掉了 这样当然不行去掉if(NULL != hBitmap) DeleteObject(hBitmap); 不要考虑太多计算,简单的办法,就是把背景绘制到内存DC上,把汽车按照位置绘制到内存DC上,再把这个内存DC整个绘制到窗口上(每次都这样)。效率低一些,但绝对没问题。 to Mackz(在相互):我也是这么想的,可是这种方法我一直试验不成功呀,我的试验程序部分代码如下:void CMainCtrl::Display(CDC *pDC, RECT rc){ ASSERT(NULL != pDC); CDC BackgrounDC; if(!BackgrounDC.CreateCompatibleDC(pDC)) return; BackgrounDC.SelectObject(m_hBitmap); CDC memDC; if(!memDC.CreateCompatibleDC(pDC)) return; //将背景绘制在内存DC上 memDC.BitBlt(m_rc.left, m_rc.top, m_rc.right - m_rc.left, m_rc.bottom - m_rc.top, &BackgrounDC, 0, 0, SRCCOPY); //将前景图片绘制在内存DC上, m_pElement1为一个CElement实例 m_pElement1.Display(&memDC, pDC, rc); //将内存DC内容绘制在屏幕上 pDC->BitBlt(m_rc.left, m_rc.top, m_rc.right - m_rc.left, m_rc.bottom - m_rc.top, &memDC, 0, 0, SRCCOPY);}//将图片绘制在传递进来的内存DC上,pDestDC为传递进来的内存DC的指针,pSrcDC为屏幕DCvoid CElement::Display(CDC* pDestDC, CDC *pSrcDC, RECT rc){ ASSERT(NULL != pDestDC && NULL != pSrcDC); CDC memDC; if(!memDC.CreateCompatibleDC(pSrcDC)) return; memDC.SelectObject(m_Bmp); BITMAP bmp; m_Bmp.GetBitmap(&bmp); //将图片绘制在内存DC上 pDestDC->BitBlt(rc.left, rc.top, bmp.bmWidth, bmp.bmHeight, &memDC, 0, 0, SRCCOPY); memDC.DeleteDC();}我的程序看不到效果,不知道在哪里出了问题,请指教! 不如用专业的: DirectDraw, 每秒可以达到显卡的刷新频率.而且很简单的,MSDN上有详细的例子和说明, 分分钟可以学会.比双缓冲更加明了 CDC memDC; if(!memDC.CreateCompatibleDC(pDC)) return; //将背景绘制在内存DC上 memDC.BitBlt(m_rc.left, m_rc.top, m_rc.right - m_rc.left, m_rc.bottom - m_rc.top, &BackgrounDC, 0, 0, SRCCOPY);memDC没有对应的缓冲区,需要先临时生成一个跟当前客户区大小一致的CBitmap,并加载后才能使用。 谢谢Kerrie,问题解决,给分! 有点不爽。 急问!!!! !!!高分求助高手,go与exe模式的区别!!!谢谢!!! 定时器的问题 关于COMBO BOX的显示排序 关于字符串判断的问题?****(500分相送)**** 断开上网 读一个别人的工程源代码?有几个问题实在不明白。 TabCtrl和CAsyncSocket的小问题(为什么我能给的分变少了??) 如何把CRichEditCtrl里的文本设置成Unicode?CRichEditCtrl字体的设置的问题····等等··· 诡异的ado初始化问题,高手帮忙 怎样获得恶意连接的IP?
{
VERIFY(NULL != m_pDC);
CDC memDC, backDC, newDC;
backDC.CreateCompatibleDC(m_pDC);
backDC.SelectObject(m_hBmp);
newDC.CreateCompatibleDC(m_pDC);
CBitmap* pBitmap = newDC.SelectObject(&m_Bmp);
BITMAP bmp;
m_Bmp.GetBitmap(&bmp);
//恢复原来位置的背景
m_pDC->BitBlt(m_OldRECT.left, m_OldRECT.top, m_OldRECT.right - m_OldRECT.left, m_OldRECT.bottom - m_OldRECT.top, &backDC, 0, 0, SRCCOPY);
if(m_rc.left > 0)
{
DeleteObject(m_hBmp);
//保存新区域的背景
m_hBmp = CopyScreenToBitmap(m_pDC, &m_rc);
}
//绘图
m_pDC->StretchBlt(m_rc.left, m_rc.top, m_rc.right - m_rc.left, m_rc.top - m_rc.bottom, &newDC, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
if(NULL != pBitmap)
{
newDC.SelectObject(pBitmap);
pBitmap->DeleteObject();
}
newDC.DeleteDC();
backDC.DeleteDC();
memDC.DeleteDC();
}
这是我的程序,可是还是达不到效果,请大虾指教!
其中m_rc为图片新位置,m_OldRECT为前次图片位置,m_hBmp为保存的前次位置的背景,m_Bmp为图片对象
--好像反了,应该是m_rc.bottom - m_rc.top
{
HDC hScrDC, hMemDC;
HBITMAP hBitmap, hOldBitmap;
int nX, nY, nX2, nY2;
int nWidth, nHeight;
VERIFY(NULL != pDC);
hScrDC = pDC->GetSafeHdc(); VERIFY(NULL != hScrDC);
hMemDC = CreateCompatibleDC(hScrDC); VERIFY(NULL != hMemDC);
nX = lpRect->left;
nY = lpRect->top;
nX2 = lpRect->right;
nY2 = lpRect->bottom;
nWidth = nX2 - nX;
nHeight = nY2 - nY; if(nHeight < 0)
nHeight *= -1;
hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight); hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap); BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY);
hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);
hScrDC = NULL;
if(NULL != hMemDC)
DeleteDC(hMemDC); if(NULL != hBitmap)
DeleteObject(hBitmap);
return hBitmap;
}
这是我的CopyScreenToBitmap函数的实现,m_hBmp是HBITMAP类型的
我还是不太明白大虾的意思,我对图形这块真的不是很清楚,还望多指教!谢谢!
因为我程序里用的是逻辑坐标,所以才这么需要反过来计算区域高度的
_______________问题出在,你第一次把m_Bmp画在m_pDC上之后,每次保存背景和绘制新背景的时候,它都留在了上面。要保证m_hBmp上没有画上m_Bmp才能消除残像
if(NULL != hBitmap)
DeleteObject(hBitmap);
返回的内存位图被你干掉了
去掉if(NULL != hBitmap)
DeleteObject(hBitmap);
我也是这么想的,可是这种方法我一直试验不成功呀,我的试验程序部分代码如下:
void CMainCtrl::Display(CDC *pDC, RECT rc)
{
ASSERT(NULL != pDC); CDC BackgrounDC;
if(!BackgrounDC.CreateCompatibleDC(pDC))
return;
BackgrounDC.SelectObject(m_hBitmap); CDC memDC;
if(!memDC.CreateCompatibleDC(pDC))
return;
//将背景绘制在内存DC上
memDC.BitBlt(m_rc.left, m_rc.top, m_rc.right - m_rc.left, m_rc.bottom - m_rc.top, &BackgrounDC, 0, 0, SRCCOPY);
//将前景图片绘制在内存DC上, m_pElement1为一个CElement实例
m_pElement1.Display(&memDC, pDC, rc);
//将内存DC内容绘制在屏幕上
pDC->BitBlt(m_rc.left, m_rc.top, m_rc.right - m_rc.left, m_rc.bottom - m_rc.top, &memDC, 0, 0, SRCCOPY);
}//将图片绘制在传递进来的内存DC上,pDestDC为传递进来的内存DC的指针,pSrcDC为屏幕DC
void CElement::Display(CDC* pDestDC, CDC *pSrcDC, RECT rc)
{
ASSERT(NULL != pDestDC && NULL != pSrcDC);
CDC memDC;
if(!memDC.CreateCompatibleDC(pSrcDC))
return;
memDC.SelectObject(m_Bmp);
BITMAP bmp;
m_Bmp.GetBitmap(&bmp);
//将图片绘制在内存DC上
pDestDC->BitBlt(rc.left, rc.top, bmp.bmWidth, bmp.bmHeight, &memDC, 0, 0, SRCCOPY); memDC.DeleteDC();
}
我的程序看不到效果,不知道在哪里出了问题,请指教!
而且很简单的,MSDN上有详细的例子和说明, 分分钟可以学会.比双缓冲更加明了
if(!memDC.CreateCompatibleDC(pDC))
return;
//将背景绘制在内存DC上
memDC.BitBlt(m_rc.left, m_rc.top, m_rc.right - m_rc.left, m_rc.bottom - m_rc.top, &BackgrounDC, 0, 0, SRCCOPY);memDC没有对应的缓冲区,需要先临时生成一个跟当前客户区大小一致的CBitmap,并加载后才能使用。