各位高手请进来解答一下
还是昨天的那个问题我在对话中加入了一个static控件,并且使它的背景颜色为黑色
同时我调用另外一个线程在static控件中播放视频图像
我现在想要在播放视频图像的同时在控件上绘制图形,这个图形又不能被视频图像覆盖掉
我使用了双缓冲;可是出现了视频图像闪烁的问题
请问如何去除这个闪烁的问题
代码如下
void CVideoWnd::OnPaint()
{
  CStatic::OnPaint();
HDC hdc = ::GetDC( this->GetSafeHwnd() );
HBRUSH brush = ::CreateSolidBrush(RGB(10,10,10));
RECT rect ;
this->GetClientRect(&rect);
HGDIOBJ old = ::SelectObject(hdc, brush);
::Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);//设置控件的背景颜色为黑色
         ::SelectObject(hdc, old); if ( !m_bSet )//判断是否创建了兼容内存dc
{
                  //这里m_dcMem, m_bmp, m_rect 为CVideoWnd的成员
CDC* pdc = GetDC();
m_dcMem.CreateCompatibleDC( NULL );//创建兼容内存dc
GetClientRect(&m_rect);
         m_bmp.CreateCompatibleBitmap(pdc, m_rect.Width(), m_rect.Height());//创建了兼容bimap
m_bSet = TRUE;
ReleaseDC(pdc);
}
}BOOL CVideoWnd::PreTranslateMessage( MSG* pMsg )
{
switch(pMsg->message)
{
case WM_LBUTTONDOWN:
ImpLButtonDown(pMsg);
break;
case WM_MOUSEMOVE:
ImpLButtonMove(pMsg);
break;
case WM_LBUTTONUP:
ImpLButtonUp(pMsg);
break;
}
return CStatic::PreTranslateMessage(pMsg);
}void CVideoWnd::ImpLButtonDown(MSG* pMsg)
{
AoutLock lock(&m_synGeometry);
HCURSOR cursor = AfxGetApp()->LoadStandardCursor(IDC_CROSS);
::SetCursor(cursor);
POINT ptCur = pMsg->pt;
ScreenToClient(&ptCur);
GetRelativePoint( ptCur ); if (m_nType == 1) //线
{
if(m_nStep == 0) //判断点操作是否开始
{
m_ps = m_pe = ptCur;
m_nStep ++;
SetCapture();
}
else //判断点操作是否结束
{
m_nStep = 0;
::ReleaseCapture();
}
}
}void CVideoWnd::ImpLButtonMove(MSG* pMsg)
{
AoutLock lock(&m_synGeometry);
HCURSOR cursor = AfxGetApp()->LoadStandardCursor(IDC_CROSS);
::SetCursor(cursor);
POINT ptCur = pMsg->pt;
ScreenToClient(&ptCur);
GetRelativePoint( ptCur );
CDC* pDc = GetDC();
if (m_nType == 1  )//线
{
if(m_nStep != 0)
{
                           CBitmap* pOldBmp = m_dcMem.SelectObject(&m_bmp);
m_dcMem.SetROP2(R2_NOTXORPEN);//设置线条模式
HDC hdc = m_dcMem.GetSafeHdc();
DrawGTLine(hdc, m_ps, m_pe);
m_pe = ptCur;
DrawGTLine(hdc, m_ps, ptCur);
BOOL b = pDc->BitBlt(0, 0, m_rect.Width(), m_rect.Height(), &m_dcMem, 0, 0, SRCCOPY);
m_dcMem.SelectObject(pOldBmp);
}
}
}这是绘制图形的过程
在这个过程中就会出现视频的闪烁
请高手帮帮忙,怎样解决这个问题

解决方案 »

  1.   

    你说的是什么背景色
    视频图像吗?
    我解决了视频图像闪烁的问题
    就是将pDc->BitBlt(0, 0, m_rect.Width(), m_rect.Height(), &m_dcMem, 0, 0, SRCCOPY); 
    改为pDc->BitBlt(0, 0, m_rect.Width(), m_rect.Height(), &m_dcMem, 0, 0, SRCPAINT); 
    让绘制的图形根视频图像进行一下or的组合
    但有个问题是加了背景色之后为什么我画的图形颜色不时我所设置的颜色
    我默认下是红色,可画出来却是个蓝色去了
    这个市怎么回事
    m_dcMem.SetROP2(R2_NOTXORPEN);//设置线条模式 
    HDC hdc = m_dcMem.GetSafeHdc(); 
    DrawGTLine(hdc, m_ps, m_pe); 
    m_pe = ptCur; 
    DrawGTLine(hdc, m_ps, ptCur); void DrawGTLine( HDC hdc, const POINT& s, const POINT& e, COLORREF color /*= RGB(255,0,0)*/, int Thick /*= 0*/ )
    {
    HPEN pen = ::CreatePen(PS_SOLID, Thick, color);
    ::SelectObject(hdc, pen);
    ::MoveToEx(hdc, s.x, s.y, NULL);
    BOOL b = ::LineTo(hdc, e.x, e.y);
    ::DeleteObject(pen);
    }
      

  2.   

    http://www.codeproject.com/KB/audio-video/VideoPicture.aspx
      

  3.   

    先截获sp的每帧到内存DC/Bitmap,在上面画,然后显示.
    而不是你画它也画.
      

  4.   

    呵呵
    lambochan说的对头
    我自己后来也想到了是这个问题
      

  5.   

    你的这种程序我没有接触过..以前做过打开bmp位图的程序,用的双缓冲..你参考下吧显示图形如何避免闪烁,如何提高显示效率是问得比较多的问题。而且多数人认为MFC的绘图函数效率很低,总是想寻求其它的解决方案。
    MFC的绘图效率的确不高但也不差,而且它的绘图函数使用非常简单,只要使用方法得当,再加上一些技巧,用MFC可以得到效率很高的绘图程序。
    我想就我长期(呵呵当然也只有2年多)使用MFC绘图的经验谈谈我的一些观点。1、显示的图形为什么会闪烁?
       我们的绘图过程大多放在OnDraw或者OnPaint函数中,OnDraw在进行屏幕显示时是由OnPaint进行调用的。当窗口由于任何原因需要重绘时,总是先用背景色将显示区清除,然后才调用OnPaint,而背景色往往与绘图内容反差很大,这样在短时间内背景色与显示图形的交替出现,使得显示窗口看起来在闪。如果将背景刷设置成NULL,这样无论怎样重绘图形都不会闪了。当然,这样做会使得窗口的显示乱成一团,因为重绘时没有背景色对原来绘制的图形进行清除,而又叠加上了新的图形。有的人会说,闪烁是因为绘图的速度太慢或者显示的图形太复杂造成的,其实这样说并不对,绘图的显示速度对闪烁的影响不是根本性的。例如在OnDraw(CDC *pDC)中这样写:
    pDC->MoveTo(0,0);
    pDC->LineTo(100,100);
    这个绘图过程应该是非常简单、非常快了吧,但是拉动窗口变化时还是会看见闪烁。其实从道理上讲,画图的过程越复杂越慢闪烁应该越少,因为绘图用的时间与用背景清除屏幕所花的时间的比例越大人对闪烁的感觉会越不明显。比如:清楚屏幕时间为1s绘图时间也是为1s,这样在10s内的连续重画中就要闪烁5次;如果清楚屏幕时间为1s不变,而绘图时间为9s,这样10s内的连续重画只会闪烁一次。这个也可以试验,在OnDraw(CDC *pDC)中这样写:
    for(int i=0;i<100000;i++)
    {
    pDC->MoveTo(0,i);
    pDC->LineTo(1000,i);
    }
    呵呵,程序有点变态,但是能说明问题。
       说到这里可能又有人要说了,为什么一个简单图形看起来没有复杂图形那么闪呢?这是因为复杂图形占的面积大,重画时造成的反差比较大,所以感觉上要闪得厉害一些,但是闪烁频率要低。那为什么动画的重画频率高,而看起来却不闪?这里,我就要再次强调了,闪烁是什么?闪烁就是反差,反差越大,闪烁越厉害。因为动画的连续两个帧之间的差异很小所以看起来不闪。如果不信,可以在动画的每一帧中间加一张纯白的帧,不闪才怪呢。
    2、如何避免闪烁
       在知道图形显示闪烁的原因之后,对症下药就好办了。首先当然是去掉MFC提供的背景绘制过程了。实现的方法很多,
    * 可以在窗口形成时给窗口的注册类的背景刷付NULL
    * 也可以在形成以后修改背景
       static CBrush brush(RGB(255,0,0));
       SetClassLong(this->m_hWnd,GCL_HBRBACKGROUND,(LONG)(HBRUSH)brush);
    * 要简单也可以重载OnEraseBkgnd(CDC* pDC)直接返回TRUE
       这样背景没有了,结果图形显示的确不闪了,但是显示也象前面所说的一样,变得一团乱。怎么办?这就要用到双缓存的方法了。双缓冲就是除了在屏幕上有图形进行显示以外,在内存中也有图形在绘制。我们可以把要显示的图形先在内存中绘制好,然后再一次性的将内存中的图形按照一个点一个点地覆盖到屏幕上去(这个过程非常快,因为是非常规整的内存拷贝)。这样在内存中绘图时,随便用什么反差大的背景色进行清除都不会闪,因为看不见。当贴到屏幕上时,因为内存中最终的图形与屏幕显示图形差别很小(如果没有运动,当然就没有差别),这样看起来就不会闪。
    3、如何实现双缓冲
       首先给出实现的程序,然后再解释,同样是在OnDraw(CDC *pDC)中:CDC MemDC; //首先定义一个显示设备对象
    CBitmap MemBitmap;//定义一个位图对象//随后建立与屏幕显示兼容的内存显示设备
    MemDC.CreateCompatibleDC(NULL);
    //这时还不能绘图,因为没有地方画 ^_^
    //下面建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的大小
    MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight);//将位图选入到内存显示设备中
    //只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上
    CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);//先用背景色将位图清除干净,这里我用的是白色作为背景
    //你也可以用自己应该用的颜色
    MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255));//绘图
    MemDC.MoveTo(……);
    MemDC.LineTo(……);//将内存中的图拷贝到屏幕上进行显示
    pDC->BitBlt(0,0,nWidth,nHeight,&MemDC,0,0,SRCCOPY);//绘图完成后的清理
    MemBitmap.DeleteObject();
    MemDC.DeleteDC();