20.6 存储应用程序资源
一个简单的小程序可能只有一个可执行文件.但是,更常见的情形是,你必须使用包括帮助文件,也许还有别的HTML文件和图片文件,以及应用程序自定义的数据文件.这些附带的文件怎么存储合适呢?
减少数据文件的数量
你可以通过一些方法来减少你需要使用的数据文件,以便创建一个更简洁的发行包.首先,对于XPM类型的图片,尽可能在你的代码中使用#include,而不是通过从文件中读取的方法来加载图片.其次,如果你正在使用XRC文件工具,位于wxWidgets发行版的utils/wxrc目录中的wxrc工具能将它变成C++的代码,如下所示:
wxrc resources.xrc --verbose --cpp-code --output resources.cpp
然后,你就可以调用生成的C++文件中的InitXmlResource函数来初始化这些资源了.
第三种方法是,你可以将所有的数据文件打包成一个zip文件,然后使用我们在前面介绍的流操作和虚拟文件系统的方法来访问它们.你可能还需要用到类wxStandardPaths,它定义在"wx/stdpaths.h"文件中,它的一些静态的成员函数包括GetConfigDir, GetInstallDir,GetDataDir,GetLocalDataDir和GetUserConfigDir等.具体这些函数在各个平台上返回的目录的为止参考wxWidgets手册中的相关描述.
在Mac OSX平台上,你需要创建一个应用程序发布包文件,这个文件用来描述你的应用程序的可执行文件路径,数据文件等.本章稍后部分我们会详细讨论有关的情况.
找到应用程序所在的位置
经常会有wxWidgets的使用者希望能够提供一个函数用来找到应用程序所在的绝对路径,以便可以从同样的路径加载资源文件.不过, wxWidgets并没有提供这样的函数,这部分是因为要在不同的平台上实现这些函数是有一定难度的,可能会返回不可靠的路径,也是部分出于鼓励开发者最好把数据文件放在系统标准的数据文件夹中(尤其是在linux系统上)的原因. 然而,将所有应用程序相关的文件都放在一个路径下也是可以理解的,因此,在随书光盘的examples/chap20/findapppath目录中,你可以找到一个函数wxFindAppPath的代码,用来实现这个功能,它的声明部分如下:
// 返回当前正在运行的可执行文件的绝对路径
wxString wxFindAppPath(const wxString& argv0, const wxString& cwd,
const wxString& appVariableName = wxEmptyString,
const wxString& appName = wxEmptyString);
argv0的值等于wxApp::argv[0],在某些平台上,它代表了当前执行文件的完整路径.
cwd是当前工作目录(你可以通过调用wxGetCwd函数得到),在某些平台上我们需要根据这个参数作出一些判断.
appVariableName是相关环境变量的值,比如环境变量MYAPPDIR,这些变量可以被在程序外部设置用来指明应用程序查找位置.
appName是你在发行包中指明的前缀,函数可能需要使用它来检查位于发行包中的某些路径.比如,DialogBlocks程序的这个参数是DialogBlocks,因此在Mac OsX系统上,这个函数会在<currentdir>/DialogBlocks.app/Content/MacOS中寻找可执行文件的全路径.
下面是这个函数的使用方法举例:
bool MyApp::OnInit()
{
wxString currentDir = wxGetCwd();
m_appDir = wxFindAppPath(argv[0], currentDir, wxT("MYAPPDIR"),
wxT("MyApp"));
...
return true;
}
在Windows平台和Mac OSX平台上,这个函数返回的路径都是可以信赖的,然而在Unix平台上,只有应用程序是从其所在的目录被启动的时候,返回的路径才是可以信赖的.或者如果你正确设置了MYAPPDIR这个环境变量,返回的路径也是可以信赖的.因此,为了让返回的值更正确,有些安装程序选择另外安装一个启动脚本,这个脚本会首先设置MYAPPDIR环境变量,然后再启动应用程序.你可以选择提示用户是否安装这个脚本,或者你可以直接把你的程序安装在标准的路径上,比如 /usr/local/bin/