动态图制作软件设计(二)

我们在配置好Duilib库之后。开始下一步操作。

  • 首先我们需要创建一个Win32工程。
    #include"UIlib.h"引入头文件。
  • 链接lib静态库。
    #pragma comment(lib,"DuiLib_ud.lib")
  • 包含命名空间
    using namespace DuiLib;

在写代码之前我们先要了解一下,CWindowWnd类,CWindowWnd是Duilib封装的一个窗口类,主要功能为窗口创建操作。在使用该类的时候,我们需要对其GetWindowClassName函数进行重写,在该函数中必须返回用户所定义窗口的类名称,注册窗口时需要用到。

class CDuiFramWnd : public CWindowWnd
{
public:
	// 在该函数中必须返回用户所定义窗口的类名称,注册窗口时需要用到
	virtual LPCTSTR GetWindowClassName() const
	{
		return _T("DuiFramWnd");
	}
};

增加按钮控件,按钮控件的显示应该是在创建窗口的时候显示出来,所以我们需要将Duilib库中的HandleMessage(消息处理函数进行重写)。
HandleMessage

class CDuiFramWnd : public CWindowWnd
{
public:
	// 在该函数中必须返回用户所定义窗口的类名称,注册窗口时需要用到
	virtual LPCTSTR GetWindowClassName() const
	{
		return _T("DuiFramWnd");
	}

	virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
	{
		if (uMsg == WM_CREATE)
		{
			//创建一个按钮
			CControlUI *pWnd = new CButtonUI;

			// 设置按钮内容
			pWnd->SetText(_T("Make Gif software"));  //_T字符串类型转换	
		}
		//处理不了的信息交给父类处理
		return __super::HandleMessage(uMsg, wParam, lParam);
	}
};

但是这样创建出来的按钮是没有办法显示出来的,因为这样创建的按钮没有相应处理的消息。
消息

  • 系统消息
  • 用户自定义消息

我们自定义的消息编译器是不认识,所以我们需要对其进行自定义处理。
解决办法:增加一个回话管理器,主要处理我们自定义的消息。
CPaintManagerUI m_PaitManager;
因此,我们只需要在HandleMessage消息处理函数中,显示调用即可。

virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	if (uMsg == WM_CREATE)
	{
		//创建一个按钮
		CControlUI *pWnd = new CButtonUI;

		// 设置按钮内容
		pWnd->SetText(_T("Make Gif software"));  //_T字符串类型转换
		pWnd->SetBkColor(0xAAFF00FF);//设置背景色
		//初始化m_PaintManager对象的窗口句柄,发送消息时需要用到
		m_Pait.Init(m_hWnd);

		//将按钮控件链接到回话管理器上
		m_Pait.AttachDialog(pWnd);
	}

	LRESULT lRes = 0;
	//使用绘画管理器处理自定义信息,lRes是返回值,通常设置为0
	if (m_Pait.MessageHandler(uMsg, wParam, lParam, lRes))
	{
		return lRes;
	}

	//处理不了的信息交给父类处理
	return __super::HandleMessage(uMsg, wParam, lParam);
}

运行截图:
在这里插入图片描述
上面的整个界面都是我们创建的按钮,但是我们点击这个按钮发现没有任何反应,这是由于没有将按钮的信息响应出来。
解决办法:让我们创建的CDuiFramWnd继承INotifyUI。
在这里插入图片描述
在这里插入图片描述
作用:当检测到按钮按下的信号,做出相应的动作。
在这里插入图片描述
我们发现INotifyUI中只有一个Notify函数,该函数的作用是用于用户捕获自定义信息,进行自定义操作。同样的我们需要将该Notify连接到绘画器中。m_Pait.AddNotifier(this);

#include"UIlib.h"
#pragma comment(lib,"DuiLib_ud.lib")
using namespace DuiLib;

class CDuiFramWnd : public CWindowWnd,public INotifyUI
{
public:
	// 在该函数中必须返回用户所定义窗口的类名称,注册窗口时需要用到
	virtual LPCTSTR GetWindowClassName() const
	{
		return _T("DuiFramWnd");
	}

	virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
	{
		if (uMsg == WM_CREATE)
		{
			//创建一个按钮
			CControlUI *pWnd = new CButtonUI;

			// 设置按钮内容
			pWnd->SetText(_T("Make Gif software"));  //_T字符串类型转换
			pWnd->SetBkColor(0xAAFF00FF);
			
			//初始化m_PaintManager对象的窗口句柄,发送消息时需要用到
			m_Pait.Init(m_hWnd);
			//将按钮控件链接到回话管理器上
			m_Pait.AttachDialog(pWnd);
			//链接自定义处理消息
			m_Pait.AddNotifier(this);
		}

		LRESULT lRes = 0;
		//使用绘画管理器处理自定义信息,lRes是返回值,通常设置为0
		if (m_Pait.MessageHandler(uMsg, wParam, lParam, lRes))
		{
			return lRes;
		}
		//处理不了的信息交给父类处理
		return __super::HandleMessage(uMsg, wParam, lParam);
	}

	//捕获自定义消息,用于自定义处理
	virtual void Notify(TNotifyUI& msg)
	{
		if (msg.sType == _T("click")) //.sType为消息类型
		{
			MessageBox(NULL, _T("Test_click"), _T("Test"), IDOK); //弹窗测试
		}
	}
private:
	CPaintManagerUI m_Pait;
};

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int
	nCmdShow)
{
	CDuiFramWnd framWnd;
	// Cashier即在窗口右上角显式的名字
	// UI_WNDSTYLE_FRAME: 窗口可视的宏,具有标题栏,最大化最小化,关闭功能等
	// WS_EX_WINDOWEDGE: Win32的窗口风格,带有边框
	framWnd.Create(NULL, _T("Test"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
	//显示窗口,激活消息循环
	framWnd.ShowModal();
	return 0;
}

在Duilib库中是没有明显区分客户区与标题栏的,所以我们需要自己设置标题栏,但是Win32程序自带标题栏,我们需要将其屏蔽掉,用客户区来模拟标题栏,
所以想怎么画就怎么画,非常方便。

在HandleMessage函数中只需要屏蔽WM_NCACTIVATE、 WM_NCCALCSIZE、WM_NCPAINT三个消息即可。

virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	if (uMsg == WM_CREATE)
	...
	else if( uMsg == WM_NCACTIVATE )
	{
		if( !::IsIconic(m_hWnd) )
		{
		return (wParam == 0) ? TRUE : FALSE;
		}
	}
	else if( uMsg == WM_NCCALCSIZE )
	{
		return 0;
	}
	else if( uMsg == WM_NCPAINT )
	{
		return 0;
	}
	...
	if (m_Pait.MessageHandler(uMsg, wParam, lParam, lRes))
	...
}

这下我们运行程序,我们会发现上面的标题栏没有了,这就导致一个很尴尬的问题,怎么关闭呢?
在这里插入图片描述
我们在.exe目录下创建一个.xml文档。
在这里插入图片描述
使用记事本打开,我们将下面的代码拷贝到.xml文档中。

<?xml version="1.0" encoding="UTF-8"?>
<Window size="800,600"> <!-- 窗口的初始尺寸 -->
<HorizontalLayout bkcolor="#AAFF00FF"> <!-- 整个窗口的背景 -->
</HorizontalLayout>
</Window>

将该文档的编码格式改成UTF-8。
在这里插入图片描述
我们将.xml文档引入到代码中。
我们只需要将.xml文档导入到HandleMessage函数中。
在这里插入图片描述
运行报错:由于编译器不知道.xml文档的路径,所以我门还需要在主函数中,获取其路径。
在这里插入图片描述
完整代码

#include"UIlib.h"

#pragma comment(lib,"DuiLib_ud.lib")

using namespace DuiLib;

class CDuiFramWnd : public CWindowWnd,public INotifyUI
{
public:
	// 在该函数中必须返回用户所定义窗口的类名称,注册窗口时需要用到
	virtual LPCTSTR GetWindowClassName() const
	{
		return _T("DuiFramWnd");
	}

	virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
	{
		if (uMsg == WM_CREATE)
		{
			m_Pait.Init(m_hWnd);
			CDialogBuilder builder;
			
			CControlUI* pRoot = builder.Create(_T("makeGif.xml"), (UINT)0, NULL, &m_Pait);
			m_Pait.AttachDialog(pRoot);
			m_Pait.AddNotifier(this);
		}
		else if (uMsg == WM_NCACTIVATE)
		{
			if (!::IsIconic(m_hWnd))
			{
				return (wParam == 0) ? TRUE : FALSE;
			}
		}
		else if (uMsg == WM_NCCALCSIZE)
		{
			return 0;
		}
		else if (uMsg == WM_NCPAINT)
		{
			return 0;
		}

		LRESULT lRes = 0;
		//使用绘画管理器处理自定义信息,lRes是返回值,通常设置为0
		if (m_Pait.MessageHandler(uMsg, wParam, lParam, lRes))
		{
			return lRes;
		}

		//处理不了的信息交给父类处理
		return __super::HandleMessage(uMsg, wParam, lParam);
	}

	//捕获自定义消息,用于自定义处理
	virtual void Notify(TNotifyUI& msg)
	{
		if (msg.sType == _T("click")) //.sType为消息类型
		{
			MessageBox(NULL, _T("Test_click"), _T("Test"), IDOK); //弹窗测试
		}
	}
private:
	CPaintManagerUI m_Pait;
};

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int
	nCmdShow)
{
	CPaintManagerUI::SetInstance(hInstance);
	// 设置资源的默认路径(此处设置为和exe在同一目录)
	CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath());

	CDuiFramWnd framWnd;

	framWnd.Create(NULL, _T("Test"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
	//显示窗口,激活消息循环
	framWnd.ShowModal();
	return 0;
}

运行截图
在这里插入图片描述
现在我们已经完成基本的函数,我们只需要在.xml文档中进行编译,即可对软件的界面进行修改。
.xml文件,我们可以通过DuiDesigner_d.exe工具进行绘画。

或许上面的代码有点过程有点复杂。这时,我们只需要将我们创建的类继承WindowImplBase
在这里插入图片描述
我们先看一下WindoImplBase类中有什么:
在这里插入图片描述
原来在底层,WindowImplBase对CWindowWnd与INotifyUI都继承,所以我们直接继承WindowImplBase比较简单。

class CDuiFramWnd : public WindowImplBase
{
protected:
	virtual CDuiString GetSkinFolder() //获取路径,由于我们已经在WinMain主函数中进行路径获取,所以返回NULL
	{
		return _T(""); 
	}
	virtual CDuiString GetSkinFile() //获取皮肤文件.xml名称
	{
		return _T("makeGif.xml");
	}
	virtual LPCTSTR GetWindowClassName(void) const//获取窗口类名
	{
		return _T("DuiWnd");
	}
	
	virtual void Notify(TNotifyUI& msg)
	{
		if (msg.sType == _T("click"))
		{
			MessageBox(m_hWnd, _T("Hello World"), _T("DuiFramWnd"), IDOK);
		}
	}
};

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int
	nCmdShow)
{
	CPaintManagerUI::SetInstance(hInstance);
	// 设置资源的默认路径(此处设置为和exe在同一目录)
	CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath());

	CDuiFramWnd framWnd;

	framWnd.Create(NULL, _T("Test"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
	
	framWnd.CenterWindow(); //窗口居中显示
	//显示窗口,激活消息循环
	framWnd.ShowModal();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值