zoukankan      html  css  js  c++  java
  • Directx11 教程(2) 基本的windows应用程序框架(2)

         在本教程中,我们把前面一个教程的代码,进行封装。把初始化函数,Run函数,窗口回调函数,ShutdownWindows函数等封装到一个System class中。

        首先我们要在前面建立的solution,myTutorialD3D11中,鼠标右键点击,选择New Project,

    image

    创建一个名为myTutorialD3D11_1的空工程,在工程中增加main.cpp文件。

    main.cpp的代码如下:

    #include "SystemClass.h"

    //应用程序入口main函数
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pScmdline, int iCmdshow)
        {
        SystemClass* System;
        bool result;


        // 创建一个system对象.
        System = new SystemClass;
        if(!System)
            {
            return 0;
            }

        // 初始化system对象.
        result = System->Initialize();
        if(result)
            {
            System->Run();
            }

        // 关闭以及释放system对象.
        System->Shutdown();
        delete System;
        System = 0;
        return 0;
        }

    在工程myTutorialD3D11_1上鼠标右键点击,选择Add->Class,创建一个名为SystemClass的类。

    image

    SystemClass.h的代码如下:

    #pragma once
    //定义该宏能够减少windows头文件的大小,使编译器不编译一些不必要的文件,加快编译时间
    #define WIN32_LEAN_AND_MEAN

    #include <windows.h>

    const bool FULL_SCREEN = false;
    static bool bexit = false;

    class SystemClass
        {
        public:
            SystemClass(void);
            SystemClass(const SystemClass &);
            ~SystemClass(void);

            bool Initialize();
            void Shutdown();
            void Run();

            LRESULT CALLBACK MessageHandler(HWND, UINT, WPARAM, LPARAM);
        private:
            bool Frame();
            void InitializeWindows(int&, int&);
            void ShutdownWindows();

            LPCWSTR m_applicationName;
            HINSTANCE m_hinstance;
            HWND m_hwnd;
        };

    //定义静态的回调函数以及应用程序句柄
    //因为定义窗口类的时候,必须指定窗口回调函数,所以我们用静态的回调函数WndProc
    static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

    static SystemClass* ApplicationHandle = 0;

    SystemClass.cpp代码如下:

    #include "SystemClass.h"


    SystemClass::SystemClass(void)
        {
        bexit = false;
        }

    SystemClass::SystemClass(const SystemClass &)
        {

        }

    SystemClass::~SystemClass(void)
        {
        }

    //调用窗口初始化函数和其它一些类的初始化函数
    //本例子中,只调用初始化窗口函数

    bool SystemClass::Initialize()
        {
        int screenWidth = 0, screenHeight = 0;

        // 初始化窗口
        InitializeWindows(screenWidth, screenHeight);

        return true;
        }

    void SystemClass::Shutdown()
        {
        //其它类的一些销毁工作
        //...

        // 执行窗口一些销毁工作.
        ShutdownWindows();

        }

    //处理消息
    void  SystemClass::Run()
        {
        MSG msg;
        bool done, result = 1;


        // 初始化消息结构.
        ZeroMemory(&msg, sizeof(MSG));

       // 循环进行消息处理,如果接收到WM_QUIT.
        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,也退出程序

                //我们的渲染或者其它处理,可以放在这儿
                //....
                //.....
                Frame();
                if(result)
                    {
                    done = true;
                    }
                }

            }

        return;
        }

    bool SystemClass::Frame()
        {
        return true;
        }

    //初始化窗口类,创建应用程序窗口
    void SystemClass::InitializeWindows(int& screenWidth, int& screenHeight)
        {
        WNDCLASSEX wc;
        DEVMODE dmScreenSettings;
        int posX, posY;

        //得到System class对象(应用程序句柄)
        ApplicationHandle = this;

        // 得到应用程序实例句柄
        m_hinstance = GetModuleHandle(NULL);

        // 应用程序名字
        m_applicationName = L"Engine";

       // 设置窗口类参数.
        wc.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
        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);


        }

    void SystemClass::ShutdownWindows()
        {
        //显示光标.
        //ShowCursor(true);

        // 恢复默认显示设置.
        if(FULL_SCREEN)
            {
            ChangeDisplaySettings(NULL, 0);
            }

        // 销毁窗口
        DestroyWindow(m_hwnd);
        m_hwnd = NULL;

        // 销毁应用程序实例.
        UnregisterClass(m_applicationName, m_hinstance);
        m_hinstance = NULL;
        ApplicationHandle = NULL;

        return;

        }

    LRESULT CALLBACK SystemClass::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);
            }
            }
        }

    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 ApplicationHandle->MessageHandler(hwnd, umessage, wparam, lparam);
            }
            }
        }

    程序执行后的界面和上次是一样的。

    image

    完整的代码请参考:

    工程文件myTutorialD3D11_1

    代码下载:

    https://files.cnblogs.com/mikewolf2002/myTutorialD3D11.zip

  • 相关阅读:
    js--获得当前系统时间
    关于react记录
    循环运用记录
    react native环境的搭建
    video,audio的使用细则
    mongoDB 将mongodb添加到服务
    react 全选和全不选
    人生那么多不确定,你怕什么
    select样式的重写
    关于动态插入出现undefined
  • 原文地址:https://www.cnblogs.com/mikewolf2002/p/2385832.html
Copyright © 2011-2022 走看看