duilib实战1-模仿百度网盘登录界面

侵权删,未经允许禁止转载!

前言:
刚上手duilib,还不太熟悉,而且没有官方文档,所以写几个实战项目来学习并巩固一下。

使用或实现的部分技术细节:
**1、**主窗体的边框
**2、**默认字体,控件默认属性的标签定义
**3、**CTextUI控件的简配html功能,包括a、c标签的使用(其中当align处于center时,点击超链接有bug)
**4、**使用到的控件标签主要有Button,Text,Control,RichEdit,Edit,CheckBox,ComboBox等
**5、**实现自定义控件(此项目中使用自定义控件的原因是因为CControlUI并没有将鼠标进入和离开事件转化为Notify,所以只能自己继承并重写标签,实现对这两个事件的控制)
**6、**通过定时器实现动画效果(在duilib中暂时没找到类似ProcessMessage这样的方法,所以暂时通过定时器来实现相关的功能)
**7、**模态窗的使用

效果展示:

duilib实战1-模仿百度网盘登录界面_第1张图片

duilib实战1-模仿百度网盘登录界面_第2张图片

duilib实战1-模仿百度网盘登录界面_第3张图片

核心代码如下:

test.xml


 
     
	
	
	
	
	
		
		
			 
				
			
				
				
				
				
			
				
				
					
				

networkset.xml



	
	
	
	
	
		
		
			
			
			
			

main.cpp

// test1.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "duiTest.h"

#include 
#include 
using namespace DuiLib;

#define TIMER_QR_MOVE 1001
#define TIMER_QR_RESTORE 1002
#define TIMER_INVALIDATE 1003

#ifdef _DEBUG
#   ifdef _UNICODE
#       pragma comment(lib, "DuiLib_ud.lib")
#   else
#       pragma comment(lib, "DuiLib_d.lib")
#   endif
#else
#   ifdef _UNICODE
#       pragma comment(lib, "DuiLib_u.lib")
#   else
#       pragma comment(lib, "DuiLib.lib")
#   endif
#endif
//重写一个可以响应mouseenter和mousemove的control控件
class CMoveControlUI :public CControlUI
{
public:
	virtual void DoEvent(TEventUI&event)
	{
		if (event.Type == UIEVENT_MOUSEENTER)
		{
			m_pManager->SendNotify(this, DUI_MSGTYPE_MOUSEENTER, event.wParam, event.lParam);
			return;
		}
		if (event.Type == UIEVENT_MOUSELEAVE)
		{
			m_pManager->SendNotify(this, DUI_MSGTYPE_MOUSELEAVE, event.wParam, event.lParam);
			return;
		}

		if (m_pParent != NULL) m_pParent->DoEvent(event);
	}
	LPVOID GetInterface(LPCTSTR pstrName)
	{
		if (_tcscmp(pstrName, _T("MoveControl")) == 0) return static_cast(this);
		return CControlUI::GetInterface(pstrName);
	}
	LPCTSTR GetClass() const
	{
		return _T("MoveControl");
	}
};


class CSetFrameWnd : public WindowImplBase
{
public:
	virtual LPCTSTR    GetWindowClassName() const { return _T("NetworkSet"); }
	virtual CDuiString GetSkinFile() { return _T("networkset.xml"); }
	virtual CDuiString GetSkinFolder() { return _T("skin"); }
	virtual void Notify(TNotifyUI& msg) override
	{
		__super::Notify(msg);
	}
};

class CMainFrameWnd : public WindowImplBase
{
public:
	virtual LPCTSTR    GetWindowClassName() const { return _T("DUIMainFrame"); }
	virtual CDuiString GetSkinFile() { return _T("test.xml"); }
	virtual CDuiString GetSkinFolder() { return _T("skin"); }

	virtual CControlUI* CreateControl(LPCTSTR pstrClass) override
	{
		//创建自定义控件
		if (0 == _tcsicmp(pstrClass, _T("MoveControl")))
		{
			return new CMoveControlUI;
		}
		return __super::CreateControl(pstrClass);
	}

	//初始化
	virtual void InitWindow() override
	{
		//刷新一次窗口,猜测richedit在绘制背景图片后有个bug??初次点击输入账号会自动focus到输入密码的richedit
		::SetTimer(GetHWND(), TIMER_INVALIDATE, 800, NULL);
	}

	virtual void Notify(TNotifyUI& msg)
	{
		if (msg.sType == DUI_MSGTYPE_CLICK)
		{
			if (msg.pSender->GetName() == _T("setbtn"))
			{
				//弹出设置窗口!
				CSetFrameWnd setFrameWnd;
				//第一个参数为NULL时为非模态窗,否则为模态窗
				setFrameWnd.Create(this->GetHWND(), _T("SetFrameWnd"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
				setFrameWnd.CenterWindow();
				setFrameWnd.ShowModal();
			}
			else if (msg.pSender->GetName() == _T("ImageQR"))
			{

			}
			else if (msg.pSender->GetName() == _T("chkAutoLogin"))
			{
				//勾选自动登录
				CCheckBoxUI* pAutoLogin = static_cast(msg.pSender);
				//此时虽然点击了勾选,但实际上控件还处于未勾选状态
				if (pAutoLogin && !pAutoLogin->GetCheck())
				{
					//自动勾选记住密码
					CCheckBoxUI* pRememberPass = static_cast(m_PaintManager.FindControl(_T("chkRememberPass")));
					if (pRememberPass && !pRememberPass->GetCheck())
					{
						pRememberPass->SetCheck(true, false);
					}
				}
			}
			else if (msg.pSender->GetName() == _T("chkRememberPass"))
			{
				//取消勾选记住密码时,自动取消自动登录选项
				CCheckBoxUI* pRememberPass = static_cast(msg.pSender);
				if (pRememberPass && pRememberPass->GetCheck())
				{
					//取消自动登录选项
					CCheckBoxUI* pAutoLogin = static_cast(m_PaintManager.FindControl(_T("chkAutoLogin")));
					if (pAutoLogin && pAutoLogin->GetCheck())
					{
						pAutoLogin->SetCheck(false, false);
					}
				}
			}
		}
		else if (msg.sType == DUI_MSGTYPE_LINK)
		{
			if (msg.pSender->GetName() == _T("LinkUseMsgLogin") || msg.pSender->GetName() == _T("LinkUsePasswordLogin"))
			{
				bool bUseMsgLogin = (msg.pSender->GetName() == _T("LinkUseMsgLogin"));
				//隐藏账号密码登录,并显示手机验证码登录
				CVerticalLayoutUI*pMsgLogin = static_cast(this->m_PaintManager.FindControl(_T("MsgLogin")));
				if (pMsgLogin)
					pMsgLogin->SetVisible(bUseMsgLogin);
				CVerticalLayoutUI*pPasswordLogin = static_cast(this->m_PaintManager.FindControl(_T("PasswordLogin")));
				if (pPasswordLogin)
					pPasswordLogin->SetVisible(!bUseMsgLogin);
				CHorizontalLayoutUI* pBDProtocol = static_cast(this->m_PaintManager.FindControl(_T("BDProtocolLayout")));
				if (pBDProtocol)
					pBDProtocol->SetVisible(bUseMsgLogin);
			}
			else if (msg.pSender->GetName() == _T("linkOpenApp") ||
				msg.pSender->GetName() == _T("linkForgetPass") ||
				msg.pSender->GetName() == _T("linkRegistry") ||
				msg.pSender->GetName() == _T("BDProtocol"))
			{
				//打开超链接
				CTextUI *pLinkOpenApp = static_cast(msg.pSender);
				if (pLinkOpenApp)
				{
					//用默认浏览器打开网页
					::ShellExecute(NULL, _T("open"), pLinkOpenApp->GetLinkContent(0)->GetData(), NULL, NULL, SW_SHOW);
				}
			}
		}
		else if (msg.sType == DUI_MSGTYPE_MOUSEENTER)
		{
			//移动图片
			if (msg.pSender->GetName() == _T("ImageQR") || msg.pSender->GetName() == _T("ImageHelp"))
			{
				::KillTimer(GetHWND(), TIMER_QR_MOVE);
				::KillTimer(GetHWND(), TIMER_QR_RESTORE);
				::SetTimer(GetHWND(), TIMER_QR_MOVE, 10, NULL);
			}
		}
		else if (msg.sType == DUI_MSGTYPE_MOUSELEAVE)
		{
			//复原图片
			if (msg.pSender->GetName() == _T("ImageQR") || msg.pSender->GetName() == _T("ImageHelp"))
			{
				::KillTimer(GetHWND(), TIMER_QR_MOVE);
				::KillTimer(GetHWND(), TIMER_QR_RESTORE);
				::SetTimer(GetHWND(), TIMER_QR_RESTORE, 10, NULL);
			}
		}
		else if (msg.sType == DUI_MSGTYPE_KILLFOCUS)
		{
			//richedit失去焦点
			if (msg.pSender->GetName() == _T("edtPhone"))
			{
				//如果此时没有数据,则显示placeholder
				CRichEditUI *pEdtPhone = static_cast(msg.pSender);
				if (pEdtPhone && pEdtPhone->GetText().IsEmpty())
				{
					pEdtPhone->SetBkImage(_T("file='edt_phone_placeholder.jpg' dest='0,4,140,34'"));
				}
			}
			else if (msg.pSender->GetName() == _T("edtCode"))
			{
				CRichEditUI *pEdtCode = static_cast(msg.pSender);
				if (pEdtCode && pEdtCode->GetText().IsEmpty())
				{
					pEdtCode->SetBkImage(_T("file='edt_msg_placeholder.jpg' dest='0,4,140,34'"));
				}
			}
			else if (msg.pSender->GetName() == _T("edtUsername"))
			{
				CRichEditUI *pEdtUsername = static_cast(msg.pSender);
				if (pEdtUsername && pEdtUsername->GetText().IsEmpty())
				{
					pEdtUsername->SetBkImage(_T("file='edt_user_placeholder.jpg' dest='0,7,140,37'"));
					pEdtUsername->Invalidate();
				}
			}
			else if (msg.pSender->GetName() == _T("edtPassword"))
			{
				CRichEditUI *pEdtPassword = static_cast(msg.pSender);
				if (pEdtPassword && pEdtPassword->GetText().IsEmpty())
				{
					pEdtPassword->SetBkImage(_T("file='edt_pass_placeholder.jpg' dest='0,7,140,37'"));
					pEdtPassword->Invalidate();
				}
			}
		}
		else if (msg.sType == DUI_MSGTYPE_SETFOCUS)
		{
			//richedit获得焦点
			if (msg.pSender->GetName() == _T("edtPhone"))
			{
				//如果没有数据,则清除placeholder背景图片
				CRichEditUI *pEdtPhone = static_cast(msg.pSender);
				if (pEdtPhone && pEdtPhone->GetText().IsEmpty())
				{
					pEdtPhone->SetBkImage(_T("file='edt_phone.jpg' dest='0,7,30,37'"));
				}
			}
			else if (msg.pSender->GetName() == _T("edtCode"))
			{
				CRichEditUI *pEdtCode = static_cast(msg.pSender);
				if (pEdtCode && pEdtCode->GetText().IsEmpty())
				{
					pEdtCode->SetBkImage(_T("file='edt_msg.jpg' dest='0,7,30,37'"));
				}
			}
			else if (msg.pSender->GetName() == _T("edtUsername"))
			{
				CRichEditUI *pEdtUsername = static_cast(msg.pSender);
				if (pEdtUsername && pEdtUsername->GetText().IsEmpty())
				{
					pEdtUsername->SetBkImage(_T("file='edt_user.png' dest='0,7,30,37'"));
					pEdtUsername->Invalidate();
				}
			}
			else if (msg.pSender->GetName() == _T("edtPassword"))
			{
				CRichEditUI *pEdtPassword = static_cast(msg.pSender);
				if (pEdtPassword && pEdtPassword->GetText().IsEmpty())
				{
					pEdtPassword->SetBkImage(_T("file='edt_pass.png' dest='0,7,30,37'"));
					pEdtPassword->Invalidate();
				}
			}
		}

		//基类中处理了一些默认按钮的点击事件,子类不处理的就给转到基类
		__super::Notify(msg);
	}

	//通过定时器来实现动画效果
	virtual LRESULT HandleCustomMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) override
	{
		//
		switch (uMsg)
		{
		case WM_TIMER:
			if (wParam == TIMER_QR_MOVE || wParam == TIMER_QR_RESTORE)
			{
				static int nMove = 0;
				if (wParam == TIMER_QR_MOVE)
				{
					//移动
					CMoveControlUI *pImageQR = static_cast(m_PaintManager.FindControl(_T("ImageQR")));
					if (pImageQR)
					{
						if (nMove > 10)
						{
							//显示帮助图片
							CMoveControlUI* pImageHelp = static_cast(m_PaintManager.FindControl(_T("ImageHelp")));
							if (pImageHelp)
							{
								pImageHelp->SetBkImage(_T("scan_help.jpg"));
								//开启mouse事件,事件响应同ImageQR控件
								pImageHelp->SetMouseEnabled(true);
							}
							::KillTimer(GetHWND(), TIMER_QR_MOVE);
							return 0;
						}
						++nMove;
						SIZE moveSize;
						moveSize.cx = -5;
						moveSize.cy = 0;
						pImageQR->Move(moveSize);
						m_PaintManager.Invalidate();
					}
				}
				else if (wParam == TIMER_QR_RESTORE)
				{
					//恢复
					CMoveControlUI *pImageQR = static_cast(m_PaintManager.FindControl(_T("ImageQR")));
					if (pImageQR)
					{
						CMoveControlUI* pImageHelp = static_cast(m_PaintManager.FindControl(_T("ImageHelp")));
						if (pImageHelp && _wcsicmp(pImageHelp->GetBkImage(), _T("scan_help.jpg")) == 0)
						{
							pImageHelp->SetBkImage(_T(""));
						}
						if (nMove <= 0)
						{
							//关闭mouse事件
							pImageHelp->SetMouseEnabled(false);
							::KillTimer(GetHWND(), TIMER_QR_RESTORE);
							return 0;
						}
						--nMove;
						SIZE moveSize;
						moveSize.cx = 5;
						moveSize.cy = 0;
						pImageQR->Move(moveSize);
						m_PaintManager.Invalidate();
					}
				}
			}
			else if (wParam == TIMER_INVALIDATE)
			{
				::KillTimer(GetHWND(), TIMER_INVALIDATE);
				m_PaintManager.Invalidate();
			}
			break;
		default:
			break;
		}
		return WindowImplBase::HandleCustomMessage(uMsg, wParam, lParam, bHandled);
	}
};

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
	CPaintManagerUI::SetInstance(hInstance);

	CMainFrameWnd mainFrame;
	mainFrame.Create(NULL, _T("MainWindow"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
	mainFrame.CenterWindow();
	mainFrame.ShowModal();
	return 0;
}

你可能感兴趣的:(java,后端,java,后端)