本人小菜,最近正在学习MFC,看有讲到windows消息机制,里面讲到:WinMain()里面会有一个循环从操作系统的消息队列中获取消息,然后在调用DispatchMessage(&msg)告知操作系统调用回调函数WndProc()处理消息;此处有一个比较幼稚的疑问,
为什么在消息发生时,操作系统不直接调用窗口的回调函数WndProc(),而要在应用程序WinMain()中获取消息->再告知操作系统调用回调函数?为什么不设计成这样:当消息或者事件发生时,操作系统直接调用某个窗口的回调函数,将消息作为参数传递给该回调函数处理呢?为什要WinMain()先用GetMessage()获取消息,再用DispatchMessage(&msg)通知操作系统调用自己的窗口函数呢?这样一来控制权岂不是由窗口发起,递交给操作系统,再递交给窗口(回调函数),绕了一圈?请高手详细解释一下,感谢!MFCwindows消息机制getmessage()
为什么在消息发生时,操作系统不直接调用窗口的回调函数WndProc(),而要在应用程序WinMain()中获取消息->再告知操作系统调用回调函数?为什么不设计成这样:当消息或者事件发生时,操作系统直接调用某个窗口的回调函数,将消息作为参数传递给该回调函数处理呢?为什要WinMain()先用GetMessage()获取消息,再用DispatchMessage(&msg)通知操作系统调用自己的窗口函数呢?这样一来控制权岂不是由窗口发起,递交给操作系统,再递交给窗口(回调函数),绕了一圈?请高手详细解释一下,感谢!MFCwindows消息机制getmessage()
修改窗口函数?你是说WndProc()?
可以改啊我想问的意思是窗口函数还是自己写,自己修改都行,但是由操作系统直接调用,不必由应用程序使用DispatchMessage()通知操作系统调用窗口函数;
其实问题的关键在于DispatchMessage到底干了什么
如果只是去调用相应的窗口,那自己写个switch不就可以了。DispatchMessage与switch不同之处在于DispatchMessage会先调用windows,进入管态(大概是range 0),然后再由windows调用窗口的函数。 为什么这么麻烦? 因为这样windows就可以知道你的程序运行到什么情况了, windows来调用你的窗口,这样你的窗口返回的时候windows就知道你已经处理过一个消息了,如果没有新的消息进入消息队列windows就不再会给你的进程分配时间片如果是你自己写switch的话,windows就不可能这样灵活的分配时间资源利用率就会降低;那么还要消息循环干什么,windows直接把消息发给窗口不就可以了吗?因为你要在消息循环里把KEY_DOWN和KEY_UP组合成WM_CHAR,还可以直接屏蔽掉许多对你来说无用的消息,加快速度。
==================================================”难道就是因为这些?没有其他原因么?求解释!!!
{
TraslateMessage(&msg);
DispatchMessage(&msg);
}WNDPROC ...典型的消息泵,系统参与工作的就只有GetMessage 这句,从系统那取到消息。然后DispatchMessage再分发消息到同一线程的各WNDPROC,真正是由DispatchMessage回调WndProc的。所以DispatchMessage在哪个线程,就相当于谁执行了WndProc。
我认为:Windows设计消息管理机制时,希望用面向对象的思想对消息进行封装(不是用面向对象的C++语法进行封装),使用的是不支持面向对象表达的C语言WIN16/WIN32 API接口。封装后的对开发者提出的强制要求就是:窗口类、窗口回调WNDPROC、消息循环GetMessage()处理Send的消息、消息派遣DispatchMessage()处理Post的消息。大家都按照这个标准来开发Windows程序。我想这也就是9楼说的一种设计思想。
TraslateMessage(&msg);
DispatchMessage(&msg);
}
这段代码保证了窗口过程,在用户程序的主线程里运行,这样对系统窗口过程的调用,才能保证在用户程序的地址空间和时间片里运行,如果系统自己调用窗口过程;
那么
1)用户程序,就没有办法控制程序的运行了。
2)程序占用了系统的时间片了。
3)用户地址空间和系统地址空间,没有办法分割了。
4)系统没有办法管理,用户程序的运行了。
GetMessage这个动作保证了,用户程序的消息不会堆积下来。
TraslateMessage(&msg);
DispatchMessage(&msg);
保证用户程序,能够正确处理窗口的消息。
有了这样一个消息循环,窗口程序就能不断的处理消息,保证用户程序的正确运行了。
我不理解你说的SendMessage/PostMessage是在什么场景下应用的?
你是说GetMessage/PeekMessage么?
能否详细讲解一下?
==================================================
DispatchMessage函数功能:该函数分发一个消息给窗口程序。通常消息从GetMessage函数获得。消息被分发到回调函数(过程函数),作用是消息传递给操作系统,然后操作系统去调用我们的回调函数,也就是说我们在窗体的过程函数中处理消息
==================================================这是度娘的原话,WinMain用DispatchMessage函数将消息传递给系统,操作系统调用回调函数!
你说不是系统调用WNDPROC?这我就迷糊了?还望详细解释!
没懂!我觉得你说的“发送消息和执行消息的两部分(两个函数或线程或窗口进程等等)彼此互相不需要知道对方是什么,这就是消息机制最大的优点”,这个我没有疑问,WinMain与WndProc是分开的,但是为什么消息发生时操作系统不直接调用WndProc?
针对你说的几点:
1)用户程序,就没有办法控制程序的运行了。——这个是说的WinMain中需要过滤一些消息这个控制动作?
2)程序占用了系统的时间片了。——那DispatchMessage函数将消息传递给系统,系统再去调用回调函数,这个动作不会占用系统的时间片段么?有什么区别?
3)这个更2)是一个道理吧?
4)这个也是由上面点造成的,暂且不谈把。综合起来看,你的观点就是,如果系统直接调用WndProc,则WndProc运行在系统的地址空间;而由WinMain调用DispatchMessage函数通知系统调用WndProc,则WndProc运行在WinMain的地址空间;可以这么理解么?但是为什么最后都是系统负责调用WndProc,到底有什么区别呢?
HOOK我就知道简单的挂钩原理,你的意思是说hook到消息后可以做一些处理、修改、过滤等等?有两点疑问,为什么要让应用程序能够hook到消息?这样有什么好处?这个有点扯远了。另外一个,WinMain与WndProc是同一个程序里,WinMain中能做的过滤、处理、修改等等,都可以放在WndProc中,感觉没必要在WinMain里获取消息,过滤、修改后再传给系统,让系统调用回调WndProc?
还望版主细讲!
我讲的也是由操作系统调用WndProc,没有与回调这个概念相悖吧?你强调回调什么意思呢?请细讲!
操作系统,只是为用户程序提供服务的,用户程序,才是真正完成工作的程序。操作系统,主要做以下工作。
1)管理用户程序。
2)为用户程序提供服务。具体执行的任务,实际上都是用户程序提供的。
像画图,NotePad这样的程序,实际上,是操作系统附带提供的,用户程序。
真正的系统内核,并不包含这些程序。
Cmd,explorer 则处于二者之间,是操作系统的外壳程序,实际上,用户程序也可以实现类似的功能。比如unix的,linux的各种shell。Windows 系统,各种驱动程序,处于系统内核位置,GDI,USER,Kenerl 三大模块,是系统的核心模块。
各种API,都可能有机会进入系统内核,从而唤醒内核调度程序。DispatchMessage是处理消息的核心API之一。如果应用程序不调用,这些API,没有办法在核心和用户状态之间转换。
系统直接调用的话,那就处于内核的地址空间,而不是用户的地址空间了。同样,也不处于用户的时间片了,用户线程,无法运行,这样系统程序到处跑,用户程序饿死,这个系统是无法正常使用的。系统是用来管理,维护用户程序,并为用户程序提供服务的,不能全速运行。系统程序,应该占用尽量少的时间,从而让用户程序,可以流畅的运行。