随机矩形(PeekMessage函数)

出处:Windows程序设计 第五版 珍藏版 Page0162

 

  在任何一个图形系统中,总存在这样一个有趣的程序,即简单地使用随机的尺寸和颜色不停地绘制一系列图像,例如,随机大小和颜色的矩形。在Windows中可以创建这样的一个程序,但是这样并不像想象的那样容易。我希望你能够意识到,不能在处理WM_PAINT消息中简单地使用while(TRUE)循环。当然,这样做会奏效,但是这样做的结果是,程序将停止对其他消息的处理,而且程序不能退出或者最小化。

 

  一种可接受的方式是设置一个向你的窗口函数发送WM_TIMER消息的Windows计时器。(我将在第8章介绍计时器。)对每个WM_TIMER消息,可以调用GetDC函数获取设备环境,然后绘制一个随机矩形,接着调用ReleaseDC函数释放设备环境。但是那样做又会使程序失去一些趣味性,因为程序不能很快地绘制随机矩形。必须等待每个WM_TIMER消息,那样会依赖于系统时钟的精度。

 

  在Windows中有很多的“空闲时间”,在这期间所有的消息队列都是空的,Windows就在等待键盘或者鼠标的输入。那么能否在空闲期间从某种程度上获取控制并绘制随机矩形,而一旦有消息加载到程序的消息队列,就释放控制呢?这正是PeekMessage函数的“用武之地”。下面是PeekMessage函数调用的一个例子:

PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);

  函数的前4个参数(一个是指向MSG结构的指针,一个是窗口句柄,另外两个值表示信息范围)与GetMessage函数相同。设置第二、三、四个参数为NULL或者0,表示我们想使用PeekMessage函数返回程序中所有窗口的所有消息。如果要删除消息队列中的消息,可以把PeekMessage函数最后一个参数设置为PM_REMOVE。如果不想删除,就设置为PM_NOREMOVE。这就是PeekMessage名字的意思,它是“偷看”而不是“获得”。它允许一个程序检查程序队列中的下一个消息,而不是真实地获得并删除它看到的消息。

 

  GetMessage函数不把控制权交还程序,除非他从程序的消息列队中获得消息。但是PeekMessage函数总是立即返回,不管消息是否出现。当一个消息在程序的消息队列中时,PeekMessage函数的返回值是TRUE(非0),而消息则像正常情况一样处理。当队列中没有消息时,PeekMessage函数返回FALSE(0)。

 

  这允许我们替换正常的消息循环,正常的消息循环如下所示:

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

  替换之后的消息循环如下:

  while(TRUE){
      if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
          if(msg.message == WM_QUIT)
              break;

          TranslateMessage(&msg);
          DispatchMessage(&msg);
      }
      else{
          /*other program lines to do some work*/ 
      }
  }
  return msg.wParam;

  如果PeekMessage函数返回TRUE,那么消息会正常执行。如果返回FALSE,那么程序可以在返回给Windows控制之前做些事情(如显示另一个随机矩形)。

 

  (尽管Windows文档中指出不能使用PeekMessage函数从消息队列中删除WM_PAINT消息,但是这并没有什么问题。毕竟,GetMessage函数其实也不能从队列中删除WM_PAINT消息。使客户区的无效区域变成有效是从队列删除WM_PAINT消息的唯一办法,可以使用ValidateRect、ValidateRgn或者成对的BeginPaint和EndPaint函数来完成。如果使用PeekMessage函数从消息队列中获取WM_PAINT消息后,按照正常的方式对它进行处理,就不会有任何问题。但使用下面的代码来清除消息队列中的所有消息是不允许的:

  while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE));

  这条语句表示从你的消息队列中删除WM_PAINT消息之外的所有消息。如果WM_PAINT在队列中,你将永远陷于while循环无法终止。)

 

  PeekMessage函数在早期版本的Windows中比Windows 98中重要得多。这是因为16位版本的Windows使用非抢占式多任务系统(我将在第20章讨论)。Windows自带的Terminal程序使用PeekMessage函数循环检查从通信端口接收到的数据。打印机管理程序也使用这项技术来打印,其他的Windows打印程序通常也使用一个PeekMessage函数的循环。在抢占式多任务的Windows 98中,应用程序可以建立多个线程,详情可参见第20章。

 

  不管怎么样,有了PeekMessage函数,就可以使用这个函数来写不停显示随机矩形的程序。

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值