DirectX图形处理(2)

 创建翻转表面
   在设置了显示模式后,必须创建用于放置应用程序的表面。因为DDex1例子程序已用IDirectDraw7::SetCooperativeLevel方法将模式设置为独占(全屏)模式,所以可以创建在表面之间进行翻转的表面。如果使用SetCooperativeLevel将模式设置为 DDSCL_NORMAL,就可以创建在表面之间进行位块传输的惟一表面。创建翻转表面的步骤如下:

(1)定义表面需求

   创建翻转表面的第一步是在DDSURFACEDESC2结构中定义表面需求。下列例子程序显示了创建翻转表面所需的结构定义和标志。

// 创建有一个后台缓冲区的主表面

ddsd.dwSize = sizeof(ddsd);

ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;

ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |

    DDSCAPS_FLIP | DDSCAPS_COMPLEX;

 

ddsd.dwBackBufferCount = 1;

   在上面的例子中,将dwSize成员设置为DDSURFACEDESC2结构的大小。这样做是为了阻止所使用的任何DirectDraw方法调用返回无效的成员错误(提供dwSize成员是为了便于将来对DDSURFACEDESC2结构进行扩展)。

   dwFlags成员用于确定将DDSURFACEDESC2结构中的哪些成员用来填充有效信息。对于DDex1例子程序,dwFlags的值用于指定希望使用DDSCAPS结构(DDSD_CAPS)以及希望创建一个后台缓冲区(DDSD_BACKBUFFERCOUNT)。

   例子程序中的dwCaps成员表明将在DDSCAPS结构中使用的标志。在这里该成员指定了一个主表面(DDSCAPS_PRIMARYSURFACE)、一个翻转表面(DDSCAPS_FLIP)和一个复合表面(DDSCAPS_COMPLEX)。

   最后,例子程序指定了一个后台缓冲区(后台缓冲区是写入背景和实体的区域),然后将后台缓冲区翻转到主表面上。在DDex1例子程序中,后台缓冲区数设置为1。但是可以创建显示内存所能支持的任意数量的后台缓冲区。

表面内存可以是显示内存或系统内存。如果应用程序用尽了显示内存,DirectDraw就使用系统内存(例如在只有1 MB RAM的显示适配器上指定了不止一个后台缓冲区)。也可以通过将DDSCAPS结构中的dwCaps成员设置为DDSCAPS_SYSTEMMEMORY或DDSCAPS_VIDEOMEMORY,来指定是否只使用系统内存或显示内存(如果指定了DDSCAPS_VIDEOMEMORY,但没有足够的内存用来创建表面,则IDirectDraw7:: CreateSurface返回一个DDERR_OUTOFVIDEOMEMORY错误)。

(2)创建表面

   填充DDSURFACEDESC2结构之后,用该结构和lpDD可以调用IDirectDraw7:: CreateSurface方法。lpDD是指向由DirectDrawCreateEx函数创建的DirectDraw对象的指针。调用IDirectDraw7::CreateSurface方法的过程如下:

ddrval = lpDD->CreateSurface(&ddsd, &lpDDSPrimary, NULL);

if(ddrval == DD_OK)

{

    // lpDDSPrimary指向新的表面

}

else

{

    // 创建表面失败

    return FALSE;

}

   如果调用成功,则lpDDSPrimary参数将指向由CreateSurface返回的主表面。在得到指向主表面的指针之后,就可以使用IDirectDrawSurface7::GetAttachedSurface方法获取指向后台缓冲区的指针,如下所示:

ddscaps.dwCaps = DDSCAPS_BACKBUFFER;

ddrval = lpDDSPrimary->GetAttachedSurface(&ddcaps, &lpDDSBack);

if(ddrval == DD_OK)

{

    // lpDDSBack指向后台缓冲区

}

else

{

    return FALSE;

}

   通过提供表面的主表面地址和用DDSCAPS_BACKBUFFER标志设置能力值,如果IDirectDrawSurface7::GetAttachedSurface调用成功,lpDDSBack参数将指向后台缓冲区。

5. 在表面上绘图
   在创建了主表面和后台缓冲区后,DDex1 例子程序通过使用标准Windows GDI函数在主表面和后台缓冲区上输出了一些文本,如下列例子所示:

if (lpDDSPrimary->GetDC(&hdc) == DD_OK)

{

    SetBkColor(hdc, RGB(0, 0, 255));

    SetTextColor(hdc, RGB(255, 255, 0));

    TextOut(hdc, 0, 0, szFrontMsg, lstrlen(szFrontMsg));

    lpDDSPrimary->ReleaseDC(hdc);

}

 

if (lpDDSBack->GetDC(&hdc) == DD_OK)

{

    SetBkColor(hdc, RGB(0, 0, 255));

    SetTextColor(hdc, RGB(255, 255, 0));

    TextOut(hdc, 0, 0, szBackMsg, lstrlen(szBackMsg));

    lpDDSBack->ReleaseDC(hdc);

}

   上面的例子用IDirectDrawSurface7::GetDC方法来获取设备环境句柄,并在方法的内部锁定了表面。如果不打算使用需要设备环境句柄的Windows函数,可以使用IDirectDrawSurface7::Lock和IDirectDrawSurface7::Unlock方法来锁定和解锁后台缓冲区。

   锁定表面内存(整个表面或表面的一部分)可确保应用程序和系统传输器不能同时访问表面内存。这样可以防止在应用程序写入表面内存时发生错误。另外,应用程序在解锁表面内存之前不能进行页面翻转。

   在锁定表面后,例子程序用标准Windows GDI函数SetBkColor设置背景颜色,用SetTextColor选择要放在背景上的文本颜色,用TextOut在表面上输出文本和背景颜色。

   在将文本写入到缓冲区后,例子程序用IDirectDrawSurface7::ReleaseDC方法来解锁表面并释放句柄。无论在什么时候,只要应用程序完成写入后台缓冲区,就必须调用IDirectDrawSurface7::ReleaseDC或IDirectDrawSurface7::Unlock,这取决于应用程序本身。应用程序在解锁表面以前不能翻转表面。

   通常将数据写入到后台缓冲区,然后将后台缓冲区翻转到主表面上使其显示出来。DDex1例子程序在第一次翻转之前有明显的延迟,因此DDex1在初始化函数中写入到主缓冲区,以便防止在显示表面之前产生的延迟。在本例子程序后面的步骤中可以看到,DDex1例子程序在WM_TIMER期间写入后台缓冲区。一般会在初始化函数或标题页中将数据写入主表面。

   注意:在用IDirectDrawSurface7::Unlock解锁表面之后,表面内存指针是无效的。必须再次使用IDirectDrawSurface7::Lock,才能获得有效的表面内存指针。

6. 输出到表面
   在DDex1中WM_TIMER消息的前面一半的作用是写入后台缓冲区,如下列例子所示:

case WM_TIMER:

    // 翻转表面

    if(bActive)

    {

        if (lpDDSBack->GetDC(&hdc) == DD_OK)

        {

            SetBkColor(hdc, RGB(0, 0, 255));

            SetTextColor(hdc, RGB(255, 255, 0));

            if(phase)

            {

                TextOut(hdc, 0, 0, szFrontMsg, lstrlen(szFrontMsg));

                phase = 0;

            }

            else

            {

                TextOut(hdc, 0, 0, szBackMsg, lstrlen(szBackMsg));

                phase = 1;

            }

            lpDDSBack->ReleaseDC(hdc);

        }
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值