自己制作的主框架系统
自己制作的主框架系统
作者:蒋轶民 创作于2011年2月9日23:03:35
在初步了解windows运行机制后,我开始制作自己的主框架系统了。这个主框架系统能够为我们程序员服务,通过一系列简单的指令,能帮助程序员减轻很多负担,并且效果也挺好。
我写这个主框架系统的思路是这样的:在一个类中包含了窗口必须的成员变量,并且写一些简单的函数来隐藏内在的实现机制。为了使程序更有灵活性,我使用了回调函数。现在我就简单得介绍一下回调函数。
首先,回调机制的技术基础是函数指针。函数指针就是带有参数的指针,只要它和一些函数的原型一致,它们就可以互相赋值。在此基础上我们定义了回调机制。回调机制就是在一个函数的形参中定义一个函数的指针,在函数的内部引用它。表面上是调用者使用一个函数指针传给被调用者,实际上被调用者继续用这个函数指针来进行调用。这就是回调机制。稍后我就会我的系统中详细地阐明这个函数。
在我的主框架系统中,我定义了一个类CFrameworkSystem,它主要包含三个成员函数:StartFramework()、RunFramework()和EndFramework()。分别代表了开始框架、运行框架和结束框架。在定义的时候我使用了函数默认值,这样我们就可以任意地传入函数的参数了。
下面就是FrameworkSystem.h文件定义。
/*--------------------------------------------------------------------------- 蒋轶民制作 E-mail:[email protected] 最后编辑:2011年2月6日18:24:39 文件名:FrameworkSystem.h 作用:主框架系统的头文件 ----------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/ // 条件编译 #ifndef _FRAMEWORKSYSTEM_H_ #define _FRAMEWORKSYSTEM_H_ // 头文件 #include <windows.h> // 定义的宏 /*--------------------------------------------------------------------------*/ // 错误代码 enum RESULT_FRAMEWORK { OK_FRAMEWORK, // 无错误 ERR_START, // 开始主框架错误 ERR_RUN, // 运行主框架错误 ERR_END // 结束主框架错误 }; /*--------------------------------------------------------------------------*/ // 主框架系统类 class CFrameworkSystem { public: CFrameworkSystem(){}// 默认构造函数 ~CFrameworkSystem(){}// 默认析构函数 RESULT_FRAMEWORK StartFramework( HINSTANCE hInst, BOOL (*pStart)( HINSTANCE, HWND ) = 0, bool bFullScreen = false, int clientWidth = 320, int clientHeight = 240, const char* szClassName = "蒋轶民的主框架ver0.1", const char* szCaption = "程序演示:蒋轶民制作" );// 开始主框架 RESULT_FRAMEWORK RunFramework( BOOL (*pRun)( HINSTANCE, HWND ) = 0 );// 运行框架 RESULT_FRAMEWORK EndFramework( BOOL (*pEnd)( HINSTANCE, HWND ) = 0 );// 结束框架 private: HINSTANCE m_hInst;// 句柄实例 HWND m_hWnd;// 窗口句柄 WNDCLASSEX m_WindowClass;// 窗口类 char m_szClassName[100];// WNDCLASSEX类名 char m_szCaption[100];// 窗口标题名 }; typedef CFrameworkSystem* LPCFrameworkSystem; /*--------------------------------------------------------------------------*/ #endif
在这个系统类的实现中,我使用了回调机制,使得这个系统更加具有弹性。这个系统可以在窗口模式和全屏模式下运行,在窗口模式下运行的程序可以指定宽和高。这一切都是优化好了的。以下就是我的FrameworkSystem.cpp文件内容。
/*--------------------------------------------------------------------------- 蒋轶民制作 E-mail:[email protected] 最后编辑:2011年2月8日17:30:43 文件名:FrameworkSystem.cpp 作用:主框架系统的实现文件 ----------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/ // 头文件 #include <cstring> #include "FrameworkSystem.h" /*--------------------------------------------------------------------------*/ HRESULT CALLBACK DefaultMsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) { if ( msg == WM_DESTROY ) { PostQuitMessage( 0 ); return 0; } else return (HRESULT)DefWindowProc( hWnd, msg, wParam, lParam ); } /*--------------------------------------------------------------------------*/ RESULT_FRAMEWORK CFrameworkSystem::StartFramework( HINSTANCE hInst, BOOL (*pStart)( HINSTANCE, HWND ), bool bFullScreen, int clientWidth, int clientHeight, const char* szClassName, const char* szCaption )// 创建主框架 { m_hInst = hInst;// 将实例句柄赋值给成员 #if _MSC_FULL_VER >= 140050320 strcpy_s( m_szClassName, 100, szClassName );// 将WNDCLASSEX类名赋值给成员 strcpy_s( m_szCaption, 100, szCaption );// 将窗口标题名赋值给成员 #else strcpy( m_szClassName, szClassName );// 将WNDCLASSEX类名赋值给成员 strcpy( m_szCaption, szCaption );// 将窗口标题名赋值给成员 #endif // 设置成员m_WindowClass的属性 m_WindowClass.cbSize = sizeof( m_WindowClass ); m_WindowClass.style = CS_CLASSDC; m_WindowClass.lpfnWndProc = DefaultMsgProc; m_WindowClass.cbClsExtra = 0L; m_WindowClass.cbWndExtra = 0L; m_WindowClass.hInstance = m_hInst; m_WindowClass.hIcon = LoadIcon( NULL, IDI_APPLICATION ); m_WindowClass.hCursor = LoadCursor( NULL, IDC_ARROW ); m_WindowClass.hbrBackground = NULL; m_WindowClass.lpszMenuName = NULL; m_WindowClass.lpszClassName = szClassName; m_WindowClass.hIconSm = LoadIcon( NULL, IDI_APPLICATION ); RegisterClassEx( &m_WindowClass );// 注册成员m_WindowClass bFullScreen == true? clientWidth = 640, clientHeight = 480: clientWidth += 6, clientHeight += 32; // 创建窗口,并且将值传给窗口句柄 m_hWnd = CreateWindow( szClassName, szCaption, bFullScreen == true? WS_EX_TOPMOST | WS_POPUP | WS_VISIBLE: WS_CAPTION | WS_SYSMENU, CW_USEDEFAULT, CW_USEDEFAULT, clientWidth, clientHeight, GetDesktopWindow(), NULL, m_WindowClass.hInstance, NULL ); if ( m_hWnd == NULL ) return ERR_START;// 创建窗口失败 ShowWindow( m_hWnd, SW_SHOWDEFAULT );// 显示窗口 UpdateWindow( m_hWnd );// 更新窗口 // 若无额外初始化或额外初始化失败,返回错误 if ( pStart == 0 || !pStart( m_hInst, m_hWnd ) ) return ERR_START; return OK_FRAMEWORK; } /*--------------------------------------------------------------------------*/ RESULT_FRAMEWORK CFrameworkSystem::RunFramework( BOOL (*pRun)( HINSTANCE, HWND ) )// 运行框架 { // 进入框架内部运行消息循环 MSG msg; ZeroMemory( &msg, sizeof( msg ) ); while( msg.message != WM_QUIT ) { // 处理消息 if ( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } else { // 运行内部循环,若无内部循环或内部循环出现错误,则返回错误循环 if ( pRun == 0 || !pRun( m_hInst, m_hWnd ) ) return ERR_RUN; } } return OK_FRAMEWORK; } /*--------------------------------------------------------------------------*/ RESULT_FRAMEWORK CFrameworkSystem::EndFramework( BOOL (*pEnd)( HINSTANCE, HWND ) )// 结束框架 { // 若无额外的结束事务或结束事务失败,返回错误 if ( pEnd == 0 || !pEnd( m_hInst, m_hWnd ) ) return ERR_END; // 解除已存在窗口注册 UnregisterClass( m_szClassName, m_WindowClass.hInstance ); return OK_FRAMEWORK; }
现在说说这个系统的性能。
这个主函数还是非常出色的。我用它和其它的两个系统(输入系统和数据存入和读取系统)联合测试一个DirectX程序,结果成功了。现在这个系统越来越健壮了。不过,这个系统在方便程序员的同时,我们也丢失了一些灵活性。不过我想自己的程序是为编辑游戏而服务的,这一些个性化的丢失也是不要紧的。
下面就是我联合测试的截图:
我对WinMain()函数是这样调用的:
#include <iostream> #include "FrameworkSystem.h" #include "DataManageSystem.h" using namespace std; // 库文件 // 注意:所有库文件可以放在一块儿,也可以放在不同的地方。放在一块儿便于管理, // 放在不同的地方可以减小不同文件的耦合度。 #pragma comment( lib, "d3d9.lib") #pragma comment( lib, "d3dx9.lib") // 外部的函数 extern BOOL InitializeD3D( HINSTANCE hInst, HWND hWnd ); extern void RenderScene( void ); extern void GameInteraction( void ); extern void CleanUp( void ); // 外部的全局变量 extern int myClientWidth; extern int myClientHeight; extern bool bMyFullScreen;// 全屏非全屏的标识符 BOOL Run( HINSTANCE, HWND ) { RenderScene(); GameInteraction(); return TRUE; } BOOL End( HINSTANCE, HWND ) { CleanUp(); return TRUE; } int WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, int ) { CFrameworkSystem obj; CDataManageSystem obj2; obj2.Load( "Configure.txt" ); if ( obj2.Read( "Width:/t%d/nHeight:/t%d/nFullScreen:%sd", &myClientWidth, &myClientHeight, &bMyFullScreen ) == ERR_READ ) MessageBox( NULL, "读取错误。", "程序消息", MB_OK ); else MessageBox( NULL, "读取成功。", "程序消息", MB_OK ); obj.StartFramework( hInst, InitializeD3D, bMyFullScreen, myClientWidth, myClientHeight ); obj.RunFramework( Run ); obj.EndFramework( End ); return 0; }
程序的结果如图所示:
有了这三个系统,我开发程序的步子更快了。将这三个程序植入IDE内置的路径,我就可以不再多次复制粘贴再引用它们了。以后我会在此基础上开发出更加优秀的DirectX程序的!
如果大家没有时间上网看的话,这里有我的说明文档和源代码,源代码有丰富的注释,非常好懂。http://download.****.net/source/3017142