| 
一、 MFC类库与DirectXSDK 
   Microsoft DirectX SDK是开发基于 Windows平台游戏的一个软件开发工具,其主要功能主要包括在五个组件中: DirectDraw、 DirectSound、DirectPlay、Direct3D和DirectInput,每个组件都具不同的功能: 
  .DirectDraw使用直接写存技术加快游戏的动画速度;   .DirecSound控制游戏声音的合成和播放;   .DirectPlay使游戏具有网络多人游戏功能;   .Direct3D让程序员更方便地开发三维游戏:   .DirectInput使游戏支待更多的输入设备(现在只支持游戏杆、鼠标和键盘)。 
  可以说DirectXSDK提供了编写一个游戏所必须的功能及基层函数,所以大多Windows游戏都使用了DitrectXSDK。 
  MFC(Microsoft Foundation Class)类库是Microsoft Visual C++中提供的一个功能强大的Windows应用程序开发类,使用这些类我们可以避免和繁琐的Windows APl打交道,而且在VisualC++中我们还可以利用C1assWizard对MFC类进行Windows消息映射,所以如果能用MFC类库来开发DirectXSDK的应用程序,至少有以下几个好处: 
  1.可以用 VC++的 C1assWizard方便地对Windows消息进行映射; 
  2.增加了程序的可读性,并且可以用VC++的ClassView方便的管理所用的类; 
  3.增加程序代码的可重用性,可以在原有的基础上开发出功能更强大的应用程序更进一步,如果我们能开发出一个能生成DirectXSDK应用程序基本框架的VC++的工程向导,则为以后开发DirectX SDK应用程序提供及大的方便。下面,我们将用Visua1 C++5.0先编写一个DirectXSDK应用程序的基本框架。 
  二、编写DirectXSDK应用程序基本框架 
  我们按下列步骤建立一个勘rectXSDK程序的基本框架: 
  1.用 Visual C++的 MFC AppWizard(EXE)生成一个基于对话框的工程文件,取名为DirectX,在向导第二步时取消About Box的复选框,然后按Finish按钮。 
  2.删除在DirectX工程目录中生成的DirectXDlg.CPP和DirectXDlg.H两个文件,并在Visual C++的FileView中删除以上两个文件,按CTRL十W启动ClassWizard删除CDirectXDlg类,然后在ResourceView中删除 IDD_DIRECTX_ DIALOG。 
  3.建立两个文件 DirectXWnd.CPP和DirectXWnd.H(这两个文件在本文的附录中,请注意不要删除有“\\{”和“\\}”之间的内容,否则将不能使用ClassWizard对窗口消息进行映射),并把它们加入到工程中。这时工程中将增加一个基于CWnd的CDirectXWnd类,这是我们的DirrectX应用程序的基类。CDirectXWnd类创建一个窗口并生成一个与该窗口相关联的DirectDraw对象lpDD,同时还生成一个显示平面(lpFrontBuffer)和一个显示缓冲平面(lpBackBuffer),该类使用了几个虚函数,必要时其派生类可以覆盖这些函数。 
  4.打开DirectX.CPP,把# include“DirectXDlg.h”改为#include“DirectXWnd.H”然后把CDirectXApp::InitInstance()函数修改如下,其中黑体字为要增加的内容: 
  BOOL CDirectXApp::lnitlnstnnce()   {   #ifdef _AFXDLL Enable3dControls();//Call this when Using MFC in a shared DLL   #else Enable3dControlsStatic();//Call this when linking to MFC statically   #endif 
  CDirectXWnd *pWnd=new CDirectXWnd();   pWnd->Create("DirectXWnd Test");   m_pMainWnd = pWnd;   pWnd->UpdateWindow();   pWnd->SetFocus();   if(pWnd->InitializeGame(640,480,8)==FALSE)   {   pWnd->DestroyWindow();   return FALSE;   }   MSG msg;   while(1)   {   if(PeekMessage(&msg,NULL,0,0,PM_NOREMOVE))   {   if(!GetMessage(&msg,NULL,0,0))   return msg.wParam;   TranslateMessage(&msg);   DispatchMessage(&msg);   }   else   {   if(pWnd->blsActive)   {   pWnd->UpdateFrame();   }   }   }   return FALSE;   } 
  编译该程序并运行,可以看到出现一个黑色的屏幕窗口,按ESC或F12则可退出程序。至此,我们的基本框架已经建立好了,虽然这个框架还比较简单,但我们可以在此基础上开发出更强大的应用框架。为了方便使用该框架,我们可以为该框架写一个Custom AppWizard,当然也可以不写,只要把该工程目录下的文件拷贝到另一个工程目录中即可。 
  三、测试框架 
  现在,我们按下列步骤写一个测试程序来测试这个框架: 
  1.把刚才创建的工程框架拷贝到一个新目录下,并打开。用C1assView创建一个基于CWnd的类CTestWnd,然后把CTestWnd.h和CTestWnd.CPP文件中的所有"CWnd"字符串替换为"CDirectXWnd",并在CTestWnd.h文件头加入下列字符串:#include"DirectXWnd.h"。 
  2.打开DirectX.CPP文件,在文件头加入#include"TestWnd.h",并把该文件中的所有"CDirectXWnd"字符串替换成"CTestWnd"并保存。 
  3.为 CTestWnd类增加一个虚函数UpdateFrame(),这个函数覆盖了其基类CDirectWnd的UpdateFrame(): 
  void CTestWnd::UpdateFrame()   {   static int x=0,dx=5;   static int y=0,dy=5;   HDC hdc;   DDBLTFX ddbltfx;   HRESULT ddrval;   UpdateWindow();   ddbltfx.dwSize=sizeof(ddbltfx);   ddbltfx.dwFillColor=0;   ddrval=lpBackBuffer->Blt(   NULL,//dest rect   NULL,//src surface   NULL,//src rect   DDBLT_COLORFILL|DDBLT_WAIT,   &ddbltfx);   if(ddrval!=DD_OK)   {   Msg("Fill failed ddrval=0x%081x",ddrval);   return;   }   if(lpBackBuffer->GetDC(&hdc)==DD_OK)   {   if(x<0)dx=5;   if(x>590)dx=-5;   if(y<0)dy=5;   if(y>430)dy=-5;   x+=dx;y+=dy;   Ellipse(hdc,x,y,x+50,y+50);   lpBackBuffer->ReleaseDC(hdc);   }   while(1)   {   HRESULT ddrval;   ddrval=lpFrontBuffer->Flip(NULL,0);   if(ddrval==DD_OK)   {   break;   };   if(ddrval==DDERR_SURFACELOST)   {   if(!CDirectXWnd::RestoreSurfaces())   {   break;   }   }   if(ddrval!=DDERR_WASSTILLDRAWING)   {   break;   }   }   } 
  无心柳按:光是这么追加在测试中没有成功,可能要在CTestWnd.H中追加两行:   public:   void UpdateFrame();   否则编译可能出错。 
  4、编译并运行该程序,屏幕上会出现一个白色球在移动。 
  附录: 
  文件:DirectXWnd.H 
  #if!defined(DIRECTXWND_H)   #define DIRECTXWND_H   //DirectXWnd.h:header file   #include<ddraw.h>   #pragma comment(lib,"ddraw.lib")//链接时加入ddraw.lib库 
  class CDirectXWnd:public CWnd   {   //Construction   public:   CDirectXWnd();   //Attributes   public:   BOOL blsActive;//应用程序是否被激活   protected:   LPDIRECTDRAW lpDD;//DirectDraw对象指针   LPDIRECTDRAWSURFACE lpFrontBuffer;//DirectDraw主缓冲区   LPDIRECTDRAWSURFACE lpBackBuffer;//DirectDraw后台缓冲区 
  int nBufferCount;//后备缓冲区个数   //Operations   protected:   void Msg(LPSTR fmt,...);   public:   BOOL Create(LPCSTR lpszAppName);//创建窗体   //Overrides   virtual BOOL InitializeGame(UINT GModex,UINT GModeY,UINT GBPP);   virtual BOOL CleanSurface();   virtual void UpdateFrame();   virtual BOOL RestoreSurfaces(void);   //{{AFX_VIRTUAL(CDirectXWnd)   //}}AFX_VIRTUAL   //implementation   public:   virtual ~CDirectXWnd();   //Generated message map functions   protected:   //{{AFX_MSG(CDirectXWnd)   afx_msg void OnKeyDown(UINT nChar,UINT nRepCnt,UINT nFlags);   afx_msg void OnActivateApp(BOOL bActive,HTASK hTask);   //}}AFX_MSG   DECLARE_MESSAGE_MAP()   };   ////////////////////{{AFX_INSERT_LOCATION}}   #endif//!define(DIRECTXWND_H) 
     文件:DirectXWnd.CPP   //DirectXWnd.cpp:implementation file   #include "stdafx.h"   #include "DirectX.h"   #include "DirectXWnd.h"   #ifdef _DUBUG   #define new DEBUG_NEW   #undef THIS_FILE   static char THIS_FILE[]=__FILE__;   #endif   CDirectXWnd::CDirectXWnd()   {   lpDD=NULL;   lpFrontBuffer=NULL;   lpBackBuffer=NULL;   nBufferCount=0;   blsActive=TRUE;   }   CDirectXWnd::~CDirectXWnd()   {   if(lpDD)   {   CleanSurface();   lpDD->Release();   lpDD=NULL;   }   }   BOOL CDirectXWnd::Create(LPCSTR lpszAppName)   {   CString className=AfxRegisterWndClass(CS_DBLCLKS,: oadCursor(NULL,IDC_ARROW),   NULL,AfxGetApp()->LoadIcon(IDR_MAINFRAME));   return(CWnd::CreateEx(WS_EX_APPWINDOW,className,lpszAppName,   WS_VISIBLE|WS_SYSMENU|WS_POPUP,0,0,GetSystemMetrics(SM_CXSCREEN),   GetSystemMetrics(SM_CYSCREEN),NULL,NULL));   }   BOOL CDirectXWnd::InitializeGame(UINT GModeX,UINT GModeY,UINT GBPP)   {   HRESULT ddrval;   ddrval=DirectDrawCreate(NULL,&lpDD,NULL);   if(ddrval!=DD_OK)   {   Msg("DirectDrawCreate failed err=%d",ddrval);   return FALSE;   }   ddrval=lpDD->SetCooperativeLevel(m_hWnd,DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN);   if(ddrval!=DD_OK)   {   Msg("SetCooperativeLevel failed err=%d",ddrval);   return FALSE;   }   ddrval=lpDD->SetDisplayMode(GModeX,GModeY,GBPP);   if(ddrval!=DD_OK)   {   Msg("SetDisplayMode failed err=%d",ddrval);   return FALSE;   }   //check capabilites   DDCAPS ddcaps;   ddcaps.dwSize=sizeof(ddcaps);   ddrval=lpDD->GetCaps(&ddcaps,NULL);   if(ddrval!=DD_OK)   {   Msg("GetCaps failed err=%d",ddrval);   return FALSE;   }   if(ddcaps.dwCaps&DDCAPS_NOHARDWARE)   {   Msg("No hardware support at all");   }   //default to double buffered on 1mb,triple buffered   if(nBufferCount==0)   {   if(ddcaps.dwVidMemTotal<=1024L*1024L*(GBPP/8)||GModeX>640)   {   nBufferCount=2;   }   else   {   nBufferCount=3;   }   }   DDSURFACEDESC ddsd;   ::ZeroMemory(&ddsd,sizeof(ddsd));   ddsd.dwSize=sizeof(ddsd);   ddsd.dwFlags=DDSD_CAPS|DDSD_BACKBUFFERCOUNT;   ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX;   ddsd.dwBackBufferCount=nBufferCount-1;   ddrval=lpDD->CreateSurface(&ddsd,&lpFrontBuffer,NULL);   if(ddrval!=DD_OK)   {   Msg("CreateSurface failed err=%d",ddrval);   return FALSE;   }   else Msg("显示内存允许建立的缓冲区数=%d(最多需要3)",nBufferCount);   DDSCAPS ddscaps;   ddscaps.dwCaps=DDSCAPS_BACKBUFFER;   ddrval=lpFrontBuffer->GetAttachedSurface(&ddscaps,&lpBackBuffer);   if(ddrval!=DD_OK)   {   Msg("GetAttachedsurface failed err=%d",ddrval);   return FALSE;   }   return TRUE;   }   void CDirectXWnd::Msg(LPSTR fmt,...)   {   char buff[256];   va_list va;   lstrcpy(buff,"DirectxWnd:");   va_start(va,fmt);   wvsprintf(&buff[lstrlen(buff)],fmt,va);   va_end(va);   lstrcat(buff,"\r\n");   AfxMessageBox(buff);   }   ////////////////////////Virtual Function   BOOL CDirectXWnd::RestoreSurfaces()   {   HRESULT ddrval;   ddrval=lpFrontBuffer->Restore();   if(ddrval!=DD_OK)   return FALSE;   return TRUE;   }   BOOL CDirectXWnd::CleanSurface()   {   if(lpBackBuffer)   {   lpBackBuffer->Release();   lpBackBuffer=NULL;   }   if(lpFrontBuffer)   {   lpFrontBuffer->Release();   lpFrontBuffer=NULL;   }   return TRUE;   }   void CDirectXWnd::UpdateFrame()   {   }   BEGIN_MESSAGE_MAP(CDirectXWnd,CWnd)   //{{AFX_MSG_MAP(CDirectXWnd,Cwnd)   ON_WM_KEYDOWN()   ON_WM_ACTIVATEAPP()   //}}AFX_MSG_MAP   END_MESSAGE_MAP()   ///////////////////CDirectXWnd message handlers   void CDirectXWnd::OnKeyDown(UINT nChar,UINT nRepCnt,UINT nFlags)   {   switch(nChar)   {   case VK_ESCAPE:   case VK_F12:   PostMessage(WM_CLOSE);   break;   }   CWnd::OnKeyDown(nChar,nRepCnt,nFlags);   }   void CDirectXWnd::OnActivateApp(BOOL bActive,HTASK hTask)   {   CWnd::OnActivateApp(bActive,hTask);   blsActive=bActive;   return;   }  |