一、 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,::LoadCursor(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;

}

用MFC构造DIRECTX应用框架的更多相关文章

  1. 使用MFC做D3D的框架

    转载请注明出处http://www.cnblogs.com/CAION/p/3192111.html (程序运行时是和其他程序挺像 = =,但我保证这是原创的) 1.将D3D的初始化,渲染等等一些行为 ...

  2. MFC单文档框架分析及执行流程(转)

    原文转自 https://blog.csdn.net/u011619422/article/details/40402705 首先来分析一下MFC单文档类的结构: 它包括如下几个类: CAboutDl ...

  3. MFC项目依赖 BCG框架示例

    1.创建一个简单的MFC工程: 2.将BCG框架项目导入到新建的mfc解决方案中,例如将BCGCBPro\BCGCBPRO140.vcxproj添加到解决方案. 3.修改mfc项目属性,包含BCG框架 ...

  4. 关于MFC视图文档框架的理解-1

    一.单个文档和多个文档的区别: MFC分为对话框程序,单文档程序和多文档程序. 单个文档程序:一个主框架内仅允许打开一个视图,若要打开另一个,则当前的文档必须得关闭.单文档程序可以打开不同格式的文档. ...

  5. MFC中 SDI/MDI框架各部分指针获取方式

    VC MFC SDI/MDI框架各部分指针获取方式   整理总结一下,希望能帮助到别人.   获得CWinApp 获得CMainFrame 获得CChildFrame 获得CDocument 获得CV ...

  6. 【2016.3.30项目技术记录】]VS2010自动生成MFC单文档框架程序的修改:去除属性框,在CViewTree类中添加鼠标单击响应

    转自http://blog.csdn.net/yanfeiouc2009/archive/2010/06/07/5653360.aspx 手头上有个东西要用到单文档,由于想省事,直接用VS2010做了 ...

  7. [direct-X] direct-X最小框架

    #include<d3d9.h> #pragma comment(lib, "d3d9.lib") #pragma comment(lib, "d3dx9.l ...

  8. 【VC++学习笔记四】MFC应用程序中框架类的获取

    一.文档类中 获取视图: 先获取主窗体,在根据主窗体获取视图 pMain->GetActiveDocument();注意类型转换 由于文档中可能包含多个视图,可以按照下面函数获取: CView* ...

  9. MFC - 微软基础类库和框架

    一 MFC的概念和作用 1 什么是MFC?? 全称 Microsoft Foundation Class Library我们称之为微软基础类库 1)从硬盘的存在形式上来说 MFC就是一个库(静/动态库 ...

随机推荐

  1. 怎样绑定this

    有三种方法: 1. Function.prototype.call();  2. Function.prototype.apply();  3. Function.prototype.bind(); ...

  2. sql注入测试(3)---现象分析

    那为什么出现以上问题呢?这是程序代码层控制不当导致的.如果web前端对输入数据控制严格,会对数据库进行操作的字符串,在客户端做敏感字符转义处理,或者在操作数据库的dao层,使用动态参数的sql,不使用 ...

  3. (七)freemarker的基本语法及入门基础

    一.freemarker模板文件(*.ftl)的基本组成部分 1. 文本:直接输出的内容部分        2. 注释:不会输出的内容,格式为<#--  注释内容  -->         ...

  4. eclipse智能提示报错(to avoid the message, disable the...)

    然后这里可能会再报别的错误  我的做法是   再重新将 code recommenders 打开 ********************************** 为什么会出现 这样错误呢 ? 简 ...

  5. 【Transact-SQL】计算整个表中所有值的出现的次数

    原文:[Transact-SQL]计算整个表中所有值的出现的次数 一个表有3列,5行,那么一共有15个值,现在要计算整个表中所有值在表中出现的次数,不过这里表的列数是不确定的,上面的例子是3列,实际上 ...

  6. 卷积神经网络(CNN)的训练过程

    卷积神经网络的训练过程 卷积神经网络的训练过程分为两个阶段.第一个阶段是数据由低层次向高层次传播的阶段,即前向传播阶段.另外一个阶段是,当前向传播得出的结果与预期不相符时,将误差从高层次向底层次进行传 ...

  7. spring-boot-actuator 常用配置

    management: endpoints: web: base-path: "/" exposure: include: "*" endpoint: heal ...

  8. 《浏览器工作原理与实践》<09>块级作用域:var缺陷以及为什么要引入let和const?

    在前面我们已经讲解了 JavaScript 中变量提升的相关内容,正是由于 JavaScript 存在变量提升这种特性,从而导致了很多与直觉不符的代码,这也是 JavaScript 的一个重要设计缺陷 ...

  9. [Selenium3+python3.6]自动化测试3-八种元素元素定位(Firebug和firepath)

    参考http://www.cnblogs.com/yoyoketang/p/6123890.html   #coding=utf-8 from selenium import webdriverdri ...

  10. EditPlus使用技巧

    1.p{$$}*10  按ctrl+E  自动 填写10行 P标签.  $表示数字,$$表示2位数...   p{b$}*10 2.cltr +j 复制当前行. 3.自动填充开启. --------锚 ...