在本教程中,我們把前面一個教程的代碼,進行封裝。把初始化函數,Run函數,視窗回呼函數,ShutdownWindows函數等封裝到一個System class中。
首先我們要在前面建立的solution,myTutorialD3D11中,滑鼠右鍵點擊,選擇New Project,
建立一個名為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的類。
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);
}
}
}
程式執行後的介面和上次是一樣的。
完整的代碼請參考:
工程檔案myTutorialD3D11_1
代碼下載:
http://files.cnblogs.com/mikewolf2002/myTutorialD3D11.zip