[手札]VC++开发(1 - 线程和消息相关)



MsgWaitForMultipleObjects Function

MSDN: Waits until one or all of the specified objects are in the signaled state or the time-out interval elapses. The objects can include input event objects, which you specify using the dwWakeMask parameter.
To enter an alertable wait state, use the MsgWaitForMultipleObjectsEx function.

微软提供了一个MsgWaitForMultipleObjects函数,该函数的特点是它不但可以等待内核对象,还可以等消息。也就是当有消息到来时,该函数也一样可以返回,并处理消息。

一般用法如下:

       while (TRUE)
       {
              dRet 
=  ::MsgWaitForMultipleObjects( 1 , m_hThread, FALSE, INFINITE, QS_ALLINPUT);
              
if  (dRet  ==  WAIT_OBJECT_0  +   1 )
              {
                     
while  (PeekMessage( & msg,NULL, 0 , 0 ,PM_REMOVE))
                     {
                            TranslateMessage(
& msg);
                            DispatchMessage(
& msg);
                     }
              }
              
else
              {
                     
break ;
              }

       }


SendMessage,SendMessageTimeout,SendMessageCallback,SendNotifyMessage和ReplyMessage

1. SendMessage未返回后,发送消息的线程是否可以处理其他的消息?

程例01

创建一个窗口,再创建两个Work Thread。第一个Thread先SendMessage给主窗口,主窗口弹出MessageBox即可(阻塞)。第二个之后SendMessage给主窗口,主窗口依然可以处理消息(例如再次弹出一个MessageBox)。

程例02
创建一个窗口,再创建两个Work Thread。第一个Thread先SendMessage给主窗口,主窗口while(1) ::Sleep(0);。第二个之后SendMessage给主窗口,主窗口无法处理消息。

 

程序例子3

程序例子4


 

消息循环全过程

GetMessage(PeekMessage)会检查消息队列状态标志,首先检查QS_SENDMESSAGE(或许由DWORD GetQueueStatus(UINT)来获取这个状态标志是否被设置),GetMessage会在函数内部处理(或许是主动CallWindowProc罢),而不返回,向相应的窗口过程发送消息后,继续等待其他要处理的消息。

然后检查QS_POSTMESSAGE标志,如果被设置,函数(/*GetMessage*/)返回TRUE,通常是DispatchMessage去分发消息。

接下去检测QS_QUIT设置,如果有则关闭QS_QUIT,GetMessage返回FALSE。

再接下去是检测QS_INPUT,包括键盘和鼠标消息,如果队列中没有键盘消息了,则关闭QS_KEY,没有鼠标按键消息了,就关闭QS_MOUSEBUTTON,最后没有鼠标移动消息了,则关闭QS_MOUSEMOVE标志,而GetMessage返回TRUE。

最后分别是处理QS_PAINT和QS_TIMER,这两种消息处理的逻辑相对复杂。

QS_PAINT标志的处理与此不同。如果线程建立的一个窗口有无效的区域,QS_PAINT标志被设置。当这个线程建立的所有窗口所占据的区域变成无效 时(通常由于对ValidateRect、ValidateRegion或BeginPaint的调用而引起),QS_PAINT标志就被关闭。只有当线 程建立的所有窗口都无效时,这个标志才关闭。调用GetMessage或PeekMessage对这个唤醒标志没有影响。【《Windows核心编程》】

该线程建立的定时器报时的时候,QS_TIMER会被设置,GetMessage和PeekMessage返回TRUE,产生WM_TIMER消息,直到下一次定时器报时。


 

 

非Active窗口点击失效

如果有一个窗口,它并没有Active,你想关闭它,直接点击右上角的x即可。但是有时候,我们会模拟按钮,例如用几张位图模拟一个Button,当窗口非Active的状态时,你直接点击它,它就收不到LBUTTONDOWN的消息。可以这么解决这个问题。

简单说来就是利用MouseMove消息,来进行SetCapture/ReleaseCapture。

(完 )

 

消息队列消息和窗口过程消息

消息有两种,一种投递到消息队列,你可以用GetMessage/PeekMessage来获取到,另外一种是直接发送到窗口过程的,比如WM_ACTIVATEAPP。

MSDN会这样写: A window receives this message through its WindowProc function。

事情是这样的:  

我想手工处理 WM_LBUTTONDOWN,WM_LBUTTONUP,和WM_LBUTTONDBLCLK,于是在处理UP消息后,PeekMessage(, NULL),但是根本获取不到(注意我第二个参数为NULL)

于是我下了结论是 WM_LBUTTONDBLCLK 走窗口过程,而不是消息队列。【MSDN里面也是这么说的哦】

但是 PeekMessage的第二个参数改为当前窗口的句柄,就可以获得了。这怎么解释呢?

----嗯,貌似还是走窗口过程的,因为我注释了DispatchMessage( &msg );... 难道发现个技巧(怎么Peek到窗口过程消息)?。。。 。。。

 

 

 

转载于:https://www.cnblogs.com/healerkx/articles/1829052.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值