关于使用定时器闪烁的问题

时间:2022-01-28 23:32:28
我写了一个使用定时器产生雪花效果的简单动画(在桌面窗口)。每隔一段时间便调用一次Draw函数,完成对雪花场景的绘制。
但是现在有一个棘手的问题,程序运行时,桌面会闪烁,而且很严重,甚至桌面的底色也变为黑色。我Draw还是用了双缓冲,仍没解决。希望能有大侠帮助,指点一二,谢谢。
void CSnowDlg::Draw(void)
{
int nSize = m_vParticles.size();  //雪花的数量
ASSERT(nSize > 0);

HWND hDesk = ::GetDesktopWindow();           
HWND hWallPaper=::GetDlgItem(hDesk,1);
HDC  hWallPaperDC = ::GetDC(hDesk);
HBITMAP hBMP = LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP1));  //雪花的位图
HDC hBMPDC = ::CreateCompatibleDC(hWallPaperDC);
::SelectObject(hBMPDC, hBMP);

::InvalidateRect(hWallPaper, NULL, TRUE);  //刷新桌面

//double buffer                             //使用双缓存
RECT   rc;   
::GetWindowRect(hDesk, &rc);  

HDC hDCMem = CreateCompatibleDC(hWallPaperDC);
HBITMAP hBMPMem = CreateCompatibleBitmap(hWallPaperDC, abs(rc.right - rc.left), abs(rc.bottom - rc.top));
::SelectObject(hDCMem, hBMPMem);

for (int i=0; i<nSize; i++)                  //绘制每片雪花
{
int x = m_vParticles[i].x;
int y = m_vParticles[i].y;
Flake(x, y, hDCMem, hBMPDC);  
}

::BitBlt(hWallPaperDC, 0, 0, abs(rc.right - rc.left), abs(rc.bottom - rc.top),
hDCMem, 0, 0, SRCCOPY);
}

11 个解决方案

#1


Sorry .HDC  hWallPaperDC = ::GetDC(hDesk);
应该是HDC  hWallPaperDC = ::GetDC(hWallPaper);
我写错了。。。可是还在闪

#2


用了双缓存还在闪?看看能不能少画一点,或者用硬件加速

#3


::InvalidateRect(hWallPaper, NULL, TRUE);  //刷新

在这刷新 不合理

#4


::InvalidateRect(hWallPaper, NULL, TRUE);  //刷新 
这个会触发底色的重画的,建议去掉这个
如果你仅仅在固定的范围内画雪花,那么,只要在固定范围内贴图即可
如果是雪花随意飘动,那么,就先将桌面位图保存下来,拷贝后,在拷贝后的位图上面画雪花,画完后,再将这个位图贴出,也可以解决底色重画!
Invalidate类的函数,特别在参数传TRUE的时候,应该会触发底色重画的,所以,当底色与所画的东西的色彩不一样的话,很容易导致闪烁!

#5


m_vParticles 是个什么类型的变量呢?
楼主自己定义的类?

看能否把 相关代码贴出来,也许数量也影响到闪烁和其他效果。

#6


重载EreasBackground,删除掉函数内容,直接返回True即可

#7


引用 6 楼 san2828 的回复:
重载EreasBackground,删除掉函数内容,直接返回True即可
.

#8


不要刷新桌面。

#9


引用 5 楼 Fireway2008 的回复:
m_vParticles 是个什么类型的变量呢? 
楼主自己定义的类? 
看能否把 相关代码贴出来,也许数量也影响到闪烁和其他效果。

这个就是一个数组。。我取很少10个,很多100个的效果是一样的。试过了

#10


引用 3 楼 wanglcho_cn 的回复:
::InvalidateRect(hWallPaper, NULL, TRUE);  //刷新 

在这刷新 不合理

可是改成FALSE也会闪

#11


使用过了,还是不行

#1


Sorry .HDC  hWallPaperDC = ::GetDC(hDesk);
应该是HDC  hWallPaperDC = ::GetDC(hWallPaper);
我写错了。。。可是还在闪

#2


用了双缓存还在闪?看看能不能少画一点,或者用硬件加速

#3


::InvalidateRect(hWallPaper, NULL, TRUE);  //刷新

在这刷新 不合理

#4


::InvalidateRect(hWallPaper, NULL, TRUE);  //刷新 
这个会触发底色的重画的,建议去掉这个
如果你仅仅在固定的范围内画雪花,那么,只要在固定范围内贴图即可
如果是雪花随意飘动,那么,就先将桌面位图保存下来,拷贝后,在拷贝后的位图上面画雪花,画完后,再将这个位图贴出,也可以解决底色重画!
Invalidate类的函数,特别在参数传TRUE的时候,应该会触发底色重画的,所以,当底色与所画的东西的色彩不一样的话,很容易导致闪烁!

#5


m_vParticles 是个什么类型的变量呢?
楼主自己定义的类?

看能否把 相关代码贴出来,也许数量也影响到闪烁和其他效果。

#6


重载EreasBackground,删除掉函数内容,直接返回True即可

#7


引用 6 楼 san2828 的回复:
重载EreasBackground,删除掉函数内容,直接返回True即可
.

#8


不要刷新桌面。

#9


引用 5 楼 Fireway2008 的回复:
m_vParticles 是个什么类型的变量呢? 
楼主自己定义的类? 
看能否把 相关代码贴出来,也许数量也影响到闪烁和其他效果。

这个就是一个数组。。我取很少10个,很多100个的效果是一样的。试过了

#10


引用 3 楼 wanglcho_cn 的回复:
::InvalidateRect(hWallPaper, NULL, TRUE);  //刷新 

在这刷新 不合理

可是改成FALSE也会闪

#11


使用过了,还是不行