2017-09-08 57 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 ... –

相關問題