第二十八篇:SOUI中自定义控件开发过程
在SOUI中已经提供了大部分常用的控件,但是内置控件不可能满足用户的所有要求,因此一个真实的应用少不得还要做一些自定义控件。
学习一个新东西,最简单的办法就是依葫芦画瓢。事实上在SOUI系统中内置控件和自定义控件的开发流程是完全一样的,因此只需要打开SOUI的源代码,随便找一个控件看一下就大体差不多了。
下面我以controls.extend目录下的的SRadioBox2控件为例对控件开发过程需要注意的地方做一点说明。
要开发一个控件,首先要确定的是应该从哪个控件来继承。选择一个合适的基类是正确开发自定义控件的前提。
之所以要开发一个SRadioBox2控件,我需要解决的问题很简单:SRadioBox控件总是在左边显示一个圆圈,这个圆圈有时候不是我想要的。
因此我需要做的就是继承SRadioBox控件的行为,重写WM_PAINT的处理。
因此就有了下面的代码:
class SRadioBox2 : public SRadioBox
{
public:
SRadioBox2(void);
~SRadioBox2(void);
}
需要注意的是,所有SOUI控件都是在namespace SOUI中,因此自定义控件也最好是放在SOUI这个namespace里。
有了上面的骨架,下面来逐步添加内容。
首先我们需要给自定义控件定义一个在XML中可以识别的标签。
只需要在类的最开始增加一行:
class SRadioBox2 : public SRadioBox
{
SOUI_CLASS_NAME(SRadioBox2,L"radio2")
public:
SRadioBox2(void);
~SRadioBox2(void);
}
SOUI_CLASS_NAME告诉XML解析器,碰到radio2时自动创建SRadioBox2对象。
实际上这一行更重要的作用是用来做对象类型运行时识别(RTTI),有了这个机制,在编译器关闭C++的RTTI时仍然可以安全的进行类型转换。
然后我们需要处理控件的WM_PAINT消息。
为了处理这个消息,我们需要加入消息映射表及消息处理函数:
class SRadioBox2 : public SRadioBox
{
SOUI_CLASS_NAME(SRadioBox2,L"radio2")
public:
SRadioBox2(void);
~SRadioBox2(void); protected:
void OnPaint(IRenderTarget *pRT); SOUI_MSG_MAP_BEGIN()
MSG_WM_PAINT_EX(OnPaint)
SOUI_MSG_MAP_END()
};
SOUI控件的消息处理机制是和WTL中抄过来的,和MFC也很相似。只是对于部分消息,由于对于消息的参数的解释不一样,消息映射的宏会有一点变化。
如这里的WM_PAINT消息,在SOUI里wparam传递的是一个IRenderTarget指针,而传统的Win32传递的是一个HDC。因此我们需要使用MSG_WM_PAINT_EX代替WTL中使用的MSG_WM_PAINT。
大家可能会问有哪些消息映射宏SOUI和WLT不一样?
实际上对于一个有经验的程序员,他应该可以找到MSG_WM_PAINT_EX的宏定义,并且在定义附近就可以找到所有的SOUI和WLT不同的映射宏。
下面是到目前为止SOUI中所有和WTL不同的宏:
// BOOL OnEraseBkgnd(IRenderTarget * pRT)
#define MSG_WM_ERASEBKGND_EX(func) \
if (uMsg == WM_ERASEBKGND) \
{ \
SetMsgHandled(TRUE); \
lResult = (LRESULT)func((IRenderTarget *)wParam); \
if(IsMsgHandled()) \
return TRUE; \
} // void OnPaint(IRenderTarget * pRT)
#define MSG_WM_PAINT_EX(func) \
if (uMsg == WM_PAINT) \
{ \
SetMsgHandled(TRUE); \
func((IRenderTarget *)wParam); \
lResult = ; \
if(IsMsgHandled()) \
return TRUE; \
} // void OnNcPaint(IRenderTarget * pRT)
#define MSG_WM_NCPAINT_EX(func) \
if (uMsg == WM_NCPAINT) \
{ \
SetMsgHandled(TRUE); \
func((IRenderTarget *)wParam); \
lResult = ; \
if(IsMsgHandled()) \
return TRUE; \
} // void OnSetFont(IFont *pFont, BOOL bRedraw)
#define MSG_WM_SETFONT_EX(func) \
if (uMsg == WM_SETFONT) \
{ \
SetMsgHandled(TRUE); \
func((IFont*)wParam, (BOOL)LOWORD(lParam)); \
lResult = ; \
if(IsMsgHandled()) \
return TRUE; \
} // void OnSetFocus()
#define MSG_WM_SETFOCUS_EX(func) \
if (uMsg == WM_SETFOCUS) \
{ \
SetMsgHandled(TRUE); \
func(); \
lResult = ; \
if(IsMsgHandled()) \
return TRUE; \
} // void OnKillFocus()
#define MSG_WM_KILLFOCUS_EX(func) \
if (uMsg == WM_KILLFOCUS) \
{ \
SetMsgHandled(TRUE); \
func(); \
lResult = ; \
if(IsMsgHandled()) \
return TRUE; \
} // void OnNcMouseHover(int nFlag,CPoint pt)
#define MSG_WM_NCMOUSEHOVER(func) \
if(uMsg==WM_NCMOUSEHOVER)\
{\
SetMsgHandled(TRUE); \
func(wParam,CPoint(GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam))); \
lResult = ; \
if(IsMsgHandled()) \
return TRUE; \
} // void OnNcMouseLeave()
#define MSG_WM_NCMOUSELEAVE(func) \
if(uMsg==WM_NCMOUSELEAVE)\
{\
SetMsgHandled(TRUE); \
func(); \
lResult = ; \
if(IsMsgHandled()) \
return TRUE; \
} // void OnTimer(char cTimerID)
#define MSG_WM_TIMER_EX(func) \
if (uMsg == WM_TIMER) \
{ \
SetMsgHandled(TRUE); \
func((char)wParam); \
lResult = ; \
if(IsMsgHandled()) \
return TRUE; \
} #define WM_TIMER2 (WM_USER+5432) //定义一个与HWND定时器兼容的SOUI定时器 #define MSG_WM_TIMER2(func) \
if (uMsg == WM_TIMER2) \
{ \
SetMsgHandled(TRUE); \
func(wParam); \
lResult = ; \
if(IsMsgHandled()) \
return TRUE; \
}
通常情况下,自定义控件还需要处理一些自定义的属性,这时我需要还需要增加一个属性映射表(如SGifPlayer):
SOUI_ATTRS_BEGIN()
ATTR_CUSTOM(L"skin", OnAttrSkin) //为控件提供一个skin属性,用来接收SSkinObj对象的name
SOUI_ATTRS_END()
完成上面几步,一个自定义控件基本上就完成了。
可能还需要实现几个修改基类行为的虚函数。
第二十八篇:SOUI中自定义控件开发过程的更多相关文章
- Android UI开发第二十八篇——Fragment中使用左右滑动菜单
Fragment实现了Android UI的分片管理,尤其在平板开发中,好处多多.这一篇将借助Android UI开发第二十六篇——Fragment间的通信. Android UI开发第二十七篇——实 ...
- Python之路(第二十八篇) 面向对象进阶:类的装饰器、元类
一.类的装饰器 类作为一个对象,也可以被装饰. 例子 def wrap(obj): print("装饰器-----") obj.x = 1 obj.y = 3 obj.z = 5 ...
- Python之路【第二十八篇】:django视图层、模块层
1.视图函数 文件在view_demo 一个视图函数简称视图,是一个简单的Python 函数,它接受Web请求并且返回Web响应.响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XM ...
- Python之路【第二十八篇】:生成器与迭代器
#!/usr/bin/env python # -*- coding:utf-8 -*- #只要函数的代码里面出现了yield关键字,这个函数就不再是一个普通的函数了,叫做生成器函数 #执行生成器函数 ...
- 第二十八篇、自定义的UITableViewCell上有图片需要显示,要求网络网络状态为WiFi时,显示图片高清图;网络状态为蜂窝移动网络时,显示图片缩略图
1)SDWebImage会自动帮助开发者缓存图片(包括内存缓存,沙盒缓存),所以我们需要设置用户在WiFi环境下下载的高清图,下次在蜂窝网络状态下打开应用也应显示高清图,而不是去下载缩略图. 2)许多 ...
- 第二十八篇-Fragment静态用法
效果图: 首先,先大致布局成这个形状 看动画中,横看分为两个区域,所以整体是一个水平排列 设置外层LinearLayout的参数 android:orientation="horizonta ...
- Android UI开发第二十九篇——Android中五种常用的menu(菜单)
Android Menu在手机的应用中起着导航的作用,作者总结了5种常用的Menu. 1.左右推出的Menu 前段时间比较流行,我最早是在海豚浏览器中看到的,当时耳目一新.最早使用左右推出菜单的,听说 ...
- 第二十八篇 玩转数据结构——堆(Heap)和有优先队列(Priority Queue)
1.. 优先队列(Priority Queue) 优先队列与普通队列的区别:普通队列遵循先进先出的原则:优先队列的出队顺序与入队顺序无关,与优先级相关. 优先队列可以使用队列的接口,只是在 ...
- flask第二十八篇——HTML【1】table标签
请关注公众号:自动化测试实战 以下内容参考:http://www.w3school.com.cn/tags/tag_table.asp <!DOCTYPE html> <html l ...
随机推荐
- 【BZOJ-1570】BlueMary的旅行 分层建图 + 最大流
1570: [JSOI2008]Blue Mary的旅行 Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 388 Solved: 212[Submit ...
- android 手机去哪儿7.2版本客户端 账号存储信息分析
1.data/data/com.qunar sharepref 文件夹下的Qunarperferences.xml文件中 username,phone等均为加密处理过字段 2.jdgui下查找关键 ...
- NodeJs + mongodb模块demo
代码比较通俗易懂,但是我还是在这个过程中浪费了不少时间,也算是看到了nodejs中异步的一个小坑.未来的坑还有很多,慢慢找坑填坑吧. 参考资料如下: 1.断言模块 : https://nodejs.o ...
- Javascript:一个屌丝的逆袭
HTML负责结构, CSS负责展示, 而我(加上AJAX, JSON) 负责逻辑.于是前端编程三剑客形成了. http://mp.weixin.qq.com/s?__biz=MzAxOTc0NzExN ...
- NAT穿越
1.NAT类型 目前主要的NAT类型有如下几种: 1)Full-cone NAT, also known as one-to-one NAT 一旦一个内网地址 (iAddr:iPort) 被映射到一个 ...
- nginx 和 IIS 实现负载均衡
Nginx的作用和优点,这里不必多说,今天主要是nginx负载均衡实验,把做的步骤记录下来,作为一个学习笔记吧,也可以给大家做下参考. 1.Nginx安装 1.下载地址:http://nginx.or ...
- Python 字符串操作及string模块使用
python的字符串操作通过2部分的方法函数基本上就可以解决所有的字符串操作需求: python的字符串属性函数 python的string模块 1.字符串属性方法操作: 1.>字符串格式输出对 ...
- [NHibernate]事务
目录 写在前面 文档与系列文章 事务 增删改查 总结 写在前面 上篇文章介绍了nhibernate的增删改查方法及增加修改操作,这篇文章将介绍nhibernate的事务操作. SQL Server中的 ...
- codevs3163 抄书问题2
题目描述 Description 现在要把M本有顺序的书分给K个人复制(抄写),每一个人的抄写速度都一样,一本书不允许给两个(或以上)的人抄写,分给每一个人的书,必须是连续的,比 如不能把第一.第三. ...
- avl树的操作证明
以下用大O表示节点,ABC表示三个集合. 仅分析左子树的情况,因为对称,右子树的情况一样. 插入节点前 O / \ O A / \ B C 插入节点后: O ...