找回密码
 注册会员
更新自动建库工具PCB Footprint Expert 2024.04 Pro / Library Expert 破解版

 Win 程序员如何过度到Symbian 程序员?(二)

[复制链接]
admin 发表于 2012-9-4 17:35:27 | 显示全部楼层 |阅读模式

本文包含原理图、PCB、源代码、封装库、中英文PDF等资源

您需要 登录 才可以下载或查看,没有账号?注册会员

×
 
  5.清洁栈及错误处理。
 
   Symbian操作系统的错误处理框架,主要是清洁栈,是个Windows程序员不太熟悉的元素。就像描述
符一样,它很优雅,Symbian宣布它比 C++语言的异常处理机制有效得多。在一篇叫做《Symbian操作系
统编程术语》的文章里对此进行了很好的讨论,可以从http://licensing.symbian.org得 到。但是,在系统层
次上几乎是一定的“正确的事”却减慢了应用开发。Symbian为需要在有限资源条件下长时间运行的应用
程序设计了这样一个框架,这需 要在开发时间为强壮度付出代价。使用TRY/CATCH这种类型的框架当然
是简单明了受到欢迎的,但是要频繁的在恰当的时候把已某种分配的内存压入和弹出 清洁栈意味着你就
会偶尔犯错误。当发生这种情况时,你就得花费大量的时间去追踪在你的代码中造成的不对称现象。作
为一个对描述符和清洁栈不熟悉的程序员是如何陷入困境的例子,让我们简单的看看一个关于串的示例
:_LIT(KBoilerplate, "Hello there, %S");TPtrC name =
GetPointerIntoNameDescriptorWithoutAllocatingAnyMemory();TPtr finishedProduct = HBufC:
:NewLC(KBoilerplate()。Length() + name.Length())->Des();finishedProduct.Format
(KBoilerplate(), &name);// 下面的就是缺少的一行——见之前的注释// CleanupStack::Pop
();这段代码确实把内存推入了清洁栈,但仅仅是对变量的数据类型一瞥而过你就发现不了这一点。
这是因为我们使用了一 种便利的方法定义了一个TPtr来持有finishedProduct并把HBufC::NewLC(…
…)->Des()的值赋给它。HBufC 是在堆上已分配内存的标识,但是如果我们仅仅看到了左边,可能就
会忽略掉刚一分配我们就使用了Des()的快捷方式这一事实。NewLC也直接把分配的内 存推入清洁栈。
一旦我们完成了finishedProduct,最好调用CleanupStack::Pop(),否则我们的清洁栈就会不平衡
。问题在 于,我们可能起先发现不了这种不平衡,直到它引发错误为止。还有比追踪这种不对称更有趣
的事情呢。
 
  6.应用框架。
 
   Symbian操作系统的确提供了一套用以建立应用程序的类,然而同时,使之能够建立基于非对话框
的应用程序界面的框架代码却非常少。要处理像焦点转移 这种事件只有靠手工。这个例子当然很容易理
解怎样来做,但实际上每个屏幕画面被设计的时候都要仔细考虑它们可是一件费时费力又容易招致错误
的事情。从 Symbian操作系统6.1版开始,Symbian操作系统增加了一个很简单的机制使用惟一的ID号来
实现不同屏幕之间的切换,但是要做的事情还很多。
 
   这里有一个适用于大多数初级情况的例子:这里没有使用API来给屏幕增加一个控制,而是使用了
视图对象中叫做 CountComponentControls和ComponentControl的两个对象,后者必须为从0到前者返回
值之间的每个整数给UI控制返回 一个指针。要添加一个控制,除了构造,调整大小,在恰当地点激活,
你必须在代码里对CountComponentControls的返回值进行累加,还要 在ComponentControl函数中给
switch语句添加一个case. Symbian操作系统确实提供了根据资源文件建立对话框的完美合理的途径。当
你在资源文件里声明对话框时,你不必直接对这些东西寻址。但是由于对话框只 允许在一个竖列中布置
控制,对于一些高级的应用程序中复杂的屏幕设置来说可能并不适合。
 
  7.窗口问题。
 
   Symbian操作系统不鼓励使用“自有窗口”控制。这就是说,一个控制并不总是持有自已的窗口(
从受按Z轴顺序裁剪的窗口系统控制的图形对象意义上来 说)。因为这些对象使用了系统资源,应用程
序应该简单的执行一个合适的绘画功能来规定它所在矩形的边界。这对于习惯每个控制有一个真正窗口
的开发者来说可 能感觉不同,但是掌握这一点并不困难。
 
  虽然Symbian操作系统的标准UI控制集十分丰富而且强壮,但是偶尔也会有误操作的情况 发生。比
如我们已经有了一个带滚动条的编辑框,现在要能够暂时用另外一个控制取代它。仅仅使编辑框不可见
并不能解决问题。编辑框的某些内容,包括滚动条, 仍然以多种有趣但不可接受的方式存在着。我们认
为这可能应该归咎于前面提到的编辑框的复杂的对象结构;看起来在这种分布式结构中要想进行隐藏可
不是无关紧 要的问题。我们最后是通过在画面以外重新定位它解决的。
 
  用这种方法,我们探究了一些其它的可能性,还研究了像控制栈以及 Symbian称之为弹出窗口的东
西,以后这可以使你按下按钮激活弹出选择列表时顺手拈来。这里进行了示范:iPopout = new
(ELeave) CEikColumnListBox;iPopout->ConstructL(NULL,CEikListBox::EPopout);iPopout
->CreateScrollBarFrameL();iPopout->ScrollBarFrame()->SetScrollBarVisibilityL
(CEikScrollBarFrame::EOff,CEikScrollBarFrame::EAuto);iPopout->SetObserver(this);
TSize popoutSize = TSize(width, height);TPoint popoutOrigin = TPoint(topLeft,
bottomRight);iPopout->Model()->SetItemTextArray(iArray);iPopout->Model()-
>SetOwnershipType(ELbmDoesNotOwnItemArray);iPopout->ItemDrawer()->ColumnData()->
SetColumnWidthPixelL(0, firstColWidth);iPopout->ItemDrawer()->ColumnData()->
SetColumnWidthPixelL(1, secondColWidth);iPopout->SetExtent(popoutOrigin, popoutSize)
;iPopout->SetCurrentItemIndex(0);iEikonEnv->AddDialogLikeControlToStackL(iPopout);
iPopout->ActivateL();iPopout->DrawNow(); 一种很早也很有趣的学习经验是必须手工书写代码
来刷新和显示列表框的内容。刷屏代码很复杂,而且要跟踪所有的插入和删除并不是一件轻而易举的事
。无论什么 样的刷新率,我们都希望代码可以在刷新过程的最后得到正确显示的结果而不管刷新了什么
,还不能丢掉滚动条的位置和选区,也不能产生不必要的闪屏和闪烁感。 Symbian操作系统在基础列表
框类中提供了叫做HandleItemRemovalL和HandleItemAdditionL的功能。另外还有设置 当前项的
SetCurrentItemIndex.但是在Symbian操作系统第5版中没有关于这些函数如何工作的文档。我们只能通
过研究源代码才知道 HandleItemAdditionL隐式使用了DrawNow,但是HandleItemRemovalL不负责重绘。
被 HandleItemRemovalL所调用的Reset也不得不通过源代码来理解,当前项索引在调用
HandleItemRemovalL后需要刷新。 这种处理重绘的不对称性看起来很奇怪又带有很多潜在问题。但是有
个好消息就是在目前的Symbian操作系统文档中,所有这些都清楚明白的被收录在你能找 到的地方。
 
  作为前面被我们一带而过的Symbian的其它方面,在图形领域,为了使系统的总开销尽可能低,有些
应用程序的代码开销 也被考虑在内。Symbian确确实实提供的特性是优雅和绝大多数情况下的一致性,
而且现在在文档方面已经做得很好了,他使创建平滑的图形动作变得相对简 单。
 
  8.消息,异步服务和活动对象。
 
  MFC在对无论是初级还是了解驱动他们应用程序的消息循环和调度机制的高级程序员隐藏Windows消
息范例方面做得很好。在Symbian操作系统中,驱动应用程序的是一套完全不同又十分强大的机制,被称
为活动对象。它与Symbian操作系统的客户端-服务器端结构紧密结合,提供了各种系统服务,同时也可
以为程序员所使用来给他们可能需要为应用程序创建的任何异步服务建立干净、标准的接口。
 
   简而言之,CActiveScheduler执行了Windows消息循环,在一个给定线程内提供了共用的多任务,
CActive(一个活动对象)充当 了消息处理者。在Symbian的UI框架中,这要比MFC把消息隐藏得更好:
接收到的消息总是由框架调度给预先定义的可以被应用程序重载的方法——比如 OfferKeyEventL(处理
键盘输入)。
 
  定时器是使用了活动对象框架的简单系统服务的一个实例。不同于Windows中调 用StartTimer来触
发WM_TIMER消息的做法,Symbian操作系统中是由一个CTimer对象与系统时钟服务进行交互,RTimer与其
RunL函数根据由API规定的时间间隔被调用。程序员从CTimer继承到一个对象,并重载RunL方法。其它的
异步系统服务,如Nokia 7650上的照相机功能也是通过类似方法提供的。CCameraManager定义了一个活
动对象提出拍照操作的请求并随即获得通知。实际的异步服务是由RCameraServ提供的,但是典型的程序
员根本用不着处理任何客户端-服务器端或者显式的进程间通信问题。
 
   使用活动对象时,头脑中时刻牢记活动对象何时按预定计划执行这个很简单的准则非常重要。这就
是说,到底什么时候CActiveScheduler会调用 一个CActive对象的RunL方法呢?。CActive对象必需是“
活动”的。这是通过调用Cactive::SetActive实现的,通常在活动 对象自己对应用程序某个请求做出
的响应中完成。。CActive对象的状态,由成员变量iStatus所示,一定不能为KRequestPending. 这个值
表示该对象正在等待服务完成。通常在提出一个服务请求时变量iStatus才会被服务提供者设为
KRequestPending.iStatus随 后在服务结束时被服务者提供者更新。。CActiveScheduler需要接收到一
个信号——该信号由异步服务在结束时发出。
 
  当 异步进程对应用程序发出结束信号,然而没有准备好的CActive对象时,就会产生一个“迷失”
信号。这在以下几种情况下可能发生:。你忘记了使用 CActive::SetActive使活动对象处于“活动”
状态。。服务提供者在发出操作完成信号时忘记将iStatus置为非 KRequestPending的值。这只会在你写
了错误的服务提供者时出现——典型的应用程序会使用系统定义的服务。。服务提供者给同一个操作发
出了不 只一个终止信号。
 
 楼主| admin 发表于 2012-9-4 17:35:32 | 显示全部楼层
  第三种情况在服务提供者设计不够仔细的情况下可能发生。例如,有一个服务已经结束并且对客户
端通知了这一事实,但 是客户端恰恰在收到这个通知之前发出了取消服务的请求。服务提供者必需忽略
这一当前不合理的请求。要是服务提供者没有忽略这一请求,而是对它做出响应并给 出一个附加信号说
已经结束了,会是怎么样呢?在这种情况中,附加的信号最终就会成为“迷失”信号,并会引起程序出
错。这对于纠错来说很困难,因为“迷失” 信号是被CActiveScheduler检测到的,没有显示是什么
CActive对象的责任。
 
  CActive对象必需确保在各种 情况下与服务相关联的终止信号都恰当。在解除程序中应该典型的具
有一个CActive::Cancel调用。如果Cancel没有被调用,而对象在有请求 仍被挂起时就被删除,错误
就会发生。而且,每个CActive对象必需以确保任何由该对象请求的服务都被取消的方式执行 CActive:
:DoCancel,否则CActive::Cancel就会一直等待服务提供者的终止信号。这两种错误都很难被检测到
,因为它们只在存 在明显的请求时才会被发现。
 
  结束语我们希望本文对Windows程序员开始Symbian操作系统下的工作能提供值得的期待和有用帮助
。我们期望看到随着这片新市场的成长未来的Symbian操作系统及相关的编程范例是如何发展的。
本文章来自中国IT实验室http://embed.chinaitlab.com/
*滑块验证:
您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

QQ|手机版|MCU资讯论坛 ( 京ICP备18035221号-2 )|网站地图

GMT+8, 2024-12-23 17:58 , Processed in 0.060634 second(s), 11 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表