“错误'SetWindowTextA':不是'CStatic'的成员,并且char * fgets(char *,int,FILE *):无法将参数1从'TCHAR'转换为'char *'

时间:2018-12-04 10:19:55

标签: c++ unicode mfc

我将C ++项目从Visual Studio 2005迁移到了Visual Studio 2017 Professional,并且当我在“调试”和“发布”模式下进行构建时,出现以下错误:

1。

在调试构建中,当我使用如下所示的SetWindowTextA时,出现错误“错误C2039'SetWindowTextA':不是'CStatic'的成员

m_status_text.SetWindowTextA(theStr);

m_status_text声明为CStatic,如下所示:

CStatic m_status_text;

如果我使用SetWindowTextW,它将在发布版本中引发错误。

m_status_text.SetWindowTextW(theStr);

当我将其更改为“ SetWindowText”时(如下所示),它既适用于调试版本也适用于发布版本。这是正确的方法吗?

m_status_text.SetWindowText(theStr);

据我所知,当我们使用“ SetWindowText”时,以Unicode格式将其视为“ SetWindowTextW”,对于多字节字符集格式,则将其视为“ SetWindowTextA”。

但是SetWindowText如何用于Debug和Release版本?

2。

如果我使用“ fgets”,也可以像在调试版本中那样使用“ _fgetts”代替“ fgets”(对于发行版本)“ fgetws”(对于调试版本),我得到以下错误:

char fgets(char ,int,FILE *):无法将参数1从'TCHAR [260]'转换为'char *'

fgets(currDir,MAX_PATH,f);    // For release build
fgetws(currDir, MAX_PATH, f); // For Debug build
  1. 我可以使用“ _tfopen”代替“ fopen”(对于发布版本)和“ _wfopen”(对于调试版本)

    f = _tfopen(fileName,_T(“ r”));

代替

f = fopen(fileName,"r");  // For release build
f = _wfopen(fileName, L"r"); // For Debug build

请帮助我。

2 个答案:

答案 0 :(得分:2)

Windows API为每个处理或允许将字符串作为参数的函数提供2种变体:

  • UNICODE,通常函数名称以W结尾
  • ANSI:函数名称将以A结尾

然后,Windows API为所有这些函数提供了一个通用变体,没有尾随的A或W字母,这将取决于是否定义了UNICODE映射到以上(A或W)之一。

示例:

  

SetWindowText

映射到:
-SetWindowTextA(如果未定义UNICODE(=> ANSI)
-SetWindowTextW(如果已定义UNICODE

UNICODE变体将字符串作为wchar_t *处理, 而ANSI变体将字符串作为char *处理。

TCHAR是宏定义的字符类型,根据是否定义了UNICODE映射到char或wchar_t:
-如果未定义UNICODE,则TCHAR = char
-如果已定义UNICODE,则TCHAR = wchar_t

对于“现代” Windows应用程序,VS2017默认情况下使用UNICODE模式(这是VC ++项目文件的选项),我建议您坚持使用该模式,除非您绝对必须支持Windows的旧版本(即98)。 /> 使用UNICODE模式,将使用SetWindowTextW()函数变体(或仅使用SetWindowText()),并向其传递wchar_t *(或TCHAR *)字符串。

如果您需要同时以ANSI和UNICODE模式支持或编译项目,则可能需要使用TCHAR类型,但是如今很少使用了。

答案 1 :(得分:2)

在您的问题中,您似乎将两个相互正交的轴混合在一起:ANSI与Uni​​code构建以及Debug与发行版本。

RE#1 ANSI与Uni​​code函数调用,当您调用MFC类方法时,您只需简单地调用“ undecorated” 方法名称,例如:

// Note the use of the "undecorated" SetWindowText method call:
m_status_text.SetWindowText(theStr);

// This gave you an error:
// m_status_text.SetWindowTextA(theStr);

这是Debug vs. Release版本中的独立,它会影响其他方面,例如运行时性能。实际上,通常在调试版本中,有更多的代码可以编译并检查不变量和其他安全方面,例如确保索引不会越过安全数组边界,或确保STL容器正确使用迭代器等。
所有这些其他调试构建检查通常会产生效率较低的代码,但是这些相同的调试检查可以帮助您检测各种错误,您可以在交付更有效的应用程序发布版本之前对其进行修复。

但是,这又独立于ANSI vs. Unicode构建模式方面。


RE#2在Release vs. Debug版本中使用不同文件功能:如果您真的需要 (确定吗?您实际上在尝试实现什么? ?),您可以像这样使用#ifdef

#ifdef _DEBUG
   // Debug-build specific code
   // ...
#else 
   // Release-build specific code
   // ...
#endif

当然,您可以在Debug和Release版本中使用fopen_wfopen_tfopen:同样,这些Unicode / MBCS和Debug / Release版本是正交的。

PS 通常,我鼓励您将代码库移至Unicode,并仅以Unicode模式(Debug-Uni​​code和Release-Unicode)构建。