【问题标题】:CreateWindow() returns nullptr and GetLastError() returns 1400CreateWindow() 返回 nullptr 并且 GetLastError() 返回 1400
【发布时间】:2020-08-26 17:24:15
【问题描述】:

您好,我最近决定通过 DirectX11 学习图形编程,为此我正在学习如何使用 Windows API。我按照在线教程设法创建了一个窗口,后来我自己成功创建了一个。但是,当我尝试创建一个框架来创建窗口时,问题就开始了,我遇到了一些错误,但是通过研究文档和查找示例,大多数都解决了,除了一个涉及 CreateWindow() 函数的问题。

每当我尝试获取它返回 nullptr 的窗口句柄时,我尝试通过 GetLastError() 获取错误代码,但我得到的只是 1400,根据 MSDN,它是“无效的窗口句柄”。我不知道我做错了什么,我还没有找到任何解决问题的线程。编译成功,但没有窗口出现。

窗口.hpp

#pragma once
#include "WindowsHeader.hpp"

class Window
{
public:

    Window(int width, int height, const char* name);
    ~Window();
    Window(const Window&) = delete;
    Window& operator=(const Window&) = delete;

private:

    class WindowClass
    {
    public:

        static const char* GetName() noexcept;
        static HINSTANCE GetInstance() noexcept;

    private:

        WindowClass() noexcept;
        ~WindowClass();
        WindowClass(const WindowClass&) = delete;
        WindowClass& operator=(const WindowClass&) = delete;

        static constexpr const char* window_class_name{ "HardwareAccelerated3D" };
        static WindowClass window_class;
        HINSTANCE hinst;
    };

    static LRESULT CALLBACK HandleMsgSetup(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) noexcept;
    static LRESULT CALLBACK HandleMsgInvoke(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) noexcept;
    LRESULT HandleMsg(HWND, UINT msg, WPARAM wparam, LPARAM lparam) noexcept;

    int width;
    int height;
    HWND hwnd;
};

窗口.cpp

#include "Window.hpp"
#include <sstream>

//Window Class

Window::WindowClass Window::WindowClass::window_class;

Window::WindowClass::WindowClass() noexcept
    : hinst(GetModuleHandle(NULL))
{
    WNDCLASSEX window_class{ {0} };
    window_class.cbSize = sizeof(window_class);
    window_class.style = CS_OWNDC;
    window_class.lpfnWndProc = &HandleMsgSetup;
    window_class.cbClsExtra = NULL;
    window_class.cbWndExtra = NULL;
    window_class.hInstance = GetInstance();
    window_class.hIcon = NULL;
    window_class.hCursor = NULL;
    window_class.hbrBackground = NULL;
    window_class.lpszMenuName = NULL;
    window_class.lpszClassName = GetName();
    window_class.hIconSm = NULL;
    RegisterClassEx(&window_class);
}

Window::WindowClass::~WindowClass()
{
    UnregisterClass(GetName(), GetInstance());
}

const char* Window::WindowClass::GetName() noexcept
{
    return window_class_name;
}

HINSTANCE Window::WindowClass::GetInstance() noexcept
{
    return window_class.hinst;
}

//Window

Window::Window(int width, int height, const char* name)
    : width(width), height(height)
{
    RECT wndrec;
    wndrec.left = 100;
    wndrec.right = wndrec.left + width;
    wndrec.top = 100;
    wndrec.bottom = wndrec.top + height;
    if (!AdjustWindowRect(&wndrec, WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU, false))
    {
        std::ostringstream oss;
        oss << GetLastError();
        OutputDebugString(oss.str().c_str());
    }

    hwnd = CreateWindow(WindowClass::GetName(), name, WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU,
        CW_USEDEFAULT, CW_USEDEFAULT, wndrec.right - wndrec.left, wndrec.bottom - wndrec.top, NULL,
        NULL, WindowClass::GetInstance(), this);

    if (!hwnd)
    {
        std::ostringstream oss;
        oss << GetLastError();
        OutputDebugString(oss.str().c_str());
    }

    ShowWindow(hwnd, SW_SHOWDEFAULT);
}

Window::~Window()
{
    DestroyWindow(hwnd);
}

LRESULT WINAPI Window::HandleMsgSetup(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) noexcept
{
    if (msg == WM_NCCREATE)
    {
        const CREATESTRUCTW* const pcreate = reinterpret_cast<CREATESTRUCTW*>(lparam);
        Window* const pwnd = static_cast<Window*>(pcreate->lpCreateParams);
        SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pwnd));
        SetWindowLongPtr(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&Window::HandleMsgInvoke));
        return pwnd->HandleMsg(hwnd, msg, wparam, lparam);
    }
    return DefWindowProc(hwnd, msg, wparam, lparam);
}

LRESULT WINAPI Window::HandleMsgInvoke(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) noexcept
{
    Window* const pwnd = reinterpret_cast<Window*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
    return pwnd->HandleMsg(hwnd, msg, wparam, lparam);
}

LRESULT Window::HandleMsg(HWND, UINT msg, WPARAM wparam, LPARAM lparam) noexcept
{
    switch (msg)
    {
    case WM_CLOSE:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, msg, wparam, lparam);
}

WinMain.cpp

#include "WindowsMessageMap.hpp"
#include "Window.hpp"

int CALLBACK WinMain(_In_ HINSTANCE hInstance, _In_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
{
    Window window(640, 480, "HardwareAccelerated3D");

    MSG msg;
    BOOL gresult;
    while (gresult = GetMessage(&msg, NULL, NULL, NULL) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    if (gresult == -1)
        return -1;
    return msg.wParam;
}

WindowsHeader.hpp 只是一些定义,Windows.h 是为了避免一些 windows 宏,而 WindowsMessageMap.hpp 只是将 windows 消息打印到调试控制台(我用它来查看正在调用的消息)。

P.S.:这是我第一次在这里发帖,如有任何问题请随时指出,以便我下次更清楚。

提前致谢! :-)

【问题讨论】:

  • 代码使用Window::hinst,但似乎没有初始化它。
  • WindowClass 构造函数正在初始化和注册一个名为 window_class 的本地变量 WNDCLASSEX,隐藏静态 WindowClass::window_class 成员。
  • 感谢您的回复。我尝试将函数成员重命名为m_wndclass,以便它们不共享相同的名称,但我仍然遇到同样的问题。是不是构造函数的逻辑有问题?
  • 您好,如果这个答案对您有帮助,请随时标记它以帮助遇到相同问题的人,如果您有任何问题,请告诉我。谢谢。

标签: c++ windows winapi


【解决方案1】:

您在代码中使用的hwndWindow.hpp中的相同:

LRESULT Window::HandleMsg(HWND, UINT msg, WPARAM wparam, LPARAM lparam) noexcept
{
    switch (msg)
    {
    case WM_CLOSE:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, msg, wparam, lparam);
}

Window.hpp的最后一行:

HWND hwnd;

当你调用HandleMsg时,Window.hpphwnd没有被初始化:

您可以在HandleMsgSetup 中使用hwnd,只需添加hwnd 参数,如下代码:

LRESULT Window::HandleMsg(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) noexcept
{
    switch (msg)
    {
    case WM_CLOSE:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, msg, wparam, lparam);
}

它对我有用:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-15
    • 1970-01-01
    • 2021-07-21
    • 1970-01-01
    相关资源
    最近更新 更多