构建可移植 BREW™ 应用程序的方法
1. 使用资源文件 - 将资源与代码分离
BREW 应用程序可设计为在多种不同设备上并以多种不同语言执行。 您无需为每台设备和每种语言单独创建应用程序,而只需使用资源编辑器创建多个资源文件(.bar 文件)- 每种设备语言组合一个。 以这种方式将资源与代码分离将使您的 BREW 应用程序可以跨设备和语言进行移植。
您应该使用资源编辑器添加应用程序使用的所有字符串、图像和对话框资源。 然后,将每个资源与一个名称相关联,应用程序代码中将使用该名称。 有关如何生成资源 (.bar) 文件的详细信息,请参阅 BREW SDK™ 随附的《资源编辑器指南》。
2. 对每个目标设备使用不同的 MIF 文件
MIF 文件包含用于在可执行应用程序的菜单中显示应用程序的字符串和图像。 因此,您应该为每个设备语言组合创建不同的 MIF 文件。
3. 参照屏幕尺寸定位控件 - 避免将绝对像素值用作屏幕坐标
不同的目标设备具有不同的屏幕尺寸和不同的字体高度、宽度。 以下 BREW API 可用于获得这些特性,在设备上布置文本、图像和控件时将用到这些 API:
• ISHELL_GetDeviceInfo()
ISHELL_GetDeviceInfo 用于确定运行应用程序的
设备的屏幕尺寸。
AEEDeviceInfo di;
int cx, cy;
ISHELL_GetDeviceInfo(pIShell, &di);
cx = di.cxScreen; //用像素表示的装备宽度
cy = di.cyScreen; //用像素表示的装备高度
• IDISPLAY_GetFontMetrics()
IDISPLAY_GetFontMetrics() 用于查找特定
字体的字符高度。
int fontHeight;
fontHeight = IDISPLAY_GetFontMetrics(pme->a.m_pIDisplay,
AEE_FONT_BOLD, NULL,
NULL);
• IDISPLAY_MeasureText()
IDISPLAY_MeasureText() 用于在使用指定字体进行绘制时
测量给定字符串的像素宽度。
int stringWidth = IDISPLAY_MeasureText(pme->a.m_pIDisplay,
AEE_FONT_NORMAL,
textString);
• IDISPLAY_MeasureTextEx()
IDISPLAY_MeasureTextEx() 用于在给定显示字符串
的最大像素宽度和字体的情况下,
确定可以显示的输入文本字符串的字符数。
pixelWidth = IDISPLAY_MeasureTextEx(pMe->m_pIDisplay,
AEE_FONT_BOLD,
(AECHAR *) textString, // 文本字符串
-1,
di.cxScreen, // maxWidth
&pnFits); // 可以放得下的字符数
// maxWidth
pixelWidth 含有输入文本字符串的像素宽度。 pnFits
含有输入文本字符串字符数,这些字符数能够
在装备的一行中放得下。
• IIMAGE_GetInfo()
IIMAGE_GetInfo() 用于获取图像尺寸。
AEEImageInfo imgInfo;
int cx,cy;
IIMAGE_GetInfo(pIImage, &imgInfo);
cx = imgInfo.cx; //图像宽度
cy = imgInfo.cy; //图像高度
使用以上 API,您无需对像素值进行硬编码就可以
定位屏幕上的元素。 例如:
要绘制跨多行的文本:
// 获取装备信息
ISHELL_GetDeviceInfo(pMe->m_pIShell,&di);
// 获取字符量度信息
charHeight = IDISPLAY_GetFontMetrics (pMe->m_pIDisplay,
AEE_FONT_NORMAL, &pnAscent, &pnDescent);
// 转换为宽字符串 (unicode)
STR_TO_WSTR ((char *)displayStr, wideStr, sizeof (wideStr));
// psz 保留从字符串缓冲区写的点的踪迹
// 用于字符串无法全部放到一行而需要接到
// 下一行时。
psz = wideStr;
// 需要计算总字符串长度以决定是否需要
// 接到下一行。
totalCh = STRLEN ((char *)wideStr);
// 在数行显示文本字符串,如果字符串无法
显示在
//单一行时。
while ((totalCh > 0) && (*psz != NULL)) {
// 获取一行中会放得下多少个字符的信息。
pixelWidth = IDISPLAY_MeasureTextEx(pMe->m_pIDisplay, font,
(AECHAR *) psz, -1, di.cxScreen - 5, &pnFits);
IDISPLAY_DrawText(pMe->m_pIDisplay, AEE_FONT_NORMAL,
psz,
pnFits, 5, dy, 0, 0);
psz += pnFits; // 把指针移到下一个要
// 显示的节
totalCh -= pnFits; // 减少总字符数以止住
// 显示
dy += charHeight; // 把下一行 charHeight 像素放到
// 前一行下方。
IDISPLAY_Update(pMe->m_pIDisplay);
if (totalCh < pnFits) {
pnFits = totalCh; // 如果总数少于 pnFits,
// 则调节 pnFits
}
}
要在屏幕中心显示图像:
// 获取装备坐标
ISHELL_GetDeviceInfo(pMe->a.m_pIShell, &dInfo);
// 从资源文件加载图像
pIImage = ISHELL_LoadResImage(pMe->a.m_pIShell, szResFile,
IDB_BROWSER_ICON);
if (pIImage) {
// 获取图像大小
IIMAGE_GetInfo(pIImage, &aii);
// 计算用于位图的坐标 --
// 我们会在屏幕中央将其显示
img_x = (dInfo.cxScreen - aii.cx) / 2;
img_y = (dInfo.cyScreen - aii.cy)/ 2;
// 设置光栅操作
IIMAGE_SetParm(pIImage, IPARM_ROP, AEE_RO_NOT, 0);
// 在指定的坐标绘出非动画位图
IIMAGE_Draw(pIImage,img1_x,img1_y);
// 释放图像接口
IIMAGE_Release (pIImage);
}
4. 使用适当颜色深度的图像
对于不同的目标设备,应使用不同的资源文件。在这些文件中,使用颜色深度适合设备的图像。 如果您从外部网络获得图像,则可以查阅设备的颜色深度(包括屏幕尺寸)并使用这些值获取合适的图像。
AEEDeviceInfo di;
int cx, cy, colorDepth;
ISHELL_GetDeviceInfo(pIShell, &di);
cx = di.cxScreen; //用像素表示的宽度
cy = di.cyScreen; //用像素表示的高度
colorDepth = di.nColorDepth; // 装备的颜色深度
5. 伸展图像
在 BREW SDK 1.1 版中,可以使用 IGRAPHICS_StretchBlt() 将位图伸展到所需宽度和高度。 您可以比较屏幕尺寸(使用 ISHELL_GetDeviceInfo)和图像尺寸 (IIMAGE_GetInfo),然后根据需要将位图伸展到更加适当的大小。
IGRAPHICS_StretchBlt(pIGraphics,
xStart, //图像的左上角 x & y 坐标
yStart,
width, // 想要的图像宽度
height, //想要的图像高度
sourceBmp //源位图
rasterCode)
6. 动态查找特定图像或声音类型的处理程序
确定图像/声音类型的处理程序函数的 Class ID,然后
创建该 BREW 类的实例。
// 找出用于 bmp 图像的处理程序的 Class ID
if ((cls = ISHELL_GetHandler(pMe->a.m_pIShell, HTYPE_VIEWER,
"image/bmp")) == 0)
break;
// 用返回的 Class ID 创建图像处理程序的实例
ISHELL_CreateInstance(pMe->a.m_pIShell, cls, (void **)(&pIImage));
if(pIImage == NULL)
break;
7. 自定义菜单样式
使用标准菜单样式创建菜单时,菜单可能在不同的目标设备上不一样。 要保持您的菜单有一致的外观,您可以使用 IMENU_SetStyle() 自定义菜单样式(项目的边框类型、项目内 x 方向的填充、项目内 y 方向的填充、项目内绘制图像的光栅操作)。
AEEItemStyle si, ni;
// 所选菜单项目的项目样式
si.ft = AEE_FT_TAB_TOP_SEL; // 项目的帧类型
si.xOffset = 8; //项目内部的X 填补 (不包括帧大小)
si.yOffset = 8; //项目内部的Y 填补 (不包括帧大小)
si.roImage = AEE_RO_COPY; // 绘制图像的光栅操作在
// 项目内部
// 一般菜单项目的项目样式
ni.ft = AEE_FT_TAB_TOP; // 项目的帧类型
ni.xOffset = 8; //项目内部的X 填补 (不包括帧大小)
ni.yOffset = 8; //项目内部的Y 填补 (不包括帧大小)
ni.roImage = AEE_RO_COPY; //绘制图像的光栅操作在
项目
// 内部
// 现在把项目样式设置为创建的样式
IMENUCTL_SetStyle(pMe->m_pStdMenu, &ni, &si);
BREW 应用程序可设计为在多种不同设备上并以多种不同语言执行。 您无需为每台设备和每种语言单独创建应用程序,而只需使用资源编辑器创建多个资源文件(.bar 文件)- 每种设备语言组合一个。 以这种方式将资源与代码分离将使您的 BREW 应用程序可以跨设备和语言进行移植。
您应该使用资源编辑器添加应用程序使用的所有字符串、图像和对话框资源。 然后,将每个资源与一个名称相关联,应用程序代码中将使用该名称。 有关如何生成资源 (.bar) 文件的详细信息,请参阅 BREW SDK™ 随附的《资源编辑器指南》。
2. 对每个目标设备使用不同的 MIF 文件
MIF 文件包含用于在可执行应用程序的菜单中显示应用程序的字符串和图像。 因此,您应该为每个设备语言组合创建不同的 MIF 文件。
3. 参照屏幕尺寸定位控件 - 避免将绝对像素值用作屏幕坐标
不同的目标设备具有不同的屏幕尺寸和不同的字体高度、宽度。 以下 BREW API 可用于获得这些特性,在设备上布置文本、图像和控件时将用到这些 API:
• ISHELL_GetDeviceInfo()
ISHELL_GetDeviceInfo 用于确定运行应用程序的
设备的屏幕尺寸。
AEEDeviceInfo di;
int cx, cy;
ISHELL_GetDeviceInfo(pIShell, &di);
cx = di.cxScreen; //用像素表示的装备宽度
cy = di.cyScreen; //用像素表示的装备高度
• IDISPLAY_GetFontMetrics()
IDISPLAY_GetFontMetrics() 用于查找特定
字体的字符高度。
int fontHeight;
fontHeight = IDISPLAY_GetFontMetrics(pme->a.m_pIDisplay,
AEE_FONT_BOLD, NULL,
NULL);
• IDISPLAY_MeasureText()
IDISPLAY_MeasureText() 用于在使用指定字体进行绘制时
测量给定字符串的像素宽度。
int stringWidth = IDISPLAY_MeasureText(pme->a.m_pIDisplay,
AEE_FONT_NORMAL,
textString);
• IDISPLAY_MeasureTextEx()
IDISPLAY_MeasureTextEx() 用于在给定显示字符串
的最大像素宽度和字体的情况下,
确定可以显示的输入文本字符串的字符数。
pixelWidth = IDISPLAY_MeasureTextEx(pMe->m_pIDisplay,
AEE_FONT_BOLD,
(AECHAR *) textString, // 文本字符串
-1,
di.cxScreen, // maxWidth
&pnFits); // 可以放得下的字符数
// maxWidth
pixelWidth 含有输入文本字符串的像素宽度。 pnFits
含有输入文本字符串字符数,这些字符数能够
在装备的一行中放得下。
• IIMAGE_GetInfo()
IIMAGE_GetInfo() 用于获取图像尺寸。
AEEImageInfo imgInfo;
int cx,cy;
IIMAGE_GetInfo(pIImage, &imgInfo);
cx = imgInfo.cx; //图像宽度
cy = imgInfo.cy; //图像高度
使用以上 API,您无需对像素值进行硬编码就可以
定位屏幕上的元素。 例如:
要绘制跨多行的文本:
// 获取装备信息
ISHELL_GetDeviceInfo(pMe->m_pIShell,&di);
// 获取字符量度信息
charHeight = IDISPLAY_GetFontMetrics (pMe->m_pIDisplay,
AEE_FONT_NORMAL, &pnAscent, &pnDescent);
// 转换为宽字符串 (unicode)
STR_TO_WSTR ((char *)displayStr, wideStr, sizeof (wideStr));
// psz 保留从字符串缓冲区写的点的踪迹
// 用于字符串无法全部放到一行而需要接到
// 下一行时。
psz = wideStr;
// 需要计算总字符串长度以决定是否需要
// 接到下一行。
totalCh = STRLEN ((char *)wideStr);
// 在数行显示文本字符串,如果字符串无法
显示在
//单一行时。
while ((totalCh > 0) && (*psz != NULL)) {
// 获取一行中会放得下多少个字符的信息。
pixelWidth = IDISPLAY_MeasureTextEx(pMe->m_pIDisplay, font,
(AECHAR *) psz, -1, di.cxScreen - 5, &pnFits);
IDISPLAY_DrawText(pMe->m_pIDisplay, AEE_FONT_NORMAL,
psz,
pnFits, 5, dy, 0, 0);
psz += pnFits; // 把指针移到下一个要
// 显示的节
totalCh -= pnFits; // 减少总字符数以止住
// 显示
dy += charHeight; // 把下一行 charHeight 像素放到
// 前一行下方。
IDISPLAY_Update(pMe->m_pIDisplay);
if (totalCh < pnFits) {
pnFits = totalCh; // 如果总数少于 pnFits,
// 则调节 pnFits
}
}
要在屏幕中心显示图像:
// 获取装备坐标
ISHELL_GetDeviceInfo(pMe->a.m_pIShell, &dInfo);
// 从资源文件加载图像
pIImage = ISHELL_LoadResImage(pMe->a.m_pIShell, szResFile,
IDB_BROWSER_ICON);
if (pIImage) {
// 获取图像大小
IIMAGE_GetInfo(pIImage, &aii);
// 计算用于位图的坐标 --
// 我们会在屏幕中央将其显示
img_x = (dInfo.cxScreen - aii.cx) / 2;
img_y = (dInfo.cyScreen - aii.cy)/ 2;
// 设置光栅操作
IIMAGE_SetParm(pIImage, IPARM_ROP, AEE_RO_NOT, 0);
// 在指定的坐标绘出非动画位图
IIMAGE_Draw(pIImage,img1_x,img1_y);
// 释放图像接口
IIMAGE_Release (pIImage);
}
4. 使用适当颜色深度的图像
对于不同的目标设备,应使用不同的资源文件。在这些文件中,使用颜色深度适合设备的图像。 如果您从外部网络获得图像,则可以查阅设备的颜色深度(包括屏幕尺寸)并使用这些值获取合适的图像。
AEEDeviceInfo di;
int cx, cy, colorDepth;
ISHELL_GetDeviceInfo(pIShell, &di);
cx = di.cxScreen; //用像素表示的宽度
cy = di.cyScreen; //用像素表示的高度
colorDepth = di.nColorDepth; // 装备的颜色深度
5. 伸展图像
在 BREW SDK 1.1 版中,可以使用 IGRAPHICS_StretchBlt() 将位图伸展到所需宽度和高度。 您可以比较屏幕尺寸(使用 ISHELL_GetDeviceInfo)和图像尺寸 (IIMAGE_GetInfo),然后根据需要将位图伸展到更加适当的大小。
IGRAPHICS_StretchBlt(pIGraphics,
xStart, //图像的左上角 x & y 坐标
yStart,
width, // 想要的图像宽度
height, //想要的图像高度
sourceBmp //源位图
rasterCode)
6. 动态查找特定图像或声音类型的处理程序
确定图像/声音类型的处理程序函数的 Class ID,然后
创建该 BREW 类的实例。
// 找出用于 bmp 图像的处理程序的 Class ID
if ((cls = ISHELL_GetHandler(pMe->a.m_pIShell, HTYPE_VIEWER,
"image/bmp")) == 0)
break;
// 用返回的 Class ID 创建图像处理程序的实例
ISHELL_CreateInstance(pMe->a.m_pIShell, cls, (void **)(&pIImage));
if(pIImage == NULL)
break;
7. 自定义菜单样式
使用标准菜单样式创建菜单时,菜单可能在不同的目标设备上不一样。 要保持您的菜单有一致的外观,您可以使用 IMENU_SetStyle() 自定义菜单样式(项目的边框类型、项目内 x 方向的填充、项目内 y 方向的填充、项目内绘制图像的光栅操作)。
AEEItemStyle si, ni;
// 所选菜单项目的项目样式
si.ft = AEE_FT_TAB_TOP_SEL; // 项目的帧类型
si.xOffset = 8; //项目内部的X 填补 (不包括帧大小)
si.yOffset = 8; //项目内部的Y 填补 (不包括帧大小)
si.roImage = AEE_RO_COPY; // 绘制图像的光栅操作在
// 项目内部
// 一般菜单项目的项目样式
ni.ft = AEE_FT_TAB_TOP; // 项目的帧类型
ni.xOffset = 8; //项目内部的X 填补 (不包括帧大小)
ni.yOffset = 8; //项目内部的Y 填补 (不包括帧大小)
ni.roImage = AEE_RO_COPY; //绘制图像的光栅操作在
项目
// 内部
// 现在把项目样式设置为创建的样式
IMENUCTL_SetStyle(pMe->m_pStdMenu, &ni, &si);