Window类,内部类WindowClass单例用于注册,Window创建窗口
myWindow.h
#pragma once
#include<Windows.h>
class Window
{
private:
class WindowClass//单例设计,用于注册类,
{
public:
static const wchar_t* GetName()noexcept;
static HINSTANCE GetInstance()noexcept;
private:
static WindowClass wndClass;
HINSTANCE hInst;//当前应用实例句柄
WindowClass()noexcept;
~WindowClass();
WindowClass(const WindowClass&) = delete;
WindowClass& operator=(const WindowClass&) = delete;
static constexpr const wchar_t* wndClassName = L"my Window";
};
public:
Window(int width, int height, const wchar_t* name)noexcept;
~Window();
Window(const Window&) = delete;
Window& operator=(const Window&) = delete;
private:
//消息处理的参数列表固定,没有this,所以static,若要该函数中获取该Window实例的指针,使用CreateWindow()的最后的一位参数
static LRESULT CALLBACK HandleMsgSetup(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);//初始化要处理的消息
static LRESULT CALLBACK HandleMsgThunk(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT HandleMsg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
private:
int width;
int height;
HWND hWnd;
};
myWindow.cpp
#include"MyWindow.h"
Window::WindowClass Window::WindowClass::wndClass;//初始化静态数据成员
Window::WindowClass::WindowClass() noexcept//class "WindowClass" construction,
:hInst{GetModuleHandle(nullptr)}
{
WNDCLASSEX wc{ 0 };
wc.cbSize = sizeof(wc);
wc.style = CS_OWNDC;
wc.lpfnWndProc = HandleMsgSetup;//function in class"Window"
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetInstance();// member function
wc.hIcon = nullptr;
wc.hCursor = nullptr;
wc.hbrBackground = nullptr;
wc.lpszMenuName = nullptr;
wc.lpszClassName = GetName();//member function
wc.hIconSm = nullptr;
RegisterClassEx(&wc);
}
Window::WindowClass::~WindowClass()
{
UnregisterClass(wndClassName, GetInstance());
}
const wchar_t* Window::WindowClass::GetName() noexcept
{
return wndClassName;
}
HINSTANCE Window::WindowClass::GetInstance() noexcept
{
return wndClass.hInst;
}
Window::Window(int width, int height, const wchar_t* name) noexcept
:width{width},height{height}
{
RECT wr;
wr.left = 100;
wr.right = width + wr.left;
wr.top = 100;
wr.bottom = height + wr.top;
AdjustWindowRect(&wr, WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU, FALSE);//传入客户端矩形区域大小,和窗口风格,计算整个窗口的大小
hWnd = CreateWindow(
WindowClass::GetName(), name,
WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU,
CW_USEDEFAULT, CW_USEDEFAULT,
wr.right - wr.left, wr.bottom - wr.top,
nullptr, nullptr, WindowClass::GetInstance(),
this//this 传入形参lpParam,用于填充结构体“CREATESTRUCT",处理WM_NCCREATE/WM_CREATE消息时,其LParam指向结构体
);
ShowWindow(hWnd, SW_SHOWDEFAULT);
}
Window::~Window()
{
DestroyWindow(hWnd);
}
LRESULT CALLBACK Window::HandleMsgSetup(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)//初始化要处理的消息
{
if (msg == WM_NCCREATE)//在WM_CREATE之前,即在“CreateWindowEx”函数,之前,产生此消息,wParam未使用,LParam是CREATESTRUCT的对象的指针,结构体包含窗口信息(其与创建window时传入的信息相同)
{
const CREATESTRUCTW* const pCreate = reinterpret_cast<CREATESTRUCTW*>(lParam);
//该结构体的lpCreateParams参数,实际为"CreateWindow"的"lpParam"所传入的this,目的是窗口实例与Win消息处理机制关联起来
Window* const pWnd = static_cast<Window*>(pCreate->lpCreateParams);
//该函数允许:修改WINAPI端的数据,这里选用GWLP_USERDATA功能,允许存储自定义用户数据,存入Window类对象
SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pWnd));
//修改了消息处理函数,让消息经由"HandleMsgThunk"处理,停止使用"HandleMsgSetup"处理消息,
SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&Window::HandleMsgThunk));
return pWnd->HandleMsg(hWnd, msg, wParam, lParam);
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
LRESULT CALLBACK Window::HandleMsgThunk(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
//获取Window类的指针,
Window* const pWnd = reinterpret_cast<Window*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
return pWnd->HandleMsg(hWnd, msg, wParam, lParam);
}
LRESULT Window::HandleMsg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CLOSE:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
WinMain.cpp
#include "MyWindow.h"
int CALLBACK WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
{
Window wnd(800, 300, L"Box");
MSG msg;
BOOL getResult;
while ((getResult = GetMessage(&msg, nullptr, 0, 0)) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (getResult == -1)
{
return -1;
}
else
{
return msg.wParam;
}
}
WindowClass包含它的一个静态成员,程序运行,就会产生该对象,且只能一次,
在其构造函数,完成窗口类的注册,析构时,取消注册。
需要Window中的 消息处理函数,
Window包含成员width,height,hWnd(该窗口的句柄),
在构造函数,CreateWindow() 和 ShowWindow()
需要WindowClass: 注册的类名,