您的位置: 嵌入式在线 > 技术中心 > Palm OS > PalmOS开发教程-3.3

PalmOS开发教程-3.3

2008-01-02      嵌入式在线      收藏 | 打印

       使用字符串资源

       当前,我们初始化了程序中的文本框,它带有不容易编码的字符串。对于这么一个小型的应用程序来说,字符串编码也许不成问题,但对于大型应用程序来说,它就可能引起不愉快的问题了,当你准备将你的软件向海外销售时,你会发现你必须无止尽的把时间花费在代码的改变问题上,为的只是把它的显示部分翻译成其它语言。我知道,唯一一个能帮助你解脱出来的办法就是使用字符串资源。

        字符串资源就是与其它界面元素一起存储在你的资源文件中的字符串。许多翻译公司都有能力把你的应用程序翻译成其它外语,只要你给他们资源文件就可以了。所以这是把你的应用程序翻译成另一种语言花代价最小的一种方法。

       在资源构造器(Constructor)中创建一个字符串资源: 
       1.启动资源构造器并打开Contacts.rsrc文件。 
       2.从资源列表中选中字符串资源类型。 
       3.按Ctrl-K来创建一个新的字符串资源。并命名为FieldInit。 
       4.双击打开新的字符串资源。输入hello。 
       要在你的代码中使用字符串资源,必须获得它,锁定它,在想用的时候用到它,最后才释放。代码实现如下:

//CH.2 If this is not a normal launch,don’t launch
if(cmd!=sysAppLaunchCmdNormalLaunch)
//CH.3 Get the initialization string resource handle
hsrc=DmGetResource(strRsc,FieldInitString);
//CH.3 Lock the resource,get the pointer
psrc=MemHandleLock(hsrc);
//CH.3 Allocate our field chunk
htext=MemHandleNew(HTEXT_SIZE);
if(htext= =NULL)
return(0);
//CH.3 Lock the memory,get the pointer
ptext=MemHandleLock(htext);
//CH.3 Initialize it
StrCopy(ptext,psrc);
//CH.3 Unlock the field’s memory
MemHandleUnlock(htext);
//CH.3 Unlock the resource’s memory
MemHandleUnlock(hsrc);
//CH.3 Release the string resource
DmReleaseResource(hsrc);

在Contacts.c中修改以上代码。Make,debug,并运行结果。程序看起来和原来并没有什么不同,但现在你的字符已经是从字符串资源中得到了的。

菜单
现在是给Contacts程序增加一个Edit菜单的时候了。Palm OS用户界面方针定义了一个标准的Edit菜单,只要你提供一个文本框,它就可以被输入和编辑。这个菜单显示如下:

首先构造菜单的资源部分:

1.启动资源构造器并打开Contacts.rsrc文件。

2.从资源列表中点击菜单条资源类型。按Ctrl-K来创建一个菜单条。并命名为Contact Detail。

3.双击打开Contact Detail菜单条资源。按Ctrl-M来创建一个新菜单。

4.在菜单条上改变名称,把Untitled改为Edit。

5.按Ctrl-K来创建一个新的菜单条目。输入Undo。按TAB键到达菜单条目快捷区域。输入U。继续这个过程,创建每一个新的菜单条目,就像前面例子中显示的那样。你可以使用C trl-连接号(-)来创建Select All和Keyboard之间的分隔条。

6.当你创建完菜单,双击打开Contact Detail窗体。在Menu Bar ID属性条中输入菜单的ID号(可能1000)。

7.以上工作完成了菜单条资源的创建,它看起来像前面例子中的一个标准的Edit菜单。
为了使用你刚才创建的菜单,必须在Contacts.c中增加一些代码。为了处理菜单事件,你必须增加一个叫MemuHandleEvent()的函数调用,在事件循环中处理菜单事件。

//CH.2 Handle system events
if (SysHandleEvent(&event))
continue;
//CH.3 Handle menu events
if(MenuHandleEvent(NULL,&event,&error))
contiue;
//CH.2 Handle form events
FrmDispatchEvent(&event);

在你事件处理器的循环中,以menuEvent函数调用替换ctlSelectEvent调用。使用它再去调用一个名为menuEventHandler()的函数。现在你新的事件处理器看起来像下面这样:

//CH.2 Our form handler function
static Boolean myHandlerEvent(EventType* event)
{
//CH.3 Parse menu events
if(event->eType= =menuEvent)
return(menuEventHandler(event));
//CH.2 We’re done
return(false);
}

现在来写menuEventHandler()函数。首先,你必须发信号给用户界面,报告菜单事件已经被接收:

//CH.3 Handle menu events
Boolean menuEventHandler(EventPtr event)
{
FormPtr form //CH.3 A pointer to our form structure
Word index //CH.2 A general purpose control index
FieldPtr field; //CH.3 Used for manipulating fields
//CH.3 Get our form pointer
form=FrmGetActiveForm();
//CH.3 Erase the menu status from the display
MenuEraseStatus(NULL);

提供单独的输入区帮助。这是因为输入区帮助应该是可用的,不管文本框当前是否被选中。

//CH.3 Handle graffiti help
if(event->data.menu.itemID= =EditGraffitiHelp)
{
//CH.3 Pop up the graffiti reference based on
//the graffiti state
SysGraffitiReferenceDialog(referenceDefault);
return(true);
}

下一步,你得到了文本框指针后就可以调用那些非常好的编辑命令了。下面的例子显示了一个用最普通的方法来得到文本框指针,这个方法我们在先前的c ase frmOpenEvent:中用到过。无论窗体上有多少文本框,它都可以工作。

//CH.3 Get the index of our field
index=FrmGetFocus(form);
//CH.3 If there is no field selected,we’re done
if(index= =noFocus)
return(false);
//CH.3 Get the pointer of our field
field=FrmGetObjectPtr(form,index);

现在我们可以执行edit命令了。调用这些编辑函数非常简单并且它们处理每一件事都比较恰当。如执行Select All命令,你只要把整个字符串传递给FldSetSelection()函数就可以了。

//CH.3 Do the edit command
switch(event->data.menu.itemID)
{
//CH.3 Undo
case EditUndo;
FldUndo(field);
break;

//CH.3 Cut
case EditCut;
FldCut(field);
break;

//CH.3 Copy
case EditCopy;
FldCopy(field);
break;

//CH.3 Paste
case EditPaste;
FldPaste (field);
break;

//CH.3 Select All
case EditSelect All;
{
//CH.3 Get the length of the string in the field
Word length=FldGetTextLength(field);

//CH.3 Select the whole string
FldSetSelection(field,0,length);
}
break;
//CH.3 Bring up the kdyboard tool
case EditKeyBoard;
SysKeyBoardDialog (kbdDefault);
break;
}
//CH.3 We’re done
rerurn(true);
}

经过以上修改,make,debug,并运行你的应用程序。你就可以使用已创建的菜单和快捷方式了。

支持各种不同版本的Palm OS
事实上,上面的代码如果拿到Pilot 1000或者Pilot 1500这些使用Palm OS1.0版本的系统上运行的话就会使系统崩溃。这是因为在1.0版本中,SysKeyboardDialog()是一个于现在不同的函数调用。但也有好几种方法可以解决这个问题。首选就是换成调用函数S ysKeyboardDialogV10(),这是一个向后兼容的函数。除了最新的系统命令外,如果你还想了解更多的话,你就有必要检查一下OS的版本,这样可以基于O S版本来正确的调用函数。

如果我们多次遭遇由于OS版本不同带来的严重后果的话,我们在编程时将变得更加老练。现在就用SysKeyboardDialogV10()替换这个SysKe yboardDialog()函数调用。

//CH.3 Bring up the keyboard tool
case EditKeyboard;
SysKeyboardDialogV10();
break;

错误和警告
Contacts程序已经扩展了它的使用范围,用户对它做的某些操作可能导致错误发生。现在是一个极好的时机来讨论出错处理。

如果你执行编辑命令,就可以发现如果你做一些无意义的事,譬如在没有选中任何文本的时候复制,编辑函数也会产生一个警告声。不只是S elect All如此,因为你已经调用了一个普通函数,即便没有错误,它也会发出声音的。为了使Select All符合其它函数的发音标准,你可以加入如下的一个SndPlaySystemSound()函数:

//CH.3 Select All
case EditSelectAll
{
//CH.3 Get the length of the String in the field
Word length=FldGetTextLength(field);
//CH.3 Sound an error if appropriate
if(legth= =0)
{
SndPlaySystemSound(sndError);
return(false);
}
//CH.3 Select the whole string
FldSetSelection(field,0,length);
}

当用户的输入超越了被调函数的职能时,就应该提示用户他们可能做错了什么。对此,有一个很好的解决方法,就是使用Alerts。Alerts `是由操作系统控制的袖珍型窗体,创建和使用都非常的方便。

作一个试验:创建一个Alert资源,来显示Select All命令的错误信息:
1.启动资源构造器。
2.从资源类型列表中选中Alert。
3.按Ctrl-K来创建一个新的警告。
4.双击打开警告。
5.改变消息属性像“There was no text to select。”
6.改变Error的标题属性。
7.改变Error的警告类型属性。
为了调用这些Alert,我们加入FrmAlert()函数。你可以从Contacts_res.h文件中得到警告ID的变量名。

//CH.3 Pop up an error if appropriate
if(length= =0)
{
SndPlaySystemSound(sndError);
FrmAlert(SelectAllErrorAlert);
return(false);
}

加入上面的代码后,make,debug,并运行应用程序。可以发现,自从我们给错误设了警告类型,就有两次嘟嘟声:一个来自SndPlaySyst emSound(),一个来自警告。

另一个我们要放置Alert,至少是一次系统嘟嘟声的地方,就是当我们检查焦点的时候。事实上,当休眠状态的应用程序被唤醒的时候,文本框是获得焦点的首选控件。在一般情况下我们就想要在此时发一个经典的系统嘟嘟声来通知用户。
由于Select All的错误提示并不是经常会出现的,就让我们移走这个Alert资源。在以后的章节中,我们再使用Alert通知用户各种不同的错误信号吧。

下一步是什么?
在下一章中,我们将研究如何在你的应用程序中拥有多个窗体。

程序清单
这里是完整的Contacts.c程序清单。从hello.c改变的行都用//CH.3注解。
//CH.2 The super-include for the Palm OS
#include

//CH.3 Our resource file
#include “Contacts_res.h”

// CH.2 prototypes for our event handler functions
static Boolean myHandleEvent(EventPtr enent);
static Boolean menuEventHandler(EventPtr event);

//CH.3 Our field memory handle
static Handle htext; //CH.3 Handle to the text in our edit field
#define HTEXT_SIZE 81 // CH.3 Size of our edit field

//CH.2 The main entry point
Dword PilotMain (Word emd,Ptr,Word)
{
FormPtr form; //CH.2 A pointer to our form structure*/
Handle hsrc; //CH.3 Handle to the string resource
Charptr psrc; //CH.3 Points to the text in the resource
Charptr ptext; //CH.3 Points to the text in the edit field
Word index; //CH.3 A general purpose index
FieldPtr field; //CH.3 Used for manipulating fields
EventType event; //CH.2 Our eent structure
Word error; //CH.3 Error word for menu event handler

//CH.2 If this in not a normal launch,don’t launch
if (cmd!=sysAppLaunchCmdNormalLaunch)
return(0);

//CH.3 Get the initialization string resource handle
hsrc=DmGetResource(strRsc, FieldInitString);

//CH.3 Lock the resource, get the pointer
psrc= MemHandleLock(hsrc);

//CH.3 Allocate our field chunk
htext=MemHandleNew(HTEXT_SIZE);
if (htext= =NULL)
return(0);

//CH.3 Lock the resource, get the pointer
ptext= MemHandleLock(htext);

//CH.3 Initialize it
StrCopy(ptext,psrc);

//CH.3 Unlock the field’s memory
MemHandleUnlock(htext);

//CH.3 Unlock the resource’s memory
MemHandleUnlock(hsrc);

//CH.3 Release the string resource
DmReleaseResource(hsrc);

//CH.2 Initialize our form
form=FrmInitForm(ContactDetailForm);
FrmSetEventHandler(form,myHandleEvent);
FrmSetActiveForm(form);

//CH.3 Get the index of our field
index=FrmGetObjectIndex(form,ContactDetailFirstNameField);

//CH.3 Get the pointer to our field
field =FrmGetObjectPtr(form,index);

//CH.3 Set the editable text
FldSetTextHandle(field,htext);

//CH.2 Draw the form
FrmDrawForm(form);

//CH.3 Set the focus to our field
FrmSetFocus(form,index);

//CH.2 Our event loop
do
{
//CH.2 Get the next event
EvtGetEvent(&envet,-1);

//CH.2 Handle system events
if(SysHandleEvent(&event))
continue;

//CH.3 Handle menu events
if (MenuHandleEvent(NULL,&event,&error))
continue;

//CH.2 Handle form events
FrmDispatchEvent(&event);

//CH.2 If it’s a stop event,exit
}while(event,eType!=appStopEvent);

//CH.2 We’re done
return(0);
}
//CH.2 Our form handler function
static Boolean myHandleEvent(EvenType* event)
{
//CH.3 Parse menu events
if (event->eType= =menuEvent)
return(menuEventHandler(event));

//CH.2 We’re done
return(false);
}

//CH.3 Handle menu events
Boolean menuEventHandler(EventPtr event)
{
FormPtr form; //CH.3 A pointer to our form structure
Word index; //CH.3 A general purpose control index
FieldPtr field; //CH.3 Used for manipulating fields

//CH.3 Get our form pointer
form=FrmGetActiveForm();

//CH.3 Erase the menu status from the display
MenuEraseStatus(NULL);

//CH.3 Handle graffiti help
if(event->data.menu.itemID= = EditGraffitiHelp)
{
//CH.3 Pop up the graffiti reference based on
//the graffiti state
SysGraffitiReferenceDialog(referenceDefault);
Return(true);
}
//CH.3 Get the index of our field
index=FrmGetFocus(form);

//CH.3 If there is no field selected,we’re done
if (index= =noFocus)
return(false);

//CH.3 Get the pointer of our fiedl
field =FrmGetObjectPtr(form,index);

//CH.3 Do the edit command
switch(event->data.menu.itemID)
{
//CH.3 Undo
case EditUndo;
FldUndo(field);
break;

//CH.3 Cut
case EditCut;
FldCut(field);
break;

//CH.3 Copy
case EditCopy;
FldCopy(field);
break;

//CH.3 Paste
case EditPaste;
FldPaste (field);
break;

//CH.3 Select All
case EditSelect All;
{
//CH.3 Get the length of the string in the field
Word length=FldGetTextLength(field);
//CH.3 Pop up an error if appropriate
if(length= =0)
{
SndPlaySystemsound(sndError);
Return(false);
}
//CH.3 Select the whole string
FldSetSelection(field,0,length);
}
break;
//CH.3 Bring up the kdyboard tool
case EditKeyBoard;
SysKeyBoardDialogv10():
Break;
}
//CH.3 We’re done
rerurn(true);


 

本文来源:嵌入式在线    作者:
热点资讯(一周点击率)
热评博文
评一评已有 0 位网友对此文发表了看法。  我也来评一下

验证码:  看不清?换一张

 

快乐大本营

    无线时代来临,移动产业生态系统将发生一些根本变化。今日头条推荐“芯片是嵌入式4G技术的关键 产业生态系统将发生变化”。

    想了解嵌入式开发工具的市场情况吗?先来体验下我们的在线调查吧!填写调查问卷

工程师之星
朱礼昆
电子信息工程专业,擅长硬件编程
  • 胡菲菲  技术专长:嵌入式系统linux
  • 柳如峰  技术专长:模电,电源
热门招聘
论坛热贴