Windows应用程序至少有一个窗口,称为主窗口。Windows应用程序通过窗口和外界交互,是一种基于消息、事件驱动的设计模式,每个窗口对应一个窗口过程函数,负责对交互信息进行处理。应用程序的设计者可以根据需要设计窗口的特征。所以Windows应用程序的设计过程如下:
l 设计一个窗体类。指定该类窗体的特征,例如是否显示最大化/最小化框,指定窗口过程函数的地址(即指定窗体过程函数的名称)
l 注册窗体类。只有注册了该窗体类,后面创建窗体类对象时,系统才知道该窗体的特征。窗体类对象涉及到与系统的交互,所以需要向系统登记该类类型,而不是简单的设计类,创建对象。
l 创建窗口类对象。
l 显示并更新窗口类对象。窗口类对象创建之后,只是在内存中存在该对象,想要显示出来还需要调用其显示函数。一开始窗体类对象的界面属于无效状态,调用更新函数使其有效。当窗体部分或全部被挡住时,被挡住的部分就处于无效状态,想要再次显示需要更新之。
l 进行消息循环。即开启一个死循环处理应用程序中窗口的消息,即根据消息调用窗口过程函数。当窗口销毁时跳出该死循环,结束应用程序。
Windows应用程序设计的关键是窗口过程函数的设计。
Windows应用程序的关键就是消息循环部分,借由消息队列存放捕获到的消息,然后循环从消息队列中取出消息进行处理。其消息处理过程如下:
l 操作系统接收到应用程序的窗口消息,例如捕获到用户在窗口单击鼠标左键事件,将消息投递到该应用程序的消息队列中;
l 应用程序在消息循环中调用GetMessage函数从消息队列中取出一条一条的消息。取出消息后,应用程序可以对消息进行一些预处理。例如,对于操作系统,鼠标按下和鼠标抬起分别对应LButtonDown和LButtonUp两个消息,应用程序将这两个消息处理为一个鼠标单击消息。
l 应用程序调用DispatchMessage,将消息回传给操作系统。
l 操作系统利用消息中包含的窗口过程函数指针调用窗口过程,对消息进行处理。
上述过程是一般的消息处理过程,其实消息又分为两类:进队消息和不进队消息,上述过程是进队消息的处理过程,不进队消息是操作系统捕获到消息后直接调用应用程序的处理过程,而不放入消息队列中。
个人认为,进队消息应该是需要预处理的消息,因为最后还是回到操作系统,由操作系统调用窗口过程函数进行处理。至于为何非要回到操作系统,个人理解也和进队/不进队有关,因为有的消息不进队则直接由操作系统调用处理函数,所以进队的消息也统一再回到操作系统,由操作系统调用处理函数。所以在这里可以看出,程序员设计的窗口过程函数不是由应用程序调用,而是由操作系统调用,所以该函数类型为回调函数,即函数的调用方和函数的设计方不是同一人。