当前位置:C++技术网 > 资讯 > Windows消息机制通俗理解

Windows消息机制通俗理解

更新时间:2015-06-07 18:10:15浏览次数:1+次

    Windows系统编程,最基本的就是消息机制。而消息机制如何运转,很多初学者其实总是摸不着头脑,说不懂其实也知道些,说懂呢,说起来又说不出什么,就是这中似是而非的感觉,让很多初学者对Windows消息机制产生畏惧感。我刚开始学习Windows时,看到消息机制,就晕了。那一套机制逻辑从来都没听说过,虽然之前写过不少控制台程序,但是对于Windows确实从未接触。因此,刚开始学时,看着那些名词就有点恐惧,对于消息机制也就先熟悉一下。
    到目前,不说很透彻,至少,消息机制还是比较清楚了。现在想起来,脑子里就有了整个消息机制的整体的理解。所以,以自学者的角度,中间穿插我个人的理解,让初学者可以从容的熟悉并掌握消息机制。
    所谓消息机制,重点就是消息。那么什么是消息?消息说白了,就是一个信息,一个信号。比如小明喊了一声你的名字,你就有反应了。那这一个叫喊,就是一个信号,使你产生反应。而你所做的反应都是根据这些信号来处理的。比如小明叫你借他一只铅笔,你的反应可以是借或者不借。你的反应就是对这个信号的处理。你的处理结果可能是借给了他一只笔,递给了他,或者告诉他你正在用,不能借。
    我们接触的一切都是消息进行驱动的,这只是一个类比。我们饿了,前方有车,等等,只要你接收到了这些信号,你就会进行处理或者忽略,忽略其实就是默认处理。微软的Windows就是借助于这种模式,将这种模式应用在系统上的。经过多年的时间的考验,Windows系统确实做的还不错。消息机制的合理,让系统很健壮。            
     上面通俗的解释,或许你有点明白,或许根本还是云里雾里。因为没有和Windows计算机结合起来,好像这个道理懂了,但是用在Windows上却还是不清楚。所以接下来,就类比生活经验,来解释Windows系统的消息机制。不要觉得这种解释方法怪异,其实这是按照事物的自然发展规律的学习。Windows不是凭空出现的,消息机制也不是做一个梦就造出来的,而这些东西的产生,就是源于生活经验的抽象和总结,总结的越好越完整,就能够更好的应用到各方面。所以我们以这种方式去解释应该是最科学的。多数人都是直接就解释什么是消息机制,直接就是Windows,对于从没接触过Windows编程的人来说,不仅是技术的挑战,更是心理的挑战。这里不要觉得是废话,沉下心,仔细理解这些话以及这些话的对你认识观的启发。我们从事物的发展根源开始看,一切就自然也好懂。
    到此,消息,我想,本身代表的意义,相信大家也理解了。那么现在来看看Windows里的消息究竟是什么?
    Windows是视窗操作系统,以屏幕键盘鼠标等作为人与计算机的接口。所谓的接口,就是大家常见到的人机接口,通俗讲,就是一个交流的桥梁。有人认为,人与计算机怎么算是交流,计算机就是一个机器而已。其实这样理解就不准确了。计算机确实是机器,但是机器有机器的运转逻辑,它有它的生活,请把它看作是一个有生命的东西来对待,只不过它非常听命与你,有点奴隶的味道。不过,不要想多了,有时候它也很霸道,说罢工就罢工。你作为人,它作为计算机,作为两个可以独立运转的个体,你要它帮你干活,你就必须让它知道你要求它干什么。小明叫你借铅笔,他不跟你说,或者用其他方式让你知道,你不会知道有借铅笔这回事。类比来看,你要计算机帮你干活,你就必须让它知道你要它干什么。小明跟你借铅笔,就是说了一声,这个声音就是一个消息,让你知道了。你让计算机知道,你只有通过鼠标键盘等来告诉它。而这些操作,比如单击鼠标,按下键盘,这些都是你给计算机的消息。计算机就得到了你的消息,然后再看看这些消息它想不想处理,或者怎么处理。这是硬件级别的消息。软件级别的消息,比如单击了窗口的关闭按钮,或者拖动了窗口等等,这些都会产生消息,告诉计算机你的动作,然后它进行响应处理。这样就完成了一个消息传递和消息处理的过程。这就是人机交互。
    消息机制其实就是这么一回事:你获取了一个消息,然后你对消息进行处理,返回处理结果。或者你也给别人发一个消息,别人根据你的消息进行处理,返回处理结果。你的动作是根据消息的类型以及消息附加的信息来区别处理的。没有消息你就什么也不做,有消息了你就处理。你就像一个大懒汉一样,没人找你就一直睡觉,有人找你了就起来干活。要让你干活,就需要有人找你,找你就是给你消息,或者说是一个任务消息。有了任务就开始干活了。就这么一个逻辑过程,就是消息机制。因为是有消息才会有所动作,所以也叫做消息驱动,驱动就是驱赶你产生动作的意思,消息驱动就是消息让你产生动作。Windows消息机制也不就是如此。
    我想,看到这里,什么是消息,什么是消息驱动,应该是懂了的。我并没有给你精确的定义,目的是让你思考,深入理解。
    现在,就来说说Windows消息机制,从控制台程序说起。因为初学者基本上都是从控制台程序学起的。对于程序的逻辑也是基于控制台的。系统的发展也是这样发展的。控制台程序是单一任务的,因此它的执行是严格按照程序逻辑进行的。把整个逻辑走完,程序就结束了。它也是单线程的,当然这是说的一般的程序。而学习Windows,却发现,程序执行思路完全不一样了,是基于消息机制的。控制台的程序好理解就是一个单线的逻辑思路,一根线走到底,没什么难得理解的。而Windows程序的逻辑是基于消息,没有单线的逻辑,因为一个用户的操作按照什么逻辑你不可能预测。就算你只有一个按钮,也是不能预测的,因为用户可以单击按钮,还可以直接关闭,或者移动窗口等等。所以控制台的那种单线逻辑根本就不能适应这种要求了。因此,微软借助于生活中的消息机制,进行抽象建模到操作系统中,就形成了Windows消息机制。这就能够满足了要求。但是一个程序始终是从头到尾的,程序还是没变,但是逻辑思路改变了,程序如何适应这种新要求,就得想办法了。光靠消息驱动,是不能满足的。消息从哪来,到哪去,如何维持一个程序持久的运转,知道使用者要它停止为止。各种各样的消息,如果直接是原始的又能不能直接处理。既然是采用了消息驱动,那么在Windows中的动作,都是消息。比如面向对象思想中,一切都是对象,文件系统中,一切都是文件,诸如此类。能够把这些消息正确的处理,完成一个良好的消息生态系统,这就是消息机制。消息驱动只是消息机制的一个基本理论,要使消息真正运作起来,是要下一番苦功夫的。微软操作系统是从DOS系统慢慢发展起来的,因此,也就会想办法将DOS演变成Windows,所以就是在Dos程序或者叫做控制台程序上做文章。
    在控制台程序中,要想一个程序永久运行,只有一个办法,那就是让它进入循环,不满足条件就不退出,这样就保持程序在没满足条件之前一直运行。而Windows程序,不是控制台类型的,除非用户发送了关闭消息,否则就不退出,当然这是正常情况下的。如果出错,系统会终止运行。也就是说,关闭与否,不是程序本身能够控制的,如果用户不关闭,就必须一直运行。微软想在控制台程序的基础发展,就只有一个办法,就是上面说到的方法 -- 循环。而这个循环用什么作为判断条件,显而易见,作为消息驱动的程序,当然是消息作为判断条件。这就是消息循环。循环得到了终止循环的消息就退出循环,然后程序就很快执行完毕了。而退出循环,其实就是使条件为假,而Windows系统是使用C、C++编写的,自然就遵从它们的习惯,0为假,非0即为真,所以,终止程序的消息就是0,而通常见到的消息就是WM_QUIT。这就是一个宏而已,就是这样的一个定义语句:#define WM_QUIT 0.所以说,什么是消息循环,我想你应该很明白了。其实就是用消息作为循环判断的循环,就是消息循环。
    那么消息从哪里来,到哪里去,消息如何处理?这些就是消息机制的其他几个部分。
    消息自然是从消息产生的地方来,比如键盘鼠标等“硬消息”,或者是程序中产生的单击菜单等“软消息”,这些硬消息就是原始消息,软消息就是转换后的消息。有的硬消息可以直接处理,有的则不可以。所以消息产生的原因是用户要告诉计算机它要干什么,消息的最根源就是使用者,是人。人机交互,就是将这个消息发给了计算机,否则计算机不知道你要它干什么。键盘等产生的消息,只不过是人的命令的一个传达方式,属于中间过渡消息,这个是一级过渡消息,比如单击键盘,计算机可以直接处理,但是组合键或者快捷键等计算机不一定认识,所以这种消息需要进行转换成特定的消息,比如CTRL+ALT+DEL的组合,转换成特定的命令,计算机才知道是什么意思。再比如拖动窗口,你单击窗口后拖动鼠标,鼠标的消息是鼠标移动,但是跟窗口移动有什么关系呢,是需要进行转换的,因此就有了窗口位置变化的消息,当然这个是粗略的描述,并不准确,只是助于理解。这些消息就这样的产生了,到了计算机那里。但是到底到了哪里呢?
    计算机的运行基本单位是线程,所以当然是去了线程那里。当然也有不进入线程的。所谓去线程那里,是要排个队的,因为会有很多的消息去线程那里报到,先来后到,不能乱来。有些特别紧急的消息就不一样,不排队了,就直接去处理了。
    消息如何处理?Windows程序,一般的都是有窗口的,当然也可以没有窗口。接受消息的就是窗口了。每个窗口都会有一个专门处理消息的地方,对于窗口的任何一个动作,都会以消息形式送到窗口处理消息的地方,所有消息都是在这里处理,无一例外。所以你见到的Windows程序都是消息和消息处理,你所要做的就是在这里对消息进行匹配,然后进行相应的处理。比如用户产生了一个关闭窗口的消息,关闭窗口不等于退出了程序,是不是真要退出程序,还是由程序员来决定。如果你让它真的退出,你就发送一个终止程序的消息,也就是上面说的WM_QUIT,其实就是一个0给循环,让循环退出就可以了。当然你接受到一个消息,你还可以发送一个消息,然后线程里又会得到一个消息。
    现在就是到目前为止,消息怎么产生,谁产生,到哪去,怎么被处理都清楚了,但是还有一个问题,消息到了线程了,那消息又怎么到处理的地方。这还有一个环节没有连起来。所以,在这之间就还有一座桥梁。
    这座桥梁就是消息的获取、转换和分派。那这个过程放在哪合适呢?仔细想想,消息是源源不断的,也就是说,消息的处理也是源源不断的,消息产生是不确定的,但是一旦产生就会传送到线程那,那叫做线程队列。然后就是要一个源源不断的消息的获取,转换和分派。类似于快递,货物到了货运中心,如果不分派走,就会出问题的,因为货运中心只是临时的存放而已。消息也是,线程队列也只是个临时的地方,消息始终要到被处理的地方才算完。而要源源不断的将消息保持通畅,也就必须放到循环中了。所以,消息循环一方面可以让程序保持运行,另一方面还可以源源不断的让消息流动起来。循环里到接受了很多消息的线程队列里取出消息,如果需要则对取出的消息进行转换,转换好后就再把消息发送至处理消息的地方,消息处理的地方叫做窗口过程。因为这些消息都是跟窗口相关的,也只有窗口才会接受消息,所以就叫做窗口过程。
    那么到此,整个消息机制就将清楚了。总的来说,消息机制就是描述的消息的生死因果,从产生到传递到处理到结束的一个过程。随着消息循环的结束,程序就结束,消息就停止了。程序的动作都是根据消息来产生的,不同的消息产生不同的动作,最后完成特定的功能,完成使用的人的任务,这样就完成了人机交互。