天地之灵16:11:17
然后呢,说一个最最最特殊的消息
天地之灵16:11:21
WM_QUIT
孙婷16:11:22
?
天地之灵16:11:36
这是唯一一个跟窗口没有关系的消息
天地之灵16:11:44
它表示:这个程序要结束了
天地之灵16:12:14
那么,最外面我们一开始那个循环,就应该结束了
天地之灵16:12:39
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
和
while( true )
{ GetMessage(&msg,NULL,0,0));
TranslateMessage(&msg);
DispatchMessage(&msg);
}
回到婷婷刚才的问题
天地之灵16:13:11
GetMessage的作用就是:等待一个消息。如果这个消息是WM_QUIT,那么返回FALSE。否则返回TRUE
wtt PureMilk16:13:52
明白
天地之灵16:13:54
所以它们的区别就是,前面一个是标准的,当收到WM_QUIT消息的时候,循环结束,正常退出程序。
而后面那个,因为不能接受WM_QUIT消息,所以永远不会结束
天地之灵16:14:40
WM_QUIT的作用糖糖明白了吗
wtt PureMilk16:14:52
等一下又不明白了
天地之灵16:14:57
孙婷16:15:08
恩呢
天地之灵16:15:16
哪里不明白了
wtt PureMilk16:15:30
在我们的WindowProc里面是不会出现WM_QUIT的是吗
天地之灵16:15:37
是的。
天地之灵16:15:43
WM_QUIT是唯一一个与窗口无关的消息
wtt PureMilk16:15:44
那它是怎么来的呢
孙婷16:15:52
WM_QUIT。。是不是就相当于我按下esc或者alt+f4的时候然后处理消息就推出了。。关了窗口了
天地之灵16:15:56
它的来源是PostQuitMessage函数
天地之灵16:16:05
糖糖:不完全是。
wtt PureMilk16:16:09
啊我知道了
天地之灵16:16:18
其实,当你按下Alt+F4的时候,分为三个步骤
wtt PureMilk16:16:20
case WM_CLOSE:
if(IDYES==MessageBox(hwnd,"是否真的结束?","weixin",MB_YESNO))
{
DestroyWindow(hwnd);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
天地之灵16:16:35
1、系统发出WM_CLOSE,表示用户试图关闭窗口
天地之灵16:16:49
当然,这时候你可以弹一个提示确认一下
wtt PureMilk16:16:57
MessageBox(hwnd,"是否真的结束?","weixin",MB_YESNO))
天地之灵16:17:13
2、DestroyWindow,真的关闭窗口,发出一个WM_DESTORY
天地之灵16:17:32
3、如果这个窗口关闭就意味着程序结束,那么处理函数里发出一个PostQuitMessage
天地之灵16:17:42
然后GetMessage返回FALSE,程序结束
wtt PureMilk16:18:06
彻底明白
孙婷16:18:36
太神奇了
天地之灵16:18:52
好,还有两个内容,第一节课就结束了
天地之灵16:19:07
内容1是:DefWindowProc
天地之灵16:19:32
实际上系统发出的消息非常非常的多,种类十分十分复杂
天地之灵16:19:40
而我们实际上只关心我们需要关心的消息
天地之灵16:19:56
而对于我们不关心的消息,如果我们不做处理,有时候就会出问题
天地之灵16:20:12
比如
case WM_CLOSE:
return;
窗口就关不掉
天地之灵16:20:33
对于这一类消息,我们通常是希望让Windows帮我们处理
天地之灵16:20:42
换句话说,“一般的窗口应该怎么做,就怎么做”
天地之灵16:20:53
这就是DefWindowProc的作用
天地之灵16:21:08
举例来说,它会在WM_CLOSE的时候自动DestoryWindow
wtt PureMilk16:21:15
真的耶
wtt PureMilk16:21:22
原来还是关掉了
天地之灵16:22:22
另外,DefWindowProc也是一个标准的WindowProc
天地之灵16:22:53
换句话说,如果你什么消息都不想自己处理,你可以直接把DefWindowProc作为窗口类的WindowProc
天地之灵16:23:25
内容2:PeekMessage
天地之灵16:23:39
我们知道GetMessage的意思是“等着一个消息的发生”
天地之灵16:23:57
而我们在还没有消息发生的时候就什么也不能做了
天地之灵16:24:36
而对于游戏来说,我们要求在没有消息发生的时候,不断地重新画整个画面
天地之灵16:25:01
所以我们不能被GetMessage占住
wtt PureMilk16:25:15
有道理
天地之灵16:25:21
PeekMessage的意思是:
如果有消息需要处理,返回TRUE,否则返回FALSE
天地之灵16:26:07
另外它的参数有很多种,比如这个被取出的消息是否从消息队列中清除
天地之灵16:27:21
所以,我们可以写
while (true)
{
if (PeekMessage(xxxx, xxx, PM_REMOVE))
{
Tranlate
Dispatch()
}
else
{
doSomething();
Sleep(0);
}
}
天地之灵16:27:43
Sleep(0);的目的是让出CPU控制权,使得其他程序可以流畅运行,详细的内容以后再讲解
wtt PureMilk16:28:03
耶,那岂不是又像我刚写的那样关不掉了
天地之灵16:28:12
是的
天地之灵16:28:29
PeekMessage的一个不同的地方就是,它收到WM_QUIT时不会做什么特殊处理
天地之灵16:28:40
我们要自己来做这个处理
天地之灵16:28:57
while (true)
{
if (PeekMessage(xxxx, xxx, PM_REMOVE))
{
if (msg.message == WM_QUIT) break;
Tranlate
Dispatch()
}
else
{
doSomething();
Sleep(0);
}
}
天地之灵16:29:56
另外,我读过的代码里,有许多程序没有这个else。婷婷能分析下这样会有什么不好么?
天地之灵16:30:16
while (true)
{
if (PeekMessage(xxxx, xxx, PM_REMOVE))
{
if (msg.message == WM_QUIT) break;
Tranlate
Dispatch()
}
doSomething();
Sleep(0);
}
他们这么写
wtt PureMilk16:30:24
cpu占用率比较高?
天地之灵16:30:29
不是
天地之灵16:30:34
仔细想想
天地之灵16:31:13
答案是,这样的代码每次只能处理一个消息
天地之灵16:31:19
然后就进入了doSomething
wtt PureMilk16:31:44
哦……
天地之灵16:31:47
1、如果doSomething是个非常慢的函数,比如渲染图形,那么对消息的处理也会很慢很慢
wtt PureMilk16:31:56
知道了
天地之灵16:32:02
积压的消息不能及时处理,就容易被windows认为没有响应
wtt PureMilk16:32:04
啊好有意思啊
天地之灵16:32:14
2、最坏的情况,如果doSomething里每次都发出了一个消息
天地之灵16:32:30
那么消息就永远处理不完了,最后程序就会出现错误
wtt PureMilk16:32:38
嗯~
wtt PureMilk16:33:02
哇猫我自己学的话要学多久才能明白这一点哦
天地之灵16:33:19
while (true)
{
if (PeekMessage(xxxx, xxx, PM_REMOVE))
{
if (msg.message == WM_QUIT) break;
Tranlate
Dispatch()
}
else
{
doSomething();
Sleep(0);
}
}
while (true)
{
while (PeekMessage(xxxx, xxx, PM_REMOVE))
{
if (msg.message == WM_QUIT) break;
Tranlate
Dispatch()
}
if (msg.message == WM_QUIT) break;
doSomething();
Sleep(0);
}
这两段代码却是等价的
天地之灵16:34:05
第二段代码里把if改为了while,意思就是:把所有的消息处理完,然后才做我想做的事情
wtt PureMilk16:34:24
嗯~~明白
天地之灵16:34:39
另外,if/while (PeekMessage(xxxx, xxx, PM_REMOVE))
{
if (msg.message == WM_QUIT) break;
这个比较有时候比较讨厌,我们可以更“优雅”的来写
wtt PureMilk16:35:00
怎么个优雅法?
天地之灵16:35:23
if/while (PeekMessage(xxxx, xxx, PM_NOREMOVE))
{
if (GetMessage(xxx, xxx))
{
Tranlate
Dispatch
}
else
break;
wtt PureMilk16:35:50
wow
天地之灵16:35:55
注意PeekMessage的参数变为了不移出
天地之灵16:36:03
然后继续利用GetMessage的返回值
孙婷16:36:18
这样有什么好处呢?
天地之灵16:36:23
比较帅
wtt PureMilk16:36:25
漂亮
孙婷16:36:27
- -0
天地之灵16:36:30
这个技巧我是在我遗留的早期代码里学到的
孙婷16:36:31
很好
天地之灵16:36:37
我已经忘记早期的我在哪里学到的了
wtt PureMilk16:36:40
是很漂亮,漂亮多了
天地之灵16:37:25
天地之灵16:37:36
关于消息、消息循环的所有内容都已经讲完了
wtt PureMilk16:37:58
猫我好崇拜你喔
天地之灵16:38:14
孙婷16:38:24
哇卡卡卡~~~我今天会失眠。。
wtt PureMilk16:40:58
天地之灵(402740419) 16:22:53
换句话说,如果你什么消息都不想自己处理,你可以直接把DefWindowProc作为窗口类的WindowProc
这句话的意思是,什么消息都自己动手写代码吗
天地之灵16:41:09
不是
天地之灵16:41:23
如果你想写一个“非常标准”的窗口,什么消息你都不需要知道
wtt PureMilk16:41:24
那是什么都不自己动手写
天地之灵16:41:32
对,你就可以什么都不写
wtt PureMilk16:41:45
哦哦哦我明白了
孙婷16:41:47
为什么呢?
wtt PureMilk16:41:49
看错了
孙婷16:42:12
自己写的和标准窗口是不一样的么?
wtt PureMilk16:42:16
就是连WindowProc都不要了对吧
天地之灵16:42:18
恩
wtt PureMilk16:42:28
谁的恩?
孙婷16:42:33
那我怎么在这个窗口做什么啊。。
天地之灵16:42:33
恩婷婷的
天地之灵16:42:54
有时候就什么也不做啊
天地之灵16:43:19
一般在游戏里写WindowProc就是为了一个WM_CLOSE一个WM_DESTORY
天地之灵16:43:28
在很特殊的时候也许会连这两个也用不着