袁瑞 的个人资料袁瑞的共享空间照片日志留言簿更多 工具 帮助

日志


动态创建的TIdTime控件无法获取准确时间的问题

在BCB2009内测试发现,使用代码动态创建的TIdTime获取到的服务器时间,总是比服务器的实际时间少两天。于是创建一个测试程序,将TIdTiime控件直接拖放到窗口中,测试发现获取到的时间是正确的。一切都是默认设置,代码中和界面中都只是设置了Host属性而已,到底区别在哪里呢?

我开始怀疑BaseDate属性,这个属性在拖放到界面上后会自动设置为一个默认值,如下图:1900/1/1,由于我使用的是英文操作系统,在其他系统上也许不是用/来分隔的。

image

查看TIdTime类的头文件,发现其属性BaseTime并没有默认值

__property System::TDateTime BaseDate = {read=FBaseDate, write=FBaseDate};

在IDE属性编辑器中的默认值也许是在窗口内创建控件时加入的,而通过代码动态创建时似乎未设置。

RFC868中要求的时间是从00:00 (midnight) 1 January 1900 GMT开始,而TDateTime是从12/30/1899 12:00开始计算,恰好是2天!

于是我在动态创建TIdTime后,再设置BaseDate,测试获取时间正常了。

这里需要提醒一下,BaseDate是TDateTime类型,如果要将字符串“1900-1-1”转换为TDateTime类型,也许会出现错误,原因是日期分隔符不一定是"-",日期格式也不一定是YYYY-MM-DD,需要设置日期格式和分隔符,再进行转换:

    DateSeparator = '-';
    ShortDateFormat = "yyyy-mm-dd";
    StrToDateTime("1900-1-1");

值得注意的是,似乎TIdTime控件在BCB6下的版本无此问题,BCB2009的TIdTime版本存在这个问题。

1月11日

bcb.exe.manifest 引发的“血案”

升级到英文Vista后,最近发现BCB6中一些使用了ImageList类的程序会启动失败报Failed to read ImageList data的错误,让人很是费解。还有的程序可以在Vista下正常运行,但是在Xp下启动却会出现这个错误。一怒之下只能怪罪于TImageList,不曾想却是一桩冤案。

在使用Xp系统时,我就为了让BCB6.0的IDE也具有XP界面风格,将bcb.exe.manifest拷贝到安装目录下,这样可以强制BCB使用XP界面风格,即启用COMCTL32.DLL版本6(Vista下应该是更高版本)支持。这样界面在IDE的设计期内使用的是新版本,但是程序运行时如果不设置启用新版本支持就出现TImageList运行时无法正常读取数据的问题。

为了反向验证,将BCB目录下的bcb.exe.manifest文件删除,再打开问题程序时,打开界面时同样开始报错了。

同样也可以解释Vista下运行正常的程序,返回到Xp下运行失败的问题。Vista下程序内支持了更高版本的界面特性,导致TImageList在XP下运行无法读取数据,程序仍然遇到了类似的问题。

1月8日

setlocale同mbstowcs函数的关系

程序中,如果要将ASCII码字符串转换为宽字符(Unicode),可以利用标准C的mbstowcs函数。

微软在MSDN中有示例,如下:

image

然而,这段代码在处理含有汉字的字符串时就会出现问题。比如将:

image 替换为image

查看运行结果就会发现,mbstowcs函数将汉字视作两个ASCII字符,这样一个汉字就变成了两个wchar_t。原因是mbstowcs需要我们明确的告诉他要转换的字符语言。这里需要使用setlocale函数。在网上发现不少人遇到这个问题,微软的MSDN也是,为什么这里就不说明一下呢?

只要在调用前,使用setlocale(LC_ALL, "chs")设置,结果就正常了。

我测试在英文Vista操作系统内,Visual Studio 2008下setlocale(LC_ALL, "chs")可以执行成功。

但是在Borland C++Builder 6、CodeGear RAD Studio 2009下执行都失败,BCB提供的帮助文件内也未找到,反复测试使用setlocale(LC_ALL, "Chinese (Simplified)_People's Republic of China")可以奏效(这么大一个长串,BCB对搞中文编码的程序员也够狠)。

更讽刺的是,在BCB内使用setlocale(LC_ALL, "jpn"),或"cht"都可以成功。唯独就不支持"chs",对BCB的做法彻底无语了。我相信在大多数unix或linux上也还是支持"chs"的。如果有时间,我再搞一个MinGW试试看。

另外如果程序运行在非中文操作系统内,使用setlocale修改运行时字符集环境,会影响当前应用程序的编码方式,因此使用前需要保留一下老的编码,使用后再恢复。

 

for 在linux上coding的兄弟们,locale别名表大概在 /usr/lib/X11/locale/locale.alias