2008年10月15日星期三

FW: 在Windows下测试Apache遇到的80端口占用问题

在Windows下测试Apache遇到的80端口占用问题

虽然我这个blog(跑在Linux服务器上,但许多调试工作还是只能用WAMP体系,即,Windows+Apache+MySQL+PHP,许多人对这个体系很是鄙视,其实我认为,如非必须使用Windows,谁也没有必要这样来用Apache,因此,苹果粉丝和命令行专家可以绕过此文了:)

下面,我来谈一谈我在配置WAMP时频繁遇到的一个问题:80端口占用。(非IIS占用)

两年多以前,我曾经发现Skype有这个坏毛病(由于用Skype不多,现在我也不知道Skype的目的在何,欢迎赐教)。几个月前,又发现PPLive也有这个毛病,只不过那次根据处理Skype问题的经验,我很快就解决了。今天,又再次遇到这个问题时,我困惑了:既没有PPLive,也没有Skype,80还是被占用了。用netstat看端口的 pid,也发现很奇怪:有时候不显示80,有时候又显示为0,这是系统限制资源,显然不是我要找的"元凶"。

Google了"pid 0 80 port",看到了答案:

Try typing 'netstat -ao' (with an 'a') at CMD and that will give you a list of everything running on each port.

我一眼就看到了那个"罪魁祸首":

C:\Users\awflasher>netstat -ao
Local Address Foreign Address State PID TCP
TCP 0.0.0.0:21 Pacers:0 LISTENING 511
TCP 0.0.0.0:80 Pacers:0 LISTENING 6421

用tasklist的FILTER,我们可以很快找到这个进程:

C:\Users\awflasher>tasklist /FI "PID eq 6421"
Image Name PID Session Name Session# Mem Usage
========================= ======== ================ =========== ============
MxDownloadServer.exe 6421 Console 1 7,980 K

原来是我电脑中"遨游浏览器"的进程。我使用遨游只是为了调试页面代码,这里我不做评价,浏览器这种敏感的话题,人各有志,各取所好。

PS:看了看netstat的帮助,分别如此描述-a和-o,也就明白了:

-a Displays all connections and listening ports.
-o Displays the owning process ID associated with each connection.

在本地用WAMP调试WordPress的blogger如果遇到类似的情况(症状主要是Apache无法启动),则可以用netstat -ao和tasklist来查出80端口到底被谁抢占了。

附,我所知道的Windows上一些默认占用80端口的非Web服务器类软件清单,欢迎补充:

* Skype
* Web迅雷
* PPLive(可能是pp.tv,我懒得管了)
* 傲游浏览器自动更新
* 迅雷默认的BT上传端口(网友补充)
* fs2you网盘(网友补充)
* Cisco IP Communicator(网友补充)
* QQMusic(网友补充)

2008年8月13日星期三

FW: CString 操作指南

原著:Joseph M. Newcomer

翻译:littleloach

原文出处:codeproject:CString Management


通过阅读本文你可以学习如何有效地使用 CString。

  CString 是一种很有用的数据类型。它们很大程度上简化了MFC中的许多操作,使得MFC在做字符串操作的时候方便了很多。不管怎样,使用CString有很多特殊的技巧,特别是对于纯C背景下走出来的程序员来说有点难以学习。这篇文章就来讨论这些技巧。
  使用CString可以让你对字符串的操作更加直截了当。这篇文章不是CString的完全手册,但囊括了大部分常见基本问题。

这篇文章包括以下内容:

1.

CString 对象的连接
2. 格式化字符串(包括 int 型转化为 CString )
3. CString 型转化成 int 型
4. CString 型和 char* 类型的相互转化
5. char* 转化成 CString
6. CString 转化成 char* 之一:使用LPCTSTR强制转化
7. CString 转化成 char* 之二:使用CString对象的GetBuffer方法
8. CString 转化成 char* 之三: 和控件的接口
9. CString 型转化成 BSTR 型;
10. BSTR 型转化成 CString 型;
11. VARIANT 型转化成 CString 型;
12. 载入字符串表资源;
13. CString 和临时对象;
14. CString 的效率;
15. 总结

下面我分别讨论。

1、CString 对象的连接

  能体现出 CString 类型方便性特点的一个方面就字符串的连接,使用 CString 类型,你能很方便地连接两个字符串,正如下面的例子:

CString gray("Gray");
CString cat("Cat");
CString graycat = gray + cat;

要比用下面的方法好得多:

char gray[] = "Gray";
char cat[] = "Cat";
char * graycat = malloc(strlen(gray) + strlen(cat) + 1);
strcpy(graycat, gray);
strcat(graycat, cat);

2、格式化字符串

  与其用 sprintf() 函数或 wsprintf() 函数来格式化一个字符串,还不如用 CString 对象的Format()方法:

CString s;
s.Format(_T("The total is %d"), total);

  用这种方法的好处是你不用担心用来存放格式化后数据的缓冲区是否足够大,这些工作由CString类替你完成。
  格式化是一种把其它不是字符串类型的数据转化为CString类型的最常用技巧,比如,把一个整数转化成CString类型,可用如下方法:

CString s;
s.Format(_T("%d"), total);

  我总是对我的字符串使用_T()宏,这是为了让我的代码至少有Unicode的意识,当然,关于Unicode的话题不在这篇文章的讨论范围。_T()宏在8位字符环境下是如下定义的:

#define _T(x) x // 非Unicode版本(non-Unicode version)

而在Unicode环境下是如下定义的:

#define _T(x) L##x // Unicode版本(Unicode version)

所以在Unicode环境下,它的效果就相当于:

s.Format(L"%d", total);

  如果你认为你的程序可能在Unicode的环境下运行,那么开始在意用 Unicode 编码。比如说,不要用 sizeof() 操作符来获得字符串的长度,因为在Unicode环境下就会有2倍的误差。我们可以用一些方法来隐藏Unicode的一些细节,比如在我需要获得字符长度的时候,我会用一个叫做DIM的宏,这个宏是在我的dim.h文件中定义的,我会在我写的所有程序中都包含这个文件:

#define DIM(x) ( sizeof((x)) / sizeof((x)[0]) )

  这个宏不仅可以用来解决Unicode的字符串长度的问题,也可以用在编译时定义的表格上,它可以获得表格的项数,如下:

class Whatever { ... };
Whatever data[] = {
{ ... },
...
{ ... },
};
for(int i = 0; i < DIM(data); i++) // 扫描表格寻找匹配项。

  这里要提醒你的就是一定要注意那些在参数中需要真实字节数的API函数调用,如果你传递字符个数给它,它将不能正常工作。如下:

TCHAR data[20];
lstrcpyn(data, longstring, sizeof(data) - 1); // WRONG!
lstrcpyn(data, longstring, DIM(data) - 1); // RIGHT
WriteFile(f, data, DIM(data), &bytesWritten, NULL); // WRONG!
WriteFile(f, data, sizeof(data), &bytesWritten, NULL); // RIGHT

造成以上原因是因为lstrcpyn需要一个字符个数作为参数,但是WriteFile却需要字节数作为参数。
同样需要注意的是有时候需要写出数据的所有内容。如果你仅仅只想写出数据的真实长度,你可能会认为你应该这样做:

WriteFile(f, data, lstrlen(data), &bytesWritten, NULL); // WRONG

但是在Unicode环境下,它不会正常工作。正确的做法应该是这样:

WriteFile(f, data, lstrlen(data) * sizeof(TCHAR), &bytesWritten, NULL); // RIGHT

  因为WriteFile需要的是一个以字节为单位的长度。(可能有些人会想"在非Unicode的环境下运行这行代码,就意味着总是在做一个多余的乘 1操作,这样不会降低程序的效率吗?"这种想法是多余的,你必须要了解编译器实际上做了什么,没有哪一个C或C++编译器会把这种无聊的乘1操作留在代码中。在Unicode环境下运行的时候,你也不必担心那个乘2操作会降低程序的效率,记住,这只是一个左移一位的操作而已,编译器也很乐意为你做这种替换。)
  使用_T宏并不是意味着你已经创建了一个Unicode的程序,你只是创建了一个有Unicode意识的程序而已。如果你在默认的8-bit模式下编译你的程序的话,得到的将是一个普通的8-bit的应用程序(这里的8-bit指的只是8位的字符编码,并不是指8位的计算机系统);当你在 Unicode环境下编译你的程序时,你才会得到一个Unicode的程序。记住,CString 在 Unicode 环境下,里面包含的可都是16位的字符哦。

3、CString 型转化成 int 型

  把 CString 类型的数据转化成整数类型最简单的方法就是使用标准的字符串到整数转换例程。
  虽然通常你怀疑使用_atoi()函数是一个好的选择,它也很少会是一个正确的选择。如果你准备使用 Unicode 字符,你应该用_ttoi(),它在 ANSI 编码系统中被编译成_atoi(),而在 Unicode 编码系统中编译成_wtoi()。你也可以考虑使用_tcstoul()或者_tcstol(),它们都能把字符串转化成任意进制的长整数(如二进制、八进制、十进制或十六进制),不同点在于前者转化后的数据是无符号的(unsigned),而后者相反。看下面的例子:

CString hex = _T("FAB");
CString decimal = _T("4011");
ASSERT(_tcstoul(hex, 0, 16) == _ttoi(decimal));

4、CString 型和 char* 类型的相互转化

  这是初学者使用 CString 时最常见的问题。有了 C++ 的帮助,很多问题你不需要深入的去考虑它,直接拿来用就行了,但是如果你不能深入了解它的运行机制,又会有很多问题让你迷惑,特别是有些看起来没有问题的代码,却偏偏不能正常工作。
比如,你会奇怪为什么不能写向下面这样的代码呢:

CString graycat = "Gray" + "Cat";

或者这样:

CString graycat("Gray" + "Cat");

  事实上,编译器将抱怨上面的这些尝试。为什么呢?因为针对CString 和 LPCTSTR数据类型的各种各样的组合," +" 运算符 被定义成一个重载操作符。而不是两个 LPCTSTR 数据类型,它是底层数据类型。你不能对基本数据(如 int、char 或者 char*)类型重载 C++ 的运算符。你可以象下面这样做:

CString graycat = CString("Gray") + CString("Cat");

或者这样:

CString graycat = CString("Gray") + "Cat";

研究一番就会发现:" +"总是使用在至少有一个 CString 对象和一个 LPCSTR 的场合。

注意,编写有 Unicode 意识的代码总是一件好事,比如:

CString graycat = CString(_T("Gray")) + _T("Cat");

这将使得你的代码可以直接移植。

char* 转化为 CString

  现在你有一个 char* 类型的数据,或者说一个字符串。怎么样创建 CString 对象呢?这里有一些例子:

char * p = "This is a test";

或者象下面这样更具有 Unicode 意识:

TCHAR * p = _T("This is a test")

LPTSTR p = _T("This is a test");

你可以使用下面任意一种写法:

CString s = "This is a test"; // 8-bit only
CString s = _T("This is a test"); // Unicode-aware
CString s("This is a test"); // 8-bit only
CString s(_T("This is a test")); // Unicode-aware
CString s = p;
CString s(p);

  用这些方法可以轻松将常量字符串或指针转换成 CString。需要注意的是,字符的赋值总是被拷贝到 CString 对象中去的,所以你可以象下面这样操作:

TCHAR * p = _T("Gray");
CString s(p);
p = _T("Cat");
s += p;

结果字符串肯定是"GrayCat"。

CString 类还有几个其它的构造函数,但是这里我们不考虑它,如果你有兴趣可以自己查看相关文档。

事实上,CString 类的构造函数比我展示的要复杂,比如:

CString s = "This is a test";

  这是很草率的编码,但是实际上它在 Unicode 环境下能编译通过。它在运行时调用构造函数的 MultiByteToWideChar 操作将 8 位字符串转换成 16 位字符串。不管怎样,如果 char * 指针是网络上传输的 8 位数据,这种转换是很有用的。

CString 转化成 char* 之一:强制类型转换为 LPCTSTR;

  这是一种略微硬性的转换,有关"正确"的做法,人们在认识上还存在许多混乱,正确的使用方法有很多,但错误的使用方法可能与正确的使用方法一样多。
  我们首先要了解 CString 是一种很特殊的 C++ 对象,它里面包含了三个值:一个指向某个数据缓冲区的指针、一个是该缓冲中有效的字符记数以及一个缓冲区长度。 有效字符数的大小可以是从0到该缓冲最大长度值减1之间的任何数(因为字符串结尾有一个NULL字符)。字符记数和缓冲区长度被巧妙隐藏。
  除非你做一些特殊的操作,否则你不可能知道给CString对象分配的缓冲区的长度。这样,即使你获得了该0缓冲的地址,你也无法更改其中的内容,不能截短字符串,也 绝对没有办法加长它的内容,否则第一时间就会看到溢出。
  LPCTSTR 操作符(或者更明确地说就是 TCHAR * 操作符)在 CString 类中被重载了,该操作符的定义是返回缓冲区的地址,因此,如果你需要一个指向 CString 的 字符串指针的话,可以这样做:

CString s("GrayCat");
LPCTSTR p = s;

  它可以正确地运行。这是由C语言的强制类型转化规则实现的。当需要强制类型转化时,C++规测容许这种选择。比如,你可以将(浮点数)定义为将某个复数 (有一对浮点数)进行强制类型转换后只返回该复数的第一个浮点数(也就是其实部)。可以象下面这样:

Complex c(1.2f, 4.8f);
float realpart = c;

如果(float)操作符定义正确的话,那么实部的的值应该是1.2。
  这种强制转化适合所有这种情况,例如,任何带有 LPCTSTR 类型参数的函数都会强制执行这种转换。 于是,你可能有这样一个函数(也许在某个你买来的DLL中):

BOOL DoSomethingCool(LPCTSTR s);

你象下面这样调用它:

CString file("c:\\myfiles\\coolstuff")
BOOL result = DoSomethingCool(file);

  它能正确运行。因为 DoSomethingCool 函数已经说明了需要一个 LPCTSTR 类型的参数,因此 LPCTSTR 被应用于该参数,在 MFC 中就是返回的串地址。

如果你要格式化字符串怎么办呢?

CString graycat("GrayCat");
CString s;
s.Format("Mew! I love %s", graycat);

  注意由于在可变参数列表中的值(在函数说明中是以"..."表示的)并没有隐含一个强制类型转换操作符。你会得到什么结果呢?
  一个令人惊讶的结果,我们得到的实际结果串是:

"Mew! I love GrayCat"。

  因为 MFC 的设计者们在设计 CString 数据类型时非常小心, CString 类型表达式求值后指向了字符串,所以这里看不到任何象 Format 或 sprintf 中的强制类型转换,你仍然可以得到正确的行为。描述 CString 的附加数据实际上在 CString 名义地址之后。
  有一件事情你是不能做的,那就是修改字符串。比如,你可能会尝试用","代替"."(不要做这样的,如果你在乎国际化问题,你应该使用十进制转换的 National Language Support 特性,),下面是个简单的例子:

CString v("1.00"); // 货币金额,两位小数
LPCTSTR p = v;
p[lstrlen(p) - 3] = '','';

  这时编译器会报错,因为你赋值了一个常量串。如果你做如下尝试,编译器也会错:

strcat(p, "each");

  因为 strcat 的第一个参数应该是 LPTSTR 类型的数据,而你却给了一个 LPCTSTR。

  不要试图钻这个错误消息的牛角尖,这只会使你自己陷入麻烦!

  原因是缓冲有一个计数,它是不可存取的(它位于 CString 地址之下的一个隐藏区域),如果你改变这个串,缓冲中的字符计数不会反映所做的修改。此外,如果字符串长度恰好是该字符串物理限制的长度(梢后还会讲到这个问题),那么扩展该字符串将改写缓冲以外的任何数据,那是你无权进行写操作的内存(不对吗?),你会毁换坏不属于你的内存。这是应用程序真正的死亡处方。

CString转化成char* 之二:使用 CString 对象的 GetBuffer 方法;

  如果你需要修改 CString 中的内容,它有一个特殊的方法可以使用,那就是 GetBuffer,它的作用是返回一个可写的缓冲指针。 如果你只是打算修改字符或者截短字符串,你完全可以这样做:

CString s(_T("File.ext"));
LPTSTR p = s.GetBuffer();
LPTSTR dot = strchr(p, ''.''); // OK, should have used s.Find...
if(p != NULL)
*p = _T(''\0'');
s.ReleaseBuffer();

  这是 GetBuffer 的第一种用法,也是最简单的一种,不用给它传递参数,它使用默认值 0,意思是:"给我这个字符串的指针,我保证不加长它"。当你调用 ReleaseBuffer 时,字符串的实际长度会被重新计算,然后存入 CString 对象中。
  必须强调一点,在 GetBuffer 和 ReleaseBuffer 之间这个范围,一定不能使用你要操作的这个缓冲的 CString 对象的任何方法。因为 ReleaseBuffer 被调用之前,该 CString 对象的完整性得不到保障。研究以下代码:

CString s(...);

LPTSTR p = s.GetBuffer();

//... 这个指针 p 发生了很多事情

int n = s.GetLength(); // 很糟D!!!!! 有可能给出错误的答案!!!

s.TrimRight(); // 很糟!!!!! 不能保证能正常工作!!!!

s.ReleaseBuffer(); // 现在应该 OK

int m = s.GetLength(); // 这个结果可以保证是正确的。

s.TrimRight(); // 将正常工作。

  假设你想增加字符串的长度,你首先要知道这个字符串可能会有多长,好比是声明字符串数组的时候用:

char buffer[1024];

表示 1024 个字符空间足以让你做任何想做得事情。在 CString 中与之意义相等的表示法:

LPTSTR p = s.GetBuffer(1024);

  调用这个函数后,你不仅获得了字符串缓冲区的指针,而且同时还获得了长度至少为 1024 个字符的空间(注意,我说的是"字符",而不是"字节",因为 CString 是以隐含方式感知 Unicode 的)。
  同时,还应该注意的是,如果你有一个常量串指针,这个串本身的值被存储在只读内存中,如果试图存储它,即使你已经调用了 GetBuffer ,并获得一个只读内存的指针,存入操作会失败,并报告存取错误。我没有在 CString 上证明这一点,但我看到过大把的 C 程序员经常犯这个错误。
  C 程序员有一个通病是分配一个固定长度的缓冲,对它进行 sprintf 操作,然后将它赋值给一个 CString:

char buffer[256];
sprintf(buffer, "%......", args, ...); // ... 部分省略许多细节
CString s = buffer;

虽然更好的形式可以这么做:

CString s;
s.Format(_T("%...."), args, ...);

如果你的字符串长度万一超过 256 个字符的时候,不会破坏堆栈。

  另外一个常见的错误是:既然固定大小的内存不工作,那么就采用动态分配字节,这种做法弊端更大:

int len = lstrlen(parm1) + 13 lstrlen(parm2) + 10 + 100;

char * buffer = new char[len];

sprintf(buffer, "%s is equal to %s, valid data", parm1, parm2);

CString s = buffer;

......

delete [] buffer;

它可以能被简单地写成:

CString s;

s.Format(_T("%s is equal to %s, valid data"), parm1, parm2);

  需要注意 sprintf 例子都不是 Unicode 就绪的,尽管你可以使用 tsprintf 以及用 _T() 来包围格式化字符串,但是基本 思路仍然是在走弯路,这这样很容易出错。

CString to char * 之三:和控件的接口;

  我们经常需要把一个 CString 的值传递给一个控件,比如,CTreeCtrl。MFC为我们提供了很多便利来重载这个操作,但是 在大多数情况下,你使用"原始"形式的更新,因此需要将墨某个串指针存储到 TVINSERTITEMSTRUCT 结构的 TVITEM 成员中。如下:

TVINSERTITEMSTRUCT tvi;
CString s;
// ... 为s赋一些值。
tvi.item.pszText = s; // Compiler yells at you here
// ... 填写tvi的其他域
HTREEITEM ti = c_MyTree.InsertItem(&tvi);

  为什么编译器会报错呢?明明看起来很完美的用法啊!但是事实上如果你看看 TVITEM 结构的定义你就会明白,在 TVITEM 结构中 pszText 成员的声明如下:

LPTSTR pszText;
int cchTextMax;

  因此,赋值不是赋给一个 LPCTSTR 类型的变量,而且编译器无法知道如何将赋值语句右边强制转换成 LPCTSTR。好吧,你说,那我就改成这样:

tvi.item.pszText = (LPCTSTR)s; //编译器依然会报错。

  编译器之所以依然报错是因为你试图把一个 LPCTSTR 类型的变量赋值给一个 LPTSTR 类型的变量,这种操作在C或C++中是被禁止的。你不能用这种方法 来滥用常量指针与非常量指针概念,否则,会扰乱编译器的优化机制,使之不知如何优化你的程序。比如,如果你这么做:

const int i = ...;
//... do lots of stuff
... = a[i]; // usage 1
// ... lots more stuff
... = a[i]; // usage 2

  那么,编译器会以为既然 i 是 const ,所以 usage1和usage2的值是相同的,并且它甚至能事先计算好 usage1 处的 a[i] 的地址,然后保留着在后面的 usage2 处使用,而不是重新计算。如果你按如下方式写的话:

const int i = ...;
int * p = &i;
//... do lots of stuff
... = a[i]; // usage 1
// ... lots more stuff
(*p)++; // mess over compiler''s assumption
// ... and other stuff
... = a[i]; // usage 2

  编译器将认为 i 是常量,从而 a[i] 的位置也是常量,这样间接地破坏了先前的假设。因此,你的程序将会在 debug 编译模式(没有优化)和 release 编译模式(完全优化)中反映出不同的行为,这种情况可不好,所以当你试图把指向 i 的指针赋值给一个 可修改的引用时,会被编译器诊断为这是一种伪造。这就是为什么(LPCTSTR)强制类型转化不起作用的原因。
  为什么不把该成员声明成 LPCTSTR 类型呢?因为这个结构被用于读写控件。当你向控件写数据时,文本指针实际上被当成 LPCTSTR,而当你从控件读数据 时,你必须有一个可写的字符串。这个结构无法区分它是用来读还是用来写。

因此,你会常常在我的代码中看到如下的用法:

tvi.item.pszText = (LPTSTR)(LPCTSTR)s;

  它把 CString 强制类型转化成 LPCTSTR,也就是说先获得改字符串的地址,然后再强制类型转化成 LPTSTR,以便可以对之进行赋值操作。 注意这只有在使用 Set 或 Insert 之类的方法才有效!如果你试图获取数据,则不能这么做。
  如果你打算获取存储在控件中的数据,则方法稍有不同,例如,对某个 CTreeCtrl 使用 GetItem 方法,我想获取项目的文本。我知道这些 文本的长度不会超过 MY_LIMIT,因此我可以这样写:

TVITEM tvi;
// ... assorted initialization of other fields of tvi
tvi.pszText = s.GetBuffer(MY_LIMIT);
tvi.cchTextMax = MY_LIMIT;
c_MyTree.GetItem(&tvi);
s.ReleaseBuffer();

  可以看出来,其实上面的代码对所有类型的 Set 方法都适用,但是并不需要这么做,因为所有的类 Set 方法(包括 Insert方法)不会改变字符串的内容。但是当你需要写 CString 对象时,必须保证缓冲是可写的,这正是 GetBuffer 所做的事情。再次强调: 一旦做了一次 GetBuffer 调用,那么在调用 ReleaseBuffer 之前不要对这个 CString 对象做任何操作。

5、CString 型转化成 BSTR 型

  当我们使用 ActiveX 控件编程时,经常需要用到将某个值表示成 BSTR 类型。BSTR 是一种记数字符串,Intel平台上的宽字符串(Unicode),并且 可以包含嵌入的 NULL 字符。

你可以调用 CString 对象的 AllocSysString 方法将 CString 转化成 BSTR:

CString s;
s = ... ; // whatever
BSTR b = s.AllocSysString();

  现在指针 b 指向的就是一个新分配的 BSTR 对象,该对象是 CString 的一个拷贝,包含终结 NULL字符。现在你可以将它传递给任何需要 BSTR 的接口。通常,BSTR 由接收它的组件来释放,如果你需要自己释放 BSTR 的话,可以这么做:

::SysFreeString(b);

  对于如何表示传递给 ActiveX 控件的字符串,在微软内部曾一度争论不休,最后 Visual Basic 的人占了上风,BSTR("Basic String"的首字母缩写)就是这场争论的结果。

6、BSTR 型转化成 CString 型

  由于 BSTR 是记数 Unicode 字符串,你可以用标准转换方法来创建 8 位的 CString。实际上,这是 CString 内建的功能。在 CString 中 有特殊的构造函数可以把 ANSI 转化成 Unicode,也可以把Unicode 转化成 ANSI。你同样可以从 VARIANT 类型的变量中获得 BSTR 类型的字符串,VARIANT 类型是 由各种 COM 和 Automation (自动化)调用返回的类型。

例如,在一个ANSI程序中:

BSTR b;
b = ...; // whatever
CString s(b == NULL ? L"" : b)

  对于单个的 BSTR 串来说,这种用法可以工作得很好,这是因为 CString 有一个特殊的构造函数以LPCWSTR(BSTR正是这种类型) 为参数,并将它转化成 ANSI 类型。专门检查是必须的,因为 BSTR 可能为空值,而 CString 的构造函数对于 NULL 值情况考虑的不是很周到,(感谢 Brian Ross 指出这一点!)。这种用法也只能处理包含 NUL 终结字符的单字符串;如果要转化含有多个 NULL 字符 串,你得额外做一些工作才行。在 CString 中内嵌的 NULL 字符通常表现不尽如人意,应该尽量避免。
  根据 C/C++ 规则,如果你有一个 LPWSTR,那么它别无选择,只能和 LPCWSTR 参数匹配。

在 Unicode 模式下,它的构造函数是:

CString::CString(LPCTSTR);

正如上面所表示的,在 ANSI 模式下,它有一个特殊的构造函数:

CString::CString(LPCWSTR);

  它会调用一个内部的函数将 Unicode 字符串转换成 ANSI 字符串。(在Unicode模式下,有一个专门的构造函数,该函数有一个参数是LPCSTR类型――一个8位 ANSI 字符串 指针,该函数将它加宽为 Unicode 的字符串!)再次强调:一定要检查 BSTR 的值是否为 NULL。
  另外还有一个问题,正如上文提到的:BSTRs可以含有多个内嵌的NULL字符,但是 CString 的构造函数只能处理某个串中单个 NULL 字符。 也就是说,如果串中含有嵌入的 NUL字节,CString 将会计算出错误的串长度。你必须自己处理它。如果你看看 strcore.cpp 中的构造函数,你会发现 它们都调用了lstrlen,也就是计算字符串的长度。
  注意从 Unicode 到 ANSI 的转换使用带专门参数的 ::WideCharToMultiByte,如果你不想使用这种默认的转换方式,则必须编写自己的转化代码。
  如果你在 UNICODE 模式下编译代码,你可以简单地写成:

CString convert(BSTR b)
{
if(b == NULL)
return CString(_T(""));
CString s(b); // in UNICODE mode
return s;
}

  如果是 ANSI 模式,则需要更复杂的过程来转换。注意这个代码使用与 ::WideCharToMultiByte 相同的参数值。所以你 只能在想要改变这些参数进行转换时使用该技术。例如,指定不同的默认字符,不同的标志集等。

CString convert(BSTR b)
{
CString s;
if(b == NULL)
return s; // empty for NULL BSTR
#ifdef UNICODE
s = b;
#else
LPSTR p = s.GetBuffer(SysStringLen(b) + 1);
::WideCharToMultiByte(CP_ACP, // ANSI Code Page
0, // no flags
b, // source widechar string
-1, // assume NUL-terminated
p, // target buffer
SysStringLen(b)+1, // target buffer length
NULL, // use system default char
NULL); // don''t care if default used
s.ReleaseBuffer();

2008年5月28日星期三

Windows Mobile 开发常见问题集(五)



Windows Mobile 开发常见问题集(五)
http://www.csai.cn 作者:不详 来源:aspxboy 2006年6月8日 发表评论 进入社区

1、Q:如果创建一个XML节点<a>1<b>2</b></a>,怎样创建a节点的第一个子节点?也就是那个没有LocalName但是有InnerText的节点?

  A:  XmlDo***ent doc = new XmlDo***ent();

    XmlElement a = doc.CreateElement("a");

    a.InnerText = "1";

    XmlElement b = doc.CreateElement("b");

    b.InnerText= "2";

    a.AppendChild(b);

    doc.AppendChild(a);

  或者:

    XmlDo***ent doc = new XmlDo***ent();

    XmlElement a = doc.CreateElement("a");

    XmlText aText = doc.CreateTextNode("1");

    XmlElement b = doc.CreateElement("b");

    XmlText bText = doc.CreateTextNode("2");

    b.AppendChild(bText);

    a.AppendChild(aText);

    a.AppendChild(b);

    doc.AppendChild(a);

2、Q:System.Environment起什么作用?

  A:System.Environment类提供有关当前环境和平台的信息以及操作它们的方法。

3、Q:100多k的数据载入都要30几秒,这个速度是否太慢了?有没有什么办法使时间提高到10秒以内?

  A:数据量大的情况下,建议使用XmlTextReader来读取而不要使用XMLDo***ent和DataSet来处理。

4、Q:能具体讲讲tick吗?

  A:Ticks的值为自0001年1月1日午夜12:00以来所经过时间,以100毫微秒为间隔表示时的数字。 

5、Q:可以使用哪些库来处理XML?保存XML的常用方法有哪些?

  A:1)在.NET Compact Framework中,我们主要使用XmlDocoment对象或者是XmlTextReader以及XmlTextWriter对象来处理XML数据。2)使用XmlDo***ent的Save方法或者XmlTextWriter可以很方便地将XML数据保存成文件。

6、Q:有没有一个标准来区分是使用XmlReader好还是XmlDo***ent好?

  A:XmlDo***ent类因为采用的是W3C的DOM模型所以在遇到大型XML数据的时候性能偏低,但是XmlDou***net类支持修改和删除;而XmlReader虽然性能较好但是是只读的。 

7、Q:Xml序列化后的数据,PDA能读取吗?有能读取条码的PDA吗?

  A:XML序列化之后的数据就是XML文本,可以用PDA读取。市面上有可以读取条形码的PDA,具体型号可以自行搜索。

8、Q:请问有没有使用XML和SQL Mobile的性能对比方面的数据?

  A:没有。 

9、Q:Windows Mobile 5.0中Pocket IE支持AJAX吗?或者.NET Compact Framework 2.0有些什么样的支持吗?

  A:AJAX其实是一组技术的一个集合,主要是DHTMLJavascript、XML等等,Pocket IE支持其中的很多特性,具体请参见http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceinternet5/html/wce50oripocketinternetexplorer.asp至于.NET Compact Framework 2.0(包括.NET Freamework 2.0)中,并没有对AJAX做什么样特殊的支持。

10、Q:请问XML跟HTML最大的区别是什么?它的优越性主要在哪里?

  A:XML注重对数据内容的描述,HTML注重数据表现的描述。优势在于XML可以将数据内容和显示分离。 

11、Q:Mobile 5.0是否支持.NET Remoting?

  A:很遗憾,在.NET Compact Framework 2.0中尚不支持Remoting。

12、Q:既然XML的效率不高,能处理的数据量不大,在哪些实用场合中使用XML更合适?

  A:在处理小数据量的数据,以及一些非结构化的不适于数据库存储的数据的时候用XML比较方便。

13、Q:在Mobile开发的时候,考虑到程序的运行性能,怎样处理好使用技术和硬件约束的矛盾呢?有没有一个量化的标准?

  A:没有量化的指标,实践是检验的指标。

14、Q:Window PC上的程序移植到CE上时,XML文件读写什么要注意的地方?

  A:.NET Compact Framework上的XML处理方式比完整版的.NET Framework要少很多可用的类和方法,需要加以修改。同时,在Mobile设备上,性能的优化很重要。 

15、Q:如果要在.NET Compact Framework 1.0上写XML反序列化为对象的方法时,该怎样进行类型转换呢?

  A:在.NET Compact Framework 1.0中不支持XML序列化,所以反序列化XML数据到对象的工作相对比较麻烦,可以自行定义一套XML数据的Schema来规范XML数据中的结构,然后再来解析它生成对象。

16、Q:既然不建议使用Web Service返回DataSet,那么使用什么方式将信息反馈回客户端好呢?能给一些建议吗?比如将一张表的信息通过Web Service反馈回客户端?

  A:建议通过纯粹的字符串数组等来传递数据,Mobile端接受到之后再将其转换为本地便于处理的对象。

17、Q:调用窗体的this.Close()方法是否将该对象在内存中销毁?

  A:是的。

18、Q:使用什么方法能在打开SIP键盘输入框时,不会挡住该范围内的控件?

  A:应该尽可能不在屏幕下方80个像素之内的区域中放置输入控件,如果一定要放置,可以在激活SIP时调整控件位置或者使用滚动条来让控件不被遮挡。 

19、Q:设置用户界面在Pocket与Smartphone有什么需要注意和区别的地方吗?可具体讲解一下InputPanel控件吗?

  A:最大的区别是Pocket PC和Smartphone可以使用的控件不同,例如最常用的Button控件在Smartphone中不能使用,还有一点就是Smartphone不支 持手写。InputPanel控件的功能是控制Pocket PC上的软输入面板(SIP),其用法十分简单,属性和事件非常少,可自行查找MSDN上面的文档。

20、Q:请问,如何在Visual Studio 2005中制作手机安装程序?

  A:在Visual Studio 2005创建Smart Device CAB Project类型的项目即可。 

21、Q:.NET 2.0中的开发的控件可以在.NET 1.0中使用吗?

  A:不可以。

22、Q:string d1 = DateTime.Now.ToString("yyyymmddhhmmssfff"); DateTime.P***(d1);为什么遮掩做会出现错误?

  A:DateTime.P***只能针对当前区域性初始化的DateTimeFormatInfo中的格式信息来分析字符串,不可能识别自定义的日期格式字符串。

Windows Mobile 开发常见问题集(四)

Windows Mobile 开发常见问题集(四)
http://www.csai.cn 作者:不详 来源:aspxboy 2006年6月8日 发表评论 进入社区

1、Q:在Smartphone 2003上可以使用.NET Compact Framework的哪一个版本?

  A:Smartphone 2003允许开发人员使用.NET Compact Framework 1.0 Service Pack 1进行编码。.NET Compact Framework可以放在Smartphone 2003的ROM中。.NET Compact Framework 1.0 Service Pack 2放在Smartphone 2003 Second Edition的ROM中。

2、Q:什么是示例Smartphone 2002设备和Smartphone 2003设备?

  A:原始的Orange SPV与Orange SPV e100运行Windows Mobile 2002。Orange和AT&T上的MPX200都是基于Windows Mobile 2002的Smartphone。Orange SPV e200运行Windows Mobile 2003。

3、Q:MFC或ATL可用于Smartphone 2003开发吗?

  A:MFC不可用于Smartphone 2003。可以使用ATL 4.0进行Smartphone 2003开发。有关ATL 4.0的更多信息,请参阅SDK文档。

4、Q:从哪里可以找到更多有关Smartphone应用程序安全模型的信息?

 A:为了帮助开发人员了解基于Windows Mobile的Smartphone应用程序安全模型,我们创作了一本白皮书。请参见http://msdn.microsoft.com/library/en-us/dnsmtphn2k3/html/smartphone_security.asp

5、Q:可以使用eMbedded Visual Basic 3.0来构建Smartphone 2003应用程序吗?

 A:不可以,不支持以Smartphone 2003为目标的eVB开发。如果您希望利用Visual Basic的开发技巧,可以考虑使用Visual Basic .NET并以.NET Compact Framework为目标。

6、Q:什么是Microsoft eMbedded Visual Tools 3.0?

  A:eMbedded Visual Tools 3.0是一种集成开发环境(IDE),用来为基于Microsoft Windows CE操作系统的32位设备编写软件应用程序。其中包括完整版的Microsoft eMbedded Visual C++ 3.0语言、Microsoft eMbedded Visual Basic 3.0语言、特定于平台的SDK、远程工具和文档。 

7、Q:eMbedded Visual Tools 3.0支持哪些设备平台?

  A:eMbedded Visual Tools 3.0 - 2002 Edition附带于Pocket PC 2000、Pocket PC 2002和Smartphone 2002的SDK,并支持开发自定义的Windows CE 3.0设备应用程序。注:Pocket PC 2002 SDK可以与eMbedded Visual Basic 3.0和eMbedded Visual C++ 3.0一起使用,但是Smartphone 2002 SDK却只受eMbedded Visual C++ 3.0 支持。 

8、Q:什么是eMbedded Visual C++ 4.0?

  A:eMbedded Visual C++ 4.0是一种强大的开发工具,在为下一代基于Windows CE的设备(包括Pocket PC 2003和Smartphone 2003)构建本机代码应用程序时可以为企业提供相当大的好处。这种独立的集成开发环境(IDE)带来了新水平的Windows CE开发效率,但却没有牺牲灵活性、性能或控制能力。要使用eMbedded Visual C++工具构建Pocket PC 2003与Smartphone 2003应用程序,还需要安装eMbedded Visual C++ 4.0 Service Pack 3和Pocket PC 2003以及Smartphone 2003 SDK。

9、Q:我可以使用eMbedded Visual C++ 4.0开发Pocket PC或Smartphone应用程序吗?

  A:可以使用带有Service Pack 2的eMbedded Visual C++ 4.0来开发包括Windows Mobile 2003 Second Edition在内的Pocket PC 2003与Smartphone 2003应用程序。也可以用它来开发Pocket PC 2002或Smartphone 2002应用程序。 

10、Q:我可以使用Windows CE Standard SDK开发Pocket PC或Smartphone应用程序吗?

  A:Windows CE SDK提供了一个通用的功能子集,使得编写的应用程序能够符合Standard SDK,以便运行在基于自定义显示的Windows CE .NET平台上。为了构建Pocket PC和Smartphone智能设备应用程序来利用这些平台提供的丰富的设备功能集,需要使用特定于设备的SDK。 

11、Q:eMbedded Visual Tools 3.0和Visual Studio .NET之间有什么不同?

  A:eMbedded Visual Tools 3.0是一种专门针对移动与嵌入式技 术开发人员的独立开发环境。对于Pocket PC和Smartphone,都可以利用eMbedded Visual Tools和适当的平台SDK来构建丰富的"本机代码"客户端应用程序。Visual Studio .NET是Microsoft的最流行桌面开发工具的最新版本。可以使用Visual Studio .NET 2003来构建基于.NET Compact Framework的Pocket PC智能客户端应用程序。同时,还可以使用Visual Studio .NET和ASP.NET移动控件构建以各种设备(包括Pocket PC和Smartphone类别的设备)为目标的基于浏览器的应用程序。

12、Q:为什么没有将eMbedded Visual C++集成到Visual Studio .NET中?

  A:根据客户的反馈,我们最初的工作主要集中于使Visual Basic .NET开发人员能够更轻松地对设备进行编程。但是,利用本机代码(C++)创建设备应用程序的功能将会集成到Visual Studio的下一个版本中。

13、Q:什么是.NET Compact Framework?

  A:.NET Compact Framework是.NET Framework的子集,设计为能运行在资源受限的设备上,以便为托管代码和XML Web服务提供支持。.NET Compact Framework大大降低了编写运行在诸如Pocket PC设备上的应用程序和服务的开发成本。由于.NET Compact Framework是开发人员用来编写桌面和服务器应用程序的.NET Framework的一个子集,所以他们已经具备了编写Pocket PC和Smartphone 2003设备应用程序所必需的全部技巧。 

14、Q:使用.NET Compact Framework的主要好处是什么?

 A:目前编 写设备应用程序的一个最大障碍在于,大多数设备都要求开发人员了解不同的API和使用不同的编程工具(与用于桌面应用程序相比)。由于.NET Compact Framework使用的.NET Framework编程模型和Visual Studio .NET开发工具与开发人员已经在桌面和服务器上使用的相同,所以它可以大大降低开发设备应用程序的成本,并提高开发人员的工作效率。而这些好处又能够使 企业以新的方式使用智能设备,从而改进他们的业务。.NET Compact Framework也是唯一带有XML Web服务本机支持的移动开发平台。

15、Q:什么设备可以运行.NET Compact Framework?

  A:NET Compact Framework 1.0可以用作Pocket PC 2000和Pocket PC 2002设备(包括Phone Edition)的RAM安装,并且可以放在Pocket PC 2003的ROM中。Smartphone 2003设备包含.NET Compact Framework 1.0 Service Pack 1。所有的Windows Mobile 2003 Second Edition设备均包含.NET Compact Framework 1.0 Service Pack 2。 

16、Q:何时可以使用.NET Compact Framework?

  A:.NET Compact Framework的1.0版可以作为Visual Studio .NET 2003版本的一部分使用。有关更多信息,请参阅Device Development。 

17、Q:.NET Compact Framework可以运行所有的.NET语言吗?

  A:最初,.NET Compact Framework可以运行Visual C#和Visual Basic。只要其他.NET言符合.NET Compact Framework支持的公共语言运行库子集,它们就可以运行。

18、Q:.NET Compact Framework应用程序和eMbedded Visual C++应用程序的执行情况一样吗?

  A:在大多数情况下,用eMbedded Visual C++编写的应用程序的运行速度比用Visual Basic .NET或Visual C# .NET编写的应用程序快。但是,对于应用程序计算密集的部分,开发人员将会看到他们的Visual Basic .NET应用程序比他们的eMbedded Visual Basic应用程序有实质性的改善。

19、Q:.NET Compact Framework与ASP.NET移动控件之间有什么不同?

  A:对设备进行编程有两种不同的方法。一种方法是将应用程序放置在智能设备上。另一种方法是将代码放置在服务器上,并通过浏览器呈现用户界 面。.NET Compact Framework支持前者,而ASP.NET移动控件(以前称为Microsoft Mobile Internet工具包)则支持后者。使用设备上的代码构建移动应用程序使应用程序在没有Internet连接的情况下可以继续工作。直接在设备上运行的 应用程序还支持更丰富的用户界面,以及与操作系统上的可用资产(例如多媒体和其他的应用程序)进行集成的可能性。可以使用.NET Compact Framework将高效模型用于构建智能设备应用程序。构建代码位于服务器的移动应用程序也有其优点。在必须使用Internet支持的各种移动设备 时,这种体系结构非常有用。这些应用程序也不受资源的限制,因为它们作为桌面Web应用程序运行在相同的服务器上。在Visual Studio .NET中使用ASP.NET移动控件可以完成这些应用程序的编写。 

20、Q:Visual Studio .NET 2003和Visual Studio 2005开发的Mobile在部署(方法和平台)上面有什么具体的不同?

  A:从Visual Studio 2005 beta版的情况来看,和Visual Studio .NET 2003的部署过程是相同的。在开发方面,Visual Studio 2005直接提供了Skin功能,可以使开发者在设计界面时能够更加直观。并且在调试时,其调试环境不再是在模拟器环境当中,而直接使用本地计算机的资 源,调试速度更快。

21、Q:我想使用GPS采集数据,然后将数据实时显示在客户机屏幕上,采用什么连接方式比较好?

  A:数据连接的方式主要取决于GPS的类型。目前GPS接收器有两种方式,串口或USB连接和蓝牙连接。如果是串口和USB连接,你可以使用 CreateFile或者OpenNETCF中的串口类进行操作;而蓝牙设备,就需要使用Windows CE的Bluetooth API了。

22、Q:怎样生成一个像PC上Setup一样的安装程序在Pocket PC上来完成安装工作?

  A:Windows Mobile设备的标准安装文件是CAB格式的。您可以在Visual Studio.NET中选择"生成CAB文件",或者直接使用命令行工具cabwiz生成CAB文件。

23、Q:用Windows Mobile把一个XML传入Web Service,处理后返回一个XML。传入的XML可有多种形式,请问共有哪几种写法?他们有什么区别?例子:1.public XmlDo***ent GetXml(XmlDo***ent xmlfile);2.public XmlElement GetXml(XmlElement xmlfile)...返回的XML其实是个SOAP消息,如何去掉SOAP?

  A:1)建议传递参数直接传递XML格式的字符串而不要传递对象。2)Web Service传递的信息中必定有SOAP消息,如果只想传递XML实体内容的话,建议通过Http请求直接POST数据,然后返回订制好的XML格式的实体数据。 

24、Q:XML数据内容的安全性如何?与SQL CE相比哪个效率更高些呢?

  A:1)XML的数据内容本质上就是纯文本,没有安全性可言。要实现安全性,您可以通过一些别的加密手段对内容进行加密。2)相比来说,在处理大数据量的时候SQL CE的处理速度要比直接处理XML快一些。

Windows Mobile 开发常见问题集(三)

Windows Mobile 开发常见问题集(三)
http://www.csai.cn 作者:不详 来源:aspxboy 2006年6月8日 发表评论 进入社区
1、Q:SQL Mobile的SQL语法和SQL Server的语法有差异么?

  A:SQL Mobile的语法和SQL Server的语法略有差异,可以从SQL Mobile的文档中查找SQL Mobile具体支持哪些SQL语句。总的来说,对绝大部分的开发来说,这些差异不会造成影响。

2、Q:SQL Mobile支持B/S模式吗?

  A:不支持。

3、Q:可以在.NET Compact Framework 1.0上访问由.NET Compact Framework 2.0产生的数据库吗?

  A:SQL Mobile数据库的格式和SQL Server CE 2.0是相同的,因此可以直接在.NET Compact Framework 1.0中进行访问。

4、Q:SQL Mobile数据库文件支持XCOPY吗?可以简单地复制到其他Windows Mobile设备上吗?

  A:是的。SQL Mobile数据库本身是一个文件数据库,直接复制到其他安装了SQL Mobile支持组件的Windows Mobile设备或模拟器上就可以使用了。

5、Q:Visual Studio .NET 2003是否支持Windows Mobile 5.0的开发?

  A:不可以,如果开发基于Windows Mobile 5.0的应用程序请使用Visual Studio 2005。

6、Q:要想从传统的PC程序员转向到移动设备的开发上来,需要在技术上作哪些准备?

  A:移动设备的开发对于基础开发语言和开发技术的要求与PC上是相同的,只需要了解移动设备在哪些方面与PC平台有所不同即可。

7、Q:C#可以开发Windows Moblie应用程序吗?

  A:可以。

8、Q:如果获取.NET Compact Framework 2.0的安装程序并将其安装到Windows Mobile 5.0设备中?

  A:Visual Studio 2005提供了.NET Compact Framework 2.0安装程序,在开发部署时会自动部署到移动设备上。

9、Q:Windows Mobile 5.0中没有集成.NET Compact Framework 2.0,是不是生成的应用程序安装包就应该带上.NET Compact Framework 2.0?

  A:技术上来说是的。但能否在应用程序中提供.NET Compact Framework 2.0取决于微软对此的授权情况。

10、Q:如何把.NET Compact Framework 2.0与应用程序一同打包发布?

  A:.NET Compact Framework 2.0有一个单独的CAB安装包,可以把此文件与应用程序打成一个安装包。

11、Q:用Visual Studio 2003开发可以获得很好的兼容性吗?

  A:用Visual Studio 2003开发的基于.NET Compact Framework 2.0的程序可以在Windows Mobile 5.0的设备上运行。

12、Q:在Windows Mobile上面是否开发COM+或者DLL?

  A:可以开发DLL动态共享库。

13、Q:C#是否支持Windows Mobile 5.0的DirectX开发?

  A:支持。

14、Q:现有的使用Visual Studio开发的Smartphone 2003应用程序,可以移植到Windows CE 5.0平台上吗?

  A:可以。

15、Q:Windows Mobile 5.0内置红外线接口API吗?

  A:Windows Mobile 5.0对红外接口的支持并没有更新,需要采用之前的方法进行红外接口的开发,例如与串口通信等。

16、Q:如何开发手机游戏,特别是能够交互的网络游戏?

  A:Windows Mobile对游戏开发的支持是比较充分的,可以采用DirectX技术进行3D或2D界面的开发;对于网络部分,Windows Mobile可以支持socket通信方式。所以,从技术上来讲,开发网络游戏是完全没有问题的。

17、Q:我们公司目前更多关注的是嵌入式领域,也就是Windows CE,而非Windows Mobile。我们主要是在关注IPTV领域,在这方面有哪些的资源

  A:Windows CE是一种可自定义的嵌入式操作系统, 适用于各种内存很少的设备。OEM可以使用Windows CE设计平台和自定义应用程序,使用户可以获得各种设备的最佳体验,例如手持设备、瘦客户机、逻辑控制器以及各种高级消费类电子产品。 Windows Mobile是基于Windows CE构建的一种完善的软件平台。与Windows CE不同,Windows Mobile Smartphone和Pocket PC操作系统专为要求特殊硬件配置的设备而设计。该软件包括标准化 的接口和应用程序,可确保在各种硬件设计中的兼容性。 所以Windows Mobile和Windows CE的资源是通用的,您可以在http://www.microsoft.com/china/mobile、http: //www.microsoft.com/windowsmobile/,以及微软社区http://www.microsoft.com/china/windowsmobile/communities/default.mspx获得相应的资源和帮助。

18、Q:我们在Windows Mobile上进行应用开发遇到一些底层的接口问题,如何取得微软的技术支持?

  A:微软将一如既往地对基于Windows Mobile操作系统开发的独立软件开发商和开发人员进行支持,可以直接向800-820-3800全球技术支持中心寻求支持,或者提供具体问题细节,我们将给出相应的解决方案。

19、Q:如何才能将我们的软件放到微软的Mobile2Market项目中去?对MVP有没有什么优惠?

 A:Mobile2Markert项目在中国是非常优惠的,目前对MVP 没有特别优惠。另外,如何将软件放到微软的Mobile2Market中请参考http: //www.microsoft.com/china/mobile/developer/developerprograms/mobile2market/default.asp

20、Q:哪些工具可用于Pocket PC 2003开发?

  A:要构建Pocket PC 2003本机C++应用程序,您需要Microsoft eMbedded Visual C++ 4.0、Microsoft eMbedded Visual C++ 4.0 Service Pack 3,以及Pocket PC 2003 SDK。

21、Q:为了支持 Windows Mobile 2003 Second Edition 的增强功能(例如高分辨率或横向屏幕),应该在应用程序中做些什么?

  A:Windows Mobile 2003 Second Edition 提供了全新的屏幕方向和分辨率,包括针对Pocket PC的横向、方形和VGA支持以及针对Smartphone的QVGA支持。这种版本不需要新的SDK。

22、Q:Pocket PC 2002应用程序可以在Pocket PC 2003 设备上工作吗?

  A:使用文档化API且功能良好的Pocket PC 2002 应用程序无需重新编译即可在 Pocket PC 2003 设备上运行。

23、Q:如何从eVB迁移到Visual Basic .NET?

 A: 从eVB迁移到Visual Basic .NET并不容易,但迁移的好处远远超过了成本: • 数据类型更丰富:eVB只有16 字节的VARIANT;Visual Basic .NET使用.NET Framework通用类型系统。 • 执行更快:eVB需要解释;Visual Basic .NET在执行前由JIT(实时)编译器编译为本机代码。 • 错误处理更完善:eVB仅支持"On Error";Visual Basic .NET支持结构化异常处理。 • 支持结构:eVB不支持;Visual Basic .NET支持命名空间、类和结构。 • 面向对象:eVB是面向过程的;Visual Basic .NET支持完全的OOP(面向对象编程)。 • "一等公民":eVB总是希望迎头赶上MFC;Visual Basic .NET则是.NET的核心。 • 本机XML支持:eVB不支持;Visual Basic .NET支持本机XML和XML Web服务。 • 数据模型更完善:ADO.NET远远超过了ADOCE;它是最好的数据模型。 • 执行更安全、更可靠:eVB是一种脚本语言;Visual Basic .NET为托管代码。 • 还有许许多多! 同时,还有各种各样的资源(从移植实验到技术文章)可以帮助开发人员进行这种过渡。

24、Q:应该使用什么开发工具来编写基于.NET Compact Framework的Pocket PC应用程序?

   A:Microsoft Visual Studio .NET 2003允许Visual Basic .NET或C#编程人员创建Pocket PC 2000、Pocket PC 2002和Pocket PC 2003设备的托管代码应用程序(即那些以.NET公共语言运行库为目标的应用程序)。要开发Pocket PC 2000和Pocket PC 2002设备的托管代码应用程序,您可以使用即装即用的Visual Studio .NET 2003。在开发过程中,Visual Studio .NET 2003将会自动地将.NET Compact Framework安装到这些设备的RAM中。.NET Compact Framework已经在所有Pocket PC 2003设备的ROM 中,而且Visual Studio .NET 2003通过Pocket PC 2003 SDK支持它。

25、Q:有什么资源可以用于进行Windows Mobile 2003 Second Edition的开发?

  A:下载新 的Windows Mobile Developer资源包,其中包括白皮书以及新的和更新的代码示例。该版本不需要全新的SDK。可以用新的模拟器软件包对应用程序进行测试。 eMbedded Visual C++ 4.0开发人员应当下载eMbedded Visual C++ 4.0 Service Pack 3。

26、Q:什么工具可用于Smartphone 2002开发?

  A:要开始开发Microsoft Smartphone 2002应用程序,您需要eMbedded Visual C++ 3.0和Smartphone 2002 SDK。两者都可以在Windows Mobile Developer获得。

27、Q:MFC或ATL可用于Smartphone 2002开发吗?

  A:不可以,Smartphone 2002不支持MFC与ATL开发。

28、Q:可以使用eMbedded Visual Basic 3.0来构建Smartphone 2002应用程序吗?

  A:不可以,不支持以Smartphone 2002为目标的eVB 开发。

29、Q:哪些工具可用于进行Microsoft Smartphone 2003开发?

   A:对于Smartphone 2003,有两种开发选择,或者通过带有Service Pack 3的eMbedded Visual C++ 4.0开发本机代码,或者通过Visual Studio .NET 2003开发托管代码。这两种情况都需要下载Smartphone 2003 SDK。Windows Mobile 2003 Second Edition模拟器软件包使您可以在Second Edition设备上测试应用程序。eMbedded Visual C++ 4.0和Smartphone 2003 SDK都可以在Windows Mobile Developer获得。



Windows Mobile 开发常见问题集(二)

Windows Mobile 开发常见问题集(二)
http://www.csai.cn 作者:不详 来源:aspxboy 2006年6月8日 发表评论 进入社区
1、Q:请问如何才能保证应用程序能够及时地释放系统资源
  
  A:由于.NET Compact Framework所运行的移动设备,受限于CPU、内存、电源,因此其中的Garbage Collection时经过调整的,垃圾回收的速度比.NET Framework更快。通过调用Dispose()方法,可以立即释放掉对象所占用的非托管资源。

2、Q:在Visual Studio中可以定义一个所有文件都可以使用的宏吗?比如:#define AA,要求在所有的.cs文件中都可以使用#if AA public class A() #else public class B();

 A:可以。在VS 2005的解决方案资源管理器中,用鼠标右键单击项目,选择其属性。在属性对话框的Build页中,可以找到conditional compilation symbol,在其中输入AA,即可在该项目的所有C#源代码文件中使用这个符号。

3、Q:可以将Smartphone应用程序转换为Pocket PC应用程序吗?

  A:可以。在.NET Compact Framework 2.0中,只要您没有用到某些特殊的API,Pocket PC应用程序与Smartphone程序是可以互相转换的,只需要在控件上做些调整即可。

4、Q:.Net Framework 2.0有没有对Media coder/decoder的支持?开发第三方的媒体播放程序可以不依赖.Net CF2.0吗?

  A:.NET Compact Framework 2.0本身可以开发Direct3D Mobile的应用程序。也可以在VS 2005中以C++开发Native Code的媒体播放程序,而无须依赖.NET Compact Framework 2.0。

5、Q:使用.Net开发的智能设备程序是否比用C语言开发的程序效率低很多?

   A:使用.NET开发的程序会比使用C语言开发的本地程序要慢一些,不过对于一般的应用软件来说,下率不会差太多,除非是需要实时处理硬件或I/O的程 序,必须要使用C语言进行开发之外,一般的应用程序用.NET Compact Framework开发即可,因为这样可以获得最好的灵活性和可移植性。

6、Q:用托管C++开发的应用程序执行效率会不会比用C#开发的应用程序高?

  A:不会。由於托管C++与C#源代码在经过编译之后,都将成为IL代码,由.NET Compact Framework来执行,因此在效率上不会有差别。

7、Q:请问.NET Compact Framework 2.0对于使用不同CPU的移动设备支持好吗?.NET Compact Framework 2.0在GSM应用方面有没有增强?
  A:.NET Compact Framework具有Windows Mobile跨平台的特性,因此开发时不需要考虑底层的OS、CPU和其它硬件因素。目前.NET Compact Framework对常见的CPU都能够支持,例如ARM、MIPS、SH、x86等。另外在GSM应用方面,主要针对Smartphone的应用作了加强。
8、Q:请问MFC在Windows Mobile Development中处于什么地位?Douglas Boling写的Programming Microsoft Windows CE .NET一书中好像并不推崇使用MFC开发Windows Mobile应用程序。

   A:MFC还是以本地C++的方式进行开发,其特点是执行效率高,但必须花费更多的心思在�源分配、回收等编程技巧上。如果使用.NET Compact Framework进行开发,虽然执行效率比本地程序略差,但整体而言,可移植性与灵活性都较好,而且不必为回收资源担心,开发者能够专注于真正重要的业 务逻辑流程。

9、Q:.NET Compact Framework 2.0与1.0有什么区别?

  A:. NET Compact Framework 2.0主要针对1.0原有的控件及类库进行了改善,提供了更多的支持,并新增了许多类型和控件,.NET Compact Framework 2.0更加接近.NET Framework,同时在效率上也相对1.0有所提升。

10、Q:在制作安装程序的时候,如何在start->program菜单中生成程序的快捷方式?

   A:在VS 2005中建立Smart Device Cab Project,在File System页面中,可以看到Application Folder,这就是Start->Program的位置,可以先建立Primary Output的快捷方式,然后将此快捷方式移到Programs Folder,并构建Cab文件即可。

11、Q:移动设备与WEB网页设计有什么主要区别?

  A:Visual Studio开发环境中移动设备与Web设计是非常类似的 ,可以使用同样的语言进行设计, 不同的只是能够使用的类以及控件有所区别。

12、Q:.NET Compact Framework中可以实现鼠标的双击、右击、中间键单击等用户事件吗?

  A:运行Windows Mobile的设备没有鼠标,所以这些事件也不存在。对于常用的右键弹出上下文相关菜单,在触摸屏上一般用单击并且按住一段时间来实现。

13、Q:Mobile应用程序的界面处理可以使用CSS样式表吗?

  A:不可以。

14、Q:Smartphone上面能够支持横屏幕吗?

  A:不支持。

15、Q:如何在Pocket PC中调整控件的位置使得应用程序可以支持横向屏幕?

  A:可通过设置控件的Anchor和Dock属性来自适应屏幕。

16、Q:界面开发完成后,在移植方面需要注意些什么?

   A:一般来说,要移植到不同平台上必需要重新设计用户界面;可以重用的只是业务逻辑,不是用户界面。
17、Q:我在移动开发过程中用到了很多控件,难以在一页之内显示,如何为它们添加一个滚动条?

  A:可以将这些控件放到一个Panel中,并设置其AutoScroll属性为true即可;如果使用VS2005,拖拽数据源到窗体上时,会自动将所有控件包括在一个Panel里。

18、Q:TableAdapter在.NET Compact Framework 1.0中从未出现过,是新特性吗?

  A:是的,TableAdapter是.NET Compact Framework 2.0中新增加的。

19、Q:SQL Mobile带有像SQL Server那样企业管理器吗?Visual Studio 2005支持在桌面上直接查看SQL Mobile的数据库吗?

  A:您可以通过SQL Server 2005的企业管理器连接到SQL Mobile数据库进行编辑。Visual Studio 2005也支持在桌面上创建或修改SQL Mobile数据库文件。

20、Q:提交成功后如何取消保存?

  A:目前BindingSource尚不支持事务,因此提交成功后是没有办法再undo的。

21、Q:移动设备内存较小,填充DataSet是否有大小限制?

  A:DataSet在逻辑上并没有对大小的限制。但是DataSet的大小必须小于当前前的可用内存,否则会有内存分配不成功的异常出现。

22、Q:如果数据源中的数据在显示前需要处理(例如格式转换),可以使用DataBinging吗?

  A:BindingSource是直接将DataSet与控件进行关联,所以如果需要进行其他操作的话,就不能使用BindingSource。或者,可以在访问数据库后,先在DataSet里对需要转换的数据进行必要的处理之后,再进行显示。

23、Q:DataSet实际上在内存中产生了一套数据副本,如何解决版本控制的问题?

  A:DataSet本身不存在版本控制的问题。在把数据提交回SQL Mobile的时候,的确需要有一些机制来保证修改完成的数据应该是最新的,但是DataSet本身的数据结构是不会发生变化的。

24、Q:能否通过Pocket PC上的程序更新服务器上的数据库信息?

  A:可以。可以使用SQL Mobile中的RDA或者是合并复制的方法和远程SQL Server数据库进行数据同步或更新。具体的实现可以参考SQL Server相关部分的文档。

25、Q:SQL Mobile一定要要安装在移动设备上吗?

  A:是的。SQL Mobile需要安装在Windows Mobile或者Windows CE设备上。

26、Q:SQL Moble支持存储过程吗?

  A:目前还不支持。

27、Q:SQL Mobile必须和应用程序部署在同一台设备上吗?可否远程连接?它是否是一个文本数据库?
 
  A:是的。SQL Mobile必须和应用程序部署在同一个设备上,现在还不支持远程连接。SQL Mobile是一个文件数据库,但不是一个文本数据库。

28、Q:能不能在一些应用中以XML替代SQL的作用?

  A:可以的。XML的查询效率比SQL Mobile要低,但是在数据比较少的情况下不需要安装更多的组件,这是XML的一个优势。

29、Q: Tableadapter与DataAdapter之间有何区别?DataAdapter是多个TableAdapter的组合吗?

   A:不是的,TableAdapter是对DataAdapter的一个扩展,TableAdapter本身包括了对应数据表的信息。 TableAdapter完成从数据库连接、执行SQL语句到将结果填充到DataSet中的一个完整操作,而DataAdapter只支持数据填充的操 作。

30、Q:做了SQL Moblie的sdf文件后,Publications后的数据库表中会出现msrepl_tran_version或rowguid字段,这是为什么?

  A:这两个字段是为了保证数据同步,由系统自动添加的,请不要进行修改。

31、Q:网上出了个Reflector反编译工具,可以99%反编译用C#开发的EXE和DLL,怎么才能更好地保护应用程序?

  A:目前大部分应用程序采用混淆和对关键字符串加密的方式,更好的方式可能还要继续探讨。

Windows Mobile 开发常见问题集(一)

Windows Mobile 开发常见问题集(一)
http://www.csai.cn 作者:不详 来源:aspxboy 2006年6月8日 发表评论 进入社区

1、Q:新建项目的时候选择哪个项目类型才能创建智能设备的应用程序?

  A:在Visual Studio的新建项目对话框中选择Visual C#或者Visual Basic项目类型,选择智能设备模板,然后再选择相应的设备SDK,最后选择"Device Application",就可以创建一个移动设备的应用程序了。

2、Q:托管代码与本地代码有哪些区别?

  A:托管代码是指使用.NET Compact Framework开发的程序代码,可执行文件被编译成IL,执行时需要有.NET的运行时环境。而本地代码指用C++等语言开发的程序代码,可执行文件被编译成与CPU指令集有关的机器码,可以直接运行。 

3、Q:能不能简要介绍一下Magneto里面对OTA和MMS的支持?

  A:Magneto对OTA有很好的支持,SDK文档的通讯部分中,有针对OTA的专门介绍。MMS的应用程序基本都是由第三方开发的,因为MMS是基于WAP协议的,而Magneto本身对WAP的支持也很好,具体的协议也可以在SDK文档里找到。

4、Q:请问用Visual Basic .NET开发PDA数据库程序能不能使用ADO.NET

  A:Visual Basic .NET开发PDA数据库不需要引用System.data.oledb,只需要引用System.Data.SqlServerCe命名空间就可以了。 该命名空间中的数据库操作类和ADO.NET是基本一致的。可以用它们来开发针对SQL Server CE的应用程序。

5、Q:在Visual C++2005中,可以使用.Net Compact Framework吗?

  A:不能,现在.NET Compact Framework只支持C#和VB.NET,而不支持C++/CLI。但是在VS.NET 2005中可以用C++来开发Native代码来支持移动设备。 

6、Q:从什么地方可以得到Smartphone开发环境?

  A:Smartphone的SDK可以在微软网站上找到,而Visual Studio 2005 Beta 2可以通过参加微软活动的方式获得。MEDC 2005的参加者都获得了VS.NET 2005和Windows Mobile 5 SDK的开发光盘。 

7、Q:托管性的代码执行效率怎么样?和使用Visual C++编写的代码相比较。

  A:托管代码的执行效率肯定不如本地代码高,但是托管代码也有一些好处是无法取代的。

8、Q:是否可以使用Visual Studio .NET 2003来开发能够运行在Windows Mobile 2005上的应用程序?

  A:首先更正一下,Windows Mobile最新一代的操作系统叫 做Windows Mobile 5,而不是Windows Mobile 2005。是的,使用VS.NET 2003开发的应用程序是可以在Windows Mobile 5上正常运行的,因为Windows Mobile 5 ROM中内置了.NET Compact Framewrok 1.0 SP3。 

9、Q:PDA上不能用Pocket Access么?SQL CE太大了。

  A:可以使用Pocket Access来开发Windows Mobile上的应用程序。可以采用C++调用OLEDB或者ADOCE的方式来访问Pocket Access数据库。

10、Q:Visual Studio 2005的新功能是否只在Windows Mobile 5里受到支持,2003是否支持?

  A:新功能分两个部分,一部分是.NET Compact Framework 2.0中提供的的新功能,这部分的功能可以被Windows Mobile 2003支持,但必须安装.NET Compact Framework 2.0;而另一部分是Windows Mobile 5的特有功能。.NET Compact Framework 2.0和Windows Mobile 5开发文档的"What's New"部分,分别描述了这两方面的新特性。

11、Q:请问如何在模拟器里面配置连接到移动网络?

  A:模拟器如果需要连接移动网络的话,必须有专门的硬件提供支持。可以在开发PC的串口上连一个GPRS的模拟器,SDK文档中对此有专门的说明。

12、Q:SQL CE可以像Pocket Access那样仅使用一个文件就能运行么?是否需要像PC上那样安个服务器才能使用?

  A:不会的,只需要在Windows Mobile上安装SQL Server CE的支持库,也就是就是一些DLL文件。而SQL Server CE的库文件是一个单独的文件,不需要安装一个服务器。

13、Q:开发好的程序通过什么方式部署到手机上?对手机有什么要求?

  A:开发的程序需要打包成cab文件部署到手机上。除了通过ActiveSync安装外,还可以通过网络下载存储卡运行等方式来安装应用程序。对手机的要求是,必须和开发程序的目标平台相兼容。比如为Windows Mobile 5开发的应用程序,可能就没办法很好地运行在Windows Mobile2003平台上。

14、Q:在模拟器上面开发程序,和真实环境有区别么?需要注意一些什么?

  A:模拟器的仿真度十分高,Windows Mobile 5的模拟器甚至可以支持ARM指令,所以基本不会遇到兼容性的问题。但是对于一些需要连接外部设备的应用场景,比如前边说的无线网络,还有GPS设备等,就需要用到实际设备了。

15、Q:当开发国际化应用程序时,应该特别注意哪些方面?

  A:对于国际化的应用程序,.NET本身就已经提供了非常好的支持。可以把用户界面的文字保存在相应的资源文件中,然后由应用程序判断操作系统的语言版本来调用相应的文字。

16、Q:用.NET开发Pocket PC程序需要考虑设备具体使用的是哪种CPU吗?

  A:不必。无论是在虚拟机上的x86指令集,还是实际设备上的ARM指令集,对.NET Compact Framework程序的运行来说都一样。 

17、Q:Windows Mobile 5 是否支持通过语音控制新的开发程序?

  A:现在还不支持。 

18、Q:可以在vwd2005 bata2中开发Pocket PC程序吗?Pocket PC是否具有浏览器?

  A:可以,Pocket PC平台是内置浏览器的。 

19、Q:Visual Studio 2005的Mobile开发,支持Mobile 2003的设备吗?

  A:支持,VS 2005本身就自带Windows Mobile 2003的SDK。

20、Q:Windows Mobile 5.0 for Smartphone较之前的版本有何明显的区别?对于测试这一领域,我们需要注意些什么?

  A:Windows Mobile 5的Smartphone平台更多的变化是在API层面,比如对数据库的支持、对GPS API的支持等, Windows Mobile 5 SDK文档中对此有详细地说明。

21、Q:对开发来说CDMA和GPRS的数据传输是透明的吗?

  A:对于软件开发来说数据传输是透明的,CDMA和GPRS对于上层应用程序来说,只要支持HTTP协议或者TCP/IP协议就可以进行数据传输的操作。 

22、Q:Visual Studio .NET能否支持Nokia的S60系列系统开发?

  A:可以,Visual C++能支持Nokia S60的开发。 

23、Q:Pocket PC与Mobile开发的主要区别在哪里?

  A:Window Mobile是微软公司基于Windows CE.NET的一个平台。它包含Pocket PC和Smartphone两个版本。 

24、Q:SDE从哪里可以下载?Pocket PC 2005的模拟器可以从哪里下载?

 A:SDE是早期用来开发移动设备程序的VS扩展,目前网 上似乎很难找到。其实不用安装它,安装所需版本的Pocket PC或者Smartphone的SDK即可。各个版本的Windows Mobile开发的SDK和模拟器的地址可以从这篇Blog上下载(http: //twodays.cnblogs.com/archive/2005/06/30/184107.htm)。 

25、Q:.NET Compact Framework 2.0能装在Windows Mobile 2003上吗?

  A:可以。.NET Compact Framework 2.0必须手动安�到Windows Mobile 2003的机器上。

26、Q:请问有没有好的Windows Mobile编程的网站或者论坛?

  A:OpenNETCF.org、www.devbuzz.comwww.codeproject.comwww.msdn.com/mobility/www.pocketpcdn.com

27、Q:Windows Mobile 2003上的.NET Compact Framework能升级到.NET Compact Framework 2.0吗?

  A:可以。.NET Compact Framework 2.0必须手动安�到Windows Mobile 2003的机器上。

28、Q:请问编写WML文件与使用.NET Compact Framework进行开发有什么联系和区别?

  A:WML是能够利用WAP浏览器进行浏览的文件,是一种基于Web的开发方式。.NET Compact Framework是在设备上运行的程序,是基于应用的开发方式。

29、Q:在使用.NET Compact Framework 1.0进行开发时,用EVC直接调用Native代码与使用C#通过P/Invoke在性能上有什么差别?在.NET Compact Framework 2.0上,用C++直接调用和用C#通过P/Invoke又如何呢?

 A:用EVC�用Native API的效率,会比使用.NET Compact Framework通过P/Invoke调用Native API要高,这是.NET Compact Framework本身的特性。在从托管代码中调用Native API时,其内部会进行一些额外的类型转换动作,这会导致效率的降低。

30、Q:有没有支持显示HTML文本的控件?

  A:WebBrowser控件可以用于HTML文本。

31、Q:CAB安装后会在Pocket PC上自动生成"卸载程序",如何制作安装包,才能不自动产生"卸载程序"?

  A:利用VS 2005建立Smart Device Cab Project,在Solution Explorer的Cab Project上点击鼠标右键选择Property,即可看到有一个选项为NoUninstall,默认为False,改为True就可以了。

32、Q:OpenNETCF能运行在.NET Framework 1.1环境下吗?其中的控件可以与.NET Framework 1.1控件混合使用吗?怎样在Visual Studio .NET 2003中加入OpenNETCF控件?

  A:当初在设计NET Compact Framework 1.0/1.1时,由于考虑到移动设备的资源有限,所以有些原本.NET Framework 1.1中已经提供的类和控件就被删除了,OpenNETCF Smart Device Framework主要是针对.NET Compact Framework 1.0/1.1中没有的功能,开发出来的类似的类型和额外的功能,以弥补.NET Compact Framework 1.0/1.1不足之处。这套Framework主要是供.NET Compact Framework程序开发所 用,除了少部份针对PC与Pocket PC的同步功能所编写的类之外,大部分都是在.NET Compact Framework上执行的,一般不支持.NET Framework。OpenNETCF的Smart Device Framework安装完毕之后,可以在VS 2003左侧的工具箱中看到OpenNETCF的控件,可以直接拖放来使用。


2008年5月15日星期四

c++中string的用法

之所以抛弃char*的字符串而选用C++标准程序库中的string类,是因为他和前者比较起来,不必担心内存是否足够、字符串长度等等,而且作为一个类出现,他集成的操作函数足以完成我们大多数情况下(甚至是100%)的需要。我们可以用 = 进行赋值操作,== 进行比较,+ 做串联(是不是很简单?)。我们尽可以把它看成是C++的基本数据类型。

首先,为了在我们的程序中使用string类型,我们必须包含头文件 <string>。如下:
#include <string> //注意这里不是string.h string.h是C字符串头文件

1.声明一个C++字符串
声明一个字符串变量很简单:
string Str;
这样我们就声明了一个字符串变量,但既然是一个类,就有构造函数和析构函数。上面的声明没有传入参数,所以就直接使用了string的默认的构造函数,这个函数所作的就是把Str初始化为一个空字符串。String类的构造函数和析构函数如下:
a) string s; //生成一个空字符串s
b) string s(str) //拷贝构造函数 生成str的复制品
c) string s(str,stridx) //将字符串str内"始于位置stridx"的部分当作字符串的初值
d) string s(str,stridx,strlen) //将字符串str内"始于stridx且长度顶多strlen"的部分作为字符串的初值
e) string s(cstr) //将C字符串作为s的初值
f) string s(chars,chars_len) //将C字符串前chars_len个字符作为字符串s的初值。
g) string s(num,c) //生成一个字符串,包含num个c字符
h) string s(beg,end) //以区间beg;end(不包含end)内的字符作为字符串s的初值
i) s.~string() //销毁所有字符,释放内存
都很简单,我就不解释了。

2.字符串操作函数
这里是C++字符串的重点,我先把各种操作函数罗列出来,不喜欢把所有函数都看完的人可以在这里找自己喜欢的函数,再到后面看他的详细解释。
a) =,assign() //赋以新值
b) swap() //交换两个字符串的内容
c) +=,append(),push_back() //在尾部添加字符
d) insert() //插入字符
e) erase() //删除字符
f) clear() //删除全部字符
g) replace() //替换字符
h) + //串联字符串
i) ==,!=,<,<=,>,>=,compare() //比较字符串
j) size(),length() //返回字符数量
k) max_size() //返回字符的可能最大个数
l) empty() //判断字符串是否为空
m) capacity() //返回重新分配之前的字符容量
n) reserve() //保留一定量内存以容纳一定数量的字符
o) [ ], at() //存取单一字符
p) >>,getline() //从stream读取某值
q) << //将谋值写入stream
r) copy() //将某值赋值为一个C_string
s) c_str() //将内容以C_string返回
t) data() //将内容以字符数组形式返回
u) substr() //返回某个子字符串
v)查找函数
w)begin() end() //提供类似STL的迭代器支持
x) rbegin() rend() //逆向迭代器
y) get_allocator() //返回配置器
下面详细介绍:

2.1 C++字符串和C字符串的转换
C ++提供的由C++字符串得到对应的C_string的方法是使用data()、c_str()和copy(),其中,data()以字符数组的形式返回字符串内容,但并不添加'\0'。c_str()返回一个以'\0'结尾的字符数组,而copy()则把字符串的内容复制或写入既有的c_string或字符数组内。C++字符串并不以'\0'结尾。我的建议是在程序中能使用C++字符串就使用,除非万不得已不选用c_string。由于只是简单介绍,详细介绍掠过,谁想进一步了解使用中的注意事项可以给我留言(到我的收件箱)。我详细解释。

2.2 大小和容量函数
一个C++字符串存在三种大小:a)现有的字符数,函数是size()和length(),他们等效。Empty()用来检查字符串是否为空。b)max_size() 这个大小是指当前C++字符串最多能包含的字符数,很可能和机器本身的限制或者字符串所在位置连续内存的大小有关系。我们一般情况下不用关心他,应该大小足够我们用的。但是不够用的话,会抛出length_error异常c)capacity()重新分配内存之前 string所能包含的最大字符数。这里另一个需要指出的是reserve()函数,这个函数为string重新分配内存。重新分配的大小由其参数决定,默认参数为0,这时候会对string进行非强制性缩减。

还有必要再重复一下C++字符串和C字符串转换的问题,许多人会遇到这样的问题,自己做的程序要调用别人的函数、类什么的(比如数据库连接函数Connect(char*,char*)),但别人的函数参数用的是char*形式的,而我们知道,c_str()、data()返回的字符数组由该字符串拥有,所以是一种const char*,要想作为上面提及的函数的参数,还必须拷贝到一个char*,而我们的原则是能不使用C字符串就不使用。那么,这时候我们的处理方式是:如果此函数对参数(也就是char*)的内容不修改的话,我们可以这样Connect((char*)UserID.c_str(), (char*)PassWD.c_str()),但是这时候是存在危险的,因为这样转换后的字符串其实是可以修改的(有兴趣地可以自己试一试),所以我强调除非函数调用的时候不对参数进行修改,否则必须拷贝到一个char*上去。当然,更稳妥的办法是无论什么情况都拷贝到一个char*上去。同时我们也祈祷现在仍然使用C字符串进行编程的高手们(说他们是高手一点儿也不为过,也许在我们还穿开裆裤的时候他们就开始编程了,哈哈…)写的函数都比较规范,那样我们就不必进行强制转换了。
2.3元素存取

我们可以使用下标操作符[]和函数at()对元素包含的字符进行访问。但是应该注意的是操作符[]并不检查索引是否有效(有效索引 0~str.length()),如果索引失效,会引起未定义的行为。而at()会检查,如果使用 at()的时候索引无效,会抛出out_of_range异常。
有一个例外不得不说,const string a;的操作符[]对索引值是a.length()仍然有效,其返回值是'\0'。其他的各种情况,a.length()索引都是无效的。举例如下:
const string Cstr("const string");
string Str("string");

Str[3]; //ok
Str.at(3); //ok

Str[100]; //未定义的行为
Str.at(100); //throw out_of_range

Str[Str.length()] //未定义行为
Cstr[Cstr.length()] //返回 '\0'
Str.at(Str.length());//throw out_of_range
Cstr.at(Cstr.length()) ////throw out_of_range

我不赞成类似于下面的引用或指针赋值:
char& r=s[2];
char* p= &s[3];
因为一旦发生重新分配,r,p立即失效。避免的方法就是不使用。

2.4比较函数
C ++字符串支持常见的比较操作符(>,>=,<,<=,==,!=),甚至支持string与C-string的比较(如 str<"hello")。在使用>,>=,<,<=这些操作符的时候是根据"当前字符特性"将字符按字典顺序进行逐一得比较。字典排序靠前的字符小,比较的顺序是从前向后比较,遇到不相等的字符就按这个位置上的两个字符的比较结果确定两个字符串的大小。同时,string ("aaaa") <string(aaaaa)。
另一个功能强大的比较函数是成员函数compare()。他支持多参数处理,支持用索引值和长度定位子串来进行比较。他返回一个整数来表示比较结果,返回值意义如下:0-相等 〉0-大于 <0-小于。举例如下:
string s("abcd");

s.compare("abcd"); //返回0
s.compare("dcba"); //返回一个小于0的值
s.compare("ab"); //返回大于0的值

s.compare(s); //相等
s.compare(0,2,s,2,2); //用"ab"和"cd"进行比较 小于零
s.compare(1,2,"bcx",2); //用"bc"和"bc"比较。
怎么样?功能够全的吧!什么?还不能满足你的胃口?好吧,那等着,后面有更个性化的比较算法。先给个提示,使用的是STL的比较算法。什么?对STL一窍不通?靠,你重修吧!

2.5 更改内容
这在字符串的操作中占了很大一部分。

首先讲赋值,第一个赋值方法当然是使用操作符=,新值可以是string(如:s=ns) 、c_string(如:s="gaint")甚至单一字符(如:s='j')。还可以使用成员函数assign(),这个成员函数可以使你更灵活的对字符串赋值。还是举例说明吧:
s.assign(str); //不说
s.assign(str,1,3);//如果str是"iamangel" 就是把"ama"赋给字符串
s.assign(str,2,string::npos);//把字符串str从索引值2开始到结尾赋给s
s.assign("gaint"); //不说
s.assign("nico",5);//把'n' 'I' 'c' 'o' '\0'赋给字符串
s.assign(5,'x');//把五个x赋给字符串
把字符串清空的方法有三个:s="";s.clear();s.erase();(我越来越觉得举例比说话让别人容易懂!)。
string提供了很多函数用于插入(insert)、删除(erase)、替换(replace)、增加字符。
先说增加字符(这里说的增加是在尾巴上),函数有 +=、append()、push_back()。举例如下:
s+=str;//加个字符串
s+="my name is jiayp";//加个C字符串
s+='a';//加个字符

s.append(str);
s.append(str,1,3);//不解释了 同前面的函数参数assign的解释
s.append(str,2,string::npos)//不解释了

s.append("my name is jiayp");
s.append("nico",5);
s.append(5,'x');

s.push_back('a');//这个函数只能增加单个字符 对STL熟悉的理解起来很简单

也许你需要在string中间的某个位置插入字符串,这时候你可以用insert()函数,这个函数需要你指定一个安插位置的索引,被插入的字符串将放在这个索引的后面。
s.insert(0,"my name");
s.insert(1,str);
这种形式的insert()函数不支持传入单个字符,这时的单个字符必须写成字符串形式(让人恶心)。既然你觉得恶心,那就不得不继续读下面一段话:为了插入单个字符,insert()函数提供了两个对插入单个字符操作的重载函数:insert(size_type index,size_type num,chart c)和insert(iterator pos,size_type num,chart c)。其中size_type是无符号整数,iterator是char*,所以,你这么调用insert函数是不行的:insert(0,1, 'j');这时候第一个参数将转换成哪一个呢?所以你必须这么写:insert((string::size_type)0,1,'j')!第二种形式指出了使用迭代器安插字符的形式,在后面会提及。顺便提一下,string有很多操作是使用STL的迭代器的,他也尽量做得和STL靠近。
删除函数erase()的形式也有好几种(真烦!),替换函数replace()也有好几个。举例吧:
string s="il8n";
s.replace(1,2,"nternationalizatio");//从索引1开始的2个替换成后面的C_string
s.erase(13);//从索引13开始往后全删除
s.erase(7,5);//从索引7开始往后删5个

2.6提取子串和字符串连接
题取子串的函数是:substr(),形式如下:
s.substr();//返回s的全部内容
s.substr(11);//从索引11往后的子串
s.substr(5,6);//从索引5开始6个字符
把两个字符串结合起来的函数是+。(谁不明白请致电120)

2.7输入输出操作
1.>> 从输入流读取一个string。
2.<< 把一个string写入输出流。
另一个函数就是getline(),他从输入流读取一行内容,直到遇到分行符或到了文件尾。

2.8搜索与查找
查找函数很多,功能也很强大,包括了:
find()
rfind()
find_first_of()
find_last_of()
find_first_not_of()
find_last_not_of()
这些函数返回符合搜索条件的字符区间内的第一个字符的索引,没找到目标就返回npos。所有的函数的参数说明如下:
第一个参数是被搜寻的对象。第二个参数(可有可无)指出string内的搜寻起点索引,第三个参数(可有可无)指出搜寻的字符个数。比较简单,不多说不理解的可以向我提出,我再仔细的解答。当然,更加强大的STL搜寻在后面会有提及。
最后再说说npos的含义,string::npos的类型是string::size_type,所以,一旦需要把一个索引与npos相比,这个索引值必须是string::size)type类型的,更多的情况下,我们可以直接把函数和npos进行比较(如:if(s.find("jia")== string::npos))。

2008年5月14日星期三

FW: CString,string,char*的综合比较



 
CString,string,char*的综合比较

(一) 概述

string和CString均是字符串模板类,string为标准模板类(STL)定义的字符串类,已经纳入C++标准之中;

CString (typedef CStringT > CString)为Visual C++中最常用的字符串类,继承自CSimpleStringT类,主要应用在MFC和ATL编程中,主要数据类型有char(应用于ANSI), wchar_t(unicode),TCHAR(ANSI与unicode均可);

char*为C编程中最常用的字符串指针,一般以'\0'为结束标志;

(二) 构造

string是方便的,可以从几乎所有的字符串构造而来,包括CString和char*;

CString次之,可以从基本的一些字符串变量构造而来,包括char*等;

char*没有构造函数,仅可以赋值;

举例:

char* psz = "joise";

CString cstr( psz );

string str( cstr );

(三) 运算符重载

a) operator=

string是最方便的,几乎可以直接用所有的字符串赋值,包括CString和char*;

CString次之,可以直接用些基本的字符串赋值,包括char*等;

char*只能由指针赋值,并且是极危险的操作,建议使用strcpy或者memcpy,而且char*在声明的时候如未赋初值建议先设为NULL,以避免野指针,令你抓狂;

举例:

char *psz = NULL;

psz = new char[10]; //当然,以上的直接写成char *psz = new char[10];也是一样

memset( psz, 0, 10 );

strcpy( psz, "joise" );

CString cstr;

cstr = psz;

string str;

str = psz;

str = cstr;

delete []psz;

b) operator+

string与CString差不多,可以直接与char*进行加法,但不可以相互使用+运算符,即string str = str + cstr是非法的,须转换成char*;

char*没有+运算,只能使用strcat把两个指针连在一起;

举例:

char* psz = "joise";

CString cstr = psz;

cstr = cstr + psz;

string str = psz;

str = str + str + psz;

strcat( psz, psz );

strcat( psz, cstr );//合法

strcat( psz, str );//非法,由此可见,CString可自动转换为const char*,而string不行

c) operator +=

string是最强大的,几乎可以与所有的字符串变量+=,包括CString和char*;

CString次之,可以与基本的一些字符串变量进行+=而来,包括char*等;

char*没有+=运算符,只能使用strcat把两个指针连在一起;

d) operator[]

CString最好,当越界时会抛出断言异常;

string与char*下标越界结果未定义;

举例:

char* psz = "joise";

CString cstr = psz;

cout << cstr[8];

string str = psz;

cout << str[8];

cout << psz[8];

e) operator== 、operator!=、operator> 、operator< 、operator>= 、perator<=

CString与string之间不可以进行比较,但均可以与char*进行比较,并且比较的是值,而不是地址;

cout << ( psz == cstr );

cout << ( psz == str );

cout << ( str == psz );

cout << ( cstr == psz );//以上代码返回均为1

(四) 常用算法

a) 查找
作用 char* string CString
查找指定值 strchr
strstr
strrstr
strspn find Find
第一个匹配的值 fild_first_of FindOneOf 从后面开始查找 ReserveFind 指定匹配方式 find_if

注:find_if中是把范围内的值挨个代入匹配函数直至返回true

b) 比较
作用 char* string CString 查找指定值(区分大小写) strcmp
strncmp
strcoll
_strncoll operator<
operator>
operator<=
operator>=
operator==
operator!= Collate

Compare 查找指定值(不区分大小写) _stricmp
_strnicmp
_stricoll
_strnicoll CollateNoCase

CompareNoCas

注:返回值如果<0则前面的值小于后面的值,反之亦然

c) 替换
作用 char* string CString 查找指定值 _strset
_strnset
replace
replace_copy
replace_copy_if
replace_if Replace

d) 插入
作用 char* string CString 查找指定值 insert Insert
e) 增加 作用 char* string CString 动态增加值 strcat push

append Append

AppendChar

AppendFormat


f) 截取
作用 char* string CString 得到部分值 用下标操作 substr Left

Mid

Right

Truncate


g) 移除
作用 char* string CString 移除部份值 remove Remove 移除空白值 RemoveBlanks

注:此为ATL提供,非C函数 remove_if Trim

TrimLeft

TrimRig


h) 转换大小写
作用 char* string CString 转换大小写 _strlwr

_strupr MakeLower

MakeUpper


i) 与其他类型转换
作用 char* string CString 转化为数字 atoi

atod

atof Format 转化为char* c_str
GetBuffer

GetBufferSetLen

j) 格式化
作用 char* string CString 格式化 sprintf Format


k) 得到长度
作用 char* string CString
得到长度 strlen length GetLength 得到大小 size GetAllocLength

l) 判断为空
作用 char* string CString 判断是否为空 判断是否==NULL或者第一个字符是否是'\0' empty IsEmpty

m) 重定义大小
作用 char* string CString 重定义大小 realloc
new resize GetBufferSetLength

n) 释放资源
作用 char* string CString 释放 free

delete (delete[]) ReleaseBuffer

ReleaseBufferSetLength

(五) 安全性>

CString > string > char*;

(六) 灵活性

CString > string >char*;

(七) 可移植性

char* = string > CString

转:如何:在各种字符串类型之间进行转换

如何:在各种字符串类型之间进行转换

本主题演示如何将各种 Visual C++ 字符串类型转换为其他字符串。可以转换的字符串类型包括 char *、wchar_t*、_bstr_t、CComBSTR、CString、basic_string 和 System.String。在所有情况下,在将字符串转换为新类型时,都会创建字符串的副本。对新字符串进行的任何更改都不会影响原始字符串,反之亦然。
从 char * 转换
示例

此示例演示如何从 char * 转换为上面列出的其他字符串类型。
复制代码

// convert_from_char.cpp
// compile with: /clr /link comsuppw.lib

#include <iostream>
#include <stdlib.h>
#include <string>

#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"

using namespace std;
using namespace System;

int main()
{
char *orig = "Hello, World!";
cout << orig << " (char *)" << endl;

// Convert to a wchar_t*
size_t origsize = strlen(orig) + 1;
const size_t newsize = 100;
size_t convertedChars = 0;
wchar_t wcstring[newsize];
mbstowcs_s(&convertedChars, wcstring, origsize, orig, _TRUNCATE);
wcscat_s(wcstring, L" (wchar_t *)");
wcout << wcstring << endl;

// Convert to a _bstr_t
_bstr_t bstrt(orig);
bstrt += " (_bstr_t)";
cout << bstrt << endl;

// Convert to a CComBSTR
CComBSTR ccombstr(orig);
if (ccombstr.Append(L" (CComBSTR)") == S_OK)
{
CW2A printstr(ccombstr);
cout << printstr << endl;
}

// Convert to a CString
CString cstring(orig);
cstring += " (CString)";
cout << cstring << endl;

// Convert to a basic_string
string basicstring(orig);
basicstring += " (basic_string)";
cout << basicstring << endl;

// Convert to a System::String
String ^systemstring = gcnew String(orig);
systemstring += " (System::String)";
Console::WriteLine("{0}", systemstring);
delete systemstring;
}

输出

Hello, World! (char *)
Hello, World! (wchar_t *)
Hello, World! (_bstr_t)
Hello, World! (CComBSTR)
Hello, World! (CString)
Hello, World! (basic_string)
Hello, World! (System::String)

从 wchar_t * 转换
示例

此示例演示如何从 wchar_t * 转换为上面列出的其他字符串类型。
复制代码

// convert_from_wchar_t.cpp
// compile with: /clr /link comsuppw.lib

#include <iostream>
#include <stdlib.h>
#include <string>

#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"

using namespace std;
using namespace System;

int main()
{
wchar_t *orig = L"Hello, World!";
wcout << orig << L" (wchar_t *)" << endl;

// Convert to a char*
size_t origsize = wcslen(orig) + 1;
const size_t newsize = 100;
size_t convertedChars = 0;
char nstring[newsize];
wcstombs_s(&convertedChars, nstring, origsize, orig, _TRUNCATE);
strcat_s(nstring, " (char *)");
cout << nstring << endl;

// Convert to a _bstr_t
_bstr_t bstrt(orig);
bstrt += " (_bstr_t)";
cout << bstrt << endl;

// Convert to a CComBSTR
CComBSTR ccombstr(orig);
if (ccombstr.Append(L" (CComBSTR)") == S_OK)
{
CW2A printstr(ccombstr);
cout << printstr << endl;
}

// Convert to a CString
CString cstring(orig);
cstring += " (CString)";
cout << cstring << endl;

// Convert to a basic_string
wstring basicstring(orig);
basicstring += L" (basic_string)";
wcout << basicstring << endl;

// Convert to a System::String
String ^systemstring = gcnew String(orig);
systemstring += " (System::String)";
Console::WriteLine("{0}", systemstring);
delete systemstring;
}

输出

Hello, World! (wchar_t *)
Hello, World! (char *)
Hello, World! (_bstr_t)
Hello, World! (CComBSTR)
Hello, World! (CString)
Hello, World! (basic_string)
Hello, World! (System::String)

从 _bstr_t 转换
示例

此示例演示如何从 _bstr_t 转换为上面列出的其他字符串类型。
复制代码

// convert_from_bstr_t.cpp
// compile with: /clr /link comsuppw.lib

#include <iostream>
#include <stdlib.h>
#include <string>

#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"

using namespace std;
using namespace System;

int main()
{
_bstr_t orig("Hello, World!");
wcout << orig << " (_bstr_t)" << endl;

// Convert to a char*
const size_t newsize = 100;
char nstring[newsize];
strcpy_s(nstring, (char *)orig);
strcat_s(nstring, " (char *)");
cout << nstring << endl;

// Convert to a wchar_t*
wchar_t wcstring[newsize];
wcscpy_s(wcstring, (wchar_t *)orig);
wcscat_s(wcstring, L" (wchar_t *)");
wcout << wcstring << endl;

// Convert to a CComBSTR
CComBSTR ccombstr((char *)orig);
if (ccombstr.Append(L" (CComBSTR)") == S_OK)
{
CW2A printstr(ccombstr);
cout << printstr << endl;
}

// Convert to a CString
CString cstring((char *)orig);
cstring += " (CString)";
cout << cstring << endl;

// Convert to a basic_string
string basicstring((char *)orig);
basicstring += " (basic_string)";
cout << basicstring << endl;

// Convert to a System::String
String ^systemstring = gcnew String((char *)orig);
systemstring += " (System::String)";
Console::WriteLine("{0}", systemstring);
delete systemstring;
}

输出

Hello, World! (_bstr_t)
Hello, World! (char *)
Hello, World! (wchar_t *)
Hello, World! (CComBSTR)
Hello, World! (CString)
Hello, World! (basic_string)
Hello, World! (System::String)

从 CComBSTR 转换
示例

此示例演示如何从 CComBSTR 转换为上面列出的其他字符串类型。
复制代码

// convert_from_ccombstr.cpp
// compile with: /clr /link comsuppw.lib

#include <iostream>
#include <stdlib.h>
#include <string>

#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"
#include "vcclr.h"

using namespace std;
using namespace System;
using namespace System::Runtime::InteropServices;

int main()
{
CComBSTR orig("Hello, World!");
CW2A printstr(orig);
cout << printstr << " (CComBSTR)" << endl;

// Convert to a char*
const size_t newsize = 100;
char nstring[newsize];
CW2A tmpstr1(orig);
strcpy_s(nstring, tmpstr1);
strcat_s(nstring, " (char *)");
cout << nstring << endl;

// Convert to a wchar_t*
wchar_t wcstring[newsize];
wcscpy_s(wcstring, orig);
wcscat_s(wcstring, L" (wchar_t *)");
wcout << wcstring << endl;

// Convert to a _bstr_t
_bstr_t bstrt(orig);
bstrt += " (_bstr_t)";
cout << bstrt << endl;

// Convert to a CString
CString cstring(orig);
cstring += " (CString)";
cout << cstring << endl;

// Convert to a basic_string
wstring basicstring(orig);
basicstring += L" (basic_string)";
wcout << basicstring << endl;

// Convert to a System::String
String ^systemstring = gcnew String(orig);
systemstring += " (System::String)";
Console::WriteLine("{0}", systemstring);
delete systemstring;
}

输出

Hello, World! (CComBSTR)
Hello, World! (char *)
Hello, World! (wchar_t *)
Hello, World! (_bstr_t)
Hello, World! (CString)
Hello, World! (basic_string)
Hello, World! (System::String)

从 CString 转换
示例

此示例演示如何从 CString 转换为上面列出的其他字符串类型。
复制代码

// convert_from_cstring.cpp
// compile with: /clr /link comsuppw.lib

#include <iostream>
#include <stdlib.h>
#include <string>

#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"

using namespace std;
using namespace System;

int main()
{
CString orig("Hello, World!");
wcout << orig << " (CString)" << endl;

// Convert to a char*
const size_t newsize = 100;
char nstring[newsize];
strcpy_s(nstring, orig);
strcat_s(nstring, " (char *)");
cout << nstring << endl;

// Convert to a wchar_t*
// You must first convert to a char * for this to work.
size_t origsize = strlen(orig) + 1;
size_t convertedChars = 0;
wchar_t wcstring[newsize];
mbstowcs_s(&convertedChars, wcstring, origsize, orig, _TRUNCATE);
wcscat_s(wcstring, L" (wchar_t *)");
wcout << wcstring << endl;

// Convert to a _bstr_t
_bstr_t bstrt(orig);
bstrt += " (_bstr_t)";
cout << bstrt << endl;

// Convert to a CComBSTR
CComBSTR ccombstr(orig);
if (ccombstr.Append(L" (CComBSTR)") == S_OK)
{
CW2A printstr(ccombstr);
cout << printstr << endl;
}

// Convert to a basic_string
string basicstring(orig);
basicstring += " (basic_string)";
cout << basicstring << endl;

// Convert to a System::String
String ^systemstring = gcnew String(orig);
systemstring += " (System::String)";
Console::WriteLine("{0}", systemstring);
delete systemstring;
}

输出

Hello, World! (CString)
Hello, World! (char *)
Hello, World! (wchar_t *)
Hello, World! (_bstr_t)
Hello, World! (CComBSTR)
Hello, World! (basic_string)
Hello, World! (System::String)

从 basic_string 转换
示例

此示例演示如何从 basic_string 转换为上面列出的其他字符串类型。
复制代码

// convert_from_basic_string.cpp
// compile with: /clr /link comsuppw.lib

#include <iostream>
#include <stdlib.h>
#include <string>

#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"

using namespace std;
using namespace System;

int main()
{
string orig("Hello, World!");
cout << orig << " (basic_string)" << endl;

// Convert to a char*
const size_t newsize = 100;
char nstring[newsize];
strcpy_s(nstring, orig.c_str());
strcat_s(nstring, " (char *)");
cout << nstring << endl;

// Convert to a wchar_t*
// You must first convert to a char * for this to work.
size_t origsize = strlen(orig.c_str()) + 1;
size_t convertedChars = 0;
wchar_t wcstring[newsize];
mbstowcs_s(&convertedChars, wcstring, origsize, orig.c_str(), _TRUNCATE);
wcscat_s(wcstring, L" (wchar_t *)");
wcout << wcstring << endl;

// Convert to a _bstr_t
_bstr_t bstrt(orig.c_str());
bstrt += " (_bstr_t)";
cout << bstrt << endl;

// Convert to a CComBSTR
CComBSTR ccombstr(orig.c_str());
if (ccombstr.Append(L" (CComBSTR)") == S_OK)
{
CW2A printstr(ccombstr);
cout << printstr << endl;
}

// Convert to a CString
CString cstring(orig.c_str());
cstring += " (CString)";
cout << cstring << endl;

// Convert to a System::String
String ^systemstring = gcnew String(orig.c_str());
systemstring += " (System::String)";
Console::WriteLine("{0}", systemstring);
delete systemstring;
}

输出

Hello, World! (basic_string)
Hello, World! (char *)
Hello, World! (wchar_t *)
Hello, World! (_bstr_t)
Hello, World! (CComBSTR)
Hello, World! (CString)
Hello, World! (System::String)

从 System::String 转换
示例

此示例演示如何从 System.String 转换为上面列出的其他字符串类型。
复制代码

// convert_from_system_string.cpp
// compile with: /clr /link comsuppw.lib

#include <iostream>
#include <stdlib.h>
#include <string>

#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"
#include "vcclr.h"

using namespace std;
using namespace System;
using namespace System::Runtime::InteropServices;

int main()
{
String ^orig = gcnew String("Hello, World!");
Console::WriteLine("{0} (System::String)", orig);

pin_ptr<const wchar_t> wch = PtrToStringChars(orig);

// Convert to a char*
size_t origsize = wcslen(wch) + 1;
const size_t newsize = 100;
size_t convertedChars = 0;
char nstring[newsize];
wcstombs_s(&convertedChars, nstring, origsize, wch, _TRUNCATE);
strcat_s(nstring, " (char *)");
cout << nstring << endl;

// Convert to a wchar_t*
wchar_t wcstring[newsize];
wcscpy_s(wcstring, wch);
wcscat_s(wcstring, L" (wchar_t *)");
wcout << wcstring << endl;

// Convert to a _bstr_t
_bstr_t bstrt(wch);
bstrt += " (_bstr_t)";
cout << bstrt << endl;

// Convert to a CComBSTR
CComBSTR ccombstr(wch);
if (ccombstr.Append(L" (CComBSTR)") == S_OK)
{
CW2A printstr(ccombstr);
cout << printstr << endl;
}

// Convert to a CString
CString cstring(wch);
cstring += " (CString)";
cout << cstring << endl;

// Convert to a basic_string
wstring basicstring(wch);
basicstring += L" (basic_string)";
wcout << basicstring << endl;

delete orig;
}

输出

Hello, World! (System::String)
Hello, World! (char *)
Hello, World! (wchar_t *)
Hello, World! (_bstr_t)
Hello, World! (CComBSTR)
Hello, World! (CString)
Hello, World! (basic_string)

如何使用 类进行文件的 I/O 处理

摘要:传统的文件 I/O 库如 Unix 的 <io.h> 和 <stdio.h> ,由于其程序接口的原因,在很大程度上强制程序员进行某些处理,缺乏类型安全和国际化支持。C++ 的 <fstream> 库则在文件的 I/O 方面提供了一个增强的、面向对象的、具有国际化意识的库。本文将介绍如何使用这个库进行文件的 I/O 处理并利用它来编写易于跨平台的代码。

  大多数 C++ 程序员都熟悉不止一个文件 I/O 库。首先是传统的 Unix 风格的库,它由一些低级函数如 read() 和 open()组成。其次是 ANSI C 的 <stdio.h> 库,它包含 fopen() 和 fread()等函数。其它的还有一些具备所有权的库或框架,比如 MFC,它有很多自己的文件处理类。

  这些库一般都很难跨平台使用。更糟的是,上述提到的 C 库由于其程序接口的原因,在很大程度上强制程序员进行某些处理,而且缺乏类型安全支持。

  标准 C++ 提供提供了一个增强的、面向对象的、具有国际化意识的 <fstream> 库。这个库包含一系列派生于标准 ios_base 和 ios 类的类模板。因此, <fstream> 提供了高级的自动控制机制和健壮性。本文下面将示范如何使用 <fstream> 类实现文件的输入/输出处理:

  第一步:创建文件流

  输入文件流(ifstream)支持重载的 >> 操作符,同样,输出文件流(ofstream)支持重载的 << 操作符。结合了输入和输出的文件流被称为 fstream。下面的程序创建了一个 ifstream 对象:dict,并将该对象中的每一个单字显示到屏幕上:
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
using namespace std;
int main()
{
  string s;
  cout<<"enter dictionary file: ";
  cin>>s;
  ifstream dict (s.c_str());
  if (!dictionary) // were there any errors on opening?
    exit(-1);
  while (dictionary >> s) cout << s <<''\n'';
}   

  我们必须调用 string::c_str() 成员函数,因为 fstream 对象只接受常量字符串作为文件名。当你将文件名作为参数传递时,构造函数试图打开指定的文件。接着,我们用重载的!操作符来检查文件的状态。如果出错,该操作符估值为 true。最后一行是个循环,每次反复都从文件读取一个单字,将它拷贝到 s,然后显示出来。注意我们不必显式地检查 EOF,因为重载操作符 >> 会自动处理。此外,我们不用显式地关闭此文件,因为析构函数会为我们做这件事情。
过时和荒废的 <fstream.h> 库支持 ios::nocreate 和 ios::noreplace 标志。但新的 <fstream> 库已经取代了 <fstream.h> 并不再支持这两个标志。

  文件的打开模式

  如果你不显式指定打开模式,fstream 类将使用默认值。例如,ifstream 默认以读方式打开某个文件并将文件指针置为文件的开始处。为了向某个文件写入数据,你需要创建一个 ofstream 对象。<fstream> 定义了下列打开模式和文件属性:
ios::app // 从后面添加
ios::ate // 打开并找到文件尾
ios::binary // 二进制模式 I/O (与文本模式相对)
ios::in // 只读打开
ios::out // 写打开
ios::trunc // 将文件截为 0 长度

  你可以用位域操作符 OR 组合这些标志:
ofstream logfile("login.dat", ios::binary | ios::app);

  fstream 类型对象同时支持读和写操作:
fstream logfile("database.dat", ios::in | ios::out);

  第二步:设置文件的位置

  文件具备一个逻辑指针,它指向该文件中的某个偏移位置。你可以通过调用seekp()成员函数,以字节为单位将这个指针定位到文件的任意位置。为了获取从文件开始处到当前偏移的字节数,调用seekp()即可。在下面的例子中,程序将文件位置前移10个字节,然后调用 tellp()报告新位置:
ofstream fout("parts.txt");
fout.seekp(10); // 从0偏移开始前进 10 个字节
cout<<"new position: "<<fout.tellp(); // 显示 10

  你可以用下面的常量重新定位文ian指针:
ios::beg // 文件开始位置
ios::cur // 当前位置,例如: ios::cur+5
ios::end // 文件尾

  第三步:读写数据

  fstream 类为所有内建数据类型以及 std::string 和 std::complex 类型重载 << 和 >> 操作符。下面的例子示范了这些操作符的使用方法:
fstream logfile("log.dat");
logfile<<time(0)<<"danny"<<''\n''; // 写一条新记录
logfile.seekp(ios::beg); // 位置重置
logfile>>login>>user; // 读取以前写入的值

2008年4月20日星期日

Windows Embedded Blog from China
Windows Mobile开发资源介绍

目前Windows Mobile的开发资源已经非常多了,我们在这里试着对这些资源进行一个归纳,使第一次进入Windows Mobile领域的开发者能够更容易得找到有用的开发资源。
Windows Mobile是什么

Windows Mobile是微软为智能手机和PDA提供的操作系统,在Windows Mobile 5.0之前分为Pocket PC和Smartphone两种版本,Pocket PC中包括PDA版本和带电话功能的Phone Edition。在Windows Mobile 6.0中分为三类:Professional,即Pocket PC Phone Edition; Standard, 即Smartphone;Classic,即无电话功能的Pocket PC。

Windows Mobile是基于Windows CE操作系统开发的针对智能手机和PDA的操作系统平台。所以Windows Mobile的硬件与应用程序都是由相关的标准要求,符合标准才能够运行Windows Mobile操作系统。
获取开发工具

目前Windows Mobile的主流开发平台/语言分为两种:.NET(包括C#和VB.NET)和C++。微软已经将这两种开发语言的支持加入到Visual Studio中。Visual Studio 2005和2008均内置了Windows Mobile的SDK,可以直接开发Windows Mobile应用程序。Visual Studio也支持安装最新版本的Windows Mobile SDK。

如果想用Visual Studio开发Windows Mobile应用程序的话,必须已经获取了Visual Studio Professional或以上版本。

除了Visual Studio外,我们还可以使用免费的eMbedded Visual C++ 4.0来开发C++应用程序。在安装SP4版本后,可以支持基于Windows CE 5.0设备的应用开发(目前Windows Mobile 5.0和6.0均基于Windows CE 5.0)。下载地址如下:

http://www.microsoft.com/downloads/details.aspx?FamilyId=1DACDB3D-50D1-41B2-A107-FA75AE960856&displaylang=en

eMbedded Visual C++ 4.0 SP4下载地址:

http://www.microsoft.com/downloads/details.aspx?familyid=4A4ED1F4-91D3-4DBE-986E-A812984318E5&displaylang=en

在安装完成开发工具后,还需要根据不同的目标设备安装不同版本的Windows Mobile SDK。我们可以在MSDN网站的下载中查询"Windows Mobile x.0 SDK",或者直接去下面链接中查找:

http://msdn2.microsoft.com/en-us/windowsmobile/bb264327.aspx

比如,Windows Mobile 6.0 SDK的下载地址:

http://www.microsoft.com/downloads/details.aspx?FamilyID=06111a3a-a651-4745-88ef-3d48091a390b&DisplayLang=en

如果要开发中文版的应用程序,还需要安装单独的本地化模拟器映像文件。Windows Mobile 6.0的语言映像文件下载链接如下:

http://www.microsoft.com/downloads/details.aspx?familyid=38C46AA8-1DD7-426F-A913-4F370A65A582&displaylang=en

除此之外,我们还需要安装ActiveSync 4.5,来使开发环境与Windows Mobile设备相连接。在Vista中Windows Mobile Device Center与ActiveSync的功能相同。

如果使用.NET Compact Framework来开发应用程序,还需要保证目标设备上安装了.NET CF的CLR,如果没有目标设备安装.NET CF,可以下载单独的.NET CF再发布包:

http://www.microsoft.com/downloads/details.aspx?FamilyID=9655156b-356b-4a2c-857c-e62f50ae9a55
网络资源

Windows Mobile开发中心

http://msdn2.microsoft.com/en-us/windowsmobile/default.aspx

Windows Mobile产品主页

http://www.microsoft.com/windowsmobile/

http://www.microsoft.com/china/windowsmobile

Windows Mobile移动解决方案联盟

http://www.wmisv.com.cn/

Pocket PC Developer Network

老牌Pocket PC开发者网站,在EVC和EVB时代曾经是开发者唯一的选择,不过后来风头逐渐被OpenNETCF盖过,但目前依旧是最完整的开发文章目录

http://www.pocketpcdn.com/

Smartphone Developer Network

Pocket PC Developer Network的姊妹网站

http://www.smartphonedn.com/

Code Project

综合性开发者网站,其中CE开发和.NET CF开发部分由许多值得借鉴的示例代码

http://www.codeproject.com/KB/mobile/

DEVBUZZ.COM

老牌Embedded Visual Basic开发网站,转型.NET CF后,仍然有一些开发资源值的一看

http://www.devbuzz.com/
开发资源

OpenNETCF

著名的开源类库,早先由多位MVP发起,进行公司化运作,后被Novell收购,先为咨询公司。OpenNETCF的最新版本仍可以免费使用,但不提供源代码。

http://www.opennetcf.com/

InTheHand

著名的开源类库,32feet.NET是以Bluetooth和IrDA开发为主的Shared Source类库。

http://inthehand.net/

Mobile Line of Business Solution Accelerator

由微软开发的一套移动商业软件开发指导包

http://www.microsoft.com/downloads/details.aspx?FamilyId=80A5C2C5-4F9B-4C1A-BFF6-2A3C6B68D15B&displaylang=en

Mobile Client Software Factory

微软开发的一套软件工厂框架,将设计模式应用于Mobile软件开发

http://msdn2.microsoft.com/en-us/library/aa480471.aspx

下载地址:

http://www.microsoft.com/downloads/details.aspx?FamilyID=F9176708-9F57-4C0F-97FB-F9C65A9BBF22&displaylang=en


开发社区

中文的开发论坛:

l 微软移动开发者论坛

微软的官方开发者论坛,目前的版主是微软最有价值专家(MVP)。

http://forums.microsoft.com/china/default.aspx?ForumGroupID=459&SiteID=15

l CSDN嵌入式开发论坛

最大的开发者社区,硬件/嵌入式开发板块中包括"嵌入开发(WinCE)"板块和移动平台板块中包括"Windows Mobile"板块

http://community.csdn.net/

l Windows Mobile开发者社区

CSIP创建的开发者讨论社区

http://www.winbile.net/BBS/

l 马宁的Windows Mobile开发研究

http://groups.csdn.net/aawolf_Mobile

l 博客园的Windows Mobile应用开发团队博客

shttp://mobiledev.cnblogs.com/

英文论坛:

l MSDN开发者社区:Smart Device Development

http://forums.microsoft.com/MSDN/default.aspx?ForumGroupID=11&SiteID=1

Webcast

l 中文MSDN与TechNet Webcast

Windows移动开发系列课程

http://www.microsoft.com/china/msdn/events/webcasts/shared/webcast/Series/WindowsMobile.aspx

Windows Mobile 技术开发黄金周

http://www.microsoft.com/china/msdn/events/webcasts/shared/webcast/Series/Mobilegoldenweek.aspx

Windows Mobile 2nd 开发黄金周

http://www.microsoft.com/china/msdn/events/webcasts/shared/webcast/Series/Mobilegoldenweek2nd.aspx

Windows Mobile 3rd 技术开发黄金周

http://www.microsoft.com/china/msdn/events/webcasts/shared/webcast/Series/mobile3rd.aspx

TechNet Windows 移动系列课程

http://www.microsoft.com/china/technet/webcasts/class/mobile.mspx

l 英文Webcast和Virtual Labs

Windows Mobility Marvels

主要针对的是Windows Mobile开发者,包括Webcast和Virtual Labs

http://www.microsoft.com/events/series/msdnmobility.aspx

Windows Mobility Marvels部分课程下载

http://www.microsoft.com/downloads/details.aspx?FamilyID=08e4391d-e07d-41fe-b2b8-aa4225281347&DisplayLang=en

Windows Mobile Solutions

针对IT Pro和Windows Mobile用户的Webcast系列

http://www.microsoft.com/events/series/msecmobility.aspx
BLOG

l Windows Mobile产品组英文BLOG

Windows Mobile Team Blog

http://blogs.msdn.com/windowsmobile/

.NET Compact Framework Team Blog

http://blogs.msdn.com/netcfteam/

Visual Studio For Device

http://blogs.msdn.com/vsdteam/

SQL Server Compact

http://blogs.msdn.com/SQLServerCompact/

l 产品组成员BLOG

Mike Hall的BLOG

http://blogs.msdn.com/mikehall/

Rob Tiffany's Windows Mobile Accelerator

主要研究领域为SQL CE和BOL Accelerator

http://blogs.msdn.com/robtiffany/

David Kline

.NET Compact Framework应用领域

http://blogs.msdn.com/davidklinems/

Steve Lasker's Web Log

SQL CE和Sync Service for ADO.NET

http://blogs.msdn.com/stevelasker/

Steven Pratschner's .Net CF WebLog

.NET Compact Framework CLR运行机制

http://blogs.msdn.com/stevenpr/

l 英文开发者BLOG

OpenNETCF Blogs

以开发OpenNETCF开源类库闻名的公司,拥有多位重量级MVP的BLOG

http://blog.opennetcf.org/

In the hand Blogs

另一个以开发InTheHand开源类库闻名的开发者BLOG

http://inthehand.net/blogs/

l 中文开发者BLOG

马宁的移动开发BLOG

http://blog.csdn.net/aawolf

张欣的BLOG

http://twodays.cnblogs.com/

黎波的BLOG

http://www.cnblogs.com/upto/

2008年2月13日星期三

Total Commander 7.02a CCF中英绿色美化版本
推荐的原因:最经典的软件之一,如果你不会使用,请到xbeta兄的新浪博客 善用佳软栏目学习:

http://blog.sina.com.cn/s/alist_1188742767_2_1.html

下载在下面附件!

预览 (7.0):

s1.jpg (375.44 KB)
2007-10-25 18:59

======================================================

1. 常见问题
配置以英文/XP-2K3/XGA/Windows Classic Theme为标准. 最佳搭配WinRAR/DAEMON/集成解码包. 其余搜索论坛.

a. Vista用户
1. Office插件
此插件貌似只能使用绝对路径.由于Vista没有自带转换器,若TC的安装目录不是C:\Program Files\Total Commander,则必须手动修改Office.ini中MSWRD832.CNV的所在目录.
2. 部分WFX不支持Vista.
b. 创建自解压档:[url=]?[/url][url=]压缩时将*.RAR/ZIP/7Z改为*.EXE. ZIP格式可以在TC中将*.ZIP 直接改名为*.EXE?[/url]
c. 别名:[url=]?[/url][url=]按左/右方向键定位到命令行后,输入别名即可打开相应程序. 如→CDO打开光驱,CDC关闭.?[/url]
d. 整合WinRAR[url=]?[/url][url=]在TOOLS下建立WinRAR目录,拷入WinRAR.exe/Default.SFX/Rarreg.key三个文件, 打开USER.ini文件,将%PROGRAMFILES%\WINRAR\WINRAR.EXE替换为%COMMANDER_PATH%\TOOLS\WINRAR\WINRAR.EXE.?[/url]
e. (批量)转换图像格式[url=]?[/url][url=]选中一/多张图片,按Alt+F5, 右侧下拉框中选择imagine, 将文件后缀由imagine改为想要的格式, 如JPG, GIF, PIC等, 确定.不建议转换多帧GIF. ?[/url]
f. CHM[url=]?[/url][url=]CHMDir是WCX&WDX, WCX时用于制作CHM或提取CHM资源, WDX时用于自定义列/鼠标悬停/批量改名/搜索等, 此插件配合TC的按目录压缩功能, 适合打包Firefox插件Scrapbook储存的网页并利用其WDX功能进行批量改名.
WCX用法:

提取资源: 选中某CHM后按Ctrl+PgDn.
制作CHM: 选中文件夹或文件后,按Alt+F5,下拉选中CHM,确定.

IEView是WLX, 使用IE核心查看CHM, 按F3. 第一次打开时可能会跳出下载的提示,选择打开, 方框打勾, 确定. 按4则用Archview查看CHM压缩情况.?[/url]
g. 报毒
使用自解压文件时会自动删除目标目录中的所有文件.手动解压亦可.

2. 插件/工具
此版本包括WCX, WDX, WFX, WLX 共47个, ADDON/工具若干. 全部汉化.

WCX - 12个:
7zip (7z), CheckSum (sha), CHMDir (chm/its), DirCopy (dircopy), ICLRead (icl), Imagine (imagine), ISO (iso&etc), MHTUnpack (mht/msg), Mover (mover), TreeCopyPlus (treecopy), Wipe (wipe), InstallExplorer (exe/msi)
---Alt+F5打包,Ctrl+PgDn提取资源. 部分如 MHTUnp & ISO & InstallExplorer 只可Ctrl+PgDn, 不适用Alt+F5

Dircopy:复制本目录结构, 不复制文件
Imagine.wcx: Ctrl+PgDn提取图片资源, Alt+F5转换图片格式.
InstallExplorer: 支持Wise/Vise Installer, Inno Setup, Gentee Installer, InstallShield, NullSoft Installer, SetupFactory, Eschalon Installer, 和 Windows Installer (MSI).
Mover: 移动归类. 以文件后缀/日期等整理本目录下选定的 (打包)文件, 子目录不受影响.
TreeCopyPlus: 复制归类. 用于整理搜索结果, 保留各文件原来的目录结构.
Wipe: 安全删除文件.

WDX - 15个:
AnyTag, CDocProp, CRCTag32, DirSizeCalc, ExeFormat, EXIF, FileX, ImgSize, Permissions, RarInfo, Shareinfo, TextLine, Torrent, UnicodeTest, WDX4I
---Shift+F1选择.

Font (WLX)/CHMDir (WCX) 同时作为WDX使用.
自定义列预设12项:
Audio, Checksum, CHM, Compiled, Directory, FileInfo, Font, Photo, Picture, Office, RAR, Torrent.
自定义提示信息:
覆盖操作提示 - 6类, 鼠标悬停提示 - 9类.

WFX - 7个:
ProcFS (查看/关闭进程), MSIE Cache (查看IE缓存), TC Services (查看/启/禁用系统服务), Uninstalle (删除程序), TConsole (命令行窗口), DevMan (设备管理器), EventNT (事件查看)
---Alt+R进入网上邻居后使用.

WLX -13个:
Archview, Excellence, FileInfo, Font, ICLView, HTMLView, IEView, Imagine, Mmedia, nfoviewer, Office, VisualDirSize.
---F3/Ctrl+Q 调用.

支持查看字体 (Font), 影音 (Mmedia), HTM?/MHT (HTMLView), CHM/PDF... (IEview), 压缩档/CHM/MHT/ISO... (ArchView), Exe/Dll... (FileInfo), Excel (Excellence), Word (Office), 图片 (Imagine), Nfo/Diz (nfoviewer), 图标 (ICLView), 屏幕保护 (SCRList), 文件/目录大小 (VisualDirSize, 只支持Ctrl+Q).
部分文件可同时被多个插件支持,如本版的WinRAR自解压程序被Archview/FileInfo/ICLView同时支持,F3查看时可按4切换插件.

---工具
Akelpad: 文本编辑器, 含以下16个插件

AutoComplete: 编辑CPP/HTML时自动完成, Ctrl+F1
AutoSave: 自动保存. F8
FullScreen: 全屏. F11
HexSel: 查看HEX值
Highlight: 语法高亮
LineBoard: 行号, F6开关, Shift+F6设置颜色.
Lines: 行处理
LinkExtract: 提取HTML中的超链接
Macros: 宏
MinimizeToTray: 最小化至系统栏. F9
RecentFiles: 自动删除列表中不存在的文件
SaveAllAs: 批量转换代码页.
SelAutoCopy: 选择后自动复制.
SpecialChar: 显示换行符等特殊字符. F7开关, Shift+F7设置颜色.
Toolbar: 工具栏
ContextMenu: F12调用. 7.02+附带Akelpad的重要插件. Lines, Macros, HexSel, SelAutoCopy和LinkExtract等均通过此插件调用.不再设置单独的快捷键. 部分插件亦可通过此插件开关/设置.

NIRCMD: 多用途命令行工具,预设10个外部命令和9个别名.
---ADDON
TotalEditor:
预设TC外部命令em_batchopen/em_batchmedia. 同时打开选定的文本或影音档. 若选定 (多重)目录,则其下所有子目录的此类文件一并打开.
NewFile: 新建文件 (夹).
Restarter: 重启TC
TCQSP: 快速查找
TC Log Viewer: 查看操作记录

3. 配置
大致说明

a. 颜色:11种. MultiMedia, Picture, Archive, Disk Image, Document, Executable, Temporary, Hidden, Checksum, Download, Database
b. 工具栏: 2个, DEFAULT (用于TC内部命令)和TOOLS (用于管理系统/绿色工具).
c.Hotlist列表: 以WXP的系统变量为准 (英).
d. 图标/帮助: X-Qute, 其它为Vicons.中文帮助文件使用本坛slownet兄作品.
e. 菜单: 整合自EE+张学思版 (6.5x)+大量改动. 快捷键大部参照张版 (6.5x).
f. 开始菜单:

加/卸载镜像: 需DAEMON支持.
快速删除目录: 用于文件数量极大的目录 (不使用回收站),慎用!!!
批量打开文本: 选定目录/文件后使用该命令, 则Akelpad会打开选定 (文件夹 (含子文件夹下))的所有文本.
批量打开影音: 同上, 调用Windows Media Player播放, 最好配合集成Codec包,如Final Codecs.
新建文件/夹: 给不知道Shift+F4的人用.
新建会话: 强行新开TC窗口
重启TC.
快速查找加强版.
查看操作记录.
备份至桌面: 打包User目录和WCX_FTP.ini至桌面.

======================================================
更新细节:
* Update on 1/10/07
更新:
TC -> 7.02a
WDX 2个: AnyTag -> 0.98(支持Vista), WDX4I -> 0.1b
Akelpad -> 3.40及全部插件
ADDON 1个: TCQSP -> 2.2
UNRAR.DLL -> 3.71.1.246 (WinRAR)
中文帮助HLP -> 7.02a Final.

增加:
ADDON 1个: TC Log Viewer(查看操作记录)及相关外部命令.
Akelpad插件 1个: FullScreen
Office插件所需的转换器.(For Vista)

调整:
部分插件设置
更换MHTUnp.wcx为MHTUnPack.wcx

* Update on 7/9/07[url=]?[/url][url=]更新:
TC -> 7.02
WDX 2个: FileX -> 1.7; CRC32Tag -> 0.21Beta
WLX 2个: Imagine -> 1.0.0.0 Beta 5, HTMLView -> 1.2
AkelPad -> 3.38 及大部分插件.
NirCMD -> 2.00, 兼容Vista
UNRAR.DLL -> 3.70.100.211 (WinRAR)
中文帮助HLP -> 7.01 Final.

增加:
WDX 5个: WDX4i, Permissions, ExeFormat, UnicodeTest, TextLine
WFX 2个: MSIE Cache (查看IE缓存), EventNT (事件查看)
WLX 2个: HTMLView (这个和IEView都有Bug,只能再次补上), SCRList (查看SCR)
ADDON 1个: TCQSP (快速查找加强版)
颜色方案 2个: Download, Database
自定义列 1个: Compiled
鼠标悬停提示 2个: Compiled及Ini/Inf
TinnyTCRestarter及相关外部命令/开始菜单项
快捷键 2个: Shift+Ctrl+F9/0
别名7个 (NirCMD相关)
AkelPad插件 3个: Macros, LinkExtract, ContextMenu, AutoSave
FileInfo插件UnUpack.dll (PE Explorer)
常用设置备份功能.

调整:
菜单/中文语言包/开始菜单/INC/插件设置/自定义列...
WDX <- DirSizeCalc: 降回1.21, 2.0B2无法按目录大小排序, 除非设置两列大小.
拆分WINCMD.INI/USER.INI, 升级保留文件大都并入USER目录, 其中USER.INI定义常用选项, HISTORY.INI保存操作记录.
汉化FileInfo (2.09), EventNT (1.3), 进一步汉化ICLView和部分WDX显示信息.
大量微调.

删除:
WFX 1个: Versions
RAR的覆盖提示设置
AkelPad插件: URLMenu?[/url]
* Update on 22/6/07[url=]?[/url][url=]修正版本.
更新:
TC -> 7.01
AkelPad -> 3.32 及部分插件.
UnRAR.dll (WinRAR)
中文帮助HLP -> 7.0 Final.

增加:
快捷键: Shift+Ctrl+Home
AkelPad插件: RecentFiles

删除:
外部命令/别名三个,RS/IS/CS.

调整:
菜单/INC描述, Ctrl+Home/End
修正英文版使用汉化MMedia及菜单中的Unicode字符.?[/url]
* Update on 8/6/07[url=]?[/url][url=]更新:
TC -> 7.0 Final
AkelPad -> 3.31, 及全部插件.
WLX 1个: Imagine -> 1.0.0.0 Beta 4
WDX 2个: FileX ->1.6, DirSizeCalc -> 2.0 Beta 2

增加:
WDX 1个: AnyTag (尺寸较大,但AudioInfo有些问题)
Addon 1个: NewFile (用于新建文件 (夹))
AkelPad插件5个: HexSel, AutoComplete, Lines, SaveAllAs, SpecialChar.
NIRCMD及相关外部命令10个/别名2个
快捷键: Shift+Alt+123456789, Shift+Ctrl+C, Shift+Ctrl+I
TotalEditor外部命令1个: BatchMedia.

删除:
CDOC及相关外部命令em_CDOC/别名CDOC
WLX 1个: HTMLView
WDX 1个: AudioInfo (速度慢/MP3只读取ID3V1/停止开发)及相应配置

调整:
所有分辨率共用设置,存入User.ini
菜单, INC, 语言包
WCX后缀: gif -> imagine, tcpy -> treecopy, move -> mover
Devcon.exe并入TC目录,用于在\\设备管理器中删除设备.
[Rename]和[Splitperfile]段并入USER.ini.
快捷键: Shift+Ctrl+123456, Ctrl+123456
默认显示属性, 记录日志.
插件参数.?[/url]
* Update on 17/3/07[url=]?[/url][url=]更新:
TC -> 7.0 PB4
ADDON 1个: TotalEditor -> 0.20
WCX 2个: ISO -> 1.74b1, 7Zip -> 0.55
WDX 1个: CRC32Tag -> 0.19B
TOOLS 1个: Akelpad -> 3.25

增加:
WLX 1个: HTMLView, 主要针对IEView和MMedia的冲突.
Akelpad插件2个: LineBoard, HighLight
程序别名18个
覆盖操作及鼠标悬停自定义提示信息, 7类/5类
外部命令20个.
自定义列2个: CHM, FileInfo
新增内部命令的菜单项及相应快捷键

调整:
NoClose并入TC所在目录.
菜单, 语言包, INC, 工具栏, 其它参数修正
快捷键:Ctrl+012349, Shift+Ctrl+012349,Alt+X/Z,Ctrl+Home/End

取消:
TotalEditor对压缩包的设置?[/url]
* Update on 24/12/6 (2007大礼包专用版)[url=]?[/url][url=]更新:
WCX 1个: 7zip -> 0.54
WLX 2个: FileInfo -> 2.09, Imagine -> 1.0.0.0 b3
WDX 1个: CRC32Tag -> 0.18B
UnRAR.dll (From WinRAR) & UnUPX.dll (From PE Explorer).
图标库: ICL->DLL, 支持菜单图标.

增加:
WFX 4个: Uninstaller (卸载程序) / TConsole (命令行窗口) / DevMan (设备管理器) / Versions (在线更新)
WCX 2个: MHTUnp (提取MHT资源) / Imagine (制作/提取GIF资源)
ADDON 1个: TotalEditor/及自定义命令em_batchopen, 已设置批量打开文本文件/压缩档 (开始菜单中).
自定义列1个: Font
菜单图标
缩略图自定义项

调整:
默认编辑器: AkelPad (含插件MinimizeToTray/SelAutoCopy/Toolbar/URLMenu).
快捷键: 细分Shift+F6和F2, Alt+L&U / 左&两侧文件夹树.
MSI: Enter运行,Ctrl+PgDn提取资源.
WLX次序,Archview增加7Zip支持,Fileinfo支持查看UPX/Aspack压缩细节.
Hotlist.
允许预览WMF (=3).
缩略图缓存目录设为..\CACHE.
开始菜单.
汉化部分插件, 如ProcFS/Services/TConsole/ICLView...
大量微调.

*****以下段值从此版开始另存入%commander_path%\user.ini文件,今后升级本美/绿版本可备份此文件保留大部分个人设置*****
[Commandlinehistory]
[DirMenu]
[DriveHints]
[MkDirHistory]
[RenameTemplates]
[RenameSearchFind]
[RenameSearchReplace]
[SearchName]
[SearchIn]
[SearchText]
[Selection]
[left]
[right]
[lefttabs]
[righttabs]
[RightHistory]
[LeftHistory]
[user]
[800x600 (8x16)]
[1152x864 (8x16)]
[1280x1024 (8x16)]
[1400x1050 (8x16)]
[1440x900 (8x16)]
[1600x1200 (8x16)]
[1680x1050 (8x16)]?[/url]
* Update on 24/11/06[url=]?[/url][url=]升级:
TC ->7.0 PB2
SkimEdit ->3.07
WCX 2个: CHMDir -> 0.40c, ICLRead -> 1.3
WLX 4个: FileInfo ->2.08, Font -> 0.09, ICLView -> 3.10.2006, Imagine -> 0.97 Final

增加:
WCX 4个: DirCopy (复制目录结构), ICLRead (制作/提取ICL资源) & Mover (文件移动归类), InstallExplorer (提取MSI资源)
WDX 1个: ShareInfo, CRCTag32
WFX 2个: ProcFS (任务管理器), TC Services (系统服务)
颜色方案1个: Checksum
自定义列1个: Checksum

修正:
菜单: TC7新增命令,冗余项
WLX: Font (中文版), 描述错误,
SFXHEAD.SFX: 替换为WinRAR的Zip.SFX.
图标库兼容Vista.

快捷键:
Alt+U: 改为开/关一列文件夹树 (左侧窗口)
Shift+Ctrl+F8: 设为开/关文件夹树
Shift+Ctrl+Y: 设为查看TC内部命令

调整:
菜单, 颜色, INC, Button Bar, blahblahblah...?[/url]
* Update on 7/8/6[url=]?[/url][url=]升级:
部分插件

修正:
菜单, 工具栏, 描述错误, WDX配置, 其它微调.

替换:
中文版帮助文件换回HLP格式, CHM对压缩免疫,:- (.
NoClose.pif 换成 NoClose Replacer
WLX 1个 - IEView (不同作者)

增加:
WCX 2个 - Wipe (Secure Delete) & TreeCopyPlus
WDX 4个 - AudioInfo & CDocProp & RarInfo & Torrent
WLX 3个 - ArchView & nfoviewer & Mmedia (调用WMP, 配合集成codecs为佳, e.g. ffdshow, MyMPC)
颜色方案 4个 - Document, Executable, Temporary, Hidden
自定义列 4个 - Office, RAR, Torrent, Photo
插件中文 - Excluding ICLView.

删除:
绿色软件 2个 - Remove Hotfix Backups & RegCompact
WDX 1个 - AnyTag (过大, 替换为AudioInfo)
图标库 Buttonbar.icl 中未用图标?[/url]
* Update on 3/8/06[url=]?[/url][url=]修正:英文版中的几个绝对路径, 菜单冗余项
增加:中文版.?[/url]