请教如何解决双缓冲刷新和半透明控件显示背景的矛盾
在下在一个对话框上想绘制一个动画,因此需要使用双缓冲进行不断地刷新;然而在该对话框上又有需要半透明效果的控件(比如半透明的PNG按钮),使他们能透过本身显示出下面对话框背景的颜色。
个人在实际的使用中,发现以我掌握到的方法,对话框的双缓冲和半透明控件之间似乎很难共存。主要是如下几个方面造成的:
1、为了动态显示动画,必须使用双缓冲;
2、由于对话框不断的刷新——即使只刷新动画那一块,一样会造成对话框上控件的闪烁;
3、为了阻止对话框在重绘时不断刷新控件,于是我只能将对话框的“Clip Children”属性设置为true;
4、“Clip Children”属性设置后,对话框重绘时不去管它的子控件,闪是不会闪了,可半透明按钮“先绘制背景,再在该区域上绘制本按钮”的要求又达不到了。
对话框中的OnPaint()函数代码:
- C/C++ code
void CtestDlg::OnPaint(){ CPaintDC dc(this); // device context for painting CRect rect; GetClientRect(&rect); int Width = rect.right - rect.left; int Height = rect.bottom - rect.top; CDC *pDC = this->GetDC(); CDC MenmDC; CBitmap MemBitmap; MenmDC.CreateCompatibleDC(NULL); MemBitmap.CreateCompatibleBitmap(pDC, Width, Height); CBitmap *pOldBit = MenmDC.SelectObject(&MemBitmap); /*********************************************************/ MenmDC.FillSolidRect(0, 0, Width, Height, RGB(255, 128, 0)); //根据变量计数,绘制当前进度条的长度 using namespace Gdiplus; Graphics graphics(MenmDC.m_hDC); graphics.DrawImage(m_ImgScroll, Rect(30, 120, m_ImgScroll->GetWidth() * ((float)m_Tick / (float)100), m_ImgScroll->GetHeight()), 0, 0, m_ImgScroll->GetWidth() * ((float)m_Tick / (float)100), m_ImgScroll->GetHeight(), UnitPixel); /*********************************************************/ pDC->BitBlt(0, 0, Width, Height, &MenmDC, 0, 0, SRCCOPY); MenmDC.SelectObject(pOldBit); MemBitmap.DeleteObject(); MenmDC.DeleteDC(); ReleaseDC(pDC);}对话框中的OnEraseBkgnd(CDC* pDC)函数代码:
- C/C++ code
BOOL CtestDlg::OnEraseBkgnd(CDC* pDC){ return TRUE;}对话框中不断刷新重绘的代码:
- C/C++ code
void CtestDlg::OnTimer(UINT nIDEvent){ switch (nIDEvent) { case 1201: { ++ m_Tick; if (m_Tick >= 100) { m_Tick = 0; } //获取当前进度条需要绘制的长度,并刷新之 CRect rect; rect.left = 30; rect.top = 120; rect.right = rect.left + m_ImgScroll->GetWidth() * ((float)m_Tick / (float)100); rect.bottom = rect.top + m_ImgScroll->GetHeight(); InvalidateRect(&rect, FALSE); } break; }}这是一张用来做按钮的图片,除了文字之外都是透明的,以便显示背景中的内容:
比如下图,在没有设置对话框的“Clip Children”属性为true时,半透明按钮是可以成功在对话框重绘之后重绘自己,从而正确半透明的显示背景的:
可是这样做的结果会造成按钮控件闪烁。
比如下图,在设置了对话框的“Clip Children”属性为true之后,控件不闪烁了,可是半透明的效果却没有了:
实在是有点没招了,求各位达人指教一下,谢谢……
这里是工程的代码
[解决办法]
按钮不用控件,直接用画的,跟背景一块画。
响应点击时判断鼠标是否点在上面就是了。
[解决办法]
可以用2楼方法
还可以:
画按钮的时候,按照合适的坐标,把对话框的背景画到按钮背景
[解决办法]
确实矛盾的。
不过,楼主可以尝试下,让按钮控件完全不重绘,直接用背景图案压住按钮。(当做按钮不存在)
[解决办法]
[解决办法]
我后来想了下,这个方法BUG比较大,因为如果其他窗口压在主窗体上面,就刷新不了了。
要不用用看TransparentBlt,把贴图画到你的按钮上去。