2017-09-08 58 views
1

如何将System :: string^in转换为LPCTSTR? 由于我的要求是能够使用的功能克隆文件的CopyFile,它如果我给修复的域名(OldFile.jpg和LatestFile.jpg)其参数正常工作(以下代码:正常工作字符串^到VC++ 2010中的LPCTSTR(Windows窗体应用程序)

LPCTSTR in_f,out_f; 

in_f = _T("d:\\Old.jpg"); 
out_f = _T("d:\\Latest.jpg"); 

CopyFile(in_f,out_f,false); 

上面的代码克隆Old.jpeg到一个Latest.jpg但是当我试图给名称(Latest.jpg),这是由一些字符串就不会创建文件出来(下面的代码:不工作

String^ Name = "Latest"; 

//------Capture Current Date & Time 
    DateTime datetime = DateTime::Now; 

//-------Convert Date Timt in to String 
    Name = Name + String::Format("{0}",datetime); 
    Name = Name->Replace('/','-'); 
    Name = Name->Replace(':','-'); 
    Name = Name + ".jpg";  

    LPCTSTR in_f,out_f; 

    in_f = _T("d:\\Old.jpg"); 
    out_f = (LPCTSTR)Name; //Trying to Assign Current Latest file Name With date Time here 

    CopyFile(in_f,out_f,false); 

The Prob lem是CopyFile Took LPCTSTR类型作为参数,因为我给一个类型System :: string ^,所以建议我如何将此System :: string ^转换为LPCTSTR,以便我可以添加当前日期时间我的文件的名称。 我使用VC++ 2010和Windows窗体应用程序

+0

如何[字符串转换为字符数组(https://msdn.microsoft.com/en-us/ library/ezftk57x(v = vs.110).aspx?cs-save-lang = 1&cs-lang = cpp),然后获取指向数组中的字符的指针? –

+0

使用Marshal :: StringToHGlobalAnsi或StringToHGlobalUnicode,具体取决于您是否使用UNICODE生成。努力摆脱tchar,它是绝望的过时,使用CopyFileW,所以你可以依靠LPCWSTR。当然可以考虑使用File :: Copy()来代替,所以这些都不是必需的。 –

+1

在.NET中使用[System.IO.File.Copy](https://msdn.microsoft.com/en-us/library/system.io.file.copy%28v=vs.110%29.aspx)方法。 –

回答

0

你需要一个\ 0字符的名称字符串的结尾追加,因为的CopyFile()预计零结尾的字符串。

编辑:作为LucasTrzesniewski所指出的,自动钉扎.NET字符串产生一个零结尾字符数组。这在C#规范中有记录。请参阅下面的评论以获取更多信息。

此外,你必须“钉”在内存中的字符串,所以垃圾收集器不会移动它。然后你可以创建一个指向字符串第一个字符的指针。 C++/CLI提供了一些实用程序类型和功能来执行此操作。下面是一个示例:

pin_ptr<const WCHAR> psName = PtrToStringChars (Name) 

PtrToStringChars()是在vcclr.h中声明的内联函数。 psName应该可分配给LPCTSTR参数 - 如果没有,请使用强制转换。请注意,如果输入字符串是nullptr,则PtrToStringChars()不起作用。你需要明确地测试这种情况。 (但是,在你的情况下,名称肯定不是nullptr)。

该字符串保持固定状态,直到变量psName超出范围。离开声明它的{...}块后会发生这种情况,例如离开当前功能后。不需要明确的取消锁定。

+1

不需要添加空终止符,因为.NET字符串已经有一个。固定是最轻量级的解决方案,因为它不需要字符串复制。该字符串将可分配给LPCWSTR或LPCTSTR,只有在UNICODE被设置的情况下,应该是这种情况,除非您正在为Windows 98开发...尽管如此,最好使用LPCWSTR。 –

+0

@LucasTrzesniewski感谢关于零终止的信息 - 实际上,我不知道这一点。这是正式记录在.NET标准? – SBS

+1

我无法在ECMA-335中找到对此的参考,这让我感到很意外。但它绝对是在.NET中实现的:明确的C#规范[声明如下](https://github.com/dotnet/csharplang/blob/master/spec/unsafe-code.md#the-fixed-statement):*固定'string'实例产生的'char *'值总是指向一个以null结尾的字符串。 [...]在调用需要“C风格”字符串的外部API时,字符串的自动空终止特别方便。*(C++中的char与C++中的wchar_t相同) –

1

标准警告:尽管可以在C++/CLI中编写应用程序的主体,甚至可以使用WinForms在C++/CLI中编写GUI,但建议不要这样做。 C++/CLI适用于互操作场景:C#或其他.Net代码需要与非托管C++接口,C++/CLI可以提供这两者之间的转换。对于初级开发,如果你想托管代码,推荐使用WinForms或者WPF,如果你想不托管的话,建议使用带有MFC的C++。


我不知道我同意汉斯的意见,即TCHAR是过时的,但做一个明确的转换为宽字符串,并呼吁CopyFileW是一个不错的选择。

此外,可以转向另一个方向,并从非托管转换为托管字符串,并使用.Net方法复制文件File::Copy(String^, String^, Boolean)

要转换为LPCTSTR,我会使用marshal_as。由于它是通过模板实现的,编译器将根据需要解析您的LPCTSTR以调用LPCSTRLPCWSTR版本。

微软没有针对每个模板版本marshal_as的专用文档页面,但Overview of Marshaling in C++页面是一个很好的开始。

我的测试程序:

#include <msclr\marshal.h> 

int main(array<System::String^>^ args) 
{ 
    String^ managedStr = "I came from managed land!\r\n"; 

    // This controls the lifetime of the LPCTSTR that marshal_as returns. 
    // When this goes out of scope, the LPCTSTR will no longer be valid, 
    // so be aware of its lifetime. 
    msclr::interop::marshal_context context; 

    LPCTSTR unmanagedStr = context.marshal_as<LPCTSTR>(managedStr); 

    OutputDebugString(unmanagedStr); 

    return 0; 
} 

结果:

I came from managed land! 
+1

你真的在2017年推荐MFC和LPCTSTR吗? : - \ –

+0

与C++/CLI WinForms相比,这在Visual Studio中非常容易选择,并且可能已被没有意识到差异的人选中?绝对。 (当然,我推荐C#通过其中任何一个,但是可能有为什么需要C++的原因。) –

+1

我对当前的C++ GUI框架知之甚少,但我说过,因为我记得有多少PITA MFC当天回来了。我很确定现在一定有更好的东西。顺便说一句,在VS中没有C++/CLI WinForms应用程序项目模板,耶! :-)但是我真的很关心你为什么认为'TCHAR'不*过时了......我上次使用ANSI函数是为了赢得98 ... –

相关问题