【问题标题】:Visual Studio 2015 WinAPI error on MessageBoxMessageBox 上的 Visual Studio 2015 WinAPI 错误
【发布时间】:2016-03-01 15:25:58
【问题描述】:

我在 Visual Studio 2015 中创建了一个基本的 Windows C++ 应用程序,但出现了一些错误:

#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    MessageBox(NULL, "Test_text", "Message Test", MB_ICONINFORMATION | MB_OKCANCEL);
    return 0;
}

错误:

'int MessageBoxW(HWND,LPCWSTR,LPCWSTR,UNIT)': cannot convert argument 2 from 
'const char [10]' to 'LPCWSTR'

argument of type "const char *" is incompatible with parameter of type "LPCWSTR"
argument of type "const char *" is incompatible with parameter of type "LPCWSTR"

【问题讨论】:

  • 不要通过图像(内联或外部链接)显示错误或代码。始终在此处将错误的全文显示为文本。
  • 如果您搜索消息文本,您已经找到了解决方案。

标签: c++ winapi visual-studio-2015 tchar lpcwstr


【解决方案1】:

您选择使用 ANSI 文本,因此您应该明确使用 MessageBoxA 而不是宏 MessageBox

#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    MessageBoxA(NULL, "Test_text", "Message Test", MB_ICONINFORMATION | MB_OKCANCEL);
    return 0;
}

或者,您可以使用TEXT 宏让编译器自动匹配字符串和函数的类型。

#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    MessageBox(NULL, TEXT("Test_text"), TEXT("Message Test"), MB_ICONINFORMATION | MB_OKCANCEL);
    return 0;
}

【讨论】:

    【解决方案2】:

    这里的问题是 Win32 TCHAR 模型

    实际上没有MessageBox 函数:MessageBox 是一个预处理器 #define,根据您的项目设置(ANSI/MBCS 或 Unicode)扩展为 MessageBoxAMessageBoxW ,分别)。

    从 VS2005 开始,Visual Studio 中的默认设置为 Unicode(更准确地说:UTF-16)。因此,在这种情况下,编译器会选择 MessageBoxW API(即 Unicode 版本)。

    MessageBoxW API 采用 Unicode (UTF-16) 字符串,通过 wchar_t 指针表示(晦涩的 LPCWSTR 预处理器宏扩展为 const wchar_t*,即 NUL -终止的 C 样式 Unicode UTF-16 字符串)。

    Unicode (UTF-16) 字符串文字使用 L"..." 语法表示(注意 L 前缀)。
    因此,"Test_text" 是 ANSI 字符串文字,L"Test_text" 是 Unicode (UTF-16) 字符串文字。

    由于您(隐含地,通过 Visual Studio 默认设置)进行 Unicode 构建,您应该使用 L 前缀来装饰您的字符串文字,例如:

    MessageBox(nullptr,   // <--- prefer nullptr to NULL in modern C++ code 
               L"Test_text",      // <--- Unicode (UTF-16) string literal 
               L"Message Test",   // <--- Unicode (UTF-16) string literal
               MB_ICONINFORMATION | MB_OKCANCEL);
    

    另一种方法是使用_T("...") or TEXT("...") macros 装饰字符串文字。这些将扩展为 ANSI/MBCS 构建中的简单 "..." ANSI 字符串文字,以及 Unicode 构建中的 Unicode (UTF-16) 字符串文字 L"..."(这是现代版本的 Visual Studio 中的默认值)。

    // TEXT("...") works in both ANSI/MBCS and Unicode builds
    MessageBox(nullptr, 
               TEXT("Test_text"),    
               TEXT("Message Test"),
               MB_ICONINFORMATION | MB_OKCANCEL);
    

    就个人而言,我认为 TCHAR 模型是过去的过时模型(我认为没有理由生成现代 C++ Win32 应用程序的 ANSI 版本),并且考虑到现代 Windows API 仅支持 Unicode(例如DrawThemeText()),我'd 只是使用 L"..." 前缀装饰字符串文字,而忘记了 ANSI 构建。

    【讨论】:

    • 在传递宽字符串文字时,您应该显式调用 API 的宽字符版本(即 MessageBoxW 而不是 MessageBox)。
    • @IInspectable:我不同意。 MessageBoxW(或一般的 DoSomethingW)在 Unicode 构建中是无用的 代码丑化:结尾 W 只是更清晰的 MessageBox(或 DoSomething)形式的噪音。
    • 这不是关于意见,而是关于语言规则。 MessageBox 是通用文本映射版本。 MessageBoxW 是 Unicode 版本。我会接受你认为的“丑化”,而不是依赖我无法控制的环境。
    • 我理解你关于 MessageBox 是映射的推理,但如果我的代码不需要以 ANSI 模式构建,我更喜欢 MessageBoxL"...",这有积极的一面- 如果有人尝试进行 ANSI 构建(而不是 UNICODE 构建),则会破坏编译。
    • 由于传递给函数的形式参数和参数不兼容,破坏代码并没有什么积极意义。更糟糕的是:如果您没有明确说明要调用的函数,则可能不会完全调用您打算调用的函数。当传递 nullptr 时,编译器不会帮助你。它只会让你不小心调用一个你从未打算调用的函数。将预处理器符号用于通用文本映射而不是真正的函数名称并没有任何优势。停止根据虚假声明提出建议。
    【解决方案3】:

    MessageBox 在这种情况下实际上是 MessageBoxW,它需要 unicode 字符串。你可以这样修复它:

    MessageBoxW(NULL, L"Test_text", L"Message Test", MB_ICONINFORMATION | MB_OKCANCEL);
    

    MessageBox(NULL, TEXT("Test_text"), TEXT("Message Test"), MB_ICONINFORMATION | MB_OKCANCEL);
    

    【讨论】:

      【解决方案4】:

      你不能像那样传递一个裸字符串文字。

      MessageBox(NULL, TEXT("Test_text"), TEXT("Message Test"), MB_ICONINFORMATION | MB_OKCANCEL);
      

      TEXT 是一个宏,可根据您的编译方式扩展为正确的字符串类型。

      【讨论】:

      • _T 用于 CRT,TEXT 用于 Windows API,因此在这种情况下使用TEXT 更好。
      【解决方案5】:

      您需要为您的项目选择正确的Character Set 设置。在 Visual Studio 项目的属性中,导航到 General 类别。其中有一个条目Character Set

      如果您选择Unicode Character Set,编译器将为您定义_UNICODE,并且像MessageBox 这样的所有函数都将评估为它们的宽字符变体,例如MessageBoxW

      如果您选择Multi-Byte(已弃用),编译器将为您定义_MBCS,并且函数将评估为多字节变体,例如MessageBoxA

      字符串也是如此,答案中提到的宏(如TEXT)将在unicode环境中的所有字符串前面添加一个L

      更多信息请看这里:https://msdn.microsoft.com/en-us/library/ey142t48.aspx

      恕我直言,很少有人想要明确地针对WA 方法进行编写。如果你必须这样做才能让你的编译器满意,你应该重新检查你的设置。

      【讨论】:

        猜你喜欢
        • 2018-04-27
        • 2015-07-15
        • 2018-03-15
        • 1970-01-01
        • 2016-04-10
        • 2016-02-10
        • 2017-02-21
        • 1970-01-01
        相关资源
        最近更新 更多