首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

请问怎么解决双缓冲刷新和半透明控件显示背景的矛盾

2012-09-12 
请教如何解决双缓冲刷新和半透明控件显示背景的矛盾在下在一个对话框上想绘制一个动画,因此需要使用双缓冲

请教如何解决双缓冲刷新和半透明控件显示背景的矛盾
在下在一个对话框上想绘制一个动画,因此需要使用双缓冲进行不断地刷新;然而在该对话框上又有需要半透明效果的控件(比如半透明的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,把贴图画到你的按钮上去。

热点排行