>
为了使应用程序的维护和支持工作尽可能少,开发人员希望使计划支持的平台都用统一的源代码,甚至希望可以使一个二进制文件在两个平台上都能运行,以下技巧将有助于您实现这个目标。
一、检查平台的版本
在编译时确定平台的版本,那样可以使用同一套源代码来在编译时适应不同平台二进制文件。
在程序运行时检查平台的版本,这样就可以根据判断来进行不同的操作,使用同一个二进制文件能运行在不同的平台上。
#define POCKETPCV1 1
#define SMARTPHONEV1 2
#define POCKETPCV2 3
#define SMARTPHONEV2 4
int MyDeviceType()
{
TCHAR szPlatform[MAX_STRING_BUFFER];
int iDeviceType=0;
OSVERSIONINFO osVer;
GetVersionEx(&osVer);
if (osVer.dwMajorVersion==3)
{
if (SystemParametersInfo(SPI_GETPLATFORMTYPE,
sizeof(szPlatform),szPlatform,0)!=0)
{
if (lstrcmp(szPlatform,TEXT("PocketPC"))==0)
iDeviceType= POCKETPCV1; // runs on Pocket PC 2000 and 2002
else if (lstrcmp(szPlatform,TEXT("Smartphone"))==0)
iDeviceType= SMARTPHONEV1; // runs on Smartphone 2002
}
else
{
if (GetLastError()==ERROR_ACCESS_DENIED) //(5)
iDeviceType= SMARTPHONEV1; // is a smartphone:
// Smartphone creates an access denied error on
// SystemParametersInfo()
}
}
else
{
if (osVer.dwMajorVersion==4)
{
if (SystemParametersInfo(SPI_GETPLATFORMTYPE,
sizeof(szPlatform),szPlatform,0)!=0)
{
if (lstrcmp(szPlatform,TEXT("PocketPC"))==0)
iDeviceType= POCKETPCV2; // runs on Pocket PC 2003
else if (lstrcmp(szPlatform,TEXT("Smartphone"))==0)
iDeviceType= SMARTPHONEV2; // runs on Smartphone 2003
}
else
{
if (GetLastError()==ERROR_ACCESS_DENIED) //(5)
iDeviceType= SMARTPHONEV2; // is a smartphone:
// Smartphone creates an access denied error on
// SystemParametersInfo()
}
}
}
return iDeviceType;
}
在 Smartphone 上调用“SystemParametersInfo()”时,如果Smartphone 锁定和应用程序签署的证书,可能会引起“Access Denied”而失败 。因为只有Smartphone 才会引起 Access Denied 失败,所以您也可以用它作为 Smartphone 的标记。
二、在程序中确定“My Document”和存储卡的位置
发现存储卡:
void ShowFlashCard()
{
BOOL bContinue = TRUE;
HANDLE hFlashCard;
WIN32_FIND_DATA lpwfdFlashCard;
hFlashCard = FindFirstFlashCard (&lpwfdFlashCard);
if (hFlashCard == INVALID_HANDLE_VALUE)
return;
while (bContinue)
{
MessageBox(NULL,lpwfdFlashCard.cFileName,
TEXT("FindFlash"),MB_OK);
bContinue = FindNextFlashCard (hFlashCard,
&lpwfdFlashCard);
}
FindClose (hFlashCard); // Close the search handle.
}
发现“My Documents”:
不同语言版本的Windows Mobile的路径名是不同的,如:
英文版是“My Documents”
简体中文版是“我的文档”
德文版是“Meine Dokumente”
应该使用以下的调用来获取指向My Documents的正确路径。
SHGetSpecialFolderPath(NULL,szTxt,CSIDL_PERSONAL,0);
CSIDL_PERSONAL 请求“My Documents”文件夹以 szTxt (TCHAR) 形式返回。
三、为每个平台使用不同的资源定义
如果您想让相同的二进制文件既可用于 Pocket PC,又可用于 Smartphone,您必须创建两种资源定义,一个平台一种。如果您只想使源代码保持同步,您可以使用资源的“condition”属性来包含正确的资源。
假如您想让二进制文件具有兼容性,您需要在代码中加载 Pocket PC 或 Smartphone 资源:
switch (iDeviceType) // Determined with tip -1- above
{
case SMARTPHONEV1:
case SMARTPHONEV2:
idd=IDD_SMARTPHONE;
break;
case POCKETPCV1:
case POCKETPCV2:
idd=IDD_POCKETPC;
break;
default:
idd=IDD_HPC;
break;
}
return DialogBox(hInst,MAKEINTRESOURCE(idd),
hWndMain,(DLGPROC)StartDlgMain);
如果您使用资源的 Condition 属性,请在 condition 字段中放入“WIN32_PLATFORM_WFSP”(对于 Smartphone)和“WIN32_PLATFORM_PSPC”(对于 Pocket PC)。请记住 Palm-size PC(Pocket PC 的前身)和最近出现的 Pocket PC 2003 与 Smartphone 有相同的定义,所以如果您想加以区分,您需要创建自己的定义。如果您试图保持二进制文件/可执行文件的平台无关性,您必须对不同平台使用不同资源,但将二者都包含在资源文件中。
四、动态加载 Pocket PC 和 Smartphone 的特定库
如果希望可以使一个二进制文件在两个平台上都能运行,任何时候加载以下 DLL 的其中一个时,请确保使用“LoadLibrary”和“GetProcAddress”,而不是将 DLL 静态链接到应用程序:
• AYGSHELL.DLL (AYGSHELL.LIB/AYGSHELL.h)。包含所有 SIP、SH… 和其他特定于 Pocket PC 的函数。该 DLL 也可用于 Smartphone,但有不同的功能集。
• CELLCORE.DLL (CellCore.LIB/TSP.h and others)。这个 DLL 只存在于 Pocket PC 2002 Phone Edition 和 Smartphone,而不存在于 Pocket PC 2000。它包含了用于连接管理器和进行电话呼叫的所有函数。
在运行时加载这些 DLL 可以让您开发一些智能的错误处理,它仍然允许应用程序在不具备这些库所提供的功能的情况下运行。如果这些库在编译过程中静态链接,则在 Pocket PC 2002 上应用程序甚至不会启动,因为它试图加载这些 DLL 并给出错误“One or more components are missing”。
如果您只想使源代码保持同步,您不需要这样做;而可以将这些库链接到编译过程中。然而要注意,每次在 Pocket PC 2000 和 Pocket PC 2002 编译过程间切换时,都必须手动取出 cellcore.lib。
五、不要假设有触摸屏
Smartphone 没有触摸屏,而 Pocket PC 没有数字键可以点击,但这两种设备都支持 D-pad 的类似于键盘的导航。因此,如果您想保持源代码同步,所有需要导航的用户输入都应该通过 D-pad 导航来实现。Pocket PC 中的菜单是通过触摸屏激活的,而在 Smartphone 中是通过热键激活的。但因为平台会为您处理该输入,所以您不需要为此担心。
参考文献:
《如何维护用于 Pocket PC 和 Smartphone 的单一二进制文件》Microsoft