高仿QQ电脑管家8 界面

去年发了高仿QQ2012登录界面,最近又优化了下代码,先看效果图







换肤 的代码和高仿QQ2012登录界面一样,代码请看那边;

这次主要是优化了控件的组合,和贴图方式

整体的框架:

首先是一个窗口,这里用的是对话框,然后根据鼠标消息和窗口消息,对界面上的控件进行状态处理并更新显示

鼠标移动的处理

void CDlgBase::OnMouseMove(UINT nFlags, CPoint point) 
{	
	// 监控鼠标离开
	if (!m_bTracking)
	{
		TRACKMOUSEEVENT tme;
		tme.cbSize = sizeof(tme);
		tme.hwndTrack = m_hWnd;
		tme.dwFlags = TME_LEAVE | TME_HOVER;
		tme.dwHoverTime = 1;
		m_bTracking = ::_TrackMouseEvent(&tme);
	}
	
	// 鼠标已经在某个控件上
	if (m_pControl)
	{
		if((m_pControl->PtInRect(point) || m_bIsLButtonDown) && m_bTracking)
		{			
			m_pControl->OnMouseMove(nFlags, point);			
			return;
		}
	}

	// 左键按下后不处理鼠标移动消息
	if (!m_bIsLButtonDown)
	{
		CControlBase * pOldControl = m_pControl;
		BOOL bIsSelect = FALSE;
		BOOL bIsSystemSelect = FALSE;

		if(m_bTracking)
		{
			// 默认控件
			for (size_t i = 0; i < m_vecBaseControl.size(); i++)
			{
				CControlBase * pControlBase = m_vecBaseControl.at(i);
				if (pControlBase)
				{
					pControlBase->OnMouseMove(nFlags, point);
					if(pControlBase->PtInRect(point) && pControlBase->GetRresponse())
					{
						m_pControl = pControlBase;
						bIsSystemSelect = TRUE;
					}
				}		
			}
			
			// 用户控件
			for (size_t i = 0; i < m_vecControl.size(); i++)
			{
				CControlBase * pControlBase = m_vecControl.at(i);
				if (pControlBase)
				{
					pControlBase->OnMouseMove(nFlags, point);
					if (!bIsSystemSelect)
					{
						if(pControlBase->PtInRect(point) && pControlBase->GetRresponse())
						{
							m_pControl = pControlBase;
							bIsSelect = TRUE;
						}
					}
				}		
			}
		}

		if (!bIsSelect && !bIsSystemSelect)
		{
			m_pControl = NULL;
		}
	}
	
	//CDialog::OnMouseMove(nFlags, point);
}

控件组合:

DirectUI 这种方式要实现不同的界面效果是很好实现的,只是控件都要自己重新写,所以要能实现控件的组合,这样当基础控件多了组合新控件就方便了

每个控件都有自己的消息处理  如鼠标移动,每个控件都能增加自己的子控件,也有当前被选中控件这些处理,代码如下(基本和窗口那处理是一样的)

BOOL CControlBase::OnMouseMove(UINT nFlags, CPoint point)
{
	if(!m_bIsVisible || !m_bRresponse) return false;
	
	BOOL bRresponse = false;
	if(m_pControl)
	{
		if(m_pControl->PtInRect(point) || m_bMouseDown)
		{			
			if(m_pControl->OnMouseMove(nFlags, point))
			{
				return true;
			}
			return false;
		}
	}

	CControlBase * pOldControl = m_pControl;
	m_pControl =  NULL;

	bRresponse = OnControlMouseMove(nFlags, point);

	if(!m_bMouseDown)
	{
		for (size_t i = 0; i < m_vecControl.size(); i++)
		{
			CControlBase * pControlBase = m_vecControl.at(i);
			if (pControlBase)
			{
				if(pControlBase->OnMouseMove(nFlags, point))
				{
					if(pControlBase->PtInRect(point))
					{
						m_pControl = pControlBase;
					}
					bRresponse = true;
				}
			}
		}


		if (pOldControl)
		{
			bRresponse = true;
		}

		if (m_pControl)
		{
			bRresponse = true;
		}
	}

	return bRresponse;
}


控件显示:

控件显示主要是为每个控件增加上个DC,只在每次控件要重绘时才去更新贴图,其他情况如只是状态更改之类的就只是从DC复制到窗口上(就是空间换速度),代码如下

void CImageButton::DrawControl(CDC &dc, CRect rcUpdate)
{
	int nWidth = m_rc.Width();
	int nHeight = m_rc.Height();

	//更新标志(如在换肤、移动位置、比他更下层的控件变化时等等一些会使控件就变化的都会更新)
	if(!m_bUpdate)
	{
		// 更新DC 如果控件大小改变会更新
		UpdateMemDC(dc, nWidth * (4 + m_nMaxIndex), nHeight);
		
		ColorMatrix matrix;
		ImageAttributes imageAttr;

		ZeroMemory(&matrix, sizeof(matrix));
		for(int i = 0; i < 5; i++)
		{
			matrix.m[i][i] = 1.0f;
		}		

		Graphics graphics(m_memDC);
		CRect  rcTemp(0, 0, nWidth, nHeight);

		// 按钮有四个状态 所以DC为按钮大小的4倍分别保存四个状态,如果只是单纯的按钮状态改变的话,就不用重绘,而是通过状态值去取不同的DC区域显示
		for(int i = 0; i < 4; i++)
		{
			// 先贴上控的背景
			m_memDC.BitBlt(i * nWidth, 0, nWidth, nHeight, &dc, m_rc.left ,m_rc.top, SRCCOPY);

			// 贴上不同状态的图
			graphics.DrawImage(m_pImage, Rect(rcTemp.left, rcTemp.top,  rcTemp.Width(), rcTemp.Height()),
				i * m_sizeImage.cx, 0, m_sizeImage.cx, m_sizeImage.cy, UnitPixel);

			rcTemp.OffsetRect(nWidth, 0);
		}

		// 实现动画效果 原理同上
		for (int i = 4; i < 4 + m_nMaxIndex; i++)
		{
			m_memDC.BitBlt(i * nWidth, 0, nWidth, nHeight, &dc, m_rc.left ,m_rc.top, SRCCOPY);

			matrix.m[3][3] = 1 - ((float)(i - 4 + 1)) / m_nMaxIndex;
			imageAttr.SetColorMatrix(&matrix);
			graphics.DrawImage(m_pImage, Rect(rcTemp.left ,rcTemp.top, rcTemp.Width(), rcTemp.Height()), 
				m_sizeImage.cx * enBSNormal, 0, m_sizeImage.cx, m_sizeImage.cy, UnitPixel ,&imageAttr);

			matrix.m[3][3] = ((float)(i - 4 + 1)) / m_nMaxIndex;
			imageAttr.SetColorMatrix(&matrix);
			graphics.DrawImage(m_pImage, Rect(rcTemp.left ,rcTemp.top, rcTemp.Width(), rcTemp.Height()), 
				m_sizeImage.cx * enBSHover, 0, m_sizeImage.cx, m_sizeImage.cy, UnitPixel ,&imageAttr);

			rcTemp.OffsetRect(nWidth, 0);
		}
	}


	// 根据不同状态显示
	if(m_nIndex != 0 && m_bRunTime && m_bTimer)
	{
		dc.BitBlt(m_rc.left,m_rc.top, m_rc.Width(), m_rc.Height(), &m_memDC, (4 + m_nIndex - 1) * nWidth, 0, SRCCOPY);
	}
	else
	{
		dc.BitBlt(m_rc.left,m_rc.top, m_rc.Width(), m_rc.Height(), &m_memDC, m_enButtonState * nWidth, 0, SRCCOPY);
	}
}

这个现在也不算库的界面库吧,还有很多问题没解决,如不支持TAB键,不支持键盘操作,控件太少等等,要完善还有很多东西要做,代码也发了,如果有好想法或解决了BUG的希望能告诉我

源代码在这

评论 42
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值