为自己创作一个好的DirectX程序风格

为自己创作一个好的DirectX程序风格
一直以来,我都是模仿别人的程序,进行参数的修改,来达到自己的目的。但是久而久之,我发现这样不行,因为演示程序又很多很多缺陷,所以我不得不使用自己的程序,希望开创自己程序的风格。
那么,下面就是我通过学习windows程序而得出的心得。可能写得不好,有疑问的请指正。
在创建Windows程序的时候,我们必须要包含windows.h头文件,这是毋庸置疑的。
首先是消息函数。消息函数是一种典型的回调函数。回调函数就是一种自己并不显示地使用,但是需要别的函数将此函数的地址传给它,用别的函数来使用。调用函数就是通过回调函数指针来进行传值调用的。在我以前的文章中,调用的Display()函数就是一种回调函数。而消息函数就是给应用程序实例进行调用的。让我们看看回调函数吧。

Code:
  1. HRESULTCALLBACKMsgProc(HWNDhwnd,UINTmsg,WPARAMwParam,LPARAMlParam)
  2. {
  3. switch(msg)
  4. {
  5. caseWM_DESTROY:
  6. PostQuitMessage(0);
  7. return0;
  8. }
  9. return(long)DefWindowProc(hwnd,msg,wParam,lParam);
  10. }

其中HRESULT就是一个返回值类型,通过windows.h头文件一层又一层的typedef,我们找出了它的源泉:long。其实HRESULT就是long类型。而CALLBACK则是一个调用约定。它也是通过一层又一层的typedef语句进行规定的,它的原型其实是__stdcall。__stdcall又是什么?在百度百科中我们找到了答案:

1.参数从右向左压入堆栈
2.函数被调用者修改堆栈
3.函数名(在编译器这个层次)自动加前导的下划线,后面紧跟一个@符号,其后紧跟着参数的尺寸

这样我们了解了什么是CALLBACK。总结一下,CALLBACK就是一个调用规定,它在汇编语言的层次规定了调用的方法。其实有很多的关键字:WINAPI、APIENTRY都是__stdcall的同义词。

扩展:c/c++还有一种调用方式,那就是__cdecl。这种方式和__stdcall有些不同,它是c/c++缺省的调用方式。详见http://baike.baidu.com/view/1280676.htm

再来看看,MsgProc()函数有这样几个参数:HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam。第一个是窗口的句柄,第二个是消息的结构体,第三个和第四个则是消息参数,其实这两个参数几乎完全相同。我们常常使用的是第一个参数wParam。函数体是对消息的处理。在一个switch语句结束后,我们就可以让操作系统来自动处理消息了。所以返回的是DefWindowProc(hwnd, msg, wParam, lParam)。

消息回调函数介绍完了,我们接下来可以介绍我们的主函数WinMain()了。大家或多或少地接触WinMain()函数,因为在MFC、ATL、WTL框架上都要使用WinMain()函数。WinMain()函数的作用就相当于控制台的main()函数,但是它的参数比main()函数要多。而且不支持重载,也就是说,我们可以使用重载的main( void ),但是不能使用WinMain( void )。使用WinMain()函数的时候,我们也必须声明函数的调用方式。使用WINAPI,或者APIENTRY就可以解决问题。但是这必须要定义相关的宏。如果你对WinMain()函数相当地了解了,那么你可以使用__stdcall来代替这些值。WinMain()函数是这样声明的:

Code:
  1. intWinMain(
  2. HINSTANCEhInstance,
  3. HINSTANCEhPrevInstance,
  4. LPSTRlpCmdLine,
  5. intnCmdShow);


第一个参数是当前程序的实例句柄,第二个参数是以前程序的实例句柄。通常为NULL。如果你限制程序一次只能打开一次,那么我们可以使用CreateMutex()函数来解决。这超出了我们的讨论范围。在这里略去。第三个参数是当前程序在命令行中的绝对路径。第四个参数是显示的方式,我们可以通过此值来确定程序的显示方式。通常要程序正常地显示,使用SW_SHOWNORMAL来标记nCmdShow即可。

然后我们在WinMain()函数中编写代码了。但无论你怎么编写,我们都必须满足这样一个流程:
1、设置Window Class结构并且注册它
2、设置窗口并且显示窗口
3、进入消息循环
4、解除窗口注册

首先设置windows class结构。我使用的是WNDCLASSEX结构,因为它提供了更多的功能。WNDCLASSEX结构如下所示:

Code:
  1. typedefstruct{
  2. UINTcbSize;
  3. UINTstyle;
  4. WNDPROClpfnWndProc;
  5. intcbClsExtra;
  6. intcbWndExtra;
  7. HINSTANCEhInstance;
  8. HICONhIcon;
  9. HCURSORhCursor;
  10. HBRUSHhbrBackground;
  11. LPCTSTRlpszMenuName;
  12. LPCTSTRlpszClassName;
  13. HICONhIconSm;
  14. }WNDCLASSEX,*PWNDCLASSEX;

现在我来说明这些数据成员。
UINT cbSize;是该结构的大小(字节)
UINT style;是窗口的风格,有多种风格可以选择。参见MSDN。
WNDPROC lpfnWndProc;窗口消息循环函数的入口指针。
int cbClsExtra;需要附加在WNDCLASSEX结构体的字节数,通常设为零。
int cbWndExtra;为窗口实例附加的字节。通常是0。但是如果是对话框形式的,并且附加了资源,则需使用DLGWINDOWEXTRA。
HINSTANCE hInstance;为程序的实例句柄。
HICON hIcon;为图标的句柄,如果为NULL,程序则会在资源中寻找图标。
HCURSOR hCursor;为光标句柄,如果使用的是自定义的光标,则可以使用LoadCursor()函数来实现。
HBRUSH hbrBackground;为背景画板刷,暂时设为NULL,我还没有学会怎么使用。
LPCTSTR lpszMenuName;为菜单的指针。如果程序中有菜单,并且在资源中有菜单的编辑,那么可以不为空,但是如果不需要使用菜单,可以将其设为NULL。
LPCTSTR lpszClassName;为NDCLASSEX类的名字。
HICON hIconSm;16×16大小的小图标的句柄。

然后调用CreateWindow()函数。这个函数可以为窗口指定样式。它是这样定义的:

Code:
  1. HWNDCreateWindow(
  2. LPCTSTRlpClassName,
  3. LPCTSTRlpWindowName,
  4. DWORDdwStyle,
  5. intx,
  6. inty,
  7. intnWidth,
  8. intnHeight,
  9. HWNDhWndParent,
  10. HMENUhMenu,
  11. HINSTANCEhInstance,
  12. LPVOIDlpParam
  13. );

下面我来说说这个参数的用法:
LPCTSTR lpClassName,为windows class(WNDCLASSEX) 类的名字;
LPCTSTR lpWindowName,为窗口的名字,它会显示在窗口上。
DWORD dwStyle,窗口的样式,通过各种样式的组合,我们可以得出不同的窗口来。因为有太多的样式了,所以有什么疑问,参照MSDN;
int x,窗口起始横坐标;
int y,窗口起始纵坐标;
int nWidth,窗口的宽;
int nHeight,窗口的高;
HWND hWndParent,这个是窗口的父窗口句柄;
HMENU hMenu,菜单的句柄。
HINSTANCE hInstance,程序实例句柄
LPVOID lpParam绘制客户区的参数

然后就调用ShowWindow()和UpdateWindow()函数来进行显示了。再进行消息循环,如果有什么消息传入的话,进入消息队列,否则进行窗口渲染。当然,我写的这个程序是非常简单的,以后我可能会使用这个程序的模板来写更多更多复杂的程序的。

下面就是我的代码,它是我在模仿多个windows程序的源代码后自己写的代码。

Code:
  1. /*---------------------------------------------------------------------------
  2. 蒋轶民制作E-mail:jiangcaiyang123@163.com
  3. 文件名:MainFrame.cpp
  4. 作用:设计自己优化的程序结构
  5. ----------------------------------------------------------------------------*/
  6. #include<windows.h>
  7. //定义的宏
  8. #defineJCLASSNAME"优化的程序"
  9. #defineJCAPTION"程序演示"
  10. #defineWINDOW_WIDTH320
  11. #defineWINDOW_HEIGHT320
  12. HRESULTCALLBACKMyAppProc(HWNDhWnd,UINTmsg,WPARAMwParam,LPARAMlParam)
  13. {
  14. switch(msg)
  15. {
  16. caseWM_DESTROY:
  17. PostQuitMessage(0);
  18. return0;
  19. }
  20. return(HRESULT)DefWindowProc(hWnd,msg,wParam,lParam);
  21. };
  22. intWINAPIWinMain(HINSTANCEhInst,HINSTANCEhPrevInst,LPSTRcmd,intshow)
  23. {
  24. //设置WindowClass结构并且注册它
  25. WNDCLASSEXjWndCls={sizeof(jWndCls),CS_CLASSDC,MyAppProc,0,0,hInst,
  26. NULL,NULL,0,NULL,JCLASSNAME,NULL};
  27. RegisterClassEx(&jWndCls);
  28. //设置窗口并且显示窗口
  29. HWNDhWnd=CreateWindow(JCLASSNAME,JCAPTION,WS_CAPTION|WS_SYSMENU,20,20,
  30. WINDOW_WIDTH,WINDOW_HEIGHT,NULL,NULL,hInst,BUTTON);
  31. if(hWnd==NULL)
  32. returnFALSE;
  33. ShowWindow(hWnd,SW_SHOWNORMAL);
  34. UpdateWindow(hWnd);
  35. //进入消息循环
  36. MSGmsg;
  37. ZeroMemory(&msg,sizeof(msg));
  38. while(msg.message!=WM_QUIT)
  39. {
  40. if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  41. {
  42. TranslateMessage(&msg);
  43. DispatchMessage(&msg);
  44. }
  45. else
  46. {
  47. //什么也不做
  48. }
  49. }
  50. //解除窗口注册
  51. UnregisterClass(JCLASSNAME,jWndCls.hInstance);
  52. return0;
  53. }

我更多的DirectX程序,请看:

设计DirectX游戏开头动画效

设计DirectX游戏开头画面淡淡出的效

我的游戏:走迷宫(DirectX版)

今天就写到这里了,如果有时间的话,我会写更多有关DirectX和Windows应用程序的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值