SOUI中提供了大部分常用的win32标准控件的实现,如pushbutton, checkbox, radiobox, edit, richedit, listbox, combobox, treectrl, listctrl (report), hotkeyctrl等。

大部分控件在接收用户输入后,会发生状态的改变,并以事件的形式传递给UI的所有者。

在SOUI中提供了两种处理事件的方式:

1、在SHostWnd的派生类中重载

    virtual BOOL SHostWnd::_HandleEvent(SOUI::EventArgs *pEvt){return FALSE;}

为了更方便的处理事件,SOUI提供了一组宏来构造这个事件处理函数,从而提供一种类似消息映射的事件处理形式。

如demo的CMainDlg中的实现:

    //UI控件的事件及响应函数映射表
EVENT_MAP_BEGIN()
EVENT_ID_COMMAND(, OnClose)
EVENT_ID_COMMAND(, OnMaximize)
EVENT_ID_COMMAND(, OnRestore)
EVENT_ID_COMMAND(, OnMinimize)
EVENT_NAME_CONTEXTMENU(L"edit_1140",OnEditMenu)
EVENT_NAME_COMMAND(L"btn_msgbox",OnBtnMsgBox)
EVENT_NAME_COMMAND(L"btnSelectGif",OnBtnSelectGIF)
EVENT_NAME_COMMAND(L"btn_menu",OnBtnMenu)
EVENT_NAME_COMMAND(L"btn_webkit_go",OnBtnWebkitGo)
EVENT_NAME_COMMAND(L"btn_webkit_back",OnBtnWebkitBackward)
EVENT_NAME_COMMAND(L"btn_webkit_fore",OnBtnWebkitForeward)
EVENT_NAME_COMMAND(L"btn_webkit_refresh",OnBtnWebkitRefresh)
EVENT_NAME_COMMAND(L"btn_hidetst",OnBtnHideTest)
EVENT_NAME_COMMAND(L"btn_insert_gif",OnBtnInsertGif2RE)
EVENT_MAP_END()

上面的EVENT_MAP_BEGIN()和EVENT_MAP_END()结合构造出一个_HandleEvent函数的实现,具体可以自己展开这两个宏查看代码。

同时SOUI也提供了一组解析SOUI::EventArgs *pEvt的宏,如上例中的EVENT_NAME_COMMAND, EVENT_ID_COMMAND等。

帮助用户直接从控件的name或者ID属性映射到消息响应函数。

这种事件响应方式最大的好处是能够集中处理事件的分发,方便阅读代码,同时也和传统的MFC,WTL的编程风格类似,降低用户的学习成本。

2、采用事件订阅的方式响应控件事件

虽然事件映射表提供了一种简单有效的事件响应机制,由于事件映射表是一种编译期形成的静态的映射表,对于在运行期动态创建的控件的事件响应就无能为力了。

在MFC中,程序员通过要重载窗口类的DefWindowProc来处理运行期间动态创建的控件发来的消息。

这种方式灵活性够了,但是不够优雅,要在一个函数里做大量的swich分枝,导致这个处理函数很难维护。

设计模式里的观察者模式可以比较好的解决这个问题。

为些在SOUI中我提供了一种事件订阅的事件处理模式。

我们先看一下demo中怎样处理列表控件的表头点击来执行排序操作:

void CMainDlg::InitListCtrl()
{
//找到列表控件
SListCtrl *pList=FindChildByName2<SListCtrl>(L"lc_test");
if(pList)
{
//列表控件的唯一子控件即为表头控件
SWindow *pHeader=pList->GetWindow(GSW_FIRSTCHILD);
//向表头控件订阅表明点击事件,并把它和OnListHeaderClick函数相连。
pHeader->GetEventSet()->subscribeEvent(EVT_HEADER_CLICK,Subscriber(&CMainDlg::OnListHeaderClick,this));
//省略列表初始化代码
}
} //表头点击事件处理函数
bool CMainDlg::OnListHeaderClick(EventArgs *pEvtBase)
{
//事件对象强制转换
EventHeaderClick *pEvt =(EventHeaderClick*)pEvtBase;
SHeaderCtrl *pHeader=(SHeaderCtrl*)pEvt->sender;
//从表头控件获得列表控件对象
SListCtrl *pList= (SListCtrl*)pHeader->GetParent();
//列表数据排序
SHDITEM hditem;
hditem.mask=SHDI_ORDER;
pHeader->GetItem(pEvt->iItem,&hditem);
pList->SortItems(funCmpare,&hditem.iOrder);
return true;
}

通过事件订阅可以在运行时方便的将一个控件的事件关联到一个处理函数上,当然也可以随时取消订阅。

同时事件订阅也是在脚本中响应控件事件的唯一方式(关于在SOUI中使用LUA脚本将在后续讲解)。

第八篇:SOUI中控件事件的响应的更多相关文章

  1. 第二十七篇:SOUI中控件属性查询方法

    SOUI项目的SVN根目录下有一个doc目录,下面有一份控件属性表.包含了大部分控件的大部分属性,不过也不一定完全准确.最保险的办法还是查源代码. SOUI对象包含控件及ISkinObj等从SObje ...

  2. 第二十五篇:在SOUI中做事件分发处理

    不同的SOUI控件可以产生不同的事件.SOUI系统中提供了两种事件处理方式:事件订阅 + 事件处理映射表(参见第八篇:SOUI中控件事件的响应) 事件订阅由于直接将事件及事件处理函数连接,不存在事件分 ...

  3. Dev中控件的js事件代码放在form标签中存在问题

    Dev中控件的js事件代码放在form标签中会获取不到(head标签中有其他js代码,未验证是否是这个问题)

  4. 第二十八篇:SOUI中自定义控件开发过程

    在SOUI中已经提供了大部分常用的控件,但是内置控件不可能满足用户的所有要求,因此一个真实的应用少不得还要做一些自定义控件. 学习一个新东西,最简单的办法就是依葫芦画瓢.事实上在SOUI系统中内置控件 ...

  5. 利用ICommand和ITool重写Arcengine中控件的事件

    Arcengine窗体开发中,不同命令或者工具可能会触发同一控件的同一事件,这样会造成该事件中代码的混乱.以主窗体的AxMapcontrol控件为例,当开始画图时因为有很多种类型的Feature,所以 ...

  6. 第八篇 Integration Services:高级工作流管理

    本篇文章是Integration Services系列的第八篇,详细内容请参考原文. 简介在前面两篇文章,我们创建了一个新的SSIS包,学习了SSIS中的脚本任务和优先约束,并检查包的MaxConcu ...

  7. Android开源项目第一篇——个性化控件(View)篇

    本文为那些不错的Android开源项目第一篇——个性化控件(View)篇,主要介绍Android上那些不错个性化的View,包括ListView.ActionBar.Menu.ViewPager.Ga ...

  8. duilib中控件拖拽功能的实现方法(附源码)

    转载请说明原出处,谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/41144283 duilib库中原本没有显示的对控件增加拖拽的功能,而实际 ...

  9. Android开发UI之开源项目第一篇——个性化控件(View)篇

    原文:http://blog.csdn.net/java886o/article/details/24355907 本文为那些不错的Android开源项目第一篇——个性化控件(View)篇,主要介绍A ...

随机推荐

  1. 【GoLang】GoLang 错误处理 -- 使用异常的思路进行处理

    go处理错误的另一种方式 go处理错误常见的方式是 err := funcReturningError() if err != nil { // 处理错误 } 然而因为过于繁琐而饱受诟病.下文简述另一 ...

  2. IPC---共享内存

    共享内存就是允许两个或多个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据时,不需要在客户进程和服务器进程之间幅值,因此是最快的一种IPC.不同进程之间共享的内存通常安 ...

  3. Linq查询非泛型集合要指定Student类型(比如List)

    #region Linq to 集合查询非泛型集合要指定Student类型            //ArrayList list = new ArrayList();            //li ...

  4. servlet 和filter 的生命周期说明

    servlet : 当客户端第一次访问servlet的时候,服务器就会创建servlet实例,servlet 就会执行init方法,每次请求,服务器会开一个新的线程访问servlet中得service ...

  5. 8. javacript高级程序设计-BOM

    1. BOM 1.1 window BOM的核心对象是window,它表示浏览器的一个实例.在浏览器中,window对象有双重身份, 1.1.1 全局作用域 由于window对象同时扮演着ECMASc ...

  6. nyoj366_D的小L_字典序_全排列

    D的小L 时间限制:4000 ms  |  内存限制:65535 KB 难度:2   描述       一天TC的匡匡找ACM的小L玩三国杀,但是这会小L忙着哩,不想和匡匡玩但又怕匡匡生气,这时小L给 ...

  7. Mathematics:Semi-prime H-numbers(POJ 3292)

      Semi-prime H-numbers 题目大意,令4n+1的数叫H数,H数素数x的定义是只能被x=1*h(h是H数),其他都叫合数,特别的,当一个数只能被两个H素数乘积得到时,叫H-semi数 ...

  8. oracle两时间相减得到相差的时间

    1.months_between(date1,date2);date1和date2相减得到相差的月份. select months_between(to_date('2015-05-11','yyyy ...

  9. linux vi 中按了ctrl+s后没法退出

    linux vi 中按了ctrl+s后无法退出 Linux 中使用vi编辑文件 不小心按了Ctrl + S (习惯了) 结果终端就跟死了一样, 解决办法: Ctrl+Q

  10. C语言文件操作相关函数

    在实际应用中,我们往往需要对文件进行操作,下面我将介绍C语言的一些关于操作文件的函数. 一.计算机文件 计算机文件是以计算机硬盘为载体存储在计算机上的信息集合,是存储在某种长期储存设备上的一段数据流. ...