【问题标题】:WinAPI Cannot create a buttonWinAPI 无法创建按钮
【发布时间】:2023-06-14 06:20:02
【问题描述】:

我的问题:我正在尝试在窗口上创建一个按钮。听起来很简单,但按钮没有出现。窗口已创建,但按钮的 CreateWindow 函数返回 1407:找不到窗口类。我也在创建第二个窗口,但你可以忽略它。无法弄清楚出了什么问题。请帮忙!代码:

#include "windows.h"
#include "CanvasWndProc.h"
#include "resource.h"

#define IDB_LINE 1001

// Main window handle
HWND hMainWindow;
// Canvas window
HWND hCanvasWindow;
// Line button
HWND hButtonLine;

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case(WM_CREATE):

        hButtonLine = CreateWindowEx(0,"ButtonLineClass", "Line", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
            10, 10, 100, 100, hWnd, (HMENU)IDB_LINE, GetModuleHandle(0), NULL);

        break;
    case (WM_DESTROY):

        DestroyWindow(hCanvasWindow);
        DestroyWindow(hButtonLine);
        PostQuitMessage(0);

        break;
    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    // MainWindow class
    WNDCLASSEX wc;
    wc.cbSize        = sizeof(wc);
    wc.style         = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hbrBackground = CreateSolidBrush(RGB(255, 168, 0));
    wc.hInstance     = hInstance;
    wc.lpszClassName = "MainWindowClass";
    wc.lpszMenuName  = NULL;
    wc.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAINICON));
    wc.hIconSm       = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAINICON));
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);



    // CanvasWindow class
    WNDCLASSEX wcCanvas;
    wcCanvas.cbSize        = sizeof(wcCanvas);
    wcCanvas.style         = CS_HREDRAW | CS_VREDRAW;
    wcCanvas.lpfnWndProc   = WndProcCanvas;
    wcCanvas.cbClsExtra    = 0;
    wcCanvas.cbWndExtra    = 0;
    wcCanvas.hbrBackground = CreateSolidBrush(RGB(255, 255, 255));
    wcCanvas.hInstance     = hInstance;
    wcCanvas.lpszClassName = "CanvasWindowClass";
    wcCanvas.lpszMenuName  = NULL;
    wcCanvas.hIcon         = LoadIcon(NULL, IDI_WINLOGO);
    wcCanvas.hIconSm       = LoadIcon(NULL, IDI_WINLOGO);
    wcCanvas.hCursor       = LoadCursor(NULL, IDC_ARROW);



    // Register classes
    if (!RegisterClassEx(&wc)) 
    {
        MessageBox(NULL, "It was not possible to register a class!", "Error", MB_OK);
        return NULL;
    }
    if (!RegisterClassEx(&wcCanvas))
    {
        MessageBox(NULL, "It was not possible to register a canvas class!", "Error", MB_OK);
        return NULL;
    }



    // Create and show main window
    hMainWindow = CreateWindowEx(NULL,"MainWindowClass", "VPainter", WS_CLIPCHILDREN | WS_VISIBLE | 
        WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_OVERLAPPED | WS_SYSMENU, 
        CW_USEDEFAULT, NULL,CW_USEDEFAULT, NULL, NULL, NULL, hInstance, NULL);
    if (!hMainWindow)
    {
        MessageBox(NULL, "It was not possible to create a window!", "Error", MB_OK);
        return NULL;
    }
    ShowWindow(hMainWindow, nCmdShow);
    UpdateWindow(hMainWindow);
    SendMessage(hMainWindow, WM_SYSCOMMAND, SC_MAXIMIZE, 0);



    // Create and show canvas window
    RECT MainWindowSize;
    GetClientRect(hMainWindow, &MainWindowSize);
    hCanvasWindow = CreateWindowEx(NULL, "CanvasWindowClass", NULL, WS_VISIBLE | WS_CHILD,
        MainWindowSize.right - (MainWindowSize.right*0.8), MainWindowSize.bottom - (MainWindowSize.bottom*0.9),
        MainWindowSize.right - (MainWindowSize.right*0.2), MainWindowSize.bottom - (MainWindowSize.bottom*0.1), hMainWindow,
        NULL, hInstance, NULL);
    if (!hCanvasWindow)
    {
        MessageBox(NULL, "It was not possible to create a canvas window!", "Error", MB_OK);
        return NULL;
    }
    ShowWindow(hCanvasWindow, nCmdShow);
    UpdateWindow(hCanvasWindow);

    // MSC loop
    MSG message;
    while (GetMessage(&message, NULL, 0, 0))
    {
        DispatchMessage(&message);
    }

    return message.wParam;
}

【问题讨论】:

  • WM_CREATECreateWindowEx 返回之前发送。
  • 如果我没记错,这是因为 WM_CREATE 是由 CreateWindow 同步执行的,即 CreateWindow 还没有返回。
  • 窗口句柄在消息处理程序的hwnd参数中
  • 1406 is ERROR_TLW_WITH_WSCHILD - "无法创建*子窗口。"
  • 永远不要忽视您有多个错误的可能性。您现在肯定会得到不同的 GetLastError() 返回码。不得不猜测,我会说“ButtonLineClass”在 sn-p 中相当不确定。考虑用“Button”来创建一个按钮控件。

标签: c++ winapi


【解决方案1】:
CreateWindowEx(0, "ButtonLineClass", ...

要创建标准按钮,请使用类名 "BUTTON"WC_BUTTON。如果您有自己的自定义类"ButtonLineClass",那么它需要自己的类注册和窗口过程。

旁注,WndProc 应该始终返回一个值。你可以把return DefWindowProc放在程序的最后。

没有必要为子窗口和子控件调用DestroyWindow。请尝试以下操作:

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg) 
    {
    case WM_CREATE:
        hButtonLine = CreateWindowEx(0, WC_BUTTON, "Line", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
            10, 10, 100, 100, hWnd, (HMENU)IDB_LINE, GetModuleHandle(0), NULL);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

【讨论】: