当前位置:文档之家› 手机高通平台BUIW简介

手机高通平台BUIW简介

BUIW Training 01/07 2008Content•预备知识•Dialog框架(历史回顾)•BUIW概述•BUIW基本原理•BUIW的使用(用BUIW构建app的UI)预备知识•高通平台的mmi由许多app组成,每个app可分为logic和ui,app的ui由一系列的界面组成,每个界面由多个界面元素组成,比如一个图标,一个字符串,都是界面元素。

在Dialog体制框架下,一个界面就是一个Dialog,一个或多个相关的界面元素构成一个Control,在BUIW下,它们分别叫做Form和Widget。

预备知识•IDisplay对象类似MFC里的CDC对象,每个app有自己IDisplay对象,重要的函数如下IDISPLAY_DrawText绘制文本IDISPLAY_MeatureTextEx测量文本宽度IDISPLAY_SetColor设置颜色(比如文的前背景色)IDISPLAY_SetClipRect设置剪切区域IDISPLAY_Update更新屏幕IDISPLAY_FillRect以指定颜色填充矩形•IImage对象IImage_Draw绘制图片IImage_SetOffset设置源图的偏移(画源图的一部分)IImage_SetDrawSize设置图的剪切大小画图的一般方法P_img=ISHELL_LoadResImage();IImage_Draw(P_img);IImage_Release(P_img);UI框架就是对上述函数的封装,app程序员可以只用上述函数实现一个app的ui,但工作量很大,不易扩展,维护。

预备知识•三个重要的接口1.IBASE接口IBASE是所有对象的基类,记录对象的引用数量,确定对象的创建和释放uint32 (*AddRef) (iname*); //加引用数量uint32 (*Release) (iname*); //减引用数量2.IQueryInforace接口继承于IBASE,支持接口查询,若查询成功,返回指针,并增加引用计数int(*QueryInterface)(iname*, AEECLSID, void **);//查询接口3.IHandler接口继承于IQueryInforace,具备消息处理机制boolean(*HandleEvent) (iname*,AEEEvent evt,uint16 wParam,uint32 dwParam);void (*SetHandler)(iname*, HandlerDesc*pDesc); //设置消息处理器•用Dialog构建app的UI的大致过程1.用Brew SDK里的Resource Editor新建Dialog,在Dialog里添加几个Control,(只能添加它支持的控件),保存为*.brx,build,生成bar,同时生成brh2.在程序中,调用ISHELL_CreateDialog创建Dialog,并设置Handleboolean wordclock_HandleEvent(wordclock*pMe,AEEEvent eCode,uint16 w,uint32 dw){switch (eCode){case EVT_APP_START:ISHELL_CreateDialog(pMe->a.m_pIShell,WC_RES_FILE, IDD_DIALOG_MAIN, NULL);return(TRUE);case EVT_DIALOG_INIT:IDIALOG_SetEventHandler((IDialog*)dwParam,(PFNAEEEVENT)WorldClockDlgEvtHdrs[wParam-WORLDCLCOK_DLG_BASE],(void *)pMe);IDIALOG_SetProperties((IDialog*)dwParam,DLG_HANDLE_ALL_EVENTS);return TRUE;…………………………….}}3.在Dialog的Handle里用如下办法访问Controlboolean wordclock_DlgHdlMain(wordclock*pMe,AEEEvent evt,uint16 w,uint32 dw) {switch(evt){case EVT_DIALOG_START:pIDialog=ISHELL_GetActiveDialog(pMe->a.m_pIShell);p_ImgCtrl=IDIALOG_GetControl(pIDialog,IDC_MAIN_TEXT);IIMAGECTL_SetRect(p_ImgCtrl,&rc);return TRUE;……………………….}}•Dialog的问题app对dialog的管理没有代码,dialog对Control的管理也没有代码,事件在它们间的传递更没有代码,很多Control也没有代码,由于brew已有的Control无法满足ui的要求,所在venice项目上,自主开发了menu和list,但menu,list没有被Dialog管理,需要app程序员主动调用相应过程来传递事件和重画。

在venice项目上,很多数界面元素都是app程序员调用IDisplay或IImage接口直接画屏,总之,控件化,模块化程序不高,app程序员和组件程序员的职责不清。

因此,在ROMA项目中,我们采用了BUIW框架BUIW概述•什么是BUIWBUIW=BREW user interface widgetBUIW 是一种UI 软件开发包.BUIW 是一种UI 开发框架BUIW能够实现更为复杂UI让UI开发更加容易和具有可扩展性•BUIW的内容Form: 应用程序窗口框架Widget: 可见UI组件框架Theme: UI主题文件工具•BUIW的思想C语言,面向对象的思精神运用多种设计模式,比如类工厂模式,组合模式,修饰模式,观察者模式,MVC模式•BUIW有全部的代码•要解决的问题App对form的管理,form对widget的管理,事件的分发,如何重画BUIW基本原理•几个重要的对象WidgetContainerRootContainerFormRootForm•Widget相关文件:AEEWidget.c WidgetBase.h WidgetBase.cWidget 是窗体上的一个控件,具有一定行为,具有一定外观,保存一定数据,(属性)能响应事件,比较复杂的widget 会采用mvc 的设计模式将一个model, view, controller 三部分,定义如下struct WidgetBase {const AEEVTBL(IWidget) *pvt;//函数表指针,(函数表分配在结构体的末尾,对象创建时初始化表)int nRefs; //引用计数IModule * piModule; //把属的app WExtent extent; //宽高IContainer * piContainer; //所属的容器HandlerDesc hd; //handlePFNHANDLER pfnDefHandler;………………………..};widget 必须属于一个容器并指向它,并没有保存它所隶属的form 的指针只在大小属性extent ,没有坐标属性。

即widget 不知道它自己的位置。

能够处理事件,通常要继承widget 时,用子类的handle 重载父类的handle ,对于某一事件,若子类不处理,默认调用父类的handletypedef struct{int width;int height;} WExtent;接口继承关系:IBase--------IQueryInterface----------IHandler---------IWidgetvoid (*GetPreferredExtent) (iname*, WExtent*pwePreferred); //获得widget的最合适的大小void (*GetExtent) (iname*, WExtent*pWExtent); //获得widget的大小void (*SetExtent) (iname*, WExtent*pWExtent); //设置widget的大小void (*GetParent) (iname*, IContainer**ppwc); //获得父容器void (*SetParent) (iname*, IContainer*pwc); //设置父容器void (*Draw) (iname*, ICanvas*piCanvas, int x, int y);//重画函数,每个widget必须重载boolean(*IntersectOpaque) (iname*, AEERect*prcDest, const AEERect*prcIn);//给出一个prcIn,询问widget是否与其相交,若相交,计算出的相交区域放在prcDest返回int(*GetModel) (iname*, AEECLSID id, IModel**ppm);//获取model(数据)int(*SetModel) (iname*, IModel*pm)//设置数据•ContainerContainer 是可容纳多个widget 的容器,Conainer 用循环队列管这些widget ,widget 在队列中的先后位置就表示在该容器中的叠放次序。

定义如下:struct ContainerBase{……………………..WExtent extent; //大小IContainer * piParent; //父容器IWidget widget;AEEVTBL(IWidget) vtWidget;//支持IWidget 接口的函数表HandlerDesc hd; //handlePFNHANDLER pfnDefHandler;WidgetNode head; //队列的头结尾WidgetNode * pFocus;//焦点widget……………………};只在大小属性extent ,没有坐标属性。

保存一个它所隶属的容器的指针。

有两个函数表,分别支持container 和widgetWidgetnode 里保存了widget 指针了wdiget 的坐标,该坐标是相对于本container ,而不是屏幕struct IWidget {IWidget_Vtbl *pvt, ContainerBase *pMe;};•接口继承关系:IBase--------IQueryInterface----------IHandler---------IWidgetIBase--------IQueryInterface----------IContainervoid (*Invalidate) (iname*, IWidget*pw, const AEERect*prcInWidget, uint32 dwInvalFlags);//申请重画int(*Locate) (iname*, IWidget*pw, IContainer**ppRoot, AEERect*prcRelative);//定位一个widget,返回该widget的区域(相对于整个app的区域)int(*Insert) (iname*, IWidget*pw, IWidget*piwBefore, const void *pDesc);//插入一个widget,插入到piwBefore之前,pDesc通常是插入的x,y坐标int(*Remove) (iname*, IWidget*pw); //移除一个widgetIWidget* (*GetWidget) (iname*, IWidget*pwRef, boolean bNext, boolean bWrap)•Container的双重身份及实现Container具有双重身份,它既是容器,同时也可以表现为widget,可以再被父容器包含,这样就可以组成一棵以rootContainer为根的树,container对form也经常表现为widget。

相关主题