使用Unicode迭代OFN_ALLOWMULTISELECT中的所有文件

时间:2016-06-22 19:29:02

标签: c winapi unicode

在启用Unicode的OFN_ALLOWMULTISELECT打开文件对话框中迭代所有文件的推荐方法是什么?

我的第一个想法是这样的:

TCHAR *tmp = ofn.lpStrFile + ofn.nFileOffset;

while(*tmp) {
    wprintf("Got file: %s\n", tmp);
    tmp += wcslen(tmp) + 1;
}

但后来我发现,如果字符串缓冲区中的字符无法以16位表示,则无法使用。因此,对于安全方法,我首先需要找出tmp TCHAR字符串的字节长度,然后将TCHAR指针强制转换为char并添加该字节长度在每次迭代中。像这样:

TCHAR *tmp = ofn.lpStrFile + ofn.nFileOffset;

while(*tmp) {
    wprintf("Got file: %s\n", tmp);
    tmp = (TCHAR *) (((char *) tmp)) + get_byte_len_of_tstr(tmp));
}

请注意,get_byte_len_of_tstr()只是一个为此目的而编写的函数的占位符。由于这种方法看起来有些笨拙,我首先想问一下这是否真的是要走的路,或者我是否错过了或误解了一些东西......

1 个答案:

答案 0 :(得分:2)

你的第一个例子是在正确的轨道上,但有几个错误:

  1. 您的变量应声明为WCHAR*而不是TCHAR*

  2. wprintf()不接受char*格式字符串作为输入,而是需要wchar_t*

  3. WCHAR *tmp = ofn.lpStrFile + ofn.nFileOffset;
    while (*tmp)
    {
        wprintf(L"Got file: %s\n", tmp);
        tmp += (wcslen(tmp) + 1);
    }
    

    如果你想使用TCHAR(你真的不应该,除非你需要支持Win9x / ME),那么它将会是这样的:

    TCHAR *tmp = ofn.lpStrFile + ofn.nFileOffset;
    while (*tmp)
    {
        _tprintf(_T("Got file: %s\n"), tmp);
        tmp += (_tcslen(tmp) + 1);
    }
    

    话虽如此,您对wcslen()的理解是错误的(但您使用它是正确的)。在Windows中,Unicode字符串以UTF-16编码,其中每个WCHAR元素是UTF-16 代码单元wcslen()计算字符串中WCHAR个元素的数量,而不是它们所代表的Unicode 代码点的数量,就像您所想的那样。因此,如果给定的代码点需要UTF-16代理项对,它将在字符串中使用两个WCHAR元素,而wcslen()将为它计数2。否则,它将使用1 WCHAR,而wcslen()将为其计数1。

    对于strlen()和MBCS字符串,当在字符串中使用多于1个codeunit(char元素)编码给定的Unicode代码点时,情况也是如此。