PALM开发教程-第十二章 专业编程技巧 |
| 作者:palmheart 来源:palmheart.net 发布时间:2005-12-21 3:39:54 |
|
Form( StartForm ); 这里引发了事件来装载StartForm。但我们的并没有一个叫StartForm的窗体,它在app.h中被定义为CalcForm。这就是我们使main.c可重用的另一个技巧。当我们需要改变开始窗体时,我们只需改变app.h,而不需在main.c中做大量的改动。 // Wait indefinitely for events ErrTry { while( true ) processEvent( -1 ); } // Stop the application ErrCatch( lError ) { } ErrEndCatch // Clean up before exit appStop(); // We're done return( 0 ); } 这段代码和我们前面接触到的事件循环代码基本相同,只不过循环中的函数调用是在一个单独的函数processEvent()里面。这样我们就可以控制事件在程序的其它部分是怎样进行的,在后面的章节中,你会发现它是如何做到这样的。 在ErrCatch()后,我们调用了appStop()。象appInit()一样,它是定义于app.h连接不同程序模块的一个纽带,在退出程序前清除程序参数。正如你看到的,甚至正常的程序也在这个catch模块中停止,所以appStop()应该在模块的出口处调用。 下面是我们的事件处理函数: //---------------------------------------------------------------------------- Boolean processEvent( //---------------------------------------------------------------------------- // Waits for and processes the next event. // Returns false if the queue is empty. //---------------------------------------------------------------------------- Long lTimeout ) // Time to wait in 100ths of a second, -1 = forever //---------------------------------------------------------------------------- { 注意引入事件中的时间控制参数,这在控制动画制作和声音的程序中很有用。由于Palm OS是一个单任务操作系统,为使程序的效果更好,我们就需要控制程序的运行时间。你也许想问为什么PilotMain()没有返回值而processEvent()却返回了一个布尔量。在以后的程序中(如在动画制作中),我们或许会想知道事件是怎样运行的以便于使动画更加平滑。这时我们就会调用processEvent()来处理或刷新其它的函数。 EventType sEvent; // Our event Word wError; // The error word for the menu event handler // Get the next event EvtGetEvent( &sEvent, lTimeout ); 这里定义了一些熟悉的变量,后面调用了函数EvtGetEvent()。注意,这个函数将我们的时间参数传递给了系统。 // If it's a stop event, exit if( sEvent.eType == appStopEvent ) { // Exit ErrThrow( 0 ); } 停止事件处理和以前相比有了些变化。它不只是向main()返回一个值,而是向mian.c中的ErrCatch()模块回馈了函数ErrThrow()。为什么我们不能象从前那样做了呢?如果我们在程序的其它地方调用了函数processEvent()并收到一个appStopEvent,它就不是向main()返回值,而是向其它的地方返回了一个值。所以我们就需要一个机制,不论在哪里收到了appStopEvent,错误处理器都会象C中那样安全。 // If it's a nil event, return queue empty if( sEvent.eType == nilEvent ) return( false ); 这是循环中一个新的检查措施。当事件队列为空时,Palm OS就会发出一个nilEvent。由于以前的程序中,我们让Palm OS一直的等待,我们就从来没收到过此事件。现在收到nilEvent后,我们就知道了事件队列是空的。在做一些耗时的工作时,如果调用processEvent来周期性的刷新事件队列,它就会派上用场。因此让它返回一个具体值是很重要的。 // Handle system events if( SysHandleEvent( &sEvent ) ) return( true ); // Handle menu events if( MenuHandleEvent( NULL, &sEvent, &wError ) ) return( true ); 以上是一些常用函数,我们用它们处理系统事件和菜单事件。 // Load a form if( sEvent.eType == frmLoadEvent ) { Word wFormID; // The form ID FormPtr spForm; // Points to the form // Get the ID wFormID = sEvent.data.frmLoad.formID; // Initialize the form spForm = FrmInitForm( wFormID ); // Establish the event handler FrmSetEventHandler( spForm, getEventHandler( wFormID ) ); // Point events to our form FrmSetActiveForm( spForm ); 这里是普通的窗体加载代码。你看起来肯定很熟悉吧,首先从事件结构(event structure)中获得窗体的ID,然后初始化并绘制窗体。然而要注意函数FrmSetEventHandler()中的getEventHandler()。这个函数定义在app.h中,可以根据支持不同窗体的模块,以相应的事件句柄获得相匹配的窗体ID,这就允许我们以相同的方式处理main.c中所有的窗体。因此这段代码是我们不必知道程序中到底有什么样的窗体,就可以重用这些代码来进行处理。 // Handle form events FrmDispatchEvent( &sEvent ); // We're done return( true ); } 这是processEvent()的最后一点。我们将余下的事件分配到活动的窗体中。如果的确还有事件没有处理的话,函数将返回true。 Main.h模块 头文件main.h中有支持main.c的定义,并且有为了自定义main.c而在app.h中添加的函数定义。创建一个main.h文件放入源文件中,将之加入Calculator工程并保存在AppIncludes中。下面是它的详细代码: #ifndef MAIN_H #define MAIN_H ////////////////////////////////////////////////////////////////////////////// // main.h // Definitions for the main entry point. // Copyright (c) 1999, Robert Mykland. All rights reserved. ////////////////////////////////////////////////////////////////////////////// /////////////////////// // Global Prototypes // /////////////////////// DWord PilotMain( Word, Ptr, Word ); // Main entry point. Boolean processEvent( Long ); // Processes the next event. /////////////// // Constants // /////////////// // The different versions of PalmOS // Pilot 1000 and Pilot 5000 #define ROM_VERSION_1 0x01003001 // PalmPilot and PalmPilot Professional #define ROM_VERSION_2 0x02003000 // Palm III, III |
| [] [返回上一页] [打 印] |
|
文章评论 |
