【问题标题】:Why do my Win32 API calls require the 'A' suffix and should I rectify that?为什么我的 Win32 API 调用需要“A”后缀,我应该纠正它吗?
【发布时间】:2011-11-05 21:35:16
【问题描述】:

从我需要的 Win shell 执行命令

ShellExecuteA(NULL, "open", "http://stackoverflow.com", NULL, NULL, SW_SHOWNORMAL);

现在我正在学习 Forgers Win32 教程,我正在寻找防止在屏幕上打印垃圾所必需的 A 后缀。我知道这与我的操作系统默认的字符格式有关。如果我可以“规范化”我的操作系统,这可能是最好的解决方案,因为无论我在第二个示例中使用了多少 *A 函数,我都从 RegisterClassExA 返回 NULL(在下面复制了我添加的 *A 后缀的 lllototttsss)

#include <windows.h>
const wchar_t g_szClassName[] = L"myWindowClass";
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{/*...*/
    return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;
    //Step 1: Registering the Window Class
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = g_szClassName;
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
    if(!RegisterClassEx(&wc))
    {
        MessageBox(NULL, L"Window Registration Failed!", L"Error!",
        MB_ICONEXCLAMATION | MB_OK);
    return 0;
    }
    // Step 2: Creating the Window...
    return Msg.wParam;
}

我重新访问了上面的代码,使其类似于 Forgers(删除了 *A)并改用 L"" 字符串初始化器,但现在分配 const char g_szClassName[] = L"myWindowClass"; 时出现错误

错误 C2053:“g_szClassName”:宽字符串不匹配

char 替换为wchar 会生成编译器错误消息,指出wchar 不是可识别的类型。

_编辑_

我认为L"" 字符串说明符是首选解决方案,也是我想要追求的解决方案,抱歉,如果我的问题似乎绕圈子,我愿意接受建议。

刚刚将该代码更新为我现在使用的代码,并删除了我无法访问的内容。

_编辑_

错误码是87,参数无效,所以我猜分配wchar_t参数( wc.lpszClassName = g_szClassName;)毕竟是不正确的... :@(

_编辑_

猜错了?! const LPCTSTR g_szClassName = L"myWindowClass"; 没有修复(或破坏)任何东西。

【问题讨论】:

  • 正确示例的所有功劳归功于 Forger(除了我的系统的 fomr wchar_t),我错过了 wc.style 初始化,因为我的 Foxit pdf 阅读器一次只能复制粘贴一个屏幕,我错过了行。

标签: c++ winapi tchar wchar


【解决方案1】:

大多数 WinAPI 调用有两种变体:SomeFunctionA 是单字符版本(即使用 char[] 表示字符串),SomeFunctionW 是宽字符版本(即使用 wchar_t[] 表示字符串)。通常会定义一个没有该后缀的宏(在本例中为 SomeFunction),它将包含 SomeFunctionASomeFunctionW,具体取决于您项目的 unicode 设置。以类似的方式,有一个宏 _T 将接受您的常量字符串文字并添加前导 L 以防使用 unicode。

要使用您的初始示例,此代码应适用于所有设置(但未经测试):

ShellExecute(NULL, _T("open"), _T("http://stackoverflow.com"), NULL, NULL, SW_SHOWNORMAL); 

【讨论】:

  • 我记得 _T 被提倡,但只是使用 L"" 限定符阅读了一个类似的线程,好吧,它刚刚工作,我现在再试试你的 _T 前缀。啊,_T() 是一个宏,无法初始化我的字符串 :( error C2099: initializer is not a constant
  • @John: The L"" 之所以有效,是因为您在构建时启用了 Unicode。 T 宏的要点是能够在 Unicode 启用和禁用之间切换。这也是为什么像ShellExecute 这样的宏是在ShellExecuteAShellExecuteW 之间切换的宏。
  • “警告 C4013:'_T' 未定义;假设 extern 返回 int”然后“错误 LNK2019:未解析的外部符号 __T 在函数 _WinMain@16 中引用”
  • 宏不是叫TEXT吗?
  • 不是“大多数”Win32 API,而是所有具有TCHAR 参数或返回值的API。
【解决方案2】:

如果你想要unicode字符串,关键字是wchar_t

const wchar_t g_szClassName[] = L"myWindowClass";

编辑:

此外,请确保将结构 WNDCLASSEX 的其余未设置成员初始化为零,即

WNDCLASSEX wc = {};

ZeroMemory(&wc, sizeof(wc));

【讨论】:

  • 谢谢,但我的 RegisterClassEx 仍然失败!
  • 应该是:WNDCLASSEX wc = {0};
【解决方案3】:

添加这一行:

wc.style = CS_HREDRAW | CS_VREDRAW;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-17
    • 2013-12-12
    • 2022-01-07
    • 2011-05-10
    • 1970-01-01
    • 2016-09-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多