设为首页 收藏本站
查看: 1228|回复: 0

[经验分享] 《Windows游戏编程大师技巧》二、Windows编程模型

[复制链接]

尚未签到

发表于 2016-5-24 04:55:39 | 显示全部楼层 |阅读模式
  

  
这一章开篇语对我有很大的启迪,一直对Windows下编程有着畏难心理。太庞大的平台和体系,
太多的API和术语,太快的技术换代节奏,而我是个想要把握住本质掌握住基础才会有安全感
和成就感的程序员,所以我只乐于学习Win32 API。而现在受到这本书的启发,对Windows编程
的畏惧少了一些,也有了一些学习计划:


1.窗体界面 -> Win32\MFC (简单了解界面消息处理机制吧,实在是不擅长画UI,MFC也有些难)
2.网络编程 -> Winsock (这是我比较想学的)
3.Web控件 -> ActiveX (不了解,应该学学)
4.动画游戏 -> GDI\DirectX (感兴趣,想写点小游戏自娱自乐)


所以我觉得写个小游戏作为业余项目是很不错的,游戏部分可以学学DirectX,设置界面可以简单
学习下MFC,然后再给游戏增加个网络对战功能就可以学到Winsock了。业余项目关键是不要追求
完美,先把基本功能完成,基础框架搭好。曾经想用Java2D写个塔防游戏,就是太想一下子就写好,
于是就半途而废了。


========================================================


Windows编程就像去见牙医:虽然明明知道对自己是有益处的,可还是没人喜欢总是找牙医。
虽然我不能保证在阅读本章之后你会变得更加喜欢去见牙医,但是我敢保证你会比以往更喜欢
Windows编程。别因为我要解放你的思想而感到害怕(特别是钟情于DOS的顽固分子)。




Windows的起源


Windows 1.0完全建立在DOS基础上,不能执行多任务,运行缓慢。Windows 3.0让开发人员和
商业应用程序逐渐脱离DOS。但游戏编程的人们还在唱着“坚守DOS岗位直到炼狱冻结”的赞歌。
Windows 95推出后,我才真正开始喜欢Windows编程。


Windows 9X/NT是多任务、多线程的,这和DOS有很大不同。DOS下,一旦你的程序开始运行,
就只能运行该程序(中断处理程序除外)。要想多线程就必须自己模拟,这也是游戏程序员多年
来所做的事。


Windows还是一个事件驱动的操作系统。我们不必关心其他正在运行的应用程序,Windows会去处理,
我们只要关心自己的应用程序中信息的处理。这在Windows 3.0/3.1中是不可能的,它们并不是真正的
多任务系统,每一个应用程序都要产生下一个程序。


DSC0000.png



匈牙利符号表示法


像微软一样的公司,有几千个程序员在干不同的项目,一个名叫Simonyi的人负责创建了一套
编写微软代码的规范。所有微软的API、界面、技术文件等等都采用这些规范。这个规范被称为
匈牙利符号表示法,也许因为他经常加班弄得饥肠辘辘吧(饥饿Hungry和匈牙利Hungary)。


DSC0001.png



1.变量:根据变量类型采用不同的前缀,之后的每个子名都要以大写字母开头。如char *szFileName;
全局变量还要在开头加上g_或g,如int g_iXPos;


2.函数:与变量相同,但没有前缀。如int PlotPixel(int ix, int iy, int ic);


3.类型和常量:所有字母大写,子名可以用下划线分隔。如#define MAX_CELLS 64


4.类:所有C++的类以大写C为前缀,其余与变量相同。如class CVector { ... };


5.参数:与变量命名相同,如GetPixel(int ix, int iy); 但GetPixel(int x, int y);也是可以的。


学会阅读匈牙利符号表示法但不代表要改变你自己的编程风格。本书在使用Win32 API函数的场合
使用匈牙利表示法,而在其他位置使用自己的风格。




世界上最简单的Windows程序


基于DOS的“Hello World”程序。注意:要用VC创建一个控制台应用程序,
这是类DOS的应用程序,只是它是32位的。将目标.EXE设为控制台应用
程序,而非Win32.EXE!


#include <stdio.h>void main(void){printf("\nTHERE CAN BE ONLY ONE!!!\n");}


Windows程序都以WinMain()开始,就像DOS都以main()开始一样。


#define WIN32_LEAN_AND_MEAN#include <windows.h>#include <windowsx.h>int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd){MessageBox(NULL, "THERE CAN BE ONLY ONE!!!","MY FIRST WINDOWS PROGRAM",MB_OK | MB_ICONEXCLAMATION);return (0);}


现实中的Windows程序


我们所需的只是一个基本的Windows程序,打开一个窗口、处理信息、调用游戏主循环等。
因此只要进行下列工作:
  1. 创建Windows类。
  2. 创建事件句柄。
  3. 注册Windows类。
  4. 用之前的Windows类创建一个窗口。
  5. 创建一个能够从事件句柄获得或向事件句柄传递信息的主循环。


1.创建Windows类


Windows中的每一个窗口、控件、列表框、对话框和小部件都是一个Windows类。你也可以
自定义Windows类,你编写的每一个应用程序都应该至少有一个Windows类,否则会非常麻
烦。控制Windows类的数据结构是:WNDCLASSEX。创建Windows类就是设置好它的各种属性。


WNDCLASSEX winclass = {
sizeof(WNDCLASSEX),
CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW,
WindowsProc,
0,
0,
hInst,
LoadIcon(NULL, IDI_APPLICATION),
LoadCursor(NULL, IDC_ARROW),
(HBRUSH) GetStockObject(BLACK_BRUSH),
NULL,
"WINCLASS1",
LoadIcon(NULL, IDI_APPLICATION)
};


2.事件句柄


由上图看到一个重要的属性 - 回调函数,它是通过lpfnWndProc设定。
来看一个事件处理函数的例子,在这里我们只关心WM_CREATE\PAINT\DESTROY三个事件。


LRESULT CALLBACK WindowsProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
{
case WM_CREATE:      
return 0 ;
caseWM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;      
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}


3.注册Windows类


很简单只需一行代码:RegisterClassEx(&winclass);
还有一个旧版本的RegisterClass()用于注册基于旧结构WNDCLASS类。
一旦注册就可以任意创建它的窗口了。


4.创建窗口


  hwnd = CreateWindowEx(
NULL, // extended style
"WINCLASS1", // class
"Your Basic Window", // title
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0, 0, 400, 400, // initial x/y/width/height
NULL, // parent window handle
NULL, // window menu handle
hInst, // program instance handle
NULL); // creation parameters



如果上面没有设置WS_VISIBLE则需要手动调用ShowWindow来让窗口显示。
调用UpdateWindow触发WM_PAINT事件。
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;


5.主事件循环


while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}


非常简单。GetMessage是关键,用途是从事件队列中获得消息,保存到MSG结构中。
MSG结构包含了WinProc参数列表中的所有参数,之后调用TranslateMessage稍加处理
和转换,并通过DispatchMessage调用WinProc进行进一步处理。


一个给力的图示,包含了所有事件处理流程!


DSC0002.png



==============================================


2012年4月22日 更新


1.创建WNDCLASSEX时指定了类名为"WINCLASS1",之后注册它,并在创建窗体时指定了类名"WINCLASS1",
所以就会关联到WNDCLASSEX,并创建出它指定样式大小的窗体。而在创建其他预定义控件时,如按钮控件,
"button"类已经预定义并注册了,我们只需在调用CreateWindowEx指定类名为"button"。


2.GetMessage()和PeekMessage()的区别:它们都是从消息队列中取消息。当消息队列中没有消息时,GetMessage()
会阻塞当前线程,而PeekMessage()直接返回不会阻塞。并且PeekMessage()只取消息不从队列中删除,取出并删除
消息需要指定PM_REMOVE参数:PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)。


3.MSG结构:
  typedef struct tagMSG {
     HWND hwnd;   // window where message occurred
     UINT message;    // message id itself
     WPARAM wParam;  // sub qualifies message
     LPARAM lParam;   //sub qualifies message
     DWORD time;     // time of message event
     POINT pt;       // position of mouse
  } MSG;


MSG结构的前四个成员变量正是WinProc函数的四个参数。验证了WinMain主循环中GetMessage()取到MSG结构后,
调用DispatchMessage()从MSG中取出参数并触发WinProc进行进一步处理。


4.wParam和lParam在不同的消息中会保存不同的值。在按钮控件的消息中,msg为WM_COMMAND,LOWORD(wParam)
为子窗口ID(创建按钮时指定),HIWORD(wParam)为通知码(1 - BN_CLICKED,2 - BN_DOUBLECLICKED),lParam为
子窗口句柄。


  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-220800-1-1.html 上篇帖子: godaddy 2012年优惠码大全 godaddy域名优惠码 godaddy主机优惠码 下篇帖子: HOWTO install Hadoop on Windows
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表