为什么 CreateWindowW 不接受 ATOM 作为 lpClassName?

Why doesn't CreateWindowW accept an ATOM as the lpClassName?

提问人:Robert Hadow 提问时间:4/22/2021 更新时间:4/22/2021 访问量:464

问:

CreateWindowW() 的 MSDN 说明中,窗口类名称 (lpClassName) 可以是文本字符串,也可以是 ATOM 类型。

我打算多次使用预定义的 COMBOBOX,因此特定的 ATOM 似乎是更好的解决方案。

ATOM MyRegisterConnectClass(HINSTANCE hInstance) {
    WNDCLASSEXW wcon;

    wcon.cbSize = sizeof(WNDCLASSEX);
    wcon.lpszClassName = TEXT("COMBOBOX");
    wcon.lpfnWndProc = ConnectProc;  
    // and all the other attributes

    RegisterClassExW(&wcon);
}

BOOL InitConnect(HINSTANCE hInstance, int nCmdShow)
{
    HWND hConnect = CreateWindowW(
        RegisterClassExW(&wcon), // lpClassName,
        TEXT("Connect"), // lpWindowName,
        CBS_DROPDOWN | WS_CHILD | WS_VISIBLE | CBS_SIMPLE | WS_OVERLAPPED, // dwStyle,
        CW_USEDEFAULT, // x,
        CW_USEDEFAULT, // y,
        0, // nWidth,
        0, // nHeight,
        hWnd, // hWndParent,
        nullptr, // hMenu,
        hInstance, // hInstance,
        nullptr // lpParam
    );

 if (hConnect) {
       OutputDebugStringW(L"InitConnect() successfully created hConnect\n");
       ShowWindow(hConnect, nCmdShow);
       UpdateWindow(hConnect);
           return TRUE;
   } else {
       OutputDebugStringW(L"InitConnect() failed to create hConnect\n");
       return FALSE;
   }
}

上面的代码生成错误 C2664

我遇到编译器故障COMBOBOX, //lpClassName

HWND hConnect = CreateWindowW(
   WC_COMBOBOX, //lpClassName

编译良好,但未创建 hConnect。

我试图这样捕获 ATOM,但它没有用。ATOM acon = MyRegisterConnectClass( ...

C++ WinAPI

评论

0赞 Ulrich Eckhardt 4/22/2021
C1 的 type2 和 type2664 是什么?无论如何,解决方案可能是一个简单的演员,但请尝试在此处搜索“CreateWindow ATOM”并阅读一些讨论。顺便说一句:摆脱字符串文字周围的那些宏,除非你真的需要一个字符串。的第二个参数 ,仅举一例,由于显式后缀,它不是 one!TEXT()TCHARCreateWindowW()W
0赞 IInspectable 4/22/2021
MAKEINTATOM的。

答:

4赞 Remy Lebeau 4/22/2021 #1

的第一个参数采用 () 指针,但返回 () 句柄。CreateWindowW()LPWSTRwchar_t*RegisterClassExW()ATOMunsigned short

lpClassName

类型:LPCTSTR

以 null 结尾的字符串或由上一次调用 RegisterClass 或 RegisterClassEx 函数创建的类原子。原子必须是 lpClassName 的低阶字;高阶字必须为零。如果 lpClassName 是字符串,则指定窗口类名称。类名可以是向 RegisterClass 或 RegisterClassEx 注册的任何名称,前提是注册类的模块也是创建窗口的模块。类名也可以是任何预定义的系统类名。有关系统类名称的列表,请参阅“备注”部分。

所以你需要一个类型转换。为此使用 MAKEINTATOM() 宏:

将指定的原子转换为字符串,以便可以将其传递给接受原子或字符串的函数。

ATOM clsAtom = RegisterClassExW(&wcon);
if (!clsAtom) {
    // error handling ...
}
...
HWND hConnect = CreateWindowW(
        MAKEINTATOM(clsAtom), // lpClassName,
        ...
    );

WC_COMBOBOX编译,因为它被定义为字符串文本 或 ,分别取决于是否定义。L"ComboBox""ComboBox"UNICODE

也就是说,您的值被声明为返回 ,但实际上并没有返回任何内容,因此返回的值是不确定的。您需要更改此内容:MyRegisterConnectClass()ATOMreturnATOM

ATOM MyRegisterConnectClass(HINSTANCE hInstance) {
    ...
    RegisterClassExW(&wcon);
}

对此:

ATOM MyRegisterConnectClass(HINSTANCE hInstance) {
    ...
    return RegisterClassExW(&wcon); // <-- add 'return'!
}

并更改此内容:

BOOL InitConnect(HINSTANCE hInstance, int nCmdShow)
{
    HWND hConnect = CreateWindowW(
        RegisterClassExW(&wcon), // lpClassName,
        ...
}

对此:

BOOL InitConnect(HINSTANCE hInstance, int nCmdShow)
{
    ATOM clsAtom = MyRegisterConnectClass(hInstance);
    if (!clsAtom) {
        // error handling ...
    }

    HWND hConnect = CreateWindowW(
        MAKEINTATOM(clsAtom), // lpClassName,
        ...
}

评论

0赞 Robert Hadow 4/23/2021
谢谢。丢失的回报是我的错别字。MAKEINTATOM 宏是一些秘诀。明。