先用 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