Chinaunix首页 | 论坛 | 博客

  • 博客访问: 480974
  • 博文数量: 86
  • 博客积分: 2010
  • 博客等级: 大尉
  • 技术积分: 878
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-06 14:11
文章分类

全部博文(86)

文章存档

2010年(12)

2009年(60)

2008年(14)

我的朋友

分类: C/C++

2009-06-27 09:51:34

一、何为资源文件
在symbian应用程序中,资源文件指的是后缀名为.rss的文件,每个应用程序至少要有一个与之关联的资源文件。资源编译器rcomp编译资源文件后,生成一个.rsc二进制文件和一个相伴的头文件(.rsg)。这样在应用程序框架启动应用程序时,会打开这个二进制文件,借助在.rsg文件中创建的资源标志符,根据需要把各个资源加载到C++代码中。

二、资源文件的作用:
在资源文件中指定用户界面的布局,如常用组件菜单、对话框、列表等在界面上的排列样式,另外还可以在其中指定界面上用户可见的文本信息。当然,这些可见文本并不一定通过字符串在.rss资源文件中定义,我们一般在.loc本地文件中定义,而只需在.rss资源文件中将.loc本地文件引入(include)即可。

三、与资源文件有关的系统头文件及其他文件:
在资源文件中,往往会引入许多头文件,这包括系统头文件和用户自定义的头文件。其中系统头文件的目录为:“SDK目录\ Epoc32\include\”,以#inlude <   >形式引入;用户头文件的目录为“工程目录\inc\”,以#include  ”   ”形式引入。比如HelloWorld.rss中的引入文件如下:
#include
#include "HelloWorld.hrh"
#include "HelloWorld.loc"
#include
#include
#include
可以看出,资源文件中引入的文件的扩展名一般不是.h。
那么这些头文件在资源文件起到什么作用呢?
经查看它们的源文件得出:
eikon.rh、avkon.rh还有uikon.rh:这些系统头文件主要用于定义一些资源的结构,即在其中定义了许多的STRUCT,在这些STRUCT中,有的项在给出声明的同时进行了默认初始化值,而有的仅仅是给出了声明。eikon.rh主要是一些通用的STRUCT,如STRUCT POINT TIME CLOCK等;uikon.rh主要是一些基本的组件STRUCT定义;avkon.rh主要是S60特有的组件STRUCT定义。
扩展名比较特殊的系统头文件:
avkon.rsg:这个文件里全是define语句,比如:
#define R_AVKON_MENUPANE_EMPTY                    0x8cc0002
#define R_AVKON_MENUPANE_EXIT                     0x8cc0003
#define R_AVKON_MENUPANE_APP_DEFAULT              0x8cc0004
#define R_AVKON_MENUPANE_VIEW_DEFAULT             0x8cc0005
#define R_AVKON_MENUPANE_FEP_DEFAULT              0x8cc0006
#define R_AVKON_MENUPANE_EDITTEXT_DEFAULT         0x8cc0007
#define R_AVKON_MENUPANE_LANGUAGE_DEFAULT         0x8cc0008
像是一些资源标志符的定义,用16进制数对avkon里面的所有资源进行定义。跟编译.rss资源文件时生成的.rsg文件一个扩展名。.rsg文件当修改.rss资源文件后编译时会自动生成,路径为:..\epoc32\include
avkon.mbg:这个文件只定义了一个枚举变量TmbmAvkon,如下:
enum TMbmAvkon
       {
       EMbmAvkonQgn_graf_tab_21,
       EMbmAvkonQgn_graf_tab_21_mask,
       EMbmAvkonQgn_graf_tab_22,
       EMbmAvkonQgn_graf_tab_22_mask,
       EMbmAvkonQgn_graf_tab_31,
       EMbmAvkonQgn_graf_tab_31_mask,
       。。。
}
HelloWorld.hrh:这是一类具有代表性的资源头文件,有用户自定义的,也有系统的。这类文件可以包含enum定义,意味着可以在资源文件.rss和C++源文件.cpp之间共享一个只包含enum定义的头文件,这是定义在两种类型的文件间共享的值的常用方法。内容如下:
#ifndef HELLOWORLD_HRH
#define HELLOWORLD_HRH
enum ThelloWorldCommandIds  //为菜单命令定义枚举值
    {
    EHelloWorldCmdAppTest = 1
    };
#endif      // HELLOWORLD_HRH
HelloWorld.loc:.loc 文件用于放置本地化的语言文字,比如你可以分别为中文和英文创建一个 .loc 文件,一个用于存放英文文本,一个用于存放中文文本。内容如下:
// LOCALISATION STRINGS
#define qtn_appl_test "YanHaitao"
// menu exit
#define qtn_appl_exit "Exit"
// example caption strings for app
#define qtn_app_caption_string "YanHaitao"
#define qtn_app_short_caption_string "YanHaitao"
// Localized string for r_message_text
#define R_MESSAGE_TEXT_STRING "Hello World!"
这其中的qtn_appl_test等变量,都能在.rss文件中找到,这个文件是对这些变量的赋值。
本地文件如果要使用中文,那么使用CHARACTER_SET UTF8指定资源字符集,另外需要注意的是,rss文件和loc等相关文件也需要保存为UTF-8格式,具体的使用Windows的记事本,EditPlus都可以。

四、资源文件的结构:
介绍完与资源文件相关的文件后,我们来看看一个资源文件的具体结构:
它由两部分构成,分别称为头部和主体。
1、头部:含有前面我们所说的包含语句和一些资源文件标准信息。
(1)名字:用NAME语句定义,该语句必须是资源文件中第一个有意义的行,即除去注释和空白语句,也就是说,这条语句要位于include包含语句之前,后面没有分号。该语句指定一个由1到4个字符组成的名字,并建议使用大写字符。如果应用程序使用了多个资源文件的话,那么可以通过它进行区分。
如:NAME HELL
(2)include包含语句:允许使用其他地方定义的符号和结构。
(3)签名:它的内容实际上被忽略,但必须有这条语句,否则加载资源时便报错。一般将实际内容置为空,如:RESOURCE RSS_SIGNATURE { } ,后面没有分号。
(4)文档名缓冲:指定应用程序默认文档名的TBUF资源。大部分程序不使用文档,但仍然必须包含此资源,否则加载资源失败。不需指定文件的扩展名,因为S60本地文档不使用扩展名。如:RESOURCE TBUF { buffer=”HelloWorld”;}
在这里的文件名将作为参数传递给CAknDocument类的OpenFileL(TBool aDoOpen, const TDesC& aFilename, RFs& aFs)方法。这允许一个应用程序在运行时打开一个默认的文档。如果这里的值为空那么程序默认文档名和应用程序名一致。
(5)应用程序信息资源:这个资源比较重要。EIK_APP_INFO资源为应用程序指定各种标准控件。如状态面板等,通常会创建一个为状态面板指定新内容的资源,然后使用EIK_APP_INFO资源的status_pane字段引用它。如:
RESOURCE EIK_APP_INFO
            {
            hotkeys = r_HelloWorld_hotkeys;
            menubar = r_HelloWorld_menubar;
            cba = R_AVKON_SOFTKEYS_OPTIONS_BACK;    
 }
注意:头部中定义的各种资源都没有资源名。
2、主体:
定义了应用程序中将要使用的资源。
它的定义格式如下:
RESOURCE STRUCTNAME resource-name
{
    resource-initializer-list
}
在这里STRUCTNAME应替换为具体的资源结构类型,而这些资源结构类型就在我们前面提到的eikon.rh、uikon.rh、avkon.rh中进行定义的。
资源名resource-name必须小写,通常以r_开头,而在C++文件中使用他们时必须大写,这和资源编译器工作方式有关。
例如:
RESOURCE HOTKEYS r_HelloWorld_hotkeys
    {
    control =
        {
        HOTKEY { command = EAknCmdExit; key=''e''; }
        };
}
下面具体研究一下,具体资源的定义方法和过程。
初始化字段有三种不同方式:简单初始化器、数组初始化器、结构初始化器。
如下:
RESOURCE STRUCT r_my_example_struct
{
       simple=EeikCtLabel;  //简单初始化器,分配单个值或字符串
       array={1,2,3};             //数组初始化器,大括号,元素用逗号隔开
       structmember=OTHERSTRUCT   //结构初始化器,编译器不进行类型检查,要小心
{
       simple1=”hello”;
       simple2=”goodbye”;
}
}
针对具体资源定义的说明:
(1)字符串资源:
可以使用TBUF资源将字符串包含在资源文件中。通常,会在一个.loc文件中或是在指定语言的.lxx文件中定义字符串文字,而不是在.rss文件中定义它们,只需在.rss文件中将.loc文件包含进来即可。
.lxx文件中的xx应该替换为e32std.h中的Tlanguage枚举定义的两位数字区域设置码,之后按照.mmp项目文件中设置的当前生成区域设置把.lxx文件包含到.loc文件中。看一个定义了.lxx文件的.loc文件实例:
#ifdef LANGUAGE_01
#include “MyApp.101”
#endif
#ifdef LANGUAGE_02
#include “MyApp.l02”
#endif
最后,.101和.102文件以各自的语言定义字符串,比如:
#define  STR_HELL0   “Hello World”
为了确保编译资源时将使用正确的字符串,应该在.mmp文件中包含一行或多行LANG语句,导致生成两个二进制资源文件:.r01和.r02。
LANG 01
LANG 02
(2)标点:介绍如何使用标点符号
a、所有赋值语句之后都应该有分号
b、列表中的元素以逗号分隔
c、资源定义后以及列表中最后一个元素之后不应有分号
举例:
RESOURCE AVKON_VIEW r_myapp_view
{
menubar=r_myapp_menubar;//赋值语句后有分号
cba=r_myapp_cba;//赋值,需要分号
}                                 //资源定义结尾,无需分号

RESOURCE TAB_GROUP r_myapp_tabgroup
{
       tab_width=EaknTabWidthWithTwoTabs;
       active=0;
       tabs={
                     TAB   //列表中的第一个TAB STRUCT
{
          id=EnavigationPaneTab1;
          txt=TAB1_TEXT;
},   //列表元素之间用逗号分隔
TAB
{
          id=EnavigationPaneTab2;
          txt=TAB2_TEXT;
}   //列表结尾无需分号
                     };       //将列表赋值给tabs,需要分号。
}
(3)创建资源结构:
RESOURCE语句用于创建特定资源的实例,而STRUCT语句则用于定义资源类型,创建的所有STRUCT定义都应改保存在一个扩展名为.rh的文件中。
注意:STRUCT的名字必须全部为大写,不能含有空格,且必须以字母字符开始。
常用STRUCT字段类型:
BYTE、WORD、LONG、DOUBLE、TEXT、LTEXT、BUF、BUF8、BUF、LINK、LLINK、SRLINK、STRUCT等
除简单字段外,还可以把字段定义为一个由相同类型的值组成的数组,在字段名后添加一对方括号即可。如:
STRUCT MENU_PANE
{
       STRUCT items[ ];
       LLINK extension=0;
}

阅读(1788) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2009-07-24 09:43:35

除简单字段外,还可以把字段定义为一个由相同类型的值组成的数组,在字段名后添加一对方括号即可。如: STRUCT MENU_PANE { STRUCT items[ ]; LLINK extension=0; } --------------------------------------------- 博主你好,请问对于items[]这种形式,应该如何使用TResourceReader进行读取?对于rcomp.exe来说,编译的时候自然可以确定有几个item,但是从代码角度进行读取的时候,如何确定? 还有,对于LLINK,应该如何读取呢?