认识soui4js(第4篇):定义一个窗口类,响应控件的事件

soui4js基于soui4设计实现。

首先我们看一下soui4中如何定义一个窗口类。

soui4最基本的窗口类是SHostWnd和SHostDialog,它需要一个布局xml。

假定布局xml在资源包中的位置为:layout:maindlg。

那么soui4中定义一个窗口可以是下面的代码(为了演示方便,这里使用SHostDialog):

SHostDialog dlg("layout:maindlg");
dlg.DoModal(NULL);

在soui4js中,这两个对象被导出为soui4.JsHostWnd, soui4.JsHostDialog。

如果不需要处理窗口消息或者事件,可以使用下面的方法来直接创建窗口:

let dlg = new soui4.JsHostDialog("layout:maindlg");
dlg.DoModal(0);

可以看出来,js的代码和C++代码基本上是一样的。

如果需要处理UI中的事件要如何处理呢?

在C++中,最简单的方法是从SHostDialog继承一个新的对象,然后使用消息或者事件映射表来响应窗口消息及控件的事件。

伪代码如下:

class CDemoDialog : public SHostDialog{
public:
CDemoDialog():SHostDialog("layout:maindlg"){}
//.... protected: void OnBtnTest(){ SSLOGI()<<"test button click"; } EVENT_MAP_BEGIN() EVENT_NAME_COMMAND(L"btn_test", OnBtnTest) EVENT_MAP_END() };

EVENT_MAP_BEGIN, EVENT_MAP_END一起构成SHostDialog的事件响应虚函数,从而实现接管事件处理流程。

在js中,用法基本类似:

class OptionDlg extends soui4.JsHostDialog{
    constructor(settings){
        super("layout:maindlg");        
        this.onEvt = this.onEvent;//这一行实现事件处理的接管
    }

        onBtnTest(){
            console.log("test button click");
        }
    onEvent(e){
             //事件处理函数,e是事件对象,可以使用GetID(),Sender()等来获取id及发送者
        let evt_id = e.GetID();
        switch(evt_id){
            case soui4.EVT_CMD:
if(e.NameFrom()=="btn_test")
this.onBtnTest(); break; } } }

这样就完成了窗口中事件的处理。

窗口消息处理也类似,只需要设定JsHostDialog.onMsg就可以接管消息处理。

SOUI中另一种常见的事件响应方法是事件订阅:

例如下面的代码实现订阅表头的子控件checkbox的点击事件:

 1 void CMainDlg::InitListCtrl()
 2 {
 3     //找到列表控件
 4     SListCtrl *pList=FindChildByName2<SListCtrl>(L"lc_test");
 5     if(pList)
 6     {
 7         //列表控件的唯一子控件即为表头控件
 8         SWindow *pHeader=pList->GetWindow(GSW_FIRSTCHILD);
 9         //向表头控件订阅表明点击事件,并把它和OnListHeaderClick函数相连。
10         pHeader->GetEventSet()->subscribeEvent(EVT_HEADER_CLICK,Subscriber(&CMainDlg::OnListHeaderClick,this));
11      }
12 }
13 
14 //表头点击事件处理函数
15 BOOL CMainDlg::OnListHeaderClick(IEvtArgs *pEvtBase)
16 {
17     //事件对象强制转换
18     EventHeaderClick *pEvt =(EventHeaderClick*)pEvtBase;
19     SHeaderCtrl *pHeader=(SHeaderCtrl*)pEvt->Sender();
20     //从表头控件获得列表控件对象
21     SListCtrl *pList= (SListCtrl*)pHeader->GetParent();
22     //列表数据排序
23     SHDITEM hditem;
24     hditem.mask=SHDI_ORDER;
25     pHeader->GetItem(pEvt->iItem,&hditem);
26     pList->SortItems(funCmpare,&hditem.iOrder);
27     return true;
28 }
29 //以上代码来自soui4 demo

soui4js包含了一个SConnect方法,可以方便的订阅一个窗口的事件:

函数原型下下:

/**
 * 将指定IWindow的指定事件对象连接到指定对象的事件处理方法
 * @param pObj IWindow窗口
 * @param evtId 事件类型
 * @param jsThis 处理事件的对象
 * @param jsFun 处理事件的方法
 */
export function SConnect(pObj:IWindow,evtId:number,jsThis:object,jsFun:(evt:IEvtArgs)=>boolean):boolean;

因此在js中可以使用下面的代码来实现事件订阅:

class MainDialog extend soui4.JsHostWnd
{
//...
    init(){
soui4.SConnect(this.GetIRoot(),soui4.EVT_MENU_CMD,this,this.onMenuCmd); } onMenuCmd(e){ let menuCmd = soui4.toEventMenuCmd(e); return true; } //... }

 

具体代码,参考 https://github.com/soui4js-app/somine

posted @ 2023-07-04 10:30  启程软件  阅读(263)  评论(0编辑  收藏  举报