从Turbo Vision源码看事件驱动(1)
1:缘起在传统的程序中,一个具有交互功能的应用程序的主体无疑是如下的一段循环代码:不断读取用户的输入,根据输入采取相应的动作,完成所需的功能。例如:bool quit=false;char ch;while(!quit) { ch=read_input(); switch(ch) { case 'i': // ... … break; case 'q': quit=true; // … … break; default: // ... … } }而基于事件驱动机制的程序则不大相同,主程序可能如下这般:int main(){ TMyApp myApp; myApp.run(); return 0;}在整个程序中,唯一与事件有点关系的要属handleEvent函数了,它可能并不像你我想像的那样(注:以Turbo Vision中的应用程序为例,根据类的继承关系,函数的调用序列依次为:TMyApp::run() TApplication::run() TGroup::execute() TMyApp::handleEvent() 来处理事件):void TMyApp::handleEvent(TEvent& event) { TApplication::handleEvent(event); // act like base! if( event.what == evCommand ) { switch( event.message.command ){ case cmMyNewWin: // but respond to additional commands myNewWindow(); // define action for cmMyNewWin break; default: // … … return; } clearEvent( event ); // clear event after handling }}从这里,我们明显可以看到一份简单,一个鸿沟:没有了令人头疼的循环,程序中的对象只需要处理自己收到的事件,程序的结构变得异常简单清晰;但也正是这份简单,让本来清楚明白的流程变得神秘起来,没有了读取用户输入,摆放在面前的已经是送到的事件,这多少有点让人措手不及,前面的路是谁铺就的?一切的一切,都缘起于事件驱动机制:读取了用户的输入,并把其包装成事件,然后按照一定的规则分发给不同的对象;正是它,造就了简单,也成就了神秘;有了它,用户才可以把所有的精力集中于事件的处理上,而不用分心其他琐事。例如:在一个非活动窗口上按下鼠标左键,用户只需确保该窗口在接收到该消息时,能够把自己调到前台,正确地显示即可。在鼠标轻点与窗口响应之间,系统在幕后默默地做了许多事情:读取鼠标的动作并形成的事件,按照一定的规则把事件发送给该非活动窗口。