众所周知:
MFC适合桌面应用的开发,而不太适合windows游戏编程,因为它封装了很多我们游戏编程中所不需要的东西,这些东西在一定程度上都影响着GDI的效率,略显冗余了。但是MFC有丰富的类库,这在写代码时又能提供很大的方便……
再来看看Win32 SDK,接近底层,效率肯定好,但是却没有MFC那样的类库,写代码着实不太方便……
这样一想,我就有个问题了:在接下来的游戏效果模拟中,是继续使用MFC,还是专用Win32SDK呢?或者还有什么更好的方法?……
这么一想,嘿,一个idea就诞生了:用C++来自行架构一个适合windows游戏编程的框架,使它既能使用MFC类库,效率又更好
这个框架如何架构呢?请继续阅读下面的内容吧^_^
二、架构的一个简易框架,MFC类库、效率都能兼顾
我的架构思路:
1>将窗口创建过程(设计窗口类结构体实例、注册窗口类、创建窗口、显示窗口、消息循环)以及消息响应函数都封装在一个名为CCWindow的C++类中
2>在Main.cpp源文件中就实现WinMain以及窗口过程
由于我的开源框架的源代码中有详尽的注释,F话就不多说了,直接贴上源代码:
StdAfx.h头文件:这是使用MFC类库所必须添加的头文件
- /***
- *
- * StdAfx.h
- * 包含一些用到的类库所在的头文件
- *
- ***/
- #pragma once
- #define _AFXDLL//动态添加MFC类库
- #include <SDKDDKVer.h>//定义最高版本windows
- #include <afxwin.h> // MFC封装的核心组件和标准组件
- #include <atlimage.h> //CImage类包含的头文件
- #include <MMSystem.h> //播放媒体(音乐)所需包含的头文件
- #pragma comment(lib, "winmm.lib")//添加媒体库
- #pragma comment(linker,"/manifestdependency:\"type='win32' \
- name='Microsoft.Windows.Common-Controls' \
- version='6.0.0.0' processorArchitecture='x86' \
- publicKeyToken='6595b64144ccf1df' language='*'\"")
/*** * * StdAfx.h * 包含一些用到的类库所在的头文件 * ***/ #pragma once #define _AFXDLL//动态添加MFC类库 #include <SDKDDKVer.h>//定义最高版本windows #include <afxwin.h> // MFC封装的核心组件和标准组件 #include <atlimage.h> //CImage类包含的头文件 #include <MMSystem.h> //播放媒体(音乐)所需包含的头文件 #pragma comment(lib, "winmm.lib")//添加媒体库 #pragma comment(linker,"/manifestdependency:\"type='win32' \ name='Microsoft.Windows.Common-Controls' \ version='6.0.0.0' processorArchitecture='x86' \ publicKeyToken='6595b64144ccf1df' language='*'\"")
CWindow.h头文件(CCWindow类的定义)
- #pragma once
- #include"StdAfx.h"
- #include<time.h>
- class CCWindow
- {
- //==================成员====================
- private:
- WNDCLASS m_wndclass; //窗口类结构体实例
- public:
- HWND m_hwnd; //窗口句柄
- CImage m_img; //背景图片
- CRect m_rect; //窗口户区大小
- //=============窗口创建相关的成员函数=============
- public:
- //设计窗口类
- bool InitWndClass(
- HINSTANCE hInstance, //实例句柄
- WNDPROC wpWndProc, //窗口过程
- LPCTSTR lpWndName, //窗口名称
- LPCTSTR lpIconPath); //图标路径
- //设计窗口类
- bool InitWndClass(WNDCLASS);
- //注册窗口类
- ATOM RegisterWndClass();
- //创建窗口(默认居中)
- void Create(
- LPCTSTR lpClassName, //窗口类名称
- LPCTSTR lpWndName, //窗口标题名称
- DWORD dwStyle, //窗口风格
- int nWidth, //窗口宽度
- int nHeight); //窗口高度
- //显示窗口
- void Show(int);
- //一般的消息循环
- int RunMsgLoop();
- //更高效的消息循环
- int RunMsgLoop(void (*Display)(), int);
- //================消息响应函数================
- public:
- //注:在这里添加需要响应的消息处理函数的声明
- public:
- //构造函数
- CCWindow(void);
- //析构函数
- ~CCWindow(void);
- };
#pragma once #include"StdAfx.h" #include<time.h> class CCWindow { //==================成员==================== private: WNDCLASS m_wndclass; //窗口类结构体实例 public: HWND m_hwnd; //窗口句柄 CImage m_img; //背景图片 CRect m_rect; //窗口户区大小 //=============窗口创建相关的成员函数============= public: //设计窗口类 bool InitWndClass( HINSTANCE hInstance, //实例句柄 WNDPROC wpWndProc, //窗口过程 LPCTSTR lpWndName, //窗口名称 LPCTSTR lpIconPath); //图标路径 //设计窗口类 bool InitWndClass(WNDCLASS); //注册窗口类 ATOM RegisterWndClass(); //创建窗口(默认居中) void Create( LPCTSTR lpClassName, //窗口类名称 LPCTSTR lpWndName, //窗口标题名称 DWORD dwStyle, //窗口风格 int nWidth, //窗口宽度 int nHeight); //窗口高度 //显示窗口 void Show(int); //一般的消息循环 int RunMsgLoop(); //更高效的消息循环 int RunMsgLoop(void (*Display)(), int); //================消息响应函数================ public: //注:在这里添加需要响应的消息处理函数的声明 public: //构造函数 CCWindow(void); //析构函数 ~CCWindow(void); };
CWindow.cpp(CCWindow类的成员函数实现)
- #include "CWindow.h"
- CCWindow::CCWindow(void)
- {
- }
- CCWindow::~CCWindow(void)
- {
- }
- /*------------------------------
- *功能:设计窗口类
- *@hInstance: 实例句柄
- *@WndProc: 窗口过程
- *@WndName: 窗口名称
- *@IconPath: 图标路径
- -----------------------------*/
- bool CCWindow::InitWndClass(HINSTANCE hInstance,//实例句柄
- WNDPROC WndProc, //窗口过程
- LPCTSTR WndName, //窗口名称
- LPCTSTR IconPath) //图标路径
- {
- ZeroMemory(&m_wndclass, sizeof(WNDCLASS));
- m_wndclass.style = CS_HREDRAW | CS_VREDRAW;
- m_wndclass.lpfnWndProc = WndProc;
- m_wndclass.hInstance = hInstance;
- m_wndclass.cbClsExtra = 0;
- m_wndclass.cbWndExtra = 0;
- m_wndclass.hIcon =
- static_cast<HICON>(LoadImage(NULL, IconPath, IMAGE_ICON,
- 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE));
- m_wndclass.hCursor = ::LoadCursor(NULL, IDC_ARROW);
- m_wndclass.hbrBackground =
- static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
- m_wndclass.lpszMenuName = NULL;
- m_wndclass.lpszClassName = WndName;
- return true;
- }
- /*--------------------------------------
- 设计窗口类
- --------------------------------------*/
- bool CCWindow::InitWndClass(WNDCLASS wndclass)
- {
- m_wndclass = wndclass;
- return true;
- }
- /*--------------------------------------
- 注册窗口类
- --------------------------------------*/
- ATOM CCWindow::RegisterWndClass()
- {
- return RegisterClass(&m_wndclass);
- }
- /*--------------------------------------
- 创建窗口
- --------------------------------------*/
- void CCWindow::Create(
- LPCTSTR lpClassName,
- LPCTSTR lpWindowName,
- DWORD dwStyle,
- int nWidth,
- int nHeight)
- {
- //获取屏幕宽度和高度
- int screenW = GetSystemMetrics(SM_CXSCREEN);
- int screenH = GetSystemMetrics(SM_CYSCREEN);
- //创建并居中显示窗口
- m_hwnd = CreateWindow(lpClassName, lpWindowName, dwStyle,
- (screenW-nWidth)/2, (screenH-nHeight)/2,
- nWidth, nHeight, NULL, NULL,
- m_wndclass.hInstance, NULL);
- }
- /*--------------------------------------
- 显示窗口
- --------------------------------------*/
- void CCWindow::Show(int nCmdShow)
- {
- ShowWindow(m_hwnd, nCmdShow);
- }
- //UpdateWindow(...)更新窗口(可以省略)
- /*--------------------------------------
- 一般的消息循环
- GetMessage()
- --------------------------------------*/
- int CCWindow::RunMsgLoop()
- {
- MSG msg;
- ZeroMemory(&msg, sizeof(MSG));
- while(GetMessage(&msg, NULL, 0, 0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- return msg.wParam;
- }
- /*--------------------------------------
- 消息循环(更好的消息循环)
- PeekMessage()
- --------------------------------------*/
- int CCWindow::RunMsgLoop(void (*Display)(), int interval)
- {
- MSG msg;
- ZeroMemory(&msg, sizeof(MSG));
- //获取运行到此处时的时间
- int last = GetTickCount();
- //如果不是退出消息
- while(msg.message != WM_QUIT)
- {
- //如果有消息
- if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- //否则, 空闲的时候执行响应函数(大多数是绘制函数)
- else
- {
- //如果窗口客户区大小不为0就是显示(有可能窗口是在最小化)
- if(m_rect.Width() &&
- m_rect.Height())
- {
- Display();
- Sleep(interval);
- }
- }
- }
- return msg.wParam;
- }
- //----------------------------------------------------------
- // 消息响应函数
- //----------------------------------------------------------
- //注:在这里添加需要响应的消息处理函数的实现
#include "CWindow.h" CCWindow::CCWindow(void) { } CCWindow::~CCWindow(void) { } /*------------------------------ *功能:设计窗口类 *@hInstance: 实例句柄 *@WndProc: 窗口过程 *@WndName: 窗口名称 *@IconPath: 图标路径 -----------------------------*/ bool CCWindow::InitWndClass(HINSTANCE hInstance,//实例句柄 WNDPROC WndProc, //窗口过程 LPCTSTR WndName, //窗口名称 LPCTSTR IconPath) //图标路径 { ZeroMemory(&m_wndclass, sizeof(WNDCLASS)); m_wndclass.style = CS_HREDRAW | CS_VREDRAW; m_wndclass.lpfnWndProc = WndProc; m_wndclass.hInstance = hInstance; m_wndclass.cbClsExtra = 0; m_wndclass.cbWndExtra = 0; m_wndclass.hIcon = static_cast<HICON>(LoadImage(NULL, IconPath, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE)); m_wndclass.hCursor = ::LoadCursor(NULL, IDC_ARROW); m_wndclass.hbrBackground = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)); m_wndclass.lpszMenuName = NULL; m_wndclass.lpszClassName = WndName; return true; } /*-------------------------------------- 设计窗口类 --------------------------------------*/ bool CCWindow::InitWndClass(WNDCLASS wndclass) { m_wndclass = wndclass; return true; } /*-------------------------------------- 注册窗口类 --------------------------------------*/ ATOM CCWindow::RegisterWndClass() { return RegisterClass(&m_wndclass); } /*-------------------------------------- 创建窗口 --------------------------------------*/ void CCWindow::Create( LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int nWidth, int nHeight) { //获取屏幕宽度和高度 int screenW = GetSystemMetrics(SM_CXSCREEN); int screenH = GetSystemMetrics(SM_CYSCREEN); //创建并居中显示窗口 m_hwnd = CreateWindow(lpClassName, lpWindowName, dwStyle, (screenW-nWidth)/2, (screenH-nHeight)/2, nWidth, nHeight, NULL, NULL, m_wndclass.hInstance, NULL); } /*-------------------------------------- 显示窗口 --------------------------------------*/ void CCWindow::Show(int nCmdShow) { ShowWindow(m_hwnd, nCmdShow); } //UpdateWindow(...)更新窗口(可以省略) /*-------------------------------------- 一般的消息循环 GetMessage() --------------------------------------*/ int CCWindow::RunMsgLoop() { MSG msg; ZeroMemory(&msg, sizeof(MSG)); while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } /*-------------------------------------- 消息循环(更好的消息循环) PeekMessage() --------------------------------------*/ int CCWindow::RunMsgLoop(void (*Display)(), int interval) { MSG msg; ZeroMemory(&msg, sizeof(MSG)); //获取运行到此处时的时间 int last = GetTickCount(); //如果不是退出消息 while(msg.message != WM_QUIT) { //如果有消息 if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } //否则, 空闲的时候执行响应函数(大多数是绘制函数) else { //如果窗口客户区大小不为0就是显示(有可能窗口是在最小化) if(m_rect.Width() && m_rect.Height()) { Display(); Sleep(interval); } } } return msg.wParam; } //---------------------------------------------------------- // 消息响应函数 //---------------------------------------------------------- //注:在这里添加需要响应的消息处理函数的实现
Main.h头文件(主程序头文件)
- /***
- *
- * Main.h
- * 主程序所需包含的头文件、宏定义、声明等
- *
- ***/
- #pragma once
- #include "CWindow.h"
- #define WNDNAME "【VC++游戏开发】窗口名称"//窗口名称
- #define WNDWIDTH 800//窗口宽度
- #define WNDHEIGHT 600//窗口高度
- //窗口关联对象:全局对象
- CCWindow wnd;
- //窗口过程
- LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
/*** * * Main.h * 主程序所需包含的头文件、宏定义、声明等 * ***/ #pragma once #include "CWindow.h" #define WNDNAME "【VC++游戏开发】窗口名称"//窗口名称 #define WNDWIDTH 800//窗口宽度 #define WNDHEIGHT 600//窗口高度 //窗口关联对象:全局对象 CCWindow wnd; //窗口过程 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
Main.cpp(主程序代码:负责WinMain、WndProc)
- <span style="font-size: 18px;">#include "Main.h"
- /*
- 显示函数:绘制随机位置、大小、颜色的矩形
- 注:由于调用很频繁,故设为内联函数
- */
- inline void Display()
- {
- //做响应的操作
- }
- //
- //==============WinMain=======================
- //
- int WINAPI WinMain(HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPSTR lpCmdLine,
- int nCmdShow)
- {
- //设计窗口类
- CString iconPath = "";//图标的路径(这里没有, 需自己设定)
- wnd.InitWndClass(hInstance, WndProc, WNDNAME, iconPath);
- //注册窗口类
- if(!wnd.RegisterWndClass())
- {
- ::AfxMessageBox("RegisterWndClass() Failed");
- return 0;
- }
- DWORD style = WS_OVERLAPPEDWINDOW &
- ~(WS_THICKFRAME | WS_MAXIMIZEBOX);
- //创建窗口并居中窗口
- wnd.Create(WNDNAME, WNDNAME, style,
- WNDWIDTH, WNDHEIGHT);
- //显示窗口
- wnd.Show(nCmdShow);
- /*进入消息循环
- 1. 使用更好的消息循环 如:wnd.RunMsgLoop(Display, 100)
- 2. 使用一般的消息循环 如:wnd.RunMsgLoop()
- */
- return wnd.RunMsgLoop();
- }
- //
- //================窗口过程:处理消息=================
- //
- LRESULT CALLBACK WndProc(
- HWND hwnd,
- UINT msg,
- WPARAM wParam,
- LPARAM lParam)
- {
- /*
- 在这里添加消息映射代码(switch-case语句)
- 如:
- switch(msg)
- {
- case WM_CREATE:
- wnd.OnCreate(); //窗口建立消息:进行一些初始化操作
- return 0;
- }
- */
- return DefWindowProc(hwnd, msg, wParam, lParam);
- }</span>
#include "Main.h" /* 显示函数:绘制随机位置、大小、颜色的矩形 注:由于调用很频繁,故设为内联函数 */ inline void Display() { //做响应的操作 } // //==============WinMain======================= // int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { //设计窗口类 CString iconPath = "";//图标的路径(这里没有, 需自己设定) wnd.InitWndClass(hInstance, WndProc, WNDNAME, iconPath); //注册窗口类 if(!wnd.RegisterWndClass()) { ::AfxMessageBox("RegisterWndClass() Failed"); return 0; } DWORD style = WS_OVERLAPPEDWINDOW & ~(WS_THICKFRAME | WS_MAXIMIZEBOX); //创建窗口并居中窗口 wnd.Create(WNDNAME, WNDNAME, style, WNDWIDTH, WNDHEIGHT); //显示窗口 wnd.Show(nCmdShow); /*进入消息循环 1. 使用更好的消息循环 如:wnd.RunMsgLoop(Display, 100) 2. 使用一般的消息循环 如:wnd.RunMsgLoop() */ return wnd.RunMsgLoop(); } // //================窗口过程:处理消息================= // LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { /* 在这里添加消息映射代码(switch-case语句) 如: switch(msg) { case WM_CREATE: wnd.OnCreate(); //窗口建立消息:进行一些初始化操作 return 0; } */ return DefWindowProc(hwnd, msg, wParam, lParam); }
下面,我简单地介绍一下这个框架的使用方法:
1>创建一个空项目(我这里是VS2010)
2>将这3个头文件以及2个cpp源文件添加到创建好的项目中
3>在 CWindow.h中添加消息响应函数(CCWindow类的成员函数)的声明
如:(名称还是遵循MFC的命名方式)
- //================消息响应函数================
- public:
- //注:在这里添加需要响应的消息处理函数的声明
- void OnCreate();;
4>CWindow.cpp中实现这些消息响应函数//================消息响应函数================ public: //注:在这里添加需要响应的消息处理函数的声明 void OnCreate();;
5>在Main.cpp的窗口过程函数中调用响应的消息响应函数
如:
- switch(msg)
- {
- case WM_CREATE:
- wnd.OnCreate(); //窗口建立消息:进行一些初始化操作
- return 0;
- }
switch(msg) { case WM_CREATE: wnd.OnCreate(); //窗口建立消息:进行一些初始化操作 return 0; }
我还是为这个框架取一个"艺名儿",名为:BCF
BC:我的csdn博客ID缩写——BlueCoder
F:frame——框架的意思
合起来就是BlueCoder的框架,当然,大家都可以用,只要你愿意,我也乐意^_^