Directx11 教程(1) 基本的windows应用程序框架(1)
原文:Directx11 教程(1) 基本的windows应用程序框架(1)
在vs2010中,建立一个新的win32工程,名字是: myTutorialD3D11, 注意:同时勾选Create directory for solution,我们同时建立一个solution,后面教程的所有的工程文件,我们都建立在这个solution中。

勾选 Emtpy project

增加source files->add new item->main.cpp

创建一个windows应用程序需要以下步骤:
1、在入口Main函数中注册窗口类
2、调用CreateWindowEx函数创建窗口
3、处理调度消息循环
4、编写回调函数,在回调函数中响应处理各种消息事件
在main.cpp中,逐步增加以下的代码:
首先增加
#include <windows.h>
这样,我们就能够使用windows中的API函数、structure,类对象等。
//窗口类的名字
LPCWSTR m_applicationName;
//应用程序实例句柄
HINSTANCE m_hinstance;
定义一个全局的windows窗口句柄,这个句柄用来表示应用程序的主窗口句柄。
//窗口句柄
HWND m_hwnd;
//用来判断是否按ESC键,按下ESC键,则退出程序
bool bexit = false;
//初始化窗口类,创建应用程序窗口
void InitializeWindows(int& screenWidth, int& screenHeight);
//调用初始化窗口函数,以及其它的接口类的初始化函数
bool Initialize();
//处理消息循环
void Run();
//关闭窗口
void ShutdownWindows();
//这两个函数是窗口的回调函数
static LRESULT CALLBACK MessageHandler(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//判断是否全屏,全屏模式和窗口模式下使用不同的创建窗口参数
const bool FULL_SCREEN = false;
下面的函数WinMain,是windows应用程序的入口函数。
四个参数简单提一下,HInstance表示当前应用程序的实例句柄,它实际上是一个内存基地址,系统将可执行程序的映像加载到进程地址空间中的这个位置。
HPrevInstance表示进程前一个实例句柄,比如对于同一个程序打开两次,出现两个窗口,第一次打开的窗口就是先前实例的窗口。该参数用于16位Windows系统,对于一个32位程序,该参数总为NULL,现在仍然保留该参数主要是为了和16位windows系统兼容。
pSCmdLine是指向应用程序命令行的字符串的指针,不包括执行文件名。获得整个命令行,使用函数GetCommandLine。
nCmdShow:指明窗口如何显示,比如SW_HIDE(隐藏),SW_MINIMIZE(最小化)等等,默认情况为SW_SHOW。
//应用程序入口main函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pScmdline, int iCmdshow)
{
Initialize();
Run();
ShutdownWindows();
return 0;
}
该函数首先调用初始化函数,初始化函数中将会设置窗口的高度、宽度,然后调用初始化窗口函数。
//调用窗口初始化函数和其它一些类的初始化函数
//本例子中,只调用初始化窗口函数
bool Initialize()
{
int screenWidth = 0, screenHeight = 0;
// 初始化窗口
InitializeWindows(screenWidth, screenHeight);
return true;
}
void InitializeWindows(int& screenWidth, int& screenHeight)
{
WNDCLASSEX wc;
DEVMODE dmScreenSettings;
int posX, posY;
// 得到应用程序实例句柄
m_hinstance = GetModuleHandle(NULL);
// 应用程序名字
m_applicationName = L"Engine";
// 设置窗口类参数.
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
指定回调函数后,windows会自动调用回调函数处理各种消息事件
wc.lpfnWndProc = WndProc; //指定回调函数
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = m_hinstance;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hIconSm = wc.hIcon;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); //默认黑色窗口黑色背景
wc.lpszMenuName = NULL;
wc.lpszClassName = m_applicationName;
wc.cbSize = sizeof(WNDCLASSEX);
// 注册窗口类
RegisterClassEx(&wc);
// 得到windows桌面分辨率
screenWidth = GetSystemMetrics(SM_CXSCREEN);
screenHeight = GetSystemMetrics(SM_CYSCREEN);
// 根据是否全屏设置不同的分辨率.
if(FULL_SCREEN)
{
//全屏模式下,设置窗口大小为windows桌面分辨率.
memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = (unsigned long)screenWidth;
dmScreenSettings.dmPelsHeight = (unsigned long)screenHeight;
dmScreenSettings.dmBitsPerPel = 32;
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
// 临时设置显示设备为全屏模式,注意:应用程序退出时候,将恢复系统默认设置。
ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
// 设置窗口的左上角坐标位置为(0,0).
posX = posY = 0;
}
else
{
// 窗口模式:800*600.
screenWidth = 800;
screenHeight = 600;
// 窗口左上角坐标位置,posX, posY
posX = (GetSystemMetrics(SM_CXSCREEN) - screenWidth) / 2;
posY = (GetSystemMetrics(SM_CYSCREEN) - screenHeight) / 2;
}
// 全屏和窗口使用不同的参数.
if( FULL_SCREEN)
{
m_hwnd = CreateWindowEx(WS_EX_APPWINDOW, m_applicationName, m_applicationName,
WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP,
posX, posY, screenWidth, screenHeight, NULL, NULL, m_hinstance, NULL);
}
else
{
m_hwnd = CreateWindowEx(WS_EX_APPWINDOW, m_applicationName, m_applicationName,
WS_OVERLAPPEDWINDOW,
posX, posY, screenWidth, screenHeight, NULL, NULL, m_hinstance, NULL);
}
// 显示窗口并设置其为焦点.
ShowWindow(m_hwnd, SW_SHOW);
SetForegroundWindow(m_hwnd);
SetFocus(m_hwnd);
// 隐藏鼠标.
//ShowCursor(false);
return;
}
在Run函数中,我们响应调度windows消息以及调用我们的render函数。
//处理消息
void Run()
{
MSG msg;
bool done, result = 1;
// 初始化消息结构.
ZeroMemory(&msg, sizeof(MSG));
// 循环进行消息处理
done = false;
while(!done)
{
// 处理windows消息.
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// 接收到WM_QUIT消息,退出程序.
if(msg.message == WM_QUIT)
{
done = true;
}
else
{
result = bexit; //如果按了ESC,也退出程序
//我们的渲染或者其它处理,可以放在这儿
//....
//.....
if(result)
{
done = true;
}
}
}
return;
}
WndProc函数为窗口回调函数,程序中的消息处理都在这个函数中。
LRESULT CALLBACK WndProc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam)
{
switch(umessage)
{
// 窗口销毁消息.
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
// 窗口关闭消息.
case WM_CLOSE:
{
PostQuitMessage(0);
return 0;
}
//MessageHandle过程处理其它所有消息.
default:
{
return MessageHandler(hwnd, umessage, wparam, lparam);
}
}
}
LRESULT CALLBACK MessageHandler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam)
{
switch(umsg)
{
// 检测按键消息.
case WM_KEYDOWN:
if(wparam==VK_ESCAPE)
bexit = true;
return 0;
//任何其它消息发送到windows缺省处理.
default:
{
return DefWindowProc(hwnd, umsg, wparam, lparam);
}
}
}
ShutdownWindows函数主要用来在程序结束后,释放一些资源。
void ShutdownWindows()
{
//显示光标.
//ShowCursor(true);
// 恢复默认显示设置.
if(FULL_SCREEN)
{
ChangeDisplaySettings(NULL, 0);
}
//释放窗口句柄.
DestroyWindow(m_hwnd);
m_hwnd = NULL;
// 释放应用程序实例.
UnregisterClass(m_applicationName, m_hinstance);
m_hinstance = NULL;
return;
}
程序执行后,界面如下,窗口是黑色,我们按下ESC,程序会退出:

完整的代码请参考:
工程文件myTutorialD3D11
代码下载:
http://files.cnblogs.com/mikewolf2002/myTutorialD3D11.zip
Directx11 教程(1) 基本的windows应用程序框架(1)的更多相关文章
- Directx11 教程(2) 基本的windows应用程序框架(2)
原文:Directx11 教程(2) 基本的windows应用程序框架(2) 在本教程中,我们把前面一个教程的代码,进行封装.把初始化函数,Run函数,窗口回调函数,ShutdownWind ...
- windows应用程序框架及实例
应用程序框架:同一类型应用程序的结构大致相同,并有很多相同的源代码,因此可以通过一个应用程序框架AFX(Application FrameWorks)编写同一类型应用程序的通用源代码. 主要向导: D ...
- Directx11教程(3) 一个最基本D3D应用程序(1)
原文:Directx11教程(3) 一个最基本D3D应用程序(1) 在前一篇教程程序代码的基础上,这次我们将增加2个类: InputClass,键盘处理的代码将放在这个类里面,Graphi ...
- Directx11教程(21) 修正程序最小化异常bug
原文:Directx11教程(21) 修正程序最小化异常bug 很长时间竟然没有注意到,窗口最小化时候,程序会异常,今天调试水面程序时,随意间最小化了窗口,发现程序异常了.经过调试,原来程 ...
- Directx11教程(4) 一个最基本D3D应用程序(2)
原文:Directx11教程(4) 一个最基本D3D应用程序(2) 接着上篇教程的代码,本篇加入基本的D3D代码,实现一个完整的D3D11程序框架. 我们增加一个新类D3DClass, 用来处理3D渲 ...
- Directx11教程(13) D3D11管线(1)
原文:Directx11教程(13) D3D11管线(1) 从本篇教程开始,我们暂停代码的学习,先来了解一下D3D11的管线,这些管线不涉及具体的硬件,而是着重于理解能够支持D3D11的管 ...
- Directx11教程(9) 增加一个TimerClass类
原文:Directx11教程(9) 增加一个TimerClass类 在上篇教程代码的基础上,我们增加一个TimerClass类,这个类的功能很简单,就是可以计算相邻2帧的时间差.利用这个时间 ...
- Directx11教程(6) 画一个简单的三角形(2)
原文:Directx11教程(6) 画一个简单的三角形(2) 在上篇教程中,我们实现了在D3D11中画一个简单的三角形,但是,当我们改变窗口大小时候,三角形形状却随着窗口高宽比例改变而改变, ...
- Directx11教程(5) 画一个简单的三角形(1)
原文:Directx11教程(5) 画一个简单的三角形(1) 在本篇教程中,我们将通过D3D11画一个简单的三角形.在D3D11中,GPU的渲染主要通过shader来操作(当然还有一些操作 ...
随机推荐
- 图像复原MATLAB实现
前言:本篇博客先介绍滤波器滤除噪声,再介绍滤波器复原,侧重于程序的实现. 一:三种常见的噪声 二:空间域滤波 空间域滤波复原是在已知噪声模型的基础上,对噪声的空间域进行滤波.空间域滤波复原方法主要包括 ...
- JavaSE_03_Thread类02
1.1 线程状态概述 当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态.在线程的生命周期中, 有几种状态呢?在API中 java.lang.Thread.State 这个 ...
- Larval报错:后台上传图片,storage目录也有相应的图片,但前台访问不到图片。
需要执行命令.在public下建立文件软链接 php artisan storage:link
- 原 JEECMS导入IDEA进行二次开发图文教程
JEECMS导入IDEA进行二次开发图文教程 2017年05月15日 17:03:53 Swain_Ho 阅读数 3257 版权声明:本文为博主原创文章,未经博主允许不得转载. https:// ...
- Django入门到进阶-更适合Python小白的系统课程
Django入门到进阶-更适合Python小白的系统课程 整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感受,单论单个知识点课程本身 ...
- webServices学习二(小试牛刀。jdk 方式发布一个应用)
一.前提 1.用Jdk1.6.0_21以后的版本发布一个WebService服务. 2.与Web服务相关的类,都位于javax.jws.*包中. 1.主要类有: 1.@WebService - 它是 ...
- Vuejs实战项目三:退出系统功能实现
1.创建Mockjs接口 method:post url:/user/logout 描述:退出系统 response: { "code": 2000, //状态码 "fl ...
- vue 如何发起网络请求 之 axios
1 1 2 3 4 5 6 7 8 9 10 // axios 请求 在main.js里边写入 import Axios from 'axios' // 配置请求信息 var $http = ...
- 【python之路24】装饰器
1.装饰器的应用场景 通常IT公司的程序开发是分工的,例如某公司某个部门负责底层函数的开发,另一个部门利用其函数实现高级功能,那么如果负责底层开发的函数需要改动,一般来说不会直接在函数上进行修改,通常 ...
- Wamp PHP 安装各种拓展
安装redis 下载dll文件地址:http://pecl.php.net/package/redis 下载对应版本nginx:NTS apache:TS 文件放在php的ext目录下 php.ini ...