geniusice18的专栏

去年发了高仿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的希望能告诉我

源代码在这

可以一个人,可以几个人,一起放松那劳累的心情或者劳累自己的身体,

geniusice18的专栏

相关文章:

你感兴趣的文章:

标签云: