zoukankan      html  css  js  c++  java
  • 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可退出。

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

  • 相关阅读:
    matlab cell
    matlab linux 快捷键设置——有问题还是要解决
    latex 小结
    TOJ 1258 Very Simple Counting
    TOJ 2888 Pearls
    HDU 1248 寒冰王座
    TOJ 3486 Divisibility
    TOJ 3635 过山车
    TOJ 1840 Jack Straws
    HDU 4460 Friend Chains
  • 原文地址:https://www.cnblogs.com/makejeffer/p/4774006.html
Copyright © 2011-2022 走看看