天地之灵学习小组
我们学习小组的OpenGL学习笔记 大家一定要互相折磨呀~~
posts - 150,  comments - 156,  trackbacks - 0
天地之灵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
在很特殊的时候也许会连这两个也用不着 
 

FeedBack:
# re: 11月9日_猫很强大_By PureMilk
2008-11-09 22:16 | 陈梓瀚(vczh)
真有耐心……我都是直接翻msdn的那个条目,按字母排序看的……  回复  更多评论
  
# re: 11月9日_猫很强大_By PureMilk
2008-11-10 08:55 | 肖赫_王婷婷_王冠_郑燚_孙婷
@陈梓瀚(vczh)
恩猫确实很有耐心  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理



<2008年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

常用链接

留言簿(6)

随笔分类(149)

随笔档案(150)

同道中人

搜索

  •  

积分与排名

  • 积分 - 43779
  • 排名 - 486

最新随笔

最新评论

阅读排行榜

评论排行榜