2 dishiji dishiji 于 2014.12.09 21:38 提问

DirectDraw Flip三重缓冲 切图时有时候会闪出窗口

/*
使用了3缓冲,1个主表面 (lpDDSPrimary)2个后台表面lpDDSBuffer,lpDDSBuffer2
在每个垂直同步信号(帧信号)来的时候,使用Flip切换
lpDDSPrimary->Flip(NULL,0);此时完成交换表面指针的操作
然后填充第1个lpDDSBuffer

问题:我是用VForm开发的,系统为WIN7 64位,VS2010,有时候肉眼能看到闪过我的Form控制台窗体,帧频设置为75Hz,退出程序,查看时间,确实也是1000/75=13.3333ms
,一闪而过,下午又突然好了,没闪了 这是为什么了,望高手解答

**/

    /*创建Surface表面*/ 
         m_hwnd=(HWND)::GetActiveWindow();
          HRESULT      ddrval; 
          DDSURFACEDESC2 ddsd; // DirectDraw的页面描述 
          ddrval=DirectDrawCreateEx (NULL, (VOID**)&lpDD, IID_IDirectDraw7, NULL);
          if(ddrval != DD_OK) 
          { 
              //DirectDraw 对象不能被创建"
               strTimerIntr+="error:DirectDrawCreateEx\r\n";
               //RunningLOG("error:DirectDrawCreateEx\r\n ");
              return FALSE;
          } 
          //这里使用了 if ( xxx != DD_OK) 的方法进行错误检测,这是最常用的方法  
          ddrval=lpDD->SetCooperativeLevel(m_hwnd,DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN);//DDSCL_NORMAL  DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN
          if (ddrval != DD_OK)  
          {
               strTimerIntr+="error:SetCooperativeLevel\r\n ";
              //RunningLOG("error:SetCooperativeLevel\r\n ");
              return FALSE; //设置DirectDraw控制级  
          }
          //if ( lpDD->SetDisplayMode( FullScrenn_Width, FullScrenn_Height, FullScrenn_Bits, 0, DDSDM_STANDARDVGAMODE ) != DD_OK ) 
          //{
             // return FALSE; //设置显示模式  
          //}
          //开始创建主页面,先清空页面描述  

          memset(&ddsd, 0, sizeof(DDSURFACEDESC2));  
          //填充页面描述  
          ddsd.dwSize = sizeof( ddsd );  
          ddsd.dwFlags = DDSD_CAPS|DDSD_BACKBUFFERCOUNT; //有后台缓存  
          ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_COMPLEX|DDSCAPS_FLIP|DDSCAPS_VIDEOMEMORY; //只使用显存来创建
          ddsd.dwBackBufferCount = 2; //一个后台缓存  
          if ( lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL ) != DD_OK )  
          {
              strTimerIntr+="error:SetCooperativeLevel\r\n ";
              //RunningLOG("error:CreateSurface lpDDSPrimary\r\n ");
              return FALSE; //创建主页面  
          }
          ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER|DDSCAPS_VIDEOMEMORY; //这是后台缓存  
          if ( DD_OK != lpDDSPrimary->GetAttachedSurface( &ddsd.ddsCaps, &lpDDSBuffer ))  
          {
              strTimerIntr+="error:GetAttachedSurface lpDDSBuffer\r\n ";
              return FALSE; //创建后台缓存 
          }

/*下面代码为关键测试代码,在一个线程中等待垂直同步信号*/
WaitForVerticalBlank();//等待垂直同步信号过来
{
while (DDERR_WASSTILLDRAWING==lpDDSBuffer->GetFlipStatus(DDGFS_ISFLIPDONE));//等待上一次后台翻面操作完成

HRESULT ddrval;
ddrval=lpDDSPrimary->Flip(NULL,0);//切换前后台
while (1)
{
if (DD_OK==ddrval)
{
break;
}
if (DDERR_SURFACELOST==ddrval)
{
ddrval=lpDDSPrimary->Restore();//尝试恢复页面
if (DD_OK==ddrval)
{
break;
}

                 }
                 if (DDERR_WASSTILLDRAWING!=ddrval)
                 {
                     break;
                 }
             }
            PainSurface(lpDDSBuffer);//填充后台缓冲

}

void PainSurface(LPDIRECTDRAWSURFACE7 LPback)
{
HRESULT hRet;
HDC mydc;
BYTE* pTmpDest = BitmapData;
int add = WIDTHBYTES(PICTURE_WIDTH*24) - PICTURE_WIDTH * 3;
if (add)
{
MessageBox::Show("图像WidthByte不是4的整数倍");
}
//保证surface可用
if(LPback->IsLost()!=DD_OK)
{
hRet = LPback->Restore();
if (hRet != DD_OK)
{
MessageBox::Show(_T("无法Restore surface"));
return;
}
}
//// 取得DC
hRet = LPback->GetDC(&mydc);

if (hRet != DD_OK)
{

MessageBox::Show(_T("无法GetDC"));
return;
}
pin_ptr pinBuff = &arrayFileRGBBuff[0];//获取图像数据地址
if(GDI_ERROR == StretchDIBits(mydc,0,0,PICTURE_WIDTH,PICTURE_HEIGHT,0,0,PICTURE_WIDTH,PICTURE_HEIGHT,
(void *)pinBuff,
&bmi,
DIB_RGB_COLORS,
SRCCOPY))
{
MessageBox::Show(_T("图片生成失败"));
return;
}
lpDDSBuffer->ReleaseDC(mydc);
}

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!