400-878-1895px51870017
葩星1752902151 淘宝旺旺passiontechinc
sales@51LM.cn 13296027252
  加载中,请稍候...
浏览历史

 


学习wince的十个忠告_

关键词: 学习wince,十个忠告,


简介:/* Generator: eWebEditor */p.MsoNormal, li.MsoNormal, div.MsoNormal {margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:inter-ideograph;font-size:10.5pt;font-family:"Times New Roman";}div.Section1 {page:Section1;}/* Generator: eWebEditor */p.MsoNormal, li.MsoNormal, div.MsoNormal {margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:inter-ideograph;font-size:10.5pt;font-f...
品 牌 葩星 葩星
产 地 中国
型 号 PXF0258
折 扣 其他电询
咨询专家:

夏工-工业总线-工业自动化-实时仿真

夏工-工业总线-工业自动化-实时仿真 ID:2937

机电电子工程专业硕士,机械设计制造及其自动化/计算机双学士,高级工程师

具有丰富的从业、管理经验,曾在机电工程公司,资深设计代理公司工作。历任组织、经理等岗位,同时具有深厚的理论基础和项目项目研发经历。...

[MORE]

赵工-总线系统-嵌入式系统-工业自动化

赵工-总线系统-嵌入式系统-工业自动化 ID:2940

机械电子工程,嵌入式系统专家,高级工程师

嵌入式项目开发,ARM,Freescale,Infilion等系列单片机系统开发,DSP嵌入式系统开发,FPGA系统开发,项目经验丰富。


...

[MORE]

产品说明:

学习wince的十个忠告

 

将已有的应用程序移植到Microsoft Windows CE中。一般说来,这个计划不是太难。我们起步于Microsoft Win32代码,当然Windows CE是基于Win32应用程序接口(API)的。有利的是,我们的应用程序(即Raima 数据管理器)有方便的使用接口,并包含一个大约由150个子函数组成的库,这些函数都是由C语言写成,可以用来创建、管理和访问数据库。

  按建立应用程序的方式来说,我们原以为将它移植到Windows CE中是一项相对简单的C语言编程练习。然而,我们不久便遇到好些困难。从粗心大意的错误开始,比如在基于Windows NT Windows CE仿真器上使用Microsoft Windows NT库,接着又违背Windows CE的编程戒律,如"千万不要给Unicode(国际标准组织10646标准)字符分配奇数内存地址"

  大约有百分之九十的问题或多或少地与Unicode有关。尽管Unicode编程不难,但是,当给单字节字符编写代码时,很容易出错(我有过许多次错误)。

  下面这些忠告是根据我们在Windows CE上编写Raima 数据管理器的经验总结出来的,但我相信,在做任何其它Windows CE程序之前,它们都值得借鉴。毕竟大多数Windows开发者,当他们创建第一个Windows CE应用程序时,真正运用的是已掌握的Win32知识。

  1. 不要在仿真器上使用Windows NT

  这里所讨论的第一个错误实在太愚蠢了,但我还是陷了进去,也许你也会。当用Microsoft VC++5.0版)创建一个Windows CE程序时,你会发现,包含路径(include)、 库路径(library)、及可执行程序路径被自动调整以匹配反应目标环境的选择。因此,比如说为Windows CE模拟器建立应用程序时,你会发现,include路径没有指向Win32的包含文件(在VC目录下),而是指向Windows CE包含文件(在WCE目录下)。千万别去修改。

  由于Windows CEWindows NT下运行,所以仿真器上运行的程序能够调用任一Windows NT动态链接库(DLL)中的函数,即使这个DLL不是模拟器的成员也一样。显然,这不是很好的事,因为相同的函数也许在手持PC(H/PC)Windows CE设备上不可用,而你的软件最终要能在这些设备上运行。

  第一次将非Unicode应用程序装入Windows CE仿真器时,你会发现,许多正在使用的函数它都不支持,例如美国国家标准协会(ANSI)定义的字符函数strcpy()。这也许引诱你去链接Windows NT 运行时间库,以便能解决所有问题。

  如果你是刚开始用Windows CE编程,可能你能用的包含文件和库文件是明显的。答案就是,你不要采用那些在写普通Win32或非Windows CE程序时使用的包含文件和库文件。

2. 不要混淆TCHARsbytes

  如果你正在Windows CE上写非Unicode应用程序,你或许要将所有的字符串从单个字符(chars)转换为宽字符(widechars)(例如,C变量类型whcar_t)。几乎所有Windows CE支持的Win32和运行时间库函数都要求宽字符变量。Windows 95不支持Unicode,然而,为了使程序代码具有可移植性,你要尽可能采用tchar.h中定义的TCHAR类型,不要直接使用wchar_t

  TCHAR是定义为wchar_t还是char,取决于预处理器的符号UNICODE是否定义。同样,所有有关字符串处理函数的宏,如_tcsncpy宏,它是定义为Unicode函数wcsncpy还是定义为ANSI函数strncpy,取决于UNICODE是否定义。

  在现存的Windows应用程序中,有些代码也许暗示字符长为单字节。这在给字符串分配内存时经常用到,例如:

int myfunc(char *p)
{
char *pszFileName;

pszFileName = malloc(MAXFILELEN);
if(pszFileName)
strncpy(pszFileName, p, MAXFILELEN);
/*etc*/

  在这段代码中,分配的内存块应该写作(MAXFILELEN * sizeof(char)),但是大多数程序员喜欢将它简化为MAXFILELEN,因为对于所有的平台来说sizeof(char)的值等于1。然而,当你用TCHARS代替多个字符时,很容易忘记这种固有的概念,于是将代码编写成下面的形式:

int myfunc(TCHAR *p)
{
TCHAR *pszFileName;

PszFileName = (TCHAR*)malloc(MAXFILELEN);
If (pszFileName)
tcsncpy(pszFileName, p, MAXFILELEN);
/*etc*/

  这是不行的。它马上会导致出错。这里的错误在于malloc函数中指定变量大小为bytes,然而_tcsncpy函数中使用的第三个变量却指定为TCHARs而不是bytes。当UNICODE被定义时,一个TCHAR等于两个字节数(bytes)

  上述代码段应该改写为:

int myfunc(TCHAR *p)
{
TCHAR *pszFileName;

PszFileName = (TCHAR*)malloc(MAXFILELEN * sizeof(TCHAR));
if(pszFileName)
tcsncpy(pszFileName, p, MAXFILELEN);
/*etc*/

  3. 不要将Unicode 字符串放入奇数内存地址

  在Intel系列处理器上,你可以在一奇数内存地址储存任何变量或数组,不会导致任何致命的错误影响。但在H/PC上,这一点不一定能行 ? 你必须对大于一个字节的数据类型小心谨慎,包括定义为无符号短型(unsigned short wchar_t。当你设法访问它们的时候,将它们置于奇地址会导致溢出。

  编辑器经常在这些问题上提醒你。你无法管理堆栈变量地址,并且编辑器会检查确定这些地址与变量类型是否相匹配。同样,运行时间库必须保证从堆中分配的内存总是满足一个word边界 ,所以你一般不必担心那两点。但是,如果应用程序含有用memcpy()函数拷贝内存区域的代码,或者使用了某种类型的指针算术以确定内存地址,问题也许就出现了。考虑下面的例子:

int send_name (TCHAR * pszName)
{
char *p, *q;
int nLen=(_tcslen(pszName) + 1) * sizeof(TCHAR);

p=maloc(HEADER_SIZE + nLen);
if(p)
{
q = p + HEADER_SIZE;
_tcscpy((TCHAR*)q, pszName);
}
/* etc */

  这段代码是从堆中分配内存并复制一个字符串,在字符串的开头留一个HEADER_SIZE的大小。假设UNICODE定义了,那么该字符串就是一个widechar字符串。如果HEADER_SIZE是一个偶数,这段代码就会正常工作,但如果HEADER_SIZE为奇数,这段代码就会出错,因为q指向的地址也将为奇数。

  注意,当你在Intel系列处理器中的Windows CE仿真器上测试这段代码时,这个问题是不会发生的。

  在这个例子中,只要确保HEADER_SIZE为偶数,你就可以避免问题的发生。然而,在某些情况下你也许不能这么做。例如,如果程序是从一台式PC输入数据,你也许不得不采用事先定义过的二进制格式,尽管它对H/PC不适合。在这种情况下,你必须采用函数,这些函数用字符指针控制字符串而不是TCHAR指针。如果你知道字符串的长度,就可以用memcpy()复制字符串。因此,采用逐个字节分析Unicode字符串的函数也许足以确定字符串在widechars中的长度。

  4. ANSIUnicode字符串之间进行翻译

  如果你的Windows CE应用程序接口于台式PC,也许你必须操作PC机中的ANSI字符串数据(例如,char字符串)。即使你在程序中只用到Unicode字符串,这都是事实。

  你不能在Windows CE上处理一个ANSI字符串,因为没有操纵它们的库函数。最好的解决办法是将ANSI字符串转换成Unicode字符串用到H/PC上,然后再将Unicode字符串转换回ANSI字符串用到PC上。为了完成这些转换,可采用MultiByteToWideChar()WideCharToMultiByte () Win32 API 函数。

5. 对于Windows CE 1.0的字符串转换,劈开(hack

  在Windows CE 1.0 版本中,这些Win32API函数还没有完成。所以如果你想既要支持CE 1.0又能支持CE 2.0,就必须采用其它函数。将ANSI字符串转换成Unicode字符串可以用wsprintf(),其中第一个参数采用一widechar字符串,并且认识"%S"(大写),意思是一个字符串。由于没有wsscanf() wsprintfA(),你必须想别的办法将Unicode字符串转换回ANSI字符串。由于Windows CE 1.0不在国家语言支持(NLS)中,你也许得求助于hack,如下所示:

/*
Definition / prototypes of conversion functions
Multi-Byte (ANSI) to WideChar (Unicode)

atow() converts from ANSI to widechar
wtoa() converts from widechar to ANSI
*/
#if ( _WIN32_WCE >= 101)

#define atow(strA, strW, lenW)
MultiByteToWidechar (CP_ACP, 0, strA, -1, strW, lenW)

#define wtoa(strW, strA, lenA)
WideCharToMutiByte (CP_ACP, 0, strW, -1, strA, lenA, NULL, NULL)

#else /* _WIN32_WCE >= 101)*/

/*
MultiByteToWideChar () and WideCharToMultiByte() not supported o-n Windows CE 1.0
*/
int atow(char *strA, wchar_t *strW, int lenW);
int wtoa(wchar_t *strW, char *strA, int lenA);

endif /* _WIN32_WCE >= 101*/

#if (_WIN32_WCE <101)

int atow(char *strA, wchar_t *strW, int lenW)
{
int len;
char *pA;
wchar_t *pW;

/*
Start with len=1, not len=0, as string length returned
must include null terminator, as in MultiByteToWideChar()
*/
for(pA=strA, pW=strW, len=1; lenW; pA++, pW++, lenW--, len++)
{
*pW = (lenW = =1) ? 0 : (wchar_t)( *pA);
if( ! (*pW))
break;
}
return len;
}

int wtoa(wxhar_t *strW, char *strA, int lenA)
{
int len;
char *pA;
wchar_t *pW;
/*
Start with len=1,not len=0, as string length returned
Must include null terminator, as in WideCharToMultiByte()
*/
for(pA=strA, pW=strW, len=1; lenA; pa++, pW++, lenA--, len++)
{
pA = (len==1)? 0 : (char)(pW);
if(!(*pA))
break;
}
return len;
}

#endif /*_WIN32_WCE<101*/

  这种适合于Windows CE 1.0的实现办法比使用wsprintf()函数要容易,因为使用wsprintf()函数更难以限制目标指针所指向的字符串的长度。

  6. 选择正确的字符串比较函数

  如果你要分类Unicode标准字符串,你会有以下几个函数可供选择:

wcscmp(), wcsncmp(), wcsicmp(), wcsnicmp()

wcscoll(), wcsncoll(), wcsicoll(),wcsnicoll()

CompareString()

  第一类函数可用来对字符串进行比较,不参考当地(Locale)或外文字符。如果你永远不想支持外文,或者你仅仅想测试一下两个字符串的内容是否相同,这类函数非常好用。

  第二类函数使用现有的当地设置(current locale settings)(系统设置,除非你在字符串比较函数之前调用了wsetlocale()函数)来比较两个字符串。这些函数也能正确分类外文字符。如果当地的字符"C""C" locale)被选定,这些函数与第一类函数就具有了相同的功能。

  第三类函数是Win32函数CompareString()。这个函数类似于第二类函数,但是它允许你指定当地设置(the locale)作为一个参数,而不是使用现有的当地设置(current locale settings)CompareString()函数允许你选择性地指定两个字符串的长度。你可以将第二个参数设置为NORM_IGNORECASE,从而使函数比较字符串时不比较大小写。

  通常,即使不将第二个参数设置为NORM_IGNORECASECompareString()函数也不用来区分大小写。我们经常用wcsncoll()函数来区分大小写,除非使用当地的字符"C""C" locale)。所以,在我们的代码中,不使用CompareString()函数来区分大小写,而用wcsncoll()函数来区分大小写

  7. 不要使用相对路径

  与Windows NT不一样,Windows CE没有当前目录这个概念,因此,任何路径只是相对于根目录而言的。如果你的软件给文件或目录使用相对路径,那么你很可能把它们移到别的地方了。例如,路径".abc"Windows CE中被当作"abc"看待。

  8.移走了对
































































参数资料:
学习wince的十个忠告_学习wince,十个忠告,
该文章系原厂商文章翻译,不通之处请参考原文
价格列表: 学习wince的十个忠告_学习wince,十个忠告,
葩星订货号 订货号 产品名称 报价 品牌  
相关产品: 学习wince的十个忠告_学习wince,十个忠告,
  咨询历史: