繁体   English   中英

CreateWindow() 返回 nullptr 和 GetLastError() 返回 1400

[英]CreateWindow() returns nullptr and GetLastError() returns 1400

您好,我最近决定通过 DirectX11 学习图形编程,为此我正在学习如何使用 Windows API。 我按照在线教程设法创建了一个窗口,后来我自己成功创建了一个窗口。 然而,当我尝试制作一个框架来创建 Window 时,问题就开始了,我遇到了一些错误,但是通过研究文档和查找示例,大多数问题都得到了解决,除了一个涉及 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 消息打印到调试控制台(我用它来查看正在调用哪些消息)。

PS:这是我在这里的第一篇文章,所以请随时指出文章本身的任何问题,以便我下次更清楚。

提前致谢! :-)

您在代码中使用的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;

当您调用HandleMsgWindow.hpp hwnd未初始化:

在此处输入图片说明

您可以在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);
}

它对我有用:

在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM