转载请说明原出处,谢谢~~
《仿酷狗音乐播放器开发日志二十》里做了换肤功能的一部分,今天完成其他的部分。酷狗的换肤窗口里的背景图可以让用户选择来换图,原酷狗的背景图的小图标,有normal、hover、down等多种状态,鼠标移动上去便会发生变化。如图
当鼠标经过时会有个黑色图片覆盖,边框变为浅蓝色。并且在他上面显示出作者的一些信息。要实现这个效果应该另外开发一个控件来支持动态的信息展示效果。我把这个小控件的开发过程和源码发一下,给学习做duilib控件的新手朋友做个例子,控件的整体代码很少,熟悉duilib的朋友就不用看这篇博客了。
我继承CButtonUI类来做这个控件,起名为CSkinPikerPictureItemUI,这个控件的行为和Button是相似的,唯一的区别就是鼠标移动和单击他的时候会显示出额外的信息的图片样式。
我本来想通过写一个布局,利用多个控件的组合来完成这个效果,但是回头一想,这个控件的效果并不复杂,使用布局去添加多个控件实在是杀鸡用牛刀,而且浪费资源。所以还是觉得直接把这个效果绘制出来。想要改变控件在hot和down状态下的显示效果,只要重写CButtonUI类的PaintStatusImage函数就可以了,编程的方法可以参考CButtonUI类的代码。
另外,由于这个控件上要显示出这个图片的名字和作者的名字,所以就应该为这个控件增加两个属性,用来在xml文件中设置这两个值,为此需要重写SetAttribute函数。先声明两个成员变量保存这两个值:
CDuiString m_BkName; CDuiString m_Author;
SetAttribute函数的代码
void CSkinPikerPictureItemUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue) { if( _tcscmp(pstrName, _T("bkname")) == 0 ) m_BkName = pstrValue; else if( _tcscmp(pstrName, _T("author")) == 0 ) m_Author += pstrValue; CButtonUI::SetAttribute(pstrName, pstrValue); }
PaintStatusImage函数的代码
void CSkinPikerPictureItemUI::PaintStatusImage(HDC hDC) { CButtonUI::PaintStatusImage(hDC); if( IsFocused() ) m_uButtonState |= UISTATE_FOCUSED; else m_uButtonState &= ~ UISTATE_FOCUSED; if( !IsEnabled() ) m_uButtonState |= UISTATE_DISABLED; else m_uButtonState &= ~ UISTATE_DISABLED; if( (m_uButtonState & UISTATE_PUSHED) != 0 || (m_uButtonState & UISTATE_HOT) != 0) { DrawImage(hDC, kSkinPickerPictureItemForeImage) ; //计算作者信息文字和背景图片名字文字的显示位置,这里是用了硬编码,请使用者自己修改 RECT rcBkName = m_rcItem; LONG nTextPadding = (m_rcItem.right - m_rcItem.left - CRenderEngine::GetTextSize(hDC, GetManager(),\ m_BkName.GetData(), m_iFont, m_uTextStyle).cx) / 2; rcBkName.left += nTextPadding; rcBkName.right -= nTextPadding; rcBkName.top += 15; rcBkName.bottom = rcBkName.top + 20; RECT rcAuthor = m_rcItem; nTextPadding = (m_rcItem.right - m_rcItem.left - CRenderEngine::GetTextSize(hDC, GetManager(),\ m_Author.GetData(), m_iFont, m_uTextStyle).cx) / 2; rcAuthor.left += nTextPadding; rcAuthor.right -= nTextPadding; rcAuthor.top += 40; rcAuthor.bottom = rcAuthor.top + 20; CRenderEngine::DrawText(hDC, m_pManager, rcBkName, m_BkName, kBkNameColor, m_iFont, m_uTextStyle); CRenderEngine::DrawText(hDC, m_pManager, rcAuthor, m_Author, kAuthorColor, m_iFont, m_uTextStyle); CRenderEngine::DrawRect(hDC, m_rcItem, 2, kBorderColor); } }
这个控件的编写非常简单,我也就不多说什么了,不知道让duilib调用自定义控件的可以看看duilib自带的360demo和QQDemo,我这里给写出CreateControl的代码:
CControlUI* CSkinPicker::CreateControl(LPCTSTR pstrClass) { if (_tcsicmp(pstrClass, kSkinPickerPictureItemInterface) == 0) return new CSkinPikerPictureItemUI(); return NULL; }
效果图:
有朋友在和我聊天中提起我博客里一些原理写的多,但是发的代码不够,我以后尽量多发布源代码出来~~
这个控件的源码:点击打开链接
Redrain 2014.8.7 18:15