duilib的通用窗口类WindowImplBase

前言

duilib程序中,编写自己的窗口类一般的继承关系有两种,一种是继承自CWindowWndINotifyUIIMessageFilterUI,而第二种方式是继承自duilib封装好的通用窗口类WindowImplBase

1、WindowImplBase类

从源码中可以看到WindowImplBase其实是继承自一般能用到的所有基础类:

#ifndef WIN_IMPL_BASE_HPP
#define WIN_IMPL_BASE_HPP

namespace DuiLib
{

	enum UILIB_RESOURCETYPE
	{
		UILIB_FILE=1,				// 来自磁盘文件
		UILIB_ZIP,						// 来自磁盘zip压缩包
		UILIB_RESOURCE,			// 来自资源
		UILIB_ZIPRESOURCE,	// 来自资源的zip压缩包
	};

	class DUILIB_API WindowImplBase
		: public CWindowWnd
		, public CNotifyPump
		, public INotifyUI
		, public IMessageFilterUI
		, public IDialogBuilderCallback
	{
	public:
		WindowImplBase(){};
		virtual ~WindowImplBase(){};
		virtual void InitWindow(){};
		virtual void OnFinalMessage( HWND hWnd );
		virtual void Notify(TNotifyUI& msg);

		DUI_DECLARE_MESSAGE_MAP()
		virtual void OnClick(TNotifyUI& msg);

	protected:
		virtual CDuiString GetSkinFolder() = 0;
		virtual CDuiString GetSkinFile() = 0;
		virtual LPCTSTR GetWindowClassName(void) const = 0 ;
		virtual LRESULT ResponseDefaultKeyEvent(WPARAM wParam);

		CPaintManagerUI m_PaintManager;
		static LPBYTE m_lpResourceZIPBuffer;

	public:
		virtual UINT GetClassStyle() const;
		virtual UILIB_RESOURCETYPE GetResourceType() const;
		virtual CDuiString GetZIPFileName() const;
		virtual LPCTSTR GetResourceID() const;
		virtual CControlUI* CreateControl(LPCTSTR pstrClass);
		virtual LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM /*lParam*/, bool& /*bHandled*/);
		virtual LRESULT OnClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled);
		virtual LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled);

#if defined(WIN32) && !defined(UNDER_CE)
		virtual LRESULT OnNcActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled);
		virtual LRESULT OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
		virtual LRESULT OnNcPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
		virtual LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
		virtual LRESULT OnGetMinMaxInfo(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
		virtual LRESULT OnMouseWheel(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled);
		virtual LRESULT OnMouseHover(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
#endif
		virtual LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
		virtual LRESULT OnChar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
		virtual LRESULT OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
		virtual LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
		virtual LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled);
		virtual LRESULT OnKillFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled);
		virtual LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled);
		virtual LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled);
		virtual LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled);
		virtual LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled);
		virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
		virtual LRESULT HandleCustomMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
		virtual LONG GetStyle();
	};
}

#endif // WIN_IMPL_BASE_HPP

2、优点

从上可以看到,一般编写自己的duilib窗口类所需要继承的几个类都已经被WindowImplBase继承了,而且已经做了部分封装,这样我们直接继承WindowImplBase不是方便了很多,而且只需要实现以下几个函数即可实现简单的duilib窗口,很简洁方便:

virtual CDuiString GetSkinFolder() = 0;
virtual CDuiString GetSkinFile() = 0;
virtual LPCTSTR GetWindowClassName(void) const = 0 ;

3、缺点

WindowImplBase通用窗口类目前不完全统计bug较多,好多地方需要自己修改,这个就要根据自己的需求不同自己去调整该类的源码,达到自己想要的效果。

4、示例

下面实现一个简单的例子:

MainFrame.h

#include "resource.h"
class CMainFrame : public WindowImplBase
{
public:
	CMainFrame();
	~CMainFrame();
public:
	LPCTSTR GetWindowClassName() const;
	virtual CDuiString GetSkinFile();
	virtual CDuiString GetSkinFolder();
	
	virtual LRESULT HandleCustomMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
	virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
	
public:
	
protected:
	void Notify(TNotifyUI& msg);
	bool OnBtnClickOfEnter(TNotifyUI& msg);
};

MainFrame.cpp

#include "stdafx.h"
#include "MainFrame.h"
#include "DefControlName.h"
#include "PersonalCenterDialog.h"
HWND g_hMainFrame = NULL;
 
CMainFrame::CMainFrame()
{
}
 
CMainFrame::~CMainFrame()
{
	PostQuitMessage(0);
}
 
LPCTSTR CMainFrame::GetWindowClassName() const
{
	return _T("App");
}
 
CDuiString CMainFrame::GetSkinFile()
{
	return _T("MainFrame.xml");
}
 
CDuiString CMainFrame::GetSkinFolder()
{
	return  _T("skin\\");
}
 
//duilib自身消息
void CMainFrame::Notify(TNotifyUI& msg)
{
	if (_tcsicmp(msg.sType, _T("windowinit")) == 0)
	{
		
	}
	else if (_tcsicmp(msg.sType, _T("killfocus")) == 0)
	{
 
	}
	else if (_tcsicmp(msg.sType, _T("click")) == 0)
	{
		if (_tcsicmp(msg.pSender->GetName(), kMainFrameBtnClose) == 0)
		{
			Close();
		}
		else if (_tcsicmp(msg.pSender->GetName(), kMainFrameBtnEnter) == 0)
		{
			OnBtnClickOfEnter(msg);
		}
	}
	else if (_tcsicmp(msg.sType, _T("timer")) == 0)
	{ }
	else if (_tcsicmp(msg.sType, _T("selectchanged")) == 0)
	{ }
	else if (_tcsicmp(msg.sType, _T("itemactivate")) == 0)
	{ }
	else if (_tcsicmp(msg.sType, _T("itemclick")) == 0)
	{ }
}
 
bool CMainFrame::OnBtnClickOfEnter(TNotifyUI & msg)
{
	CPersonalCenterDialog* pDialog = new CPersonalCenterDialog();
	if (pDialog == NULL)
		return false;
 
	DWORD dwStyle = UI_WNDSTYLE_FRAME;
	dwStyle = dwStyle^WS_MAXIMIZEBOX;
#if defined(WIN32) && !defined(UNDER_CE)
	pDialog->Create(NULL, _T("个人中心"), dwStyle | WS_POPUP, NULL, 0, 0, 0, 0);
#else
	pDialog->Create(NULL, _T("个人中心"), dwStyle | WS_POPUP, NULL, 0, 0, 0, 0);
#endif
 
	pDialog->CenterWindow();
	::ShowWindow(g_hMainFrame, SW_HIDE);
	::ShowWindow(*pDialog, SW_SHOW);
 
	return true;
 
}
 
//处理自定义消息
LRESULT CMainFrame::HandleCustomMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	switch (uMsg)
	{
	/*case WM_APPOBD_MSG_SHOW_MAIN_FRAME:
	{
		::ShowWindow(m_hWnd, SW_SHOW);
		break;
	}*/
	default:
		break;
	}
 
	return 0;
}
 
//处理事件消息
LRESULT CMainFrame::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_DEVICECHANGE:
	{
		break;
	}
	//case WM_CLOSE:
	//	PostQuitMessage(0);
	//	break;
	default:
		break;
	}
 
	return WindowImplBase::HandleMessage(uMsg, wParam, lParam);
}

stdafx.h:

// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
//
 
#pragma once
 
#include "targetver.h"
 
#define WIN32_LEAN_AND_MEAN             // 从 Windows 头中排除极少使用的资料
// Windows 头文件: 
#include <windows.h>
#include "..\DuiLib\UIlib.h"
using namespace DuiLib;
 
 
#ifdef _DEBUG
#   ifdef _UNICODE
#       pragma comment(lib, "..\\Lib\\DuiLib_ud.lib")
#   else
#       pragma comment(lib, "..\\Lib\\DuiLib_d.lib")
#   endif
#else
#   ifdef _UNICODE
#       pragma comment(lib, "..\\Lib\\DuiLib_u.lib")
#   else
#       pragma comment(lib, "..\\Lib\\DuiLib.lib")
#   endif
#endif
 
extern HWND g_hMainFrame;
// TODO:  在此处引用程序需要的其他头文件

main.cpp

#include "stdafx.h"
#include "MainFrame.h"
 
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int nCmdShow)
{
	CPaintManagerUI::SetInstance(hInstance);     
	CWndShadow::Initialize(hInstance);           
	CMainFrame* pFrame = new CMainFrame();
	if (pFrame == NULL)
		return 0;
	DWORD dwStyle = UI_WNDSTYLE_FRAME;
	dwStyle = dwStyle^WS_MAXIMIZEBOX;
	pFrame->Create(NULL, _T("云端软件"), dwStyle, WS_EX_STATICEDGE | WS_EX_APPWINDOW, 1, 1, 0, 0);  //倒数第3第4个参数可以设置duilib左上角的坐标,倒数第1第2个参数因为继承了WindowImpBase,
	                                                                                               //WindowImpBase类中在创建窗口大小时会取xml文件中的窗口大小数据,顾此处两个参数值无效。
	pFrame->CenterWindow();
	::ShowWindow(*pFrame, SW_SHOW);
 
	CPaintManagerUI::MessageLoop();   //消息循环
 
	::CoUninitialize();
	return 0;
}

5、TNotifyUI事件消息结构体解释

// Structure for notifications to the outside world
typedef struct tagTNotifyUI 
{
	CDuiString sType;
	CDuiString sVirtualWnd;
	CControlUI* pSender;
	DWORD dwTimestamp;
	POINT ptMouse;
	WPARAM wParam;
	LPARAM lParam;
} TNotifyUI;

TNotifyUI结构体是用于传递通知消息的数据结构。它包含了一些成员变量,用于在Notify函数中传递事件消息的相关信息。以下是TNotifyUI结构体的成员变量及其解释:

  • TNotifyUI::pSender:
    类型:CControlUI*
    解释:指向触发通知消息的控件的指针。通过这个成员变量,你可以知道是哪个控件触发了当前的通知消息。

  • TNotifyUI::sType:
    类型:LPCTSTR
    解释:表示通知消息的类型。通常,开发者可以根据这个成员变量来判断当前通知消息的类型,然后执行相应的操作。

  • TNotifyUI::wParam:
    类型:WPARAM
    解释:消息的附加参数,用于传递额外的数据。具体的含义取决于不同的通知消息类型。

  • TNotifyUI::lParam:
    类型:LPARAM
    解释:消息的附加参数,用于传递额外的数据。具体的含义取决于不同的通知消息类型。

  • TNotifyUI::ptMouse:
    类型:POINT
    解释:表示鼠标在触发通知消息的控件上的位置。通常在处理鼠标事件时会使用到这个成员变量。

  • TNotifyUI::wKeyState:
    类型:WORD
    解释:表示当前键盘的状态,例如是否按下了Ctrl、Shift、Alt等键。在处理键盘事件时,可以使用这个成员变量。

  • TNotifyUI::dwTimestamp:
    类型:DWORD
    解释:表示通知消息的时间戳,即消息发生的时间。在某些情况下,你可能需要知道消息发生的时间。

TNotifyUI结构体中的成员变量提供了处理通知消息所需的基本信息,你可以根据具体的通知消息类型和需求,使用这些成员变量来执行相应的操作。在处理消息时,通常会先判断通知消息的类型(通过sType成员变量),然后根据需要使用wParamlParam来传递数据或执行特定的逻辑。

typedef struct tagTNotifyUI 是一个定义了TNotifyUI结构体的类型别名。

TNotifyUI结构体是在DuiLib中用于传递通知消息的数据结构。它包含了以下成员变量:

  • CDuiString sType:
    类型:CDuiString
    解释:表示通知消息的类型。通常,开发者可以根据这个成员变量来判断当前通知消息的类型,然后执行相应的操作。

  • CDuiString sVirtualWnd:
    类型:CDuiString
    解释:表示虚拟窗口的名称。在DuiLib中,虚拟窗口用于区分不同的UI界面,每个UI界面都有一个唯一的虚拟窗口名称。

  • CControlUI* pSender:
    类型:CControlUI*
    解释:指向触发通知消息的控件的指针。通过这个成员变量,你可以知道是哪个控件触发了当前的通知消息。

  • DWORD dwTimestamp:
    类型:DWORD
    解释:表示通知消息的时间戳,即消息发生的时间。在某些情况下,你可能需要知道消息发生的时间。

  • POINT ptMouse:
    类型:POINT
    解释:表示鼠标在触发通知消息的控件上的位置。通常在处理鼠标事件时会使用到这个成员变量。

  • WPARAM wParam:
    类型:WPARAM
    解释:消息的附加参数,用于传递额外的数据。具体的含义取决于不同的通知消息类型。

  • LPARAM lParam:
    类型:LPARAM
    解释:消息的附加参数,用于传递额外的数据。具体的含义取决于不同的通知消息类型。

TNotifyUI结构体中的成员变量提供了处理通知消息所需的基本信息。你可以根据具体的通知消息类型和需求,使用这些成员变量来执行相应的操作。在处理消息时,通常会先判断通知消息的类型(通过sType成员变量),然后根据需要使用wParamlParam来传递数据或执行特定的逻辑。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

森明帮大于黑虎帮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值