PalmOS开发教程-2.2
步骤如下:
1. 运行Palm上构造器,这是Metrowerks的资源编辑器。在Code Warrior中也会发现相同的菜单;
2. 选择File | New Project File。这样将产生一个空的资源文件。现在的工程属性取缺省就行了,在下面的章节会详细讲到它们还能做什么;
3. 改变Application Icon Name为工程名称“Hello”;
4. 在Resource Type and Name列表箱里选中Forms行;
5. 选择Edit New Form Resource或者按CTRL-K创建一个新的窗体。新窗体将出现在Forms行并被命名为“untitled”;
6. 单击name,出现编辑框后,取名字为“Hello”;
7. 双击窗体打开,在下面的章节中将详细的讲解这些属性的意义并论述它们如何使用;
8. 选择Window | Catalog或按CTRL-Y打开控件工具箱;
9. 拖动一个按钮至窗体的中心。现在按钮的属性将代替窗体的属性出现在窗体对话框的左边。这些属性缺省就可以了,以后将详细讨论它们。你如果十分渴望改变按钮的位置的话,你可以改变L eft Origin 和Top Origin属性;
10. 单击Label属性,将其名称由OK改为Hello;
11. 单击右侧的面板,重新得到窗体属性;
12. 选择Layout | Hide Object Ids。这将使你确实看到写有“Hello”的按钮。如果“Hello”看起来字体比较大,这是因为你遇到了我在安装部分讲到的古怪字体问题。为解决这个问题,关闭构造器,打开W indows文件夹中的Fonts文件夹,然后重新打开构造器。你的“Hello”窗体将如图2-5所示;
13. 选择Fiel | Save保存工程资源。将其保存在Hello工程文件夹的Src子文件夹下面。并命名为hello.rsrc。
14. 当你完成你的新工程后,下一步该涉及到总工程。资源工程是总工程的一部分,总工程将包括所有有关用户界面的图形描述的各个方面,例如:大小、布局及窗体和控件的外观等;
15. 再次打开Code Warrior集成开发环境,选择File | Open Recent | hello.mcp;
16. 选择Project | Add Files。置文件类型为“All Files”以便能看见的资源文件。找到hello.rsrc打开;
17. 这时资源文件会出现在工程的顶部。为简洁起见,把它拖到应用程序(AppResource)资源组的下边。为此,你可以按住鼠标把文件图标拖到应用程序(A ppResource)资源组的下部,当出现在资源组下面出现一直线时,松开鼠标;
18. 到此为止,你已成功的创建和添加了新的资源。
生成代码
为使你的程序能够运行,必须添加C代码,步骤如下:
1. 建立可以写入代码的新文件,你可以选择File | New Text File创建之;
2. 选择File | Save As保存文件为hello.c;
3. 选择Project窗口,选中Project | Add Files。找到hello.c添加之;
4. 如果它不在AppSource文件夹,可把它拖到该文件夹中。当你拖动文件的时候,你会发现一条直线,它允许你把文件插入;
将下面的代码输入到hello.c文件中。在下一部分将逐行进行详细的讲解。
/* The super-include for Palm OS */
#include
/* Our resource file */
#include "hello_res.h"
/* A prototype for our form handler function */
static Boolean myHandleEvent( EventType* event );
/* The main entry point */
DWord PilotMain( Word cmd, Ptr, Word )
{
FormPtr form; /* A pointer to our form structure */
EventType event; /* Our event structure */
/* If this is not a normal launch, don't launch */
if( cmd != sysAppLaunchCmdNormalLaunch )
return( 0 );
/* Initialize our form */
form = FrmInitForm( HelloForm );
FrmSetEventHandler( form, myHandleEvent );
FrmSetActiveForm( form );
FrmDrawForm( form );
/* Our event loop */
do
{
/* Get the next event */
EvtGetEvent( &event, -1 );
/* Handle system events */
if( SysHandleEvent( &event ) )
continue;
/* Handle form events */
FrmDispatchEvent( &event );
/* If it's a stop event, exit */
} while( event.eType != appStopEvent );
/* We're done */
return( 0 );
}
/* Our form handler function */
static Boolean myHandleEvent( EventType* event )
{
/* Parse the event */
if( event->eType == ctlSelectEvent )
SndPlaySystemSound( sndAlarm );
/* We're done */
return( false );
}
代码分析
源代码由两个函数组成。它创建了一个窗体和可以退出应用程序的按钮。当然,在程序为解决实际问题而变的更复杂时,我们必须增加更深层的程序结构。
下面是代码的逐行解释。
/* The super-include for Palm OS */
#include
Pilot.h包括了所有Palm OS相关的头文件。
/* Our resource file */
#include "hello_res.h"
深入(IN DEPTH)注意到Pilot.h包含在<>中而hello_res.h包含在引号中了吗?这就是说,编译器将在Palm OS所指定的系统文件夹中寻找Pilot.h,而对于hello_res.h,则先在Hello\Src中寻找,若找不到再到所有的文件夹中寻找。
当你创建hello.rsrc时,hello_res.h随之也建立了。hello_res.h中包含了窗体和控件的ID标识符常量。
注意:在运行之前,应把hello_res.h添加到你的工程中,它允许你方便的查看和编辑。添加文件时,首先选择Project | Add Files。找到hello_res.h将之拖到AppSource文件夹中。
/* A prototype for our form handler function */
static Boolean myHandleEvent( EventType* event );
以上就是处理窗体事件和控件事件的回调函数的原型,所谓回调函数就是在应用程序中的一个系统调用,它一般用来响应系统或用户自定义的事件,譬如你用输入笔点击窗体中的按钮所产生的事件。
函数PilotMain()
/* The main entry point */
DWord PilotMain( Word cmd, Ptr, Word )
{
PilotMain()就是包含了被称为启动代码的函数。变量cmd 提供了激活应用程序的入口。接下来我将告诉你开始运行启动代码后,其它参数将起到什么样的作用。
如下定义了指向窗体的指针。
FormPtr form; /* A pointer to our form structure */
如下定义了指向当前事件的指针。EventType是一个数据结构,包含了当前事件的所有信息。
EventType event; /* Our event structure */
小技巧:
一般我们会先查看一下PilotMain()函数头部是否存在一些识别Palm OS版本的代码,以确保程序在发现操作系统存在任何不兼容的现象后,安全而体面的退出。为了达到这个简单的目的,我先把这部分代码分离出来如下。需要事先说明的是,现在提供的这个应用程序确实能够运行在任何P alm 设备上,因为它只用到了很少的系统资源,但是在运行其它复杂的程序时就存在一些不可预料的问题了。让我们从下面的代码看起。
Dword ROMVersion;
//Get the ROM version
ROMVersion = 0;
FtrGet ( sysFtrCreator ,sysFtrNumROMVersion, &ROMVersion );
//Alert and bail if the ROM version is too low
if ( ROMVersion < ROM_VERSION_MIN )
{
// Do something here that reports an error
//Palm OS 1.0 will continuously re-launch this app
//unless we switch to another safe one
if ( ROMVersion < ROM_VERSION_2 )
{
AppLaunchWithCommand( sysFileCDefaultApp,
sysAppLaunchCmdNormalLaunch, NULL );
}
return ( 0 );
}
通过函数Ftret()的调用可以得到ROM中Palm OS的版本。从而得知当前运行的Palm OS版本是否达到了你应用程序的最低运行配置。一般Palm OS 1.0版本的处理方法是不停的重新加载应用程序(如果上一次加载不成功的话),直到你主动切换到其它的应用程序。这样就有可能使你陷入一种近乎死循环的尴尬局面,所以,在这样的情况发生前你应该先调用A ppLaunchWithCommand()函数,使你得以从容跳出当前的应用。
下面是环境检查代码,你可以藉此查验当前的运行环境是否是一个正常的运行环境(normal cicumstances)。到下一章,我们还将看到其它的运行环境。
/* If this is not a normal launch, don't launch */
if( cmd != sysAppLaunchCmdNormalLaunch )
return( 0 );
下面是一些关于Palm OS内嵌窗体管理器的函数调用。首先,调用FrmInitForm()函数,使我们的窗体进入备用状态。通过使用FrmSetEventHandler()函数为窗体绑定事件处理函数(e vent handling function)。然后,使用FrmSetActiveForm()函数来激活窗体。最后,调用FrmDrawForm()显示窗体。
/* Initialize our form */
form = FrmInitForm( HelloForm );
FrmSetEventHandler( form, myHandleEvent );
FrmSetActiveForm( form );
FrmDrawForm( form );
下面是事件循环的开始部分。
/* Our event loop */
do
{
深入: 什么是事件循环?事件循环是用来处理应用与用户,及应用之间交互的一种程序循环,譬如处理输入笔运动、按钮被按下等用户事件。许多现代图形用户界面(G UI),如Mac OS、Windows等都是事件驱动的操作系统。事件是一种操作系统和你的应用程序精确交互的手段,从而可以得知用户正在对应用程序做一些什么样的操作。一般,如P alm OS这样简单的操作系统,通常按发生的顺序来保存事件,用户可以请求事件和处理事件。
下面这个函数从ROM中调用事件处理器(Event Manager),并把老的事件放到队列中,以操作系统接收的先后顺序来处理事件。
/* Get the next event */
EvtGetEvent( &event, -1 );
下面的函数调用了系统管理器用来处理系统事件。
/* Handle system events */
if( SysHandleEvent( &event ) )
continue;
下面这个函数不但调用了回调函数处理事件,而且还执行了很多其它的任务。譬如,使用penUpEvent 和penDownEvent 两个原始事件来产生新的事件,这就像ctlSelectEvent事件,我们使用在窗体事件处理函数中去决定按钮是否被按下了。这就是我们使用系统回调函数处理事件而不是把所有事件都放到一个巨大的事件循环中去的原因。
/* Handle form events */
FrmDispatchEvent( &event );
一旦另一个应用程序被用户选择,就交由下面的代码来处理程序退出前的一切善后工作。 在这个例子程序中并没有什么需要清除的,所以我们就可以通过结束循环来退出执行中的应用程序。这些代码往往出现在循环的底部,因为我们在退出时总是需要往窗体事件处理器(或者其它的处理函数)中添点什么代码的,所以让这个退出事件接收循环贯穿整个程序结构是很有好处的。
/* If it's a stop event, exit */
} while( event.eType != appStopEvent );
/* We're done */
return( 0 );
}
helloHandleEvent() 函数
还记得吗?我们调用FrmSetEventHandler()函数的时候就是通过传递helloHandleEvent()函数的入口地址给Palm OS来实现的。这个函数通过调用FrmDispatchEvent()函数来处理窗体事件。
/* Our form handler function */
static Boolean myHandleEvent( EventType* event )
{
这个事件发生在窗体上的”Hello”按钮被按下后,在例子中,我同时让系统发出了警报音。
/* Parse the event */
if( event->eType == ctlSelectEvent )
SndPlaySystemSound( sndAlarm );
/* We're done */
return( false );
}
我的编程风格是通过超过500,000行以上代码,16年的程序生涯养成的。然而,看了我的程序并不意味着就学到了我的风格。我认为,不应该全部照搬书中的内容,而是要采用自己的方法来编程,并且不为尝试自己独特的编程风格而感到惭愧不安。用自己的方法写自己的样列程序,往往能使人更好的学习和理解那些内在的原理,所以我是非常赞同程序员编写自己风格的代码的。
本文来源:嵌入式在线 作者:
热点资讯(一周点击率)
最受工程师关注文章
热评博文
快乐大本营
无线时代来临,移动产业生态系统将发生一些根本变化。今日头条推荐“芯片是嵌入式4G技术的关键 产业生态系统将发生变化”。
想了解嵌入式开发工具的市场情况吗?先来体验下我们的在线调查吧!填写调查问卷。

