创建窗口就是纯的Win API,我设想的窗口是这样的:
我们调用WinMain启动窗口,然后在WinMain初始化和启动消息循环。
消息会传入OnEvent,
WndProc是窗口过程函数(每个窗口都有一个WndProc函数,用于接收和处理窗口相关的消息,如鼠标点击、键盘输入、窗口大小调整等。)
#pragma once
#include<Windows.h>
namespace LocalRenderer
{
class Window
{
MSG msg;
public:
HWND WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
void OnEvent(MSG& msg) const;
static LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
};
}
//然后就实现窗口吧
#include"Window.h"
#include <wrl/client.h>
#include <DirectXMath.h>
using namespace Microsoft::WRL;
namespace LocalRenderer
{
HWND Window::WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
#pragma region Win32 API 创建窗口
//注册窗口类
WNDCLASSEX wc = { 0 };
//结构大小
wc.cbSize = sizeof(WNDCLASSEX);
//窗口样式: 水平大小改变重绘|竖直大小改变重绘|窗口拥有自己的绘制设备|检测鼠标双击事件
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
//这一句是窗口过程函数的初始化,如果有需要可以在Window里定义一个静态函数
//函数签名如下,也可也不定义,自己处理MSG(下文会提到)
//LRESULT CALLBACK Window::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
wc.lpfnWndProc = Window::WndProc;
//指向应用程序实例的句柄
wc.hInstance = hInstance;
//指定窗口的鼠标样式
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
//设备窗口背景刷
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
//唯一的窗口类名称,确保窗口类在系统中是唯一的,不会与其他窗口类冲突。
wc.lpszClassName = L"DXRenderer";
//注册窗口类,在这里我们可以实现一个应用只能打开一次的效果
if (!RegisterClassExW(&wc))
{
MessageBox(NULL, L"窗口类注册失败", L"错误", MB_ICONERROR);
}
//创建窗口句柄
HWND hwnd = CreateWindow(L"DXRenderer", L"D3D12离线渲染器 - DXRenderer", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
//窗口创建失败错误检查
if (hwnd == nullptr)
{
DWORD error = GetLastError();
LPVOID errorMsg;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
error,
0,
(LPWSTR)&errorMsg,
0,
NULL
);
MessageBox(NULL, (LPCWSTR)errorMsg, L"错误", MB_ICONERROR);
return nullptr;
}
//展示窗口,nCmdShow有大量的宏标志可以使用,表示不同的打开方式
ShowWindow(hwnd, nCmdShow);
//一般在Show后立刻调用一次,立即更新窗口,保证良好的响应
UpdateWindow(hwnd);
#pragma endregion
//消息循环
MSG msg = {};
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
OnEvent(msg);
}
}
return hwnd;
}
LRESULT CALLBACK Window::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_CLOSE:
PostQuitMessage(0);
break;
// 处理其他窗口消息
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
}
很快乐,成功创建了一个窗口