在创建窗口时不能每一次都对各种参数进行设定,这样的话会使代码复杂而且降低开发效率,创建自定义窗口类可以在使用时直接进行实例化,只需要一行代码便可以实现。
以下代码学习此项目https://github.com/planetchili/hw3d
创建自定义窗口类windowst.h
#pragma once
#include <string>
#include <sstream>
#include <windows.h>
#include "ChiliExceptrion.h"
#include "keyboard.h"
#define CHWND_EXCEPT( hr ) window::HrException( __LINE__,__FILE__,(hr) )
#define CHWND_LAST_EXCEPT() window::HrException( __LINE__,__FILE__,GetLastError() )
class window
{
private:
//单例模式创建实例得实例
class windowst
{
public:
static const char* getname() noexcept;
static HINSTANCE getinstance() noexcept;
static void setname();
private:
windowst() noexcept;
~windowst();
//delete禁止函数类外调用
windowst(const windowst&) = delete;
windowst operator=(const windowst&) = delete;
static constexpr const char* wndClassname="gfdgfd";
static windowst sinwindows;
HINSTANCE hinst;
};
public:
window(int width, int height, const char* name) noexcept;
~window();
window(const window&) = delete;
window& operator=(const window&) = delete;
private:
//
static LRESULT WINAPI HandleMsgSetup(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) noexcept;
static LRESULT CALLBACK HandleMsgThunk(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) noexcept;
LRESULT HandleMsg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) noexcept;
private:
int height;
int width;
HWND hwnd;
keyboard kbd;
};
windowst.cpp如下所示
#include "windowst.h"
#include "windows.h"
#include "resource.h"
window::windowst window::windowst::sinwindows;
//GetModuleHandle(nullptr)获取当前进程的窗口句柄
window::windowst::windowst() noexcept:hinst(GetModuleHandle(nullptr))
{
//wndClassname = window::classname;
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(wc);
wc.style = CS_OWNDC;
wc.lpfnWndProc = HandleMsgSetup;//消息处理函数
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = getinstance();
wc.hIcon = LoadIcon(getinstance(), MAKEINTRESOURCE(IDI_ICON1)); //设置图标
wc.hCursor = LoadIcon(getinstance(), MAKEINTRESOURCE(IDI_ICON1));
wc.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE;
wc.lpszMenuName = nullptr;
wc.lpszClassName = getname();
wc.hIconSm = nullptr;
RegisterClassEx(&wc);
}
window::windowst::~windowst()
{
UnregisterClass(wndClassname, getinstance());
}
void window::windowst::setname()
{
//wndClassname=window::transmsg();
}
const char* window::windowst::getname() noexcept
{
return wndClassname;
}
HINSTANCE window::windowst::getinstance() noexcept
{
return sinwindows.hinst;
}
window::window(int width, int height, const char* name) noexcept
{
RECT rect;
rect.left = 100;
rect.right = width + rect.left;
rect.top = 100;
rect.bottom = height + rect.top;
AdjustWindowRect(&rect, WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU, FALSE);
hwnd = CreateWindow(windowst::getname(), name, WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU,CW_USEDEFAULT, CW_USEDEFAULT,
width,height, nullptr, nullptr, windowst::getinstance(), this);
ShowWindow(hwnd, SW_SHOWDEFAULT);
}
window::~window()
{
DestroyWindow(hwnd);
}
LRESULT CALLBACK window::HandleMsgSetup(HWND hwnd, UINT msg, WPARAM wparem, LPARAM lparam) noexcept
{
//判断是否在非消息区域创建,否则返回默认处理方式
if (msg == WM_NCCREATE)
{
const CREATESTRUCT* const pcreat = reinterpret_cast<CREATESTRUCT*>(lparam);
//lpCreateParams就是之前创建的this,将窗口实例与winapi关联起来
window* const pWnd = static_cast<window*>(pcreat->lpCreateParams);
//把窗口实例数据在winapi方面进行存储
SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pWnd));
SetWindowLongPtr(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&window::HandleMsgThunk));
return pWnd->HandleMsg(hwnd, msg, wparem, lparam);
}
return DefWindowProc(hwnd, msg, wparem, lparam);
}
LRESULT CALLBACK window::HandleMsgThunk(HWND hwnd, UINT msg, WPARAM wparem, LPARAM lparam) noexcept
{
window* const pWnd = reinterpret_cast<window*>(GetWindowLongPtr(hwnd,GWLP_USERDATA));
return pWnd->HandleMsg(hwnd, msg, wparem, lparam);
}
//不能通过winapi函数调用成员函数,因此创建了静态函数,数据是winapi端的userdata中取得的
LRESULT window::HandleMsg(HWND hwnd, UINT msg, WPARAM wparem, LPARAM lparam) noexcept
{
switch (msg)
{
case WM_CLOSE:
PostQuitMessage(0);
return 0;
case WM_KEYDOWN:
kbd.OnKeyPressed(static_cast<unsigned char> (wparem));
MessageBox(nullptr, "WM_KEYDOWN", "OnKeyPressed", MB_OK | MB_ICONEXCLAMATION);
break;
case WM_KEYUP:
kbd.OnKeyReleased(static_cast<unsigned char> (wparem));
MessageBox(nullptr, "WM_KEYUP", "OnKeyReleased", MB_OK | MB_ICONEXCLAMATION);
break;
case WM_CHAR:
kbd.OnChar(static_cast<unsigned char> (wparem));
MessageBox(nullptr, "WM_KEYUP", "OnChar", MB_OK | MB_ICONEXCLAMATION);
break;
}
return DefWindowProc(hwnd, msg, wparem, lparam);
}
主函数如下所示
int CALLBACK WinMain( HINSTANCE hinstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
window mywin1(720, 640, "yang1");//创建一个窗口
window mywin2(720, 640, "yang2");//创建另一个
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}