DirectX8.1的DirectDraw7研究手记(二) 中

来源:互联网 发布:英国 知乎 编辑:程序博客网 时间:2024/06/03 18:03

我们边看程序边讲解,程序的框架是用vc6windows application生成的hello World改写的。这里没有解释程序在Alt+Tab切换一次后图片不见的问题,也没有说为什么用BltFast而没用Blt,同样也没有说AddRef()函数是干什么的。没用g_lpdd->CreatePalette(,,,,);函数时,用256色即#define BPP 8时,可能会有颜色失真,而16位色/时就不必用这个函数了!也不会有颜色失真。不过先这样用着,以后我在解释。

 

// directx.cpp : Defines the entry point for the application.

//

 

#include "stdafx.h"

#include "resource.h"

#include <ddraw.h>

 

#define MAX_LOADSTRING 100

 

// Global Variables:

HINSTANCE hInst;                                                              // current instance

TCHAR szTitle[MAX_LOADSTRING];                                           // The title bar text

TCHAR szWindowClass[MAX_LOADSTRING];                      // The title bar text

 

// Foward declarations of functions included in this code module:

ATOM                           MyRegisterClass(HINSTANCE hInstance);

BOOL                            InitInstance(HINSTANCE, int);

LRESULT CALLBACK         WndProc(HWND, UINT, WPARAM, LPARAM);

//---------------------全局变量和一些预定义宏---------------------------------------

//这两个预定义宏是为了方便释放指针用的在下面的FreeDraw()函数中有用

#define SAFE_DELETE(p)  { if(p) { delete (p);     (p)=NULL; } }

#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }

 

//显示模式的设定640×480×8

#define WIDTH 640

#define HEIGHT 480

#define BPP 8

//试试#define BPP 16会有什么效果??

//没用g_lpdd->CreatePalette(,,,,);函数时,用256色即#define BPP 8时,可能会有颜色失真,而16位色//时就不必用这个函数了!也不会有颜色失真。

HRESULT initDirectDraw(HINSTANCE hInst);//初始化DirectDraw

HRESULT MainLoop();//熟称GameLoop

void FreeDraw();//释放所有DirectDraw的指针

 

LPDIRECTDRAW7 g_lpdd;//指向实体的指针

LPDIRECTDRAWSURFACE7 g_lpFrontSurface;//A page

LPDIRECTDRAWSURFACE7 g_lpBackSurface;//B page

LPDIRECTDRAWSURFACE7 g_lpOffScreen;//用于后台的离屏页面

BOOL g_bActive=TRUE;//决定mainloop是否运行的标志

 

//-----------------------------------------------------------------------------

//Function:iniDirectDraw()

//用于初始化

//完成任务:创建g_lpdd指针实体、获取显示模式、设置显示模式、制作页面信息

//                           创建主表面对象、提取后台缓存表面指针、用图片创建离屏页面

HRESULT initDirectDraw(HINSTANCE hInst)

{

  HRESULT hr;

  DDSURFACEDESC2 ddsd;

  DDSCAPS2 ddscaps;

 

  ZeroMemory(&ddsd,sizeof(ddsd));

  ZeroMemory(&ddscaps,sizeof(ddscaps));

 

  FreeDraw();

  //创建g_lpdd指针实体

  if(FAILED(hr = DirectDrawCreateEx(NULL, (void**)&g_lpdd,IID_IDirectDraw7, NULL)))

           return E_FAIL;

 

  //获取显示模式

  if(FAILED(hr = g_lpdd->SetCooperativeLevel(GetActiveWindow(),DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN)))

           return E_FAIL;

 

  //设置显示模式

  if(FAILED(hr = g_lpdd->SetDisplayMode(WIDTH,HEIGHT,BPP,0,0)))

           return E_FAIL;

 

  //制作页面信息

  ddsd.dwSize = sizeof(ddsd);

  ddsd.dwFlags = DDSD_CAPS|DDSD_BACKBUFFERCOUNT;

  ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX;

  ddsd.dwBackBufferCount = 1 ;

  //创建主表面对象

  if(FAILED(hr = g_lpdd->CreateSurface(&ddsd,&g_lpFrontSurface,NULL)))

           return E_FAIL;

 

  //提取后台缓存表面指针

  ddscaps.dwCaps = DDSCAPS_BACKBUFFER;

  if(FAILED(hr = g_lpFrontSurface->GetAttachedSurface(&ddscaps,&g_lpBackSurface)))

           return E_FAIL;

 

  g_lpBackSurface->AddRef();//没有他似乎也能运行正常?

 

  //用图片创建离屏页面

  HBITMAP         hbm=NULL;

  BITMAP         bmp;

// IDB_BITMAP1是图片资源

    hbm = (HBITMAP) LoadImage( GetModuleHandle(NULL), MAKEINTRESOURCE( IDB_BITMAP1 ),

                                IMAGE_BITMAP, 1500, 280, //图片读取进来后变形成多大的尺寸width,height

                                LR_CREATEDIBSECTION );

 

    GetObject( hbm, sizeof(bmp), &bmp );

 

 

  ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;

    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;

  ddsd.dwWidth  = bmp.bmWidth ;

    ddsd.dwHeight = bmp.bmHeight ;

 

  hr = g_lpdd->CreateSurface(&ddsd,&g_lpOffScreen,NULL);

  if(FAILED(hr))

  {

           if(hr == DDERR_OUTOFVIDEOMEMORY)

           {//这是最后机会

                    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN |  DDSCAPS_SYSTEMMEMORY;

                   

                    if(FAILED(hr = g_lpdd->CreateSurface(&ddsd, &g_lpOffScreen, NULL )))

                             return E_FAIL;

           }

  }

 

 

 

  HDC hdc;

  HDC         hdcImage;

 

    hdcImage = CreateCompatibleDC(NULL);

  SelectObject(hdcImage, hbm);

 

  g_lpOffScreen->Restore();

  g_lpOffScreen->GetSurfaceDesc(&ddsd);

 

  if((hr = g_lpOffScreen->GetDC(&hdc))==DD_OK)

  {

          StretchBlt(hdc, 0, 0, ddsd.dwWidth, ddsd.dwHeight, hdcImage, 0, 0,

                                bmp.bmWidth ,bmp.bmHeight  , SRCCOPY);

 

           g_lpOffScreen->ReleaseDC(hdc);

  }

 

  DeleteDC(hdcImage);

 

  return S_OK;        

}

 

//这里的宏在最上面定义了

void FreeDraw()

{

  SAFE_RELEASE(g_lpFrontSurface);

  SAFE_RELEASE(g_lpBackSurface);

  SAFE_RELEASE(g_lpOffScreen);

  SAFE_RELEASE(g_lpdd);

}

//Function:MainLoop()

//

//

HRESULT MainLoop()

{

  HRESULT hRet;

  RECT rect;

  rect.left =0;

  rect.top = 0;

  rect.right = 150;

  rect.bottom = 140;

//从离屏页面把存在OffScreen的图片取出rect举行位置的图片,拷贝到后台缓存中

  g_lpBackSurface->BltFast(0,0,g_lpOffScreen,&rect,DDBLTFAST_NOCOLORKEY);

//后台缓存画上了图象,那么就Flip放到前台让他显示出来

  g_lpFrontSurface->Flip(NULL, 0 );

  return S_OK;

}

//

原创粉丝点击