Duilib 创建自定义控件
来源:互联网 发布:数控铣床编程简单100例 编辑:程序博客网 时间:2024/05/22 23:01
在群里经常会有刚接触Duilib的朋友问题怎么建立自己的自定义控件,或者建立的控件无法正常创建出来。我简单写一篇博客,把创建自定义控件的完整过程,和一些注意事项说明一下。另外说一下如果把win32的子窗体封装为控件,希望能有帮助。
创建自定义控件包含两个过程:1、继承现有的控件类创建新的控件类2、让程序识别新的控件并可以在xml中使用
class ComputerExamineUI : public CContainerUI //1.创建一定要的控件{public:ComputerExamineUI(){CDialogBuilder builder;//2.自定义控件绑定xml文件CContainerUI* pComputerExamine = static_cast<CContainerUI*>(builder.Create(_T("ComputerExamine.xml"), (UINT)0));if( pComputerExamine ) {//3.添加xml绘制控件到自定义控件this->Add(pComputerExamine);}else {this->RemoveAll();return;}}};
class CDialogBuilderCallbackEx : public IDialogBuilderCallback{//4.让程序识别出自定义控件public:CControlUI* CreateControl(LPCTSTR pstrClass) {if( _tcscmp(pstrClass, _T("ComputerExamine")) == 0 ) return new ComputerExamineUI;return NULL;}};新的控件名为CSkinPickerPictureItemUI。一般来说,建立新控件后,最先应该重写的两个函数是GetClass和GetInterface。他们后用来区分控件的类型的虚函数,用于动态识别控件类型和做控件的类型转换。
从Duilib的自带控件上可以看出,比如当前的自定义控件类名为CSkinPickerPictureItemUI,那么GetClass函数返回的字符串SkinPickerPictureItemUI。而GetInterface函数是根据传入的参数,是否与自身的字符串匹配,来决定能否把自己转换为需要的控件类型。GetInterface中用来匹配的字符串,应该与xml中的对应的控件的标签名称一直,这里应该是SkinPickerPictureItem。
比如CButtonUI类,GetClass对应ButtonUI,GetInterface对应Button。这不是强制的,但是保持这个风格很重要!
理论上,完成这两个接口就创建好最基本的自定义控件了。但是为了让自定义控件的行为和外观更丰富,就需要重写更多的函数了,我这里把经常会重写的函数说明一下!
virtual void DoEvent(TEventUI& event); virtual void DoPaint(HDC hDC, const RECT& rcPaint); virtual void PaintBkColor(HDC hDC); virtual void PaintBkImage(HDC hDC); virtual void PaintStatusImage(HDC hDC); virtual void PaintText(HDC hDC); virtual void PaintBorder(HDC hDC); virtual void DoInit(); virtual void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue); virtual bool IsVisible() const; virtual void SetVisible(bool bVisible = true); virtual void SetInternVisible(bool bVisible = true); // 仅供内部调用,有些UI拥有窗口句柄,需要重写此函数 virtual void SetPos(RECT rc);以上列出的函数,是最常被重写的。
DoEvent函数:控件的核心函数,他是消息处理函数,用来处理Duilib封装过的各个消息,比如鼠标的移入移出、出现的悬停、单击双击、右击、获取焦点、设置光标等等。所以如果你的控件需要修改这些行为,必须重写这个函数,具体的处理方法可以参考Duilib现有的控件或者仿酷狗程序。
DoPaint函数:控件的核心函数,他是控件的绘制处理函数,当Duilib底层要重新绘制这个控件,或者控件自己调用Invalidata函数强制自己刷新时,这个函数就会被触发,在这个函数里完成了各种状态下的背景前景绘制,背景色绘制,文本绘制,边框绘制。而这个函数会调用PaintBkColor、PaintBkImage、PaintStatusImage、PaintText、PaintBorder等函数来完成各个绘制步骤。所以你可以根据需求来决定重写DoPaint或者只重写某几个PaintXXX函数。DoPaint函数经常和DoEvent函数结合使用,DoEvent得到了某个消息后,改变控件的状态,然后调用Invalidate函数让控件重绘。
SetAttribute函数:用于扩展自定义控件的属性,Duilib的控件本身已经包含name、text、bkimage等属性,如果要增加新属性,就需要重写此函数来扩展属性,上面的CSkinPickerPictureItemUI例子中已经有用法了。
DoInit函数:当控件被添加到容器后,由容器调用的函数。在这里,整个Duilib程序框架已经完成,当需要做一些界面的初始操作时可以重写此函数,常见的用法就是在此建立Win32子窗体并且封装它,相关内容我在后面再说。
IsVisible、SetVisible、SetInternelVisible、SetPos:这几个函数同样也是,当控件封装了Win32子窗口后,重写这几个函数来控制子窗口的显示和隐藏、和位置。
这样就创建完成了自定义控件。
习惯上,在xml中自定义控件的标签名称应该和控件的GetInterface中的判断字符串一致,比如这里就是SkinPickerPictureItem。这样,在解析xml过程中,当解析到名为SkinPickerPictureItem的标签时,就会创建出CSkinPickerPictureItemUI控件了。
实际上,谁来继承IDialogBuilderCallback接口肯定都可以,比如QQDemo和仿酷狗里面,都给自定义控件本身继承了这个接口。
当程序响应WM_CREATE消息时,会建立一个CDialogBuilder对象,并且调用他的Create方法来解析xml文件。
CControlUI* CDialogBuilder::Create(STRINGorID xml, LPCTSTR type, IDialogBuilderCallback* pCallback, CPaintManagerUI* pManager, CControlUI* pParent)这个函数 的第一个参数指定为xml文件的路径;第二个参数一般指定为NULL,我这里不详解了;第三个参数,就是识别自定义控件的关键了,这个参数要指定为继承了IDialogBuilderCallback接口的类对象的指针,比如窗体类继承IDialogBuilderCallback,这个参数就填写窗体类对象的指针。只有填写了这个参数,自定义控件才会被识别,经常有人问自己的自定义控件为什么无法被识别。多数情况就是这里没处理好;第四个参数指定CPaintManagerUI类对象指针,这个肯定会伴随着窗体类对象一起存在。最后一个参数一般为NULL。
这几步都完成后,你的自定义控件就可以被xml布局正确的识别并创建了。至此,创建自定义控件的基本过程就完成了!如果有不明白的,可以多看看仿酷狗的代码、QQDemo等。
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
LONG styleValue = ::GetWindowLong(*this, GWL_STYLE);
styleValue &= ~WS_CAPTION;
::SetWindowLong(*this, GWL_STYLE, styleValue | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
m_pm.Init(m_hWnd);
CDialogBuilder builder;
CDialogBuilderCallbackEx cb;
CControlUI* pRoot = builder.Create(_T("skin.xml"), (UINT)0, &cb, &m_pm);
ASSERT(pRoot && "Failed to parse XML");
m_pm.AttachDialog(pRoot);
m_pm.AddNotifier(this);
Init();
return 0;
}
- Duilib 创建自定义控件
- Duilib创建添加自定义控件
- duilib中,子xml创建自定义控件
- duilib学习记录之创建自定义控件
- DuiLib实现自定义控件
- duilib自定义控件
- duilib开发基础:创建自定义控件的过程
- duilib开发基础:创建自定义控件的过程
- duilib创建自定义消息
- duilib 自定义控件1 CTileLayoutUI
- duilib 自定义控件TeamList 继承与CListUI
- 【duilib进阶】自定义控件响应指定命令
- duilib进阶教程 -- XML嵌套及自定义控件 (4)
- Duilib中为RichEdit\Edit控件添加自定义右键菜单
- duilib获取CSliderUI滑动事件 - 用自定义控件实现
- Duilib中为RichEdit\Edit控件添加自定义右键菜单
- Duilib 入门教程: 怎么创建一个自定义的窗口
- 自定义控件 创建复合控件
- C qsort函数
- 基于CSS实现的尖角提示符
- 无线路由器的设置简记
- PAT_A 1021. Deepest Root (25)
- JavaScript高级程序设计读书笔记(第五章)(三)
- Duilib 创建自定义控件
- Log4J使用详解(整理)
- [机械键盘]Filco87 奶酪绿 FKBN87MRL/ECW2 开箱
- 依赖注入
- Http、TCP/IP、UDP
- WebSphere数据源中的连接被意外关闭案例
- Codeforces 673D Bear and Two Paths【贪心】
- Java中有关Null的注意事项
- 【译】Android 7.0 for Developers