DirectX API 编程起步 #02 窗口的诞生

先用 windows API 制作一个窗口出来,以后我们用 DirectX API 渲染的东西就会显示在这里,控制台那黑白的画面肯定是没法用的。

每次的代码都会更新到Github

首先贴出来目前为止的文件结构图,由上到下表示#include“XXXXX”关系

系统头文件的调用不包含在内

由于.h和.cpp都是对应出现的,我就不写的那么详细了

Main.cpp 是调用 SoftwareClass 类的主函数。

那么我们从上往下开始吧。

Main.cpp

由于只用调用接下来的类成员函数就行,所以这个代码非常简单。

 1 ////////////////
 2 // Main.cpp //
 3 ////////////////
 4 #include"SoftwareClass.h"
 5
 6 /*********************************
 7 这里是整个程序的入口函数
 8 WinMain
 9 仅适用于Win32编程
10 **********************************/
11
12 int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR pScmdline,int nCmdshow)
13 {
14     //新建类指针
15     SoftwareClass *Software;
16     //new一个类出来
17     Software = new SoftwareClass;
18     //初始化、运行、结束该程序
19     if (Software->Initialize())
20     {
21         Software->Run();
22     }
23     Software->Shutdown();
24     //删除并清理类指针
25     delete Software;
26     Software = NULL;
27     return 0;
28 }

SoftwareClass

接下来就是重点的主要类SoftwareClass,它管理着这个程序的生杀大权,并调用InputClass(记录输入的类)和GraphicsClass(渲染图形的类)来完成更高级的操作。

首先是他的header

SoftwareClass.h

 1 ////////////////////////
 2 // SoftwareClass.h //
 3 ///////////////////////
 4
 5 /*******************************
 6 该类包含整个程序运行所需的功能
 7 ********************************/
 8
 9 #ifndef _SOFTWARECLASS_H_
10 #define _SOFTWARECLASS_H_
11
12 //////////////
13 // include //
14 //////////////
15 #include<Windows.h>
16
17 //////////////////
18 // File include //
19 //////////////////
20 #include"InputClass.h"
21 #include"GraphicsClass.h"
22
23 /////////////////////////
24 // Class Declaration //
25 /////////////////////////
26 class SoftwareClass
27 {
28 public:
29     //默认构造,复制,析构函数
30     SoftwareClass();
31     SoftwareClass(const SoftwareClass&);
32     ~SoftwareClass();
33
34     bool Initialize();//初始化
35     void Shutdown();//关闭
36     void Run();//运行
37
38     //主要消息处理函数
39     //系统级消息丢给另外的一个WndProc
40     //比如窗口的关闭等消息
41     LRESULT CALLBACK MessageHandler(HWND, UINT, WPARAM, LPARAM);
42
43 //以下为私有成员函数
44 private:
45     bool Frame();
46     //创建窗口最重要的函数
47     void InitializeWindows(int&, int&);
48     void ShutdownWindows();
49 //以下为私有数据成员
50 private:
51     //创建窗口程序需要的参数,无需过度关心
52     LPCWSTR m_SoftwareName;
53     HINSTANCE m_hinstance;
54     HWND m_hwnd;
55
56     //m_* 代表成员数据
57     InputClass *m_Input;
58     GraphicsClass *m_Graphics;
59 };
60
61 ////////////////////////
62 // Static Function //
63 ///////////////////////
64
65 //次要消息处理函数
66 //用于处理系统级消息
67 static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
68
69 /////////////
70 // Global //
71 /////////////
72
73 //用于消息处理函数的调用
74 //因为我们有两个
75 //所以需要这个静态变量指向该类
76 static SoftwareClass *SoftwareHandle = NULL;
77
78 #endif

SoftwareClass.cpp

接着是他的.cpp

  1 ///////////////////////////
  2 // SoftwareClass.cpp //
  3 //////////////////////////
  4 #include "SoftwareClass.h"
  5
  6 //////////////////////////////////////////////////////////
  7 SoftwareClass::SoftwareClass()
  8 {
  9     m_hinstance = NULL;
 10     m_hwnd = NULL;
 11     m_SoftwareName = NULL;
 12
 13     m_Input = NULL;
 14 }
 15 SoftwareClass::SoftwareClass(const SoftwareClass &other)
 16 {
 17 }
 18 SoftwareClass::~SoftwareClass()
 19 {
 20 }
 21 //////////////////////////////////////////////////////////
 22
 23 bool SoftwareClass::Initialize()
 24 {
 25     int screenWidth, screenHeight;
 26     bool result;
 27
 28     screenHeight = 0;
 29     screenWidth = 0;
 30     InitializeWindows(screenWidth, screenHeight);
 31
 32     //new一个输入处理类
 33     m_Input = new InputClass;
 34     if (!m_Input)
 35     {
 36         return false;
 37     }
 38     m_Input->Initialize();
 39
 40     //new一个图形处理类
 41     m_Graphics = new GraphicsClass;
 42     if (!m_Graphics)
 43     {
 44         return false;
 45     }
 46
 47     //由于图形类涉及到窗口的创建
 48     //容易失败
 49     //因此测试一下new是否成功
 50     result = m_Graphics->Initialize(screenWidth, screenHeight, m_hwnd);
 51     if (!result)
 52     {
 53         return false;
 54     }
 55
 56     return true;
 57 }
 58
 59 //先清除输入类和图形类
 60 //再关闭窗口程序
 61 void SoftwareClass::Shutdown()
 62 {
 63     if (m_Graphics)
 64     {
 65         m_Graphics->Shutdown();
 66         delete m_Graphics;
 67         m_Graphics = NULL;
 68     }
 69
 70     if (m_Input)
 71     {
 72         delete    m_Input;
 73         m_Input = NULL;
 74     }
 75
 76     ShutdownWindows();
 77 }
 78
 79 //消息的翻译分配在此
 80 void SoftwareClass::Run()
 81 {
 82     MSG msg;
 83     bool done, result;
 84     done = false;
 85
 86     ZeroMemory(&msg, sizeof(MSG));
 87
 88     //程序的最主要循环
 89     //不停地渲染、输出画面
 90     while (!done)
 91     {
 92         //消息队列的查找
 93         if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
 94         {
 95             TranslateMessage(&msg);
 96             DispatchMessage(&msg);
 97         }
 98
 99         //这说明PostQuitMessage被调用了
100         if (msg.message == WM_QUIT)
101         {
102             done = true;
103         }
104         else
105         {
106             result = Frame();
107             if (!result)
108             {
109                 done = true;
110             }
111         }
112     }
113 }
114
115 LRESULT SoftwareClass::MessageHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
116 {
117     switch (msg)
118     {
119     case WM_KEYDOWN:
120         m_Input->KeyDown((unsigned int)wParam);
121
122         //当ESC被按下时,退出程序
123         if (wParam == VK_ESCAPE)
124         {
125             PostQuitMessage(0);
126         }
127         return 0;
128     case WM_KEYUP:
129         m_Input->KeyUp((unsigned int)wParam);
130         return 0;
131     default:
132         return DefWindowProc(hwnd, msg, wParam, lParam);
133     }
134 }
135
136 bool SoftwareClass::Frame()
137 {
138     bool result;
139
140     result = m_Graphics->Frame();
141     if (!result)
142     {
143         return false;
144     }
145     return true;
146 }
147
148 //窗口程序的创建,注册,显示
149 void SoftwareClass::InitializeWindows(int &screenWidth, int &screenHeight)
150 {
151     WNDCLASSEX wc = {};
152     DEVMODE dmScreenSettings;
153     int posX, posY;
154
155     //赋值那个静态变量
156     //指向该类
157     SoftwareHandle = this;
158     //别管
159     m_hinstance = GetModuleHandle(NULL);
160     //由于Unicode的原因
161     //所有字符串要用 TEXT() 括起来
162     m_SoftwareName = TEXT("MyShabbyEngine");
163
164     //填写对象wc的有关信息
165     wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
166     //该窗口的消息处理函数
167     wc.lpfnWndProc = WndProc;
168     //以下全部不用管
169     wc.cbClsExtra = 0;
170     wc.cbWndExtra = 0;
171     wc.hInstance = m_hinstance;
172     wc.hIcon = NULL;
173     wc.hIconSm = NULL;
174     wc.hCursor = NULL;
175     wc.lpszMenuName = NULL;
176     //设置程序窗口背景
177     wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
178     //类名,意义不明
179     wc.lpszClassName = m_SoftwareName;
180     //这步绝不能漏了
181     wc.cbSize = sizeof(WNDCLASSEX);
182
183     //向系统注册该窗口
184     RegisterClassEx(&wc);
185
186     //从系统得到显示的分辨率
187     screenWidth = GetSystemMetrics(SM_CXSCREEN);
188     screenHeight = GetSystemMetrics(SM_CYSCREEN);
189
190     //如果GraphicsClass文件里设置为全屏
191     if (FULL_SCREEN)
192     {
193         memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
194         dmScreenSettings.dmSize = sizeof(dmScreenSettings);
195         dmScreenSettings.dmPelsWidth = (unsigned long)screenWidth;
196         dmScreenSettings.dmPelsHeight = (unsigned long)screenHeight;
197         dmScreenSettings.dmBitsPerPel = 32;
198         dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
199
200         ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
201
202         posX = posY = 0;
203     }
204     else
205     {
206         screenWidth = 800;
207         screenHeight = 600;
208
209         posX = (GetSystemMetrics(SM_CXSCREEN) - screenWidth) / 2;
210         posY = (GetSystemMetrics(SM_CYSCREEN) - screenHeight) / 2;
211     }
212
213     //在显示屏创建窗口
214     //无边框
215     m_hwnd = CreateWindowEx(WS_EX_APPWINDOW,
216         m_SoftwareName, m_SoftwareName,
217         WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP,
218         posX, posY, screenWidth, screenHeight,
219         NULL, NULL, m_hinstance, NULL);
220
221     //将窗口显示出来
222     ShowWindow(m_hwnd, SW_SHOW);
223     SetFocus(m_hwnd);
224
225     ShowCursor(false);
226 }
227
228 void SoftwareClass::ShutdownWindows()
229 {
230     //显示鼠标指针
231     ShowCursor(true);
232
233     if (FULL_SCREEN)
234     {
235         ChangeDisplaySettings(NULL, 0);
236     }
237
238     DestroyWindow(m_hwnd);
239     m_hwnd = NULL;
240
241     UnregisterClass(m_SoftwareName, m_hinstance);
242     m_hinstance = NULL;
243
244     SoftwareHandle = NULL;
245 }
246
247 LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
248 {
249     switch (Msg)
250     {
251     case WM_DESTROY:
252     case WM_CLOSE:
253         PostQuitMessage(0);
254         return 0;
255     default:
256         return SoftwareHandle->MessageHandler(hWnd, Msg, wParam, lParam);
257     }
258 }

InputClass

该类监控并记录哪些键被按下

InputClass.h

 1 ////////////////////
 2 // InputClass.h //
 3 ///////////////////
 4
 5 /******************************
 6 该类包含记录输入按键的功能
 7 ******************************/
 8
 9 #ifndef _INPUTCLASS_H_
10 #define _INPUTCLASS_H_
11
12 /////////////////////////
13 // Class Declaration //
14 /////////////////////////
15 class InputClass
16 {
17 public:
18     //默认构造、复制、析构函数
19     InputClass();
20     ~InputClass();
21     InputClass(const InputClass&);
22     //初始化
23     void Initialize();
24     //当按键被按下或抬起时调用
25     void KeyDown(unsigned int);
26     void KeyUp(unsigned int);
27     //检测某键是否被按下
28     bool IsKeyDown(unsigned int);
29 private:
30     //储存哪些键被按下
31     //true表示正被按下
32     bool m_keys[256];
33 };
34
35 #endif

Input.cpp

 1 ////////////////////
 2 // InputClass.cpp //
 3 ///////////////////
 4 #include "InputClass.h"
 5
 6 InputClass::InputClass()
 7 {
 8 }
 9 InputClass::~InputClass()
10 {
11 }
12 InputClass::InputClass(const InputClass &other)
13 {
14 }
15
16 //初始化按键表
17 void InputClass::Initialize()
18 {
19     int i;
20     for (i = 0; i < 256; i++)
21     {
22         m_keys[i] = false;
23     }
24 }
25
26 void InputClass::KeyDown(unsigned int input)
27 {
28     //将该键设为true
29     m_keys[input] = true;
30 }
31
32 void InputClass::KeyUp(unsigned int input)
33 {
34     //将该键设为false
35     m_keys[input] = false;
36 }
37
38 bool InputClass::IsKeyDown(unsigned int key)
39 {
40     return m_keys[key];
41 }

GraphicsClass

最后是GraphicsClass,由于目前只做了窗口的显示,其实还并未涉及到任何 DirectX 的代码,所以这个类基本上是空的。

GraphicsClass.h

 1 /////////////////////////
 2 // GraphicsClass.h //
 3 ///////////////////////
 4
 5 /***********************
 6 该类处理图像
 7 ********************/
 8
 9 #ifndef _GRAPHICSCLASS_H_
10 #define _GRAPHICSCLASS_H_
11
12 //////////////
13 // include //
14 //////////////
15 #include<Windows.h>
16
17 /////////////
18 // Global //
19 /////////////
20
21 //是否全屏显示
22 const bool FULL_SCREEN = false;
23 //是否垂直同步
24 const bool VSYNC_ENABLED = true;
25 //场景相关数据
26 const float SCREEN_DEPTH = 1000.0;
27 const float SCREEN_NEAR = 0.1f;
28
29 /////////////////////////
30 // Class Declaration //
31 ////////////////////////
32 class GraphicsClass
33 {
34 public:
35     GraphicsClass();
36     GraphicsClass(const GraphicsClass&);
37     ~GraphicsClass();
38
39     bool Initialize(int, int, HWND);
40     void Shutdown();
41     bool Frame();
42 private:
43     bool Render();
44 };
45
46 #endif

GraphicsClass.cpp

 1 ///////////////////////////
 2 // GraphicsClass.cpp //
 3 //////////////////////////
 4 #include "GraphicsClass.h"
 5
 6
 7
 8 GraphicsClass::GraphicsClass()
 9 {
10 }
11
12 GraphicsClass::GraphicsClass(const GraphicsClass &other)
13 {
14 }
15
16
17 GraphicsClass::~GraphicsClass()
18 {
19 }
20
21 bool GraphicsClass::Initialize(int screenWidth, int screenHeight, HWND hWnd)
22 {
23     return true;
24 }
25
26 void GraphicsClass::Shutdown()
27 {
28 }
29
30 bool GraphicsClass::Frame()
31 {
32     return true;
33 }
34
35 bool GraphicsClass::Render()
36 {
37     return true;
38 }

最后程序正确运行后,会在屏幕中间产生一个黑色的矩形,没有边框,也没有鼠标指针。按ESC可退出。

我知道。。。光贴代码屁用没有。。。。。日后补上注释

时间: 2024-11-23 23:21:52

DirectX API 编程起步 #02 窗口的诞生的相关文章

56 java编程思想——创建窗口和程序片 用户接口API

56.java编程思想--创建窗口和程序片 用户接口API Java 1.1 版同样增加了一些重要的新功能,包括焦点遍历,桌面色彩访问,打印"沙箱内"及早期的剪贴板支持. 焦点遍历十分的简单,因为它显然存在于AWT 库里的组件并且我们不必为使它工作而去做任何事.如果我们制造我们自己组件并且想使它们去处理焦点遍历,我们过载isFocusTraversable()以使它返回真值.如果我们想在一个鼠标单击上捕捉键盘焦点,我们可以捕捉鼠标按下事件并且调用requestFocus()需求焦点方法

Windows API 编程学习记录&lt;二&gt;

恩,开始写Windows API编程第二节吧. 上次介绍了几个关于Windows API编程最基本的概念,但是如果只是看这些概念,估计还是对Windows API不是很了解.这节我们就使用Windows API 让大家来了解下Windows API的用法. 第一个介绍的Windows API 当然是最经典的MessageBox,这个API 的作用就是在电脑上显示一个对话框,我们先来看看这个API的定义吧: int WINAPI MessageBox(HWND hWnd, LPCTSTR lpTe

Windows API 编程学习记录&lt;三&gt;

恩,开始写API编程的第三节,其实马上要考试了,但是不把这节写完,心里总感觉不舒服啊.写完赶紧去复习啊       在前两节中,我们介绍了Windows API 编程的一些基本概念和一个最基本API函数 MessageBox的使用,在这节中,我们就来正式编写一个Windows的窗口程序. 在具体编写代码之前,我们必须先要了解一下API 编写窗口程序具体的三个基本步骤:             1. 注册窗口类:             2.创建窗口:             3.显示窗口: 恩,

Linux统系统开发11 Socket API编程2 多进程 多线程 高并发处理

[本文谢绝转载原文来自http://990487026.blog.51cto.com] <纲要> Linux统系统开发11 Socket API编程2 多进程 多线程 高并发处理 UDP服务器 客户端最小模型,处理字符转大写 TCP 多进程并发服务器模型,为每个客户端开启一个进程: TCP 多线程服务器模型,使用wrap函数封装 作业: ---------------------------------------------------- UDP服务器 客户端最小模型,处理字符转大写 [em

Flink Program Guide (2) -- DataStream API编程指导 -- For Java

v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VML);} .shape {behavior:url(#default#VML);} 张安 张安 2 1 2016-08-02T10:56:00Z 2016-08-02T10:56:00Z 1 2945 16790 139 39 19696 16.00 false false false false

Mysql C语言API编程入门讲解

原文:Mysql C语言API编程入门讲解 软件开发中我们经常要访问数据库,存取数据,之前已经有网友提出让鸡啄米讲讲数据库编程的知识,本文就详细讲解如何使用Mysql的C语言API进行数据库编程.  API,全称Application Programming Interfaces,即应用程序编程接口,我们可以调用这些接口,执行API函数提供的功能.  Mysql C语言API就是用C语言编写的Mysql编程接口,使用这些接口函数可以实现对Mysql数据库的查询等操作.  Mysql的安装  要进

Maya API编程快速入门

一.Maya API编程简介 Autodesk? Maya? is an open product. This means that anyone outside of Autodesk can change Maya's existing features or add entirely new features. There are several ways you can modify Maya: · MEL?-(Maya Embedded Language) is a powerful

ASP.NET Web API编程——路由

路由过程大致分为三个阶段: 1)请求URI匹配已存在路由模板 2)选择控制器 3)选择操作 1匹配已存在的路由模板 路由模板 在WebApiConfig.Register方法中定义路由,例如模板默认生成的路由为: config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Opti

浅谈Windows API编程

WinSDK是编程中的传统难点,个人写的WinAPI程序也不少了,其实之所以难就难在每个调用的API都包含着Windows这个操作系统的潜规则或者是windows内部的运行机制…… WinSDK是编程中的传统难点,曾经听有一个技术不是很好的朋友乱说什么给你API谁都会用,其实并非那么简单,个人写的WinAPI程序也不少了,其实之所以难就难在每个调用的API都包含着Windows这个操作系统的潜规则或者是windows内部的运行机制. 首先来谈谈句柄,初学习WinSDK的朋友刚看到这个词头大了吧?