创建窗口基类QWnd的头文件
QWnd.h
为了能像MFC一样处理消息所以定义了一个消息结构体,让这些消息结构体组成一个链表,
当消息在链表中找到对应的消息时返回对应的函数来处理消息
//定义消息函数指针类型
typedef LRESULT (QWnd::PWNDMSG)(WPARAM,LPARAM);
//消息结构
struct WNDMSG_MAP
{
UINT msg; //窗口消息id
UINT code; //通知消息id
UINT id; //范围第一个id
UINT endid; //范围最后一个id
PWNDMSG pfn; //函数指针
WNDMSG_MAP* pNext; //指向下一个消息结构的指针
//构造函数
WNDMSG_MAP(UINT msg,UINT code,UINT id,UINT endid,PWNDMSG pfn)
:msg(msg),code(code),id(id),endid(endid),pfn(pfn),pNext(nullptr)
{
}
};
#pragma once
#include <Windows.h>
//窗口基类
class QWnd
{
public:
QWnd();
virutal ~QWnd();
public:
//窗口过程
static LRESULT CALLBACK AfxQWindowProc(HWND,UINT,WPARAM,LPARAM);
public:
//创建窗口
HWND CreateQWnd(DWORD dwExStyle,LPCTSTR lpClassName,LPCTSTR lpCaption,
DWORD dwStyle,int x,int y,int nWidth,int nHeight,
QWnd* pParent,UINT id,LPVOID lpVoid=0);
//创建自定义窗口类
BOOL CreateEx(LPCTSTR lpCaption,DWORD dwStyle,RECT const& rc,QWnd* pParent,UINT id=0);
//添加消息到链表中
void AddMsg(WNDMSG_MAP* pNewmsg);
//清除空链表
void ClearNode();
//查找消息(模板函数)
template<class FIND_FUNC>
WNDMSG_MAP* FindMsg(FIND_FUNC findFunc);
public:
HWND m_hWnd;
HINSTANCE m_hInstance;
protected:
WNDMSG_MAP* m_pWndMsgHead; //消息链表头节点
};
//查找消息(模板函数要在头文件中实现)
template<class FIND_FUNC>
WNDMSG_MAP* QWnd::FindMsg(FIND_FUNC findFunc)
{
WNDMSG_MAP* pCur=m_pWndMsgHead;
while(pCur)
{
if(findFunc(pCur))
return pCur;
pCur=pCur->pNext;
}
return nullptr;
}
//添加消息宏
//添加窗口消息
#define ON_WNDMSG(msg,pfn)\
AddMsg(new WNDMSG_MAP(msg,0,0,0,(PWNDMSG)&pfn))
//添加命令消息
#define ON_COMMAND(id,pfn)\
AddMsg(new WNDMSG_MAP(WM_COMMAND,0,id,id,(PWNDMSG)&pfn))
//添加范围id的命令消息
#define ON_COMMAND_RNG(firid,endid,pfn)\
AddMsg(new WNDMSG_MAP(WM_COMMAND,0,firid,endid,(PWNDMSG)&pfn))
//添加命令通知消息
#define ON_COMMAND_NOTIFY(code,id,pfn)\
AddMsg(new WNDMSG_MAP(WM_COMMAND,code,id,id,(PWNDMSG)&pfn))
//添加范围id的命令通知消息
#define ON_COMMAND_NOTIFY_RNG(code,firid,endid,pfn)\
AddMsg(new WNDMSG_MAP(WM_COMMAND,code,firid,endid,(PWNDMSG)&pfn))
//添加子窗口通知消息
#define ON_NOTIFY(code,id,pfn)\
AddMsg(new WNDMSG_MAP(WM_NOTIFY,code,id,id,(PWNDMSG)&pfn))
//添加范围id的子窗口通知消息
#define ON_NOTIFY_RNG(code,firid,endid,pfn)\
AddMsg(new WNDMSG_MAP(WM_NOTIFY,code,firid,endid,(PWNDMSG)&pfn))
//大概就这七种样式吧,以后有需要再添加
QWnd窗口类的实现
QWnd.cpp
#include "QWnd.h"
QWnd::QWnd()
{
m_hInstance=::GetModuleHandle(NULL);
m_hWnd=NULL;
}
~QWnd::QWnd(){
ClearNode(); //析构的时候清空链表节点
}
//窗口过程
LRESULT CALLBACK QWnd::AfxQWindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
QWnd* pWnd=nullptr;
if(uMsg==WM_CREATE || uMsg==WM_NCCREATE)
{
pWnd=(QWnd*)((LPCREATESTRUCT)lParam)->lpCreateParams;
if(pWnd)
{
pWnd->m_hWnd=hWnd;
::SetWindowLongPtr(hWnd,GWLP_USERDATA,(LONG_PTR)pWnd);
}
}
else
{
pWnd=(QWnd*)::GetWindowLongPtr(hWnd,GWLP_USERDATA);
}
if(pWnd)
{
WNDMSG_MAP* pMsg=nullptr;
if(uMsg==WM_COMMAND)
{
pMsg=pWnd->FindMsg([wParam](WNDMSG_MAP* p){
return p->msg==WM_COMMAND &&
p->code==HIWORD(wParam) &&
LOWORD(wParam)>=p->id &&
LOWORD(wParam)<=p->endid;
});
}
else if(uMsg==WM_NOTIFY)
{
LPNMHDR lpNMhdr=(LPNMHDR)lParam;
pMsg=pWnd->FindMsg([lpNMhdr](WNDMSG_MAP* p){
return p->msg==WM_NOTIFY &&
p->code==lpNMhdr->code &&
lpNMhdr->idFrom>=p->id &&
lpNMhdr->idFrom<=p->endid;
});
}
else
{
pMsg=pWnd->FindMsg([uMsg](WNDMSG_MAP* p){
return p->msg==uMsg;
});
}
if(pMsg)
{
return (pWnd->*pMsg->pfn)(wParam,lParam);
}
}
return ::DefWindowProc(hWnd,uMsg,wParam,lParam);
}
HWND QWnd::CreateQWnd(DWORD dwExStyle,LPCTSTR lpClassName,LPCTSTR lpCaption,
DWORD dwStyle,int x,int y,int nWidth,int nHeight,
QWnd* pParent,UINT id,LPVOID lpVoid=0)
{
return ::CreateWindowEx(dwExStyle,lpClassName,lpCaption,
dwStyle,x,y,nWidth,nHeight,pParent,(HMENU)id,m_hInstance,lpVoid);
}
//创建自定义窗口类
BOOL QWnd::CreateEx(LPCTSTR lpCaption,DWORD dwStyle,RECT const& rc,QWnd* pParent,UINT id)
{
TCHAR clsName[]=TEXT("QWndClassName");
//设计窗口类
WNDCLASSEX wcEx={0};
wcEx.cbSize=sizeof(WNDCLASSEX);
//检查窗口类是否已经注册过
if(FALSE==GetClassInfoEx(m_hInstance,clsName,&wcEx))
{
wcEx.style=CS_HREDRAW|CS_VREDRAW;
wcEx.lpfnWndProc=AfxQWindowProc;
wcEx.hInstance=m_hInstance;
wcEx.lpszClassName=clsName;
wcEx.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wcEx.cbClsExtra=0;
wcEx.cbWndExtra=0;
wcEx.hIcon=::LoadIcon(NULL,IDI_APPLICATION);
wcEx.hIconSm=wcEx.hIcon;
wcEx.hCursor=::LoadCursor(NULL,IDC_ARROW);
wcEx.lpszMenuName=nullptr;
//注册窗口类
if(FALSE==::RegisterClassEx(&wcEx))
return FALSE;
}
//创建窗口
m_hWnd=CreateQWnd(0,clsName,lpCaption,dwStyle,rc.left,rc.top,
rc.right-rc.left,rc.bottom-rc.top,pParent,id,this);
return m_hWnd!=NULL;
}
//添加消息到链表中
void QWnd::AddMsg(WNDMSG_MAP* pNewmsg)
{
if(m_pWndMsgHead==nullptr)
{
m_pWndMsgHead=pNewmsg;
}
else
{
pNewmsg->pNext=m_pWndMsgHead;
m_pWndMsgHead=pNewmsg;
}
}
//清除空链表
void QWnd::ClearNode()
{
WNDMSG_MAP* pDel=nullptr;
While(m_pWndMsgHead)
{
pDel=m_pWndMsgHead;
m_pWndMsgHead=m_pWndMsgHead->pNext;
delete pDel;
}
}
应用:
创建一个窗口类继承QWnd
//MyMainWnd.h
#include "QWnd.h"
class MyMainWnd:public QWnd
{
public:
MyMainWnd();
private:
LRESULT OnClose(WPARAM,LPARAM);
LRESULT OnCrate(WPARAM,LPARAM);
LRESULT OnOK(WPARAM,LPARAM);
};
//MyMainWnd.cpp
#include "MyMainWnd.h"
MyMainWnd::MyMainWnd()
{
//在构造函数中添加消息到链表中
/*
AddMsg(new WNDMSG_MAP(WM_CLOSE,0,0,0,(PWNDMSG)&MyMainWnd::OnClose));
AddMsg(new WNDMSG_MAP(WM_CREATE,0,0,0,(PWNDMSG)&MyMainWnd::OnCreate));
*/
//这样写有点累,所以就用宏来替换
ON_WNDMSG(WM_CLOSE,MyMainWnd::OnClose);
ON_WNDMSG(WM_CREATE,MyMainWnd::OnCreate);
ON_COMMAND(IDOK,MyMainWnd::OnOK);
}
LRESULT MyMainWnd::OnClose(WPARAM,LPARAM){
return PostQuitMessage(0),0;
}
LRESULT MyMainWnd::OnCrate(WPARAM,LPARAM){
return 0;
}
LRESULT MyMainWnd::OnOK(WPARAM,LPARAM){
return 0;
}
在主函数中实例MyMainWnd窗口类测试
#include <windows.h>
#include "MyMainWnd.h"
int WINAPI WinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine, _In_ int nShowCmd)
{
MyMainWnd* pWnd=new MyMainWnd();
if(FALSE==pWnd->CreateEx(TEXT("TestWnd"),WS_OVERLAPPEDWINDOW,
RECT{300,200,1000,700}, nullptr))
{
return -1;
}
ShowWindow(pWnd->m_hWnd,SW_SHOW);
UpdateWindow(pWnd->m_hWnd);
//消息循环
MSG msg;
while (::GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
delete pWnd;
return msg.wParam;
}
//窗口效果展示图