Win32窗口对象的封装

创建窗口基类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;
}


//窗口效果展示图

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值