c++ - 如何将 SHFileOperation() 与 CString 路径一起使用

标签 c++ string winapi mfc null-terminated

我正在尝试将 CString 转换为 LPCWSTR 并且效果很好。但是在代码处理过程中出了点问题。

我想将目录复制到另一个路径,所以我使用 SHFILEOPSTRUCT:

HWND console = GetConsoleWindow();
SHFILEOPSTRUCT s = { 0 };
s.hwnd = console;
s.wFunc = FO_COPY;
s.fFlags = FOF_SILENT;

CString _folderName("a6_töüst-Oa5Z.OZS-CI5O5235"),
        firstPath("C:\\ORTIM-Daten\\a5Pc 2.0.3\\Temp\\"),
        lastPart("\\Documents\\*\0"),
        firstPathDest("C:\\ORTIM-Daten\\a5Pc 2.0.3\\"),
        lastPartDest("Documents\\"),
        _folderNameDest("a6_töüst-Oa5Z.OZS-CI5O5235\0");

CString cstrTemp = firstPath + _folderName + lastPart,
    cstrTempDest = firstPathDest + lastPartDest + _folderNameDest;

s.pTo   = cstrTempDest /*_TEXT("C:\\ORTIM-Daten\\a5Pc 2.0.3\\Documents\\a6_töüst-Oa5Z.OZS-CI5O5235\0")*/;
s.pFrom = cstrTemp     /*_TEXT("C:\\ORTIM-Daten\\a5Pc 2.0.3\\Temp\\a6_töüst-Oa5Z.OZS-CI5O5235\\Documents\\*\0")*/;

SHFileOperation(&s);

当我直接使用 CString 时,复制操作不起作用,但是当我使用 _TEXT() 宏(如评论中)来分配LPCWSTR 结构中的成员一切正常。

编辑 1

代码在源路径和目标路径的两种变体中编译。

在此变体中,代码编译并执行复制操作:

s.pTo   = _TEXT("C:\\ORTIM-Daten\\a5Pc 2.0.3\\Documents\\a6_töüst-Oa5Z.OZS-CI5O5235\0");
s.pFrom = _TEXT("C:\\ORTIM-Daten\\a5Pc 2.0.3\\Temp\\a6_töüst-Oa5Z.OZS-CI5O5235\\Documents\\*\0");

在我实际需要的另一个变体中,代码也可以编译,但复制操作不会发生:

 s.pTo   = cstrTempDest;
 s.pFrom = cstrTemp;

最佳答案

SHFILEOPSTRUCT 需要以两个 NUL 字符结尾的字符串,但根据定义,NUL 终止字符串以一个 结尾,并且任何其他 NUL 字符都将被忽略不采用显式长度参数的 CString 方法。

您可以通过手动添加一个来强制使用双 NUL:

CString cstrTempDest = firstPathDest + lastPartDest + _folderNameDest;

// *** Add NUL manually ***
cstrTempDest.AppendChar( 0 );
s.pTo = cstrTempDest;

// For debuging - verify resulting string with example.
TCHAR* test = _TEXT("C:\\ORTIM-Daten\\a5Pc 2.0.3\\Documents\\a6_töüst-Oa5Z.OZS-CI5O5235\0");
// +2 because we want to check two NULs at end.
ASSERT( memcmp( s.pTo, test, (_tcslen(test)+2)*sizeof(TCHAR) ) == 0 );

替代解决方案可以使用带有显式长度参数的方法:

CString cstrTempDest = firstPathDest + lastPartDest
                           + CString(_folderNameDest, _tcslen(_folderNameDest)+1);


如果您的项目配置为使用 unicode 字符集,请使用宽字符串调用 CString 构造函数:

CString _folderName(_T("a6_töüst-Oa5Z.OZS-CI5O5235")),
        firstPath(_T("C:\\ORTIM-Daten\\a5Pc 2.0.3\\Temp\\"))
        ...
unicode 模式下的

CString 会自动将窄字符串转换为宽字符串,但当运行时和开发代码页之间存在差异时,它可能会失败。如果您打算使用 Unicode 并且永不回头,请扔掉 _TEXTTEXT_T 宏,只使用宽文字:

CString _folderName( L"a6_töüst-Oa5Z.OZS-CI5O5235" ),
        firstPath( L"C:\\ORTIM-Daten\\a5Pc 2.0.3\\Temp\\" )
        ...


您还应该检查 SHFileOperation 返回值。

关于c++ - 如何将 SHFileOperation() 与 CString 路径一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52440995/

相关文章:

c# - 删除所有不匹配的内容

c# - 在 C# 中构建 wParam 或 lParam 的好方法是什么? (比轮类运算符(operator)更友好的东西吗?)

c++ - 从文件 C++ 获取输入(矩阵数组输入)

c++ - 将位插入字节

android - 如何在 EditText 中搜索和突出显示文本

java - 从 HTML 字符串 Java 中提取文本

c++ - 如何使用 winsock 在 C++ 应用程序中实现安全套接字通信?

windows - 如何在 Windows 中检测何时连接了新硬件?

c++ - 错误 : Compiling simple PjSIP program under ubuntu

c++ - 为 QlineEdit 设置背景图像时如何在 QLineEdit 中设置文本颜色