资源文件(.rss)

    资源文件是带有.rss文件扩展名的文本文件。用于在源代码外独立的指定应用程序的用户可见元素。可以使用资源文件指定菜单、对话框和列表之类的UI元素的布局,以及应用程序使用的所有用户可见文本。没个应用程序至少有一个与之关联的资源文件。

    资源文件通过资源编译器(rcomp.exe)编译成一个二进制文件(.rsc)和一个头文件(.rsg)。应用程序框架在应用程序启动时打开这个二进制文件(.rsc),借助头文件(.rsg)中资源标识符ID,将各个资源加载到源文件中。

    源代码与资源信息分离为开发人员提供了便利,即不需要修改源代码或重新编译应用程序便能任意的修改和重新生成应用程序UI外观,又能方便的进行应用程序本地化。

 

1、资源文件的语法

    资源文件的语法与C++相似,但不完全相同。编译资源文件之前会使用C++的预处理器对资源文件进行预处理。因此,可以在资源文件中使用C++风格的注释,以及#include、#if、#else、#endif之类的预处理语句。

    除此之外,资源文件还可以包含枚举(enum)类型定义。这意味着可以在资源文件和C++源文件之间共享只包含枚举(enum)类型定义的头文件,这是在这两种文件类型之间共享值的常用方法。通常这种头文件使用扩展名.hrh,该文件中只能包含枚举和预处理语句。

 

2、资源文件的结构

    资源文件的结构总体上可分为两个部分:

  • 文件头部:#include语句和与资源文件有关的标准信息,资源编译器和应用程序框架会使用它们。
  • 文件主体:定义资源。

2.1、文件头部

NAME TEST

 

#include<avkon.rh>
#include<eikon.rh>
#include<uikon.rh>
 
RESOURCE RSS_SIGNATURE {}
 
RESOURCE TBUF { buf = "test"; }
 
RESOURCE EIK_APP_INFO 
{
   
   
   
}
 
RESOURCE LOCALISABLE_APP_INFO r_test_localisable_app_info
 {
    short_caption = qtn_hewb_short_caption_string;
    caption_and_icon = 
    CAPTION_AND_ICON_INFO
    {
               number_of_icons = 1;
        icon_file = "//resource//apps//Test_reg.mif ";
     };
 }

    资源文件的头部由一下元素组成:

  • 名字(NAME): 在NAME语句中定义。NAME语句必须是资源文件中第一个有意义的行。该语句指定一个由4个字母组成的名字,在多资源文件应用程序中,通过名字区分。名字必须在应用程序内唯一,此外还应该确保与系统资源文件使用的名字不同。
  • #include: 可以使用#include语句包含其他文件,从而允许资源文件使用文件外定义的符号和资源结构体。
  • 签名(RSS_SIGNATURE): 由应用程序框架调用,必须在资源文件中定义。但其内容实际上被忽略,因此该资源通常定义为空。
  • 文档名缓冲 :指定应用程序的默认文档名的 TBUF 资源。大部分S60应用程序都不使用文档,此时该值并不重要,但仍必须包含此资源。不需要指定文档的扩展名,因为S60本地文档不使用扩展名 。
  • 应用程序信息资源(EIK_APP_INFO): 为应用程序指定各种标准控件,例如菜单(menubar)、软件面板(CBA)、状态面板(StatusPane)、热键(hotkey)。
  • 本地化应用程序信息(LOCALISABLE_APP_INFO): 第三版中资源文件新加入的资源结构。为了实现国际化的要求,对资源中的一些比如说文字进行统一。

2.2、文件主体

RESOURCE  STRUCTNAME   resource-name  
{ 
    resource-initializer-list  
}

    资源文件的主体定义了应用程序将使用的资源。每个资源均使用RESOURCE语句定义:

  • STRUCTNAME : 应替换为所需的资源结构类型。这些结构在.rh文件中定义,然后在.rss文件中使用#include语句包含.rh文件。系统资源结构类型在avkon.rh、uikon.rh和eikon.rh中定义。
  • resource-name : 应替换为资源的唯一名字。必须使用小写字母,通常以r_开始。
  • resource-initializer-list : 为资源结构的字段进行初始化,每个初始值都要以分号结束。每种资源可以包含在初始化列表中的字段各不相同。

    根据资源结构中不同类型的字段,初始化有三种不同方式: 简单初始化、数组初始化、结构初始化。

RESOURCE EXAMPLESTRUCT r_my_example_struct 
{ 
    
    
    
    
        
        
    
}
  • 简单初始化: 用单个值或字符串初始化字段。
  • 数组初始化: 用大括号括起的多值列表初始化字段,其中列表中的元素以逗号分隔。
  • 结构初始化: 首先需要提供所需的结构(STRUCT) 名称,而后初始化该结构中的各个字段。

2.3、标点

    在资源文件中,资源的声明中必须正确的使用分号和逗号,否则会编译错误。标点的使用规则为:

  • 所以赋值语句后必须有分号。
  • 数组初始化中列表元素必须以逗号分隔。
RESOURCE TAB_GROUP r_my_tabgroup 
{ 
}

 

 

原文:http://www.cppblog.com/franksunny/archive/2007/09/19/32484.html

Symbian 资源文件解析

 

一、何为资源文件:

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

 

二、资源文件的作用:

在资源文件中指定用户界面的布局,如常用组件菜单、对话框、列表等在界面上的排列样式,另外还可以在其中指定界面上用户可见的文本信息。当然,这些可见文本并不一定通过字符串在.rss 资源文件中定义,我们一般在.loc 本地文件中定义,而只需在.rss 资源文件中将.loc 本地文件引入(include )即可。(刚开始我百思不得其解,真不知道程序终相关的字符串定义在哪里的)

 

三、资源文件的结构(语法):

资源文件的具体结构由两部分构成,分别称为头部和主体。

1 、头部:主要包括五部分,分别是文件名字、include 包含语句、签名、文档名缓冲、应用程序信息资源这些些资源文件标准信息。

(1 )名字:用NAME 语句定义,该语句必须是资源文件中第一个有意义的行(注释和空白语句不在有意义行定义内),即这条语句要位于include 包含语句之前,后面没有分号。该语句指定一个由1 到4 个字符组成的名字,并建议使用大写字符。如果应用程序使用了多个资源文件的话,那么可以通过它进行区分。如:NAME HELL

(2 )include 包含语句:允许使用其他地方定义的符号和结构。常见的有uikon.rh 、eikon.rh 、avkon.rh 等

(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 应替换为具体的资源结构类型,而这些资源结构类型已在文件头部include 包含的eikon.rh 、uikon.rh 、avkon.rh 中进行了定义。

资源名resource-name 必须小写,通常以r_ 开头,而在C++ ,这和资源编译器工作方式有关。例如:

// 资源名定义
RESOURCE AVKON_VIEW r_viewmychannelhot
{
     hotkeys=r_xv_hotkeys;
     menubar=r_menubar_viewmychannelhot;
     cba=R_AVKON_SOFTKEYS_SELECTION_LIST;
}
// 资源调用
BaseConstructL(R_VIEWMYCHANNELHOT);
下面具体研究resource-initializer-list (初始化资源字段),根据要资源字段的不同类型,初始化字段有三种不同方式:简单初始化器、数组初始化器、结构初始化器。如下:
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 。(从这里显然我们可以试着去打开eikon.rh 、uikon.rh 、avkon.rh 文件看看,里面是否都是STRUCT 打头的资源类型定义)

常用STRUCT 字段类型见资源文件STRUCT 字段类型表。,除简单字段外,还可以把字段定义为一个由相同类型的值组成的数组,在字段名后添加一对方括号即可。如:

STRUCT MENU_PANE
{
       STRUCT items[ ];
       LLINK extension=0;
}

 

常用资源字段类型

字段类型

说明

BYTE

单字节,解释为一个有符号或无符号整数

WORD

双字节,解释为一个有符号或无符号整数

LONG

四字节,解释为一个有符号或无符号整数

DOUBLE

八字节,表示一个双精度浮点数

TEXT

以NULL 结尾的字符串,已废弃,建议使用LTEXT

LTEXT

Unicode 字符串,带有一个前导字节保存长度,没有终止NULL

BUF

Unicode 字符串,没有前导字节,没有终止NULL

BUF8

8 位字符组成的字符串,没前导和终止,用于放入8 位数据

BUF<n>

最大长度为n 的Unicode 字符串,没有前导和终止

LINK

另一个资源的16 位ID ,类似于拥有指定资源的一个引用

LLINK

另一个资源的32 位ID

SRLINK

自引用LINK ,该类型字段值由资源编译器自动分配,不能自行提供初始化值,是一个32 位ID

STRUCT

结构,创建本身就是STRUCT 的字段,使用它可以把STRUCT 嵌入到STRUCT 中

STRUCT 的类型名字必须都大写,不能含有空格,且以字母字符开始;在具体每个字段的定义时,依次由字段类型、字段名、可选初始值和一个分号组成。类型必须全部大写,字段名必须小写,如果提供默认值,则在资源定义中使用此类型资源结构是可以省略该字段,此时将使用默认值。

 

三、与资源文件有关的系统头文件及其他文件:

如上提到的与资源文件相关的*.rh 、*.loc 和*.*.rsg 之外,在资源文件中,往往还会引入其它诸如*.hrh 和*.mbg 文件,由于这是本人第一篇关于Symbian 的小结,所以在这里借资源文件的解析顺带将其它文件也小结一下:

*.h 和*.cpp 是最基础的C++ 头文件和C++ 源文件(这个不用做介绍都知道);

*.rss 是Symbian 的资源源文件,主要定义资源实例,具体定义了应用程序UI 所需所有字符串、按键、菜单和列表等等控件资源,在Series 60 以后,将字符串的具体定义放在了*.loc 文件中,更有益于UI 本地化和国际化,另据文档说明,*.rss 可以扩展为*.r?? 用于多国语言版本;

*.rh 是Symbian 的资源头文件,负责资源结构类型的定义,除了预处理语句外就是STRUCT 语句,它只能被资源源文件包含;

*.hrh 是可以被C++ 文件(包括头文件和源文件)和Symbian 资源文件(包括*.rss 和*.rh )包含的头文件,其内基本是预处理语句和enum 枚举语句,这些枚举语句往往是菜单、工具条等的命令索引值,在switch …case 语句中使用;

*.rsc 文件是*.rss 文件编译生成的资源(二进制)文件,在资源源文件编译过程中还会产生*.rsg 文件,该文件内是*.rss 资源源文件中资源的ID 值,C++ 源文件包含它后可以通过资源ID 直接装载资源。

与资源相关的还有*.mbg 文件,它和*.rsg 一样是编译生成的ID 文件,具体实现通常在*.mmp (后面介绍)文件中将各种Window bmp 位图包含进来,通过编译生成*.mbm 的过程中产生(该过程可能调用了aifbuilder 这一图标设计工具)。而*.mbm 是Symbian 系统的图像文件。在这里只要对照rsc 文件的过程就行,只不过mbm 是UI 的图形和图像资源。(这里至于换肤和aifbuilder 的一些东西,我还不是很清楚,为此没做展开)

*.inl 文件是内联函数的源文件,通常内联函数在C++ 头文件中实现,但有时为了考虑将其实现与头文件分离,故意在另一文件中实现,通常它在声明内联函数的头文件的末尾被#include 语句包含进来。

*.pan 文件是为应用程序创建一份应急代码,字面意思应急代码在开发过程中显示程序的错误用的,但是具体我也没有用到过,所以也不知道如何解释更好些。

*.aif 的文件,查到说是Symbian 系统的应用程序信息文件,Aif , 由专门的aiftool 应用程序产生,也跟本地化有关。

 

构建文件*.mmp 是为控制台应用程序abld 准备的项目定义文件,其功能类似makefile ,但是它可能比makefile 还复杂,因为Symbian 构建工具在mmp 文件基础上才能产生makefile 文件,具体项目定义文件的格式后面再另作解析。

构建文件bld.inf 是构建时的信息文件,通常其内只有一个*.mmp 用于指向要编译的项目定义文件,但是也可以包含多个*.mmp ,具体多个时我试过,只要路径设置正确就可以实现。

根据不同的构建目的,执行abld 命令将产生各种不同的目标文件,具体由:*.app (Symbian 的系统执行文件相当于Windows 的exe 文件,它是多态的DLL )、*.dll (共享的dll 文件)、*.exe (Symbian 系统服务或可执行文件,我将其理解为控制台程序,不知道是否正确,该文件在Window 上装有模拟器情况下可以自动运行模拟器)。

打包文件*.pkg 文件,该文件是为控制台应用程序makesis 准备用来生成*.sis 手机安装文件的的定义文件,其语法比较简单,在这里不做展开。

 

既然对文件已经做了如上分析,那么顺其自然对常见的文件目录也用下表列出做下简单描述

文件夹

内容描述

/aif

存放*.aif 和*.aif 的源位图(*.bmp )

/data

用于产生*.src 的*.rss 资源源文件

/group

与平台无关的项目文件如*.mmp 、*.inf 有时也放*.rss

/inc

*.h 、*.loc 、*.l** 、*.pan 、*.hrh 等能被#include”” 包含的文件

/install

*.pkg 和随后生成的安装文件*.sis

/src

*.cpp 类的C++ 源文件