0

我已将字符串移动到资源中,幸运的是我有 LPCTSTR 运算符可以方便地实例化字符串,例如:

CString str( (LPCSTR) IDS_MY_STRING);

现在我想用 MessageBox() 做类似的类型转换,所以它也从资源中加载字符串,所以我这样做:

MessageBox( hWnd, (LPCTSTR) IDS_MY_STRING ,"Error", MB_RETRYCANCEL);

但这不起作用,它编译但在运行时崩溃。现在以下工作:

MessageBox( hWnd, (CString) (LPCTSTR) IDS_MY_STRING ,"Error", MB_RETRYCANCEL);

我的问题是 MessageBox() 无论如何都将 LPCTSTR 作为第二个参数,那么为什么我们必须另外从 LPCTSTR 类型转换为 CString 才能使其工作?

4

4 回答 4

3

IDS_MY_STRING实际上并不是指向字符串的指针。它是一个整数。(如果它是一个字符串指针,你一开始就不需要强制转换LPCTSTR。)CString知道如何从完整的资源 ID 加载资源字符串。

MessageBox没有;它需要一个真正的字符指针,它CString隐式提供。

于 2012-04-17T20:55:32.563 回答
3

真正的问题(或至少答案中有趣的部分)不是关于第二个如何失败,而是更多关于第一个如何工作。

第一个有效,因为 CString 的构造函数采用 LPCSTR 实际上查看该值以确定它是否真的是指向字符串的指针,还是字符串资源的标识符。在后一种情况下,它会自动加载字符串资源并创建具有相同内容的 CString。IOW,您已经获得了从字符串标识符到 CString 的隐式转换。

CString 还支持隐式转换为 LPCSTR/LPCSTR/LPCWSTR。

然而,C++ 只会进行一次用户定义的隐式转换,以从传递给表达式的任何类型到所需的任何类型。在这种情况下,要从字符串 ID 到 a LPCTSTR,您需要两个 - 一个从字符串 ID 到CString,另一个从CStringLPCTSTR。编译器不会自动为您执行此操作。

因此,要将字符串 ID 转换为LPCTSTR,您需要将字符串 ID 显式转换为CString,它使用CString' 构造函数,该构造函数采用LPCTSTR. 因此,您将字符串 ID 转换为LPCTSTR,然后从该转换为CString,这将创建一个CString. 然后编译器会自动CString为你转换为(真正的)`LPCTSTR。

于 2012-04-17T20:58:56.607 回答
1

其他人已经解释了类型转换等的细节。

此外,为了简化代码,您可能需要#define一个方便的宏,如下所示:

#define _S(id) (CString(LPCTSTR(id))) 

然后将其与MessageBox(或其他LPCTSTR参数)一起使用:

MessageBox( hWnd, _S(IDS_MY_STRING), _S(IDS_TITLE), MB_RETRYCANCEL );
于 2012-04-17T21:56:56.237 回答
1

MessageBox没有采用资源 ID 的重载,但您可以使用它AfxMessageBox

于 2012-04-17T20:54:02.207 回答