用MFC构造DIRECTX应用框架
一、 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应用框架的更多相关文章
- 使用MFC做D3D的框架
转载请注明出处http://www.cnblogs.com/CAION/p/3192111.html (程序运行时是和其他程序挺像 = =,但我保证这是原创的) 1.将D3D的初始化,渲染等等一些行为 ...
- MFC单文档框架分析及执行流程(转)
原文转自 https://blog.csdn.net/u011619422/article/details/40402705 首先来分析一下MFC单文档类的结构: 它包括如下几个类: CAboutDl ...
- MFC项目依赖 BCG框架示例
1.创建一个简单的MFC工程: 2.将BCG框架项目导入到新建的mfc解决方案中,例如将BCGCBPro\BCGCBPRO140.vcxproj添加到解决方案. 3.修改mfc项目属性,包含BCG框架 ...
- 关于MFC视图文档框架的理解-1
一.单个文档和多个文档的区别: MFC分为对话框程序,单文档程序和多文档程序. 单个文档程序:一个主框架内仅允许打开一个视图,若要打开另一个,则当前的文档必须得关闭.单文档程序可以打开不同格式的文档. ...
- MFC中 SDI/MDI框架各部分指针获取方式
VC MFC SDI/MDI框架各部分指针获取方式 整理总结一下,希望能帮助到别人. 获得CWinApp 获得CMainFrame 获得CChildFrame 获得CDocument 获得CV ...
- 【2016.3.30项目技术记录】]VS2010自动生成MFC单文档框架程序的修改:去除属性框,在CViewTree类中添加鼠标单击响应
转自http://blog.csdn.net/yanfeiouc2009/archive/2010/06/07/5653360.aspx 手头上有个东西要用到单文档,由于想省事,直接用VS2010做了 ...
- [direct-X] direct-X最小框架
#include<d3d9.h> #pragma comment(lib, "d3d9.lib") #pragma comment(lib, "d3dx9.l ...
- 【VC++学习笔记四】MFC应用程序中框架类的获取
一.文档类中 获取视图: 先获取主窗体,在根据主窗体获取视图 pMain->GetActiveDocument();注意类型转换 由于文档中可能包含多个视图,可以按照下面函数获取: CView* ...
- MFC - 微软基础类库和框架
一 MFC的概念和作用 1 什么是MFC?? 全称 Microsoft Foundation Class Library我们称之为微软基础类库 1)从硬盘的存在形式上来说 MFC就是一个库(静/动态库 ...
随机推荐
- 轻松搭建CAS 5.x系列(9)-登录后显示通知信息
概述说明 用户在账号名密码认证通过后,CAS可以跳转到登陆完成页面前,显示相关的通知页面. 搭建步骤 `1. 首先,您需要有个CAS Server端 如果您没有,可以按照我之前写的文章<轻松搭建 ...
- 15-MySQL DBA笔记-运维管理
第15章 运维管理 随着各种技术的快速发展,现今的DBA可以比以前的DBA维护多得多的数据库实例.DBA已经越来越像一个资源的管理者,而不是简单的操作步骤执行人.本章将为读者介绍规模化运维之道.首先, ...
- (九)shiro之web集成
Url 匹配方式? 匹配一个字符 /admin? 可以匹配/admin1 或者/admin2 但是不能匹配/admin12 或者/admin* 匹配零个或者一个或者多个字符 /admin* 可以匹配 ...
- 我对DES AES RSA的认识
1.DES(Data Encryption Standard)算法:数据加密标准.是替换和置换细致而复杂的结合体,替换和置换一个接着一个,共循环16次.算法首先将明文分块,每块64位.密钥也是64位, ...
- 监控神器-普罗米修斯Prometheus的安装
搬砖党的福音:普罗米修斯-监控神器 功能: 在业务层用作埋点系统 Prometheus支持多种语言(Go,java,python,ruby官方提供客户端,其他语言有第三方开源客户端).我们可以通过客户 ...
- gentoo use-flag 全局标识 大全 (官方搬运) 英文 适用funtoo
连接 https://www.gentoo.org/support/use-flags/ 提示 ctrl+F 可在页面查找 搬运 Global USE flags FlagDescription 3d ...
- S2-045、S2-046
前言 S2-045依然是一个Ognl表达式注入导致的RCE漏洞,且漏洞很严重.另外,还是建议读者阅读本篇文章前先看下系列文章的第一篇. 正文 依然是第一篇文章中讲过,StrutsPrepareFilt ...
- 由java派生出来的证书错误
未安装请求对应接口证书时的异常:> javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: ...
- PAT Basic 1045 快速排序 (25 分)
著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边. 给定划分后的 N 个互不相同的正整数的排列,请问 ...
- 【Java基础-实验7】Banking_7 -添加银行透支扣款系统的 thorw异常机制
实验基本要求: 实验题目 7:(在6基础上修改) 将建立一个 OverdraftException 异常,它由 Account 类的withdraw()方法 抛出. 实验目的: 自定义异常 实验说明: ...