﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-一针见血-文章分类-S60</title><link>http://www.cppblog.com/gtwdaizi/category/5209.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 30 Oct 2008 05:02:35 GMT</lastBuildDate><pubDate>Thu, 30 Oct 2008 05:02:35 GMT</pubDate><ttl>60</ttl><item><title>[S60] S60中Socket Api的调用方法[转载]</title><link>http://www.cppblog.com/gtwdaizi/articles/57505.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Wed, 30 Jul 2008 05:33:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/57505.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/57505.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/57505.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/57505.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/57505.html</trackback:ping><description><![CDATA[<dl>
<dt>翻译说明
<dd>本文翻译自英文Wiki部分的<a title="Using the sockets API" href="http://wiki.forum.nokia.com/index.php/Using_the_sockets_API"><u><font color=#0000ff>Using the sockets API</font></u></a>，因为原文较长，所以我将一部分一部分地翻译，同时欢迎大家帮助我一起完成这个任务，并且对我已经翻译的内容作修改和指正。 </dd></dl>
<table class=toc id=toc summary=Contents>
    <tbody>
        <tr>
            <td>
            <div id=toctitle>
            <h2>Contents</h2>
            <span class=toctoggle>[<a class=internal id=togglelink href="javascript:toggleToc()"><u><font color=#0000ff>hide</font></u></a>]</span></div>
            <ul>
                <li class=toclevel-1><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E7.AE.80.E4.BB.8B"><u><font color=#0000ff><span class=tocnumber>1</span> <span class=toctext>简介</span></font></u></a>
                <li class=toclevel-1><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E6.9C.89.E5.85.B3Socket.E7.9A.84.E6.9C.8D.E5.8A.A1.E6.9E.84.E6.9E.B6"><u><font color=#0000ff><span class=tocnumber>2</span> <span class=toctext>有关Socket的服务构架</span></font></u></a>
                <ul>
                    <li class=toclevel-2><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E4.BB.80.E4.B9.88.E6.98.AFsocket.3F"><u><font color=#0000ff><span class=tocnumber>2.1</span> <span class=toctext>什么是socket?</span></font></u></a>
                    <li class=toclevel-2><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E5.8D.8F.E8.AE.AE.E6.A8.A1.E5.9D.97"><u><font color=#0000ff><span class=tocnumber>2.2</span> <span class=toctext>协议模块</span></font></u></a>
                    <li class=toclevel-2><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E4.BC.A0.E8.BE.93.E7.9A.84.E7.8B.AC.E7.AB.8B.E6.80.A7"><u><font color=#0000ff><span class=tocnumber>2.3</span> <span class=toctext>传输的独立性</span></font></u></a>
                    <li class=toclevel-2><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E2.80.9C.E5.AE.A2.E6.88.B7.E7.AB.AF-.E6.9C.8D.E5.8A.A1.E5.99.A8.E2.80.9D.E6.8E.A5.E5.8F.A3"><u><font color=#0000ff><span class=tocnumber>2.4</span> <span class=toctext>&#8220;客户端-服务器&#8221;接口</span></font></u></a> </li>
                </ul>
                <li class=toclevel-1><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#sockets.E6.9C.8D.E5.8A.A1.E5.99.A8.E7.9A.84.E4.B8.BB.E8.A6.81.E7.B1.BB"><u><font color=#0000ff><span class=tocnumber>3</span> <span class=toctext>sockets服务器的主要类</span></font></u></a>
                <li class=toclevel-1><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E4.BD.BF.E7.94.A8RSocketServ.E7.B1.BB"><u><font color=#0000ff><span class=tocnumber>4</span> <span class=toctext>使用RSocketServ类</span></font></u></a>
                <ul>
                    <li class=toclevel-2><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E5.BB.BA.E7.AB.8B.E4.B8.80.E4.B8.AA.E8.BF.9E.E6.8E.A5.E5.88.B0sockets.E6.9C.8D.E5.8A.A1.E7.9A.84.E4.BC.9A.E8.AF.9D"><u><font color=#0000ff><span class=tocnumber>4.1</span> <span class=toctext>建立一个连接到sockets服务的会话</span></font></u></a>
                    <li class=toclevel-2><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E9.A2.84.E8.BD.BD.E5.85.A5.E5.8D.8F.E8.AE.AE.E6.A8.A1.E5.9D.97"><u><font color=#0000ff><span class=tocnumber>4.2</span> <span class=toctext>预载入协议模块</span></font></u></a> </li>
                </ul>
                <li class=toclevel-1><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E4.BD.BF.E7.94.A8RSocket.E7.B1.BB"><u><font color=#0000ff><span class=tocnumber>5</span> <span class=toctext>使用RSocket类</span></font></u></a>
                <li class=toclevel-1><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E4.B8.BB.E6.9C.BA.E8.A7.A3.E6.9E.90.E6.9C.8D.E5.8A.A1"><u><font color=#0000ff><span class=tocnumber>6</span> <span class=toctext>主机解析服务</span></font></u></a>
                <ul>
                    <li class=toclevel-2><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E4.BB.80.E4.B9.88.E6.98.AF.E4.B8.BB.E6.9C.BA.E8.A7.A3.E6.9E.90.3F"><u><font color=#0000ff><span class=tocnumber>6.1</span> <span class=toctext>什么是主机解析?</span></font></u></a>
                    <li class=toclevel-2><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E4.BD.BF.E7.94.A8RHostResolver.E7.B1.BB"><u><font color=#0000ff><span class=tocnumber>6.2</span> <span class=toctext>使用RHostResolver类</span></font></u></a>
                    <li class=toclevel-2><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E5.9F.9F.E5.90.8D.E6.9C.8D.E5.8A.A1.28DNS.29"><u><font color=#0000ff><span class=tocnumber>6.3</span> <span class=toctext>域名服务(DNS)</span></font></u></a> </li>
                </ul>
                <li class=toclevel-1><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E5.9C.A8socket.E4.BB.A3.E7.A0.81.E4.B8.AD.E4.BD.BF.E7.94.A8.E6.B4.BB.E5.8A.A8.E5.AF.B9.E8.B1.A1.EF.BC.88active_objects.EF.BC.89"><u><font color=#0000ff><span class=tocnumber>7</span> <span class=toctext>在socket代码中使用活动对象（active objects）</span></font></u></a>
                <li class=toclevel-1><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E4.BB.A3.E7.A0.81.E7.A4.BA.E4.BE.8B:_.E8.BF.9E.E6.8E.A5sockets"><u><font color=#0000ff><span class=tocnumber>8</span> <span class=toctext>代码示例: 连接sockets</span></font></u></a>
                <ul>
                    <li class=toclevel-2><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E6.9C.8D.E5.8A.A1.E2.80.98.E7.9B.91.E5.90.AC.E2.80.99.E7.B1.BB.E7.9A.84.E5.AE.9A.E4.B9.89"><u><font color=#0000ff><span class=tocnumber>8.1</span> <span class=toctext>服务&#8216;监听&#8217;类的定义</span></font></u></a>
                    <li class=toclevel-2><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E5.81.9A.E5.A5.BD.E6.8E.A5.E6.94.B6.E5.AE.A2.E6.88.B7.E7.AB.AF.E8.BF.9E.E6.8E.A5.E7.9A.84.E5.87.86.E5.A4.87"><u><font color=#0000ff><span class=tocnumber>8.2</span> <span class=toctext>做好接收客户端连接的准备</span></font></u></a>
                    <li class=toclevel-2><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E5.A4.84.E7.90.86.E8.BF.9E.E6.8E.A5.E8.AF.B7.E6.B1.82"><u><font color=#0000ff><span class=tocnumber>8.3</span> <span class=toctext>处理连接请求</span></font></u></a>
                    <li class=toclevel-2><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E4.BD.BF.E7.94.A8.E6.9C.89.E8.BF.9E.E6.8E.A5.E7.9A.84socket"><u><font color=#0000ff><span class=tocnumber>8.4</span> <span class=toctext>使用有连接的socket</span></font></u></a> </li>
                </ul>
                <li class=toclevel-1><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E4.BC.A0.E8.BE.93.E6.95.B0.E6.8D.AE"><u><font color=#0000ff><span class=tocnumber>9</span> <span class=toctext>传输数据</span></font></u></a>
                <ul>
                    <li class=toclevel-2><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E6.8E.A5.E6.94.B6.E6.95.B0.E6.8D.AE"><u><font color=#0000ff><span class=tocnumber>9.1</span> <span class=toctext>接收数据</span></font></u></a>
                    <ul>
                        <li class=toclevel-3><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E4.BD.BF.E7.94.A8.E6.97.A0.E8.BF.9E.E6.8E.A5.E7.9A.84sockets"><u><font color=#0000ff><span class=tocnumber>9.1.1</span> <span class=toctext>使用无连接的sockets</span></font></u></a>
                        <li class=toclevel-3><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E4.BD.BF.E7.94.A8.E8.BF.9E.E6.8E.A5.E7.9A.84sockets"><u><font color=#0000ff><span class=tocnumber>9.1.2</span> <span class=toctext>使用连接的sockets</span></font></u></a> </li>
                    </ul>
                    <li class=toclevel-2><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E5.8F.91.E9.80.81.E6.95.B0.E6.8D.AE"><u><font color=#0000ff><span class=tocnumber>9.2</span> <span class=toctext>发送数据</span></font></u></a>
                    <ul>
                        <li class=toclevel-3><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E4.BD.BF.E7.94.A8.E6.9C.AA.E8.BF.9E.E6.8E.A5.E7.9A.84sockets"><u><font color=#0000ff><span class=tocnumber>9.2.1</span> <span class=toctext>使用未连接的sockets</span></font></u></a>
                        <li class=toclevel-3><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E4.BD.BF.E7.94.A8.E8.BF.9E.E6.8E.A5.E7.9A.84sockets_2"><u><font color=#0000ff><span class=tocnumber>9.2.2</span> <span class=toctext>使用连接的sockets</span></font></u></a> </li>
                    </ul>
                    </li>
                </ul>
                <li class=toclevel-1><a href="http://wiki.forum.nokia.com/index.php?title=%E4%BD%BF%E7%94%A8Socket_API&amp;diff=cur&amp;oldid=2318#.E6.80.BB.E7.BB.93"><u><font color=#0000ff><span class=tocnumber>10</span> <span class=toctext>总结</span></font></u></a> </li>
            </ul>
            <ul></ul>
                <ul></ul>
                    </td>
                </tr>
            </tbody>
        </table>
        <script type=text/javascript> if (window.showTocToggle) { var tocShowText = "show"; var tocHideText = "hide"; showTocToggle(); } </script>
        <a name=.E7.AE.80.E4.BB.8B></a>
        <h2><span class=mw-headline>简介 </span></h2>
        <p>通过这篇文章我们想为大家带来一些Symbian操作系统的有关sockets API的基本介绍。 本文的读者应该是希望在他们的应用程序中增添socket通信功能的Symbian操作系统的开发者，本文不仅提供了理论介绍，同样给出了可供实践参考的代码范例。 </p>
        <p>本文包含的内容有: </p>
        <ul>
            <li>概括介绍了有关socket通信的有关组件。
            <li>概括介绍了socket服务架构以及使用两个主要API类<em>RSocketServ</em>和<em>RSocket</em>的使用。
            <li>讨论了创建两个终端之间进行通信的过程。
            <li>讨论了socket之间通信的不同模式：基于一串数据流的模式以及基于离散消息的模式。
            <li>一个如何使用活动对象来进行socket连接的实践范例。 </li>
        </ul>
        <a name=.E6.9C.89.E5.85.B3Socket.E7.9A.84.E6.9C.8D.E5.8A.A1.E6.9E.84.E6.9E.B6></a>
        <h2><span class=mw-headline>有关Socket的服务构架 </span></h2>
        <p>本文的一个内容是介绍给大家如何将基于Socket服务的通信功能加入到应用程序中来。尽管如此，计算机通信系统乃是一个十分复杂的系统，本文介绍的基于socket服务的通信仍然是在一个相对比较高级的层次，没有深入底层探讨的话题和技术。要想让socket服务来发挥作用，许多底层支持软件将是必须的。 </p>
        <p>下图说明了socket服务组件在Symbian系统的通信子系统中的哪一层位置，扮演如何一个角色。 </p>
        <p><a class=image title=Image:CommsComponents_CN.gif href="http://wiki.forum.nokia.com/index.php/Image:CommsComponents_CN.gif"><img height=206 alt=Image:CommsComponents_CN.gif src="http://wiki.forum.nokia.com/images/0/00/CommsComponents_CN.gif" width=507 border=0></a> </p>
        <p><em><strong>Symbian OS通信系统组件</strong></em> </p>
        <p>首先我们来考虑传输层协议。上图的Internet互联网协议和红外协议，从Symbian 6.0之后支持的蓝牙&#174;无线通讯技术以及都在这一层中。 </p>
        <p>当我们谈到Internet协议时，我们其实包括了一个隐式的依赖动作，那就是向ISP（互联网服务提供商）进行拨号连接。因此，如图所示我们可以看到Symbian系统提供了拨号网络接入组件。而在本图中，最重要的的系统组件是电话通信服务组件。 </p>
        <p>最终，我们需要设计到一个硬件设备，有了硬件我们才可以在选定的网络环境中接收和发送数据。上图的核心部分就是使用Internet协议的拨号接入网络，并且显示了串行通信组件在整个通信系统扮演了如何的角色。串行通信服务组件通过特定的硬件设备驱动，完成了硬件设备与它周围环境的通信。 </p>
        <p><br></p>
        <a name=.E4.BB.80.E4.B9.88.E6.98.AFsocket.3F></a>
        <h3><span class=mw-headline>什么是socket? </span></h3>
        <p>那么什么是socket呢? 用一句引自伯克利（Berkeley）UNIX关于socket实现的经典定义来回答就是&#8220;socket就是通信终端&#8221;。 </p>
        <p>那究竟是什么意思呢? </p>
        <p>一个socket代表了一条通信&#8216;通道&#8217;逻辑上的终端。而实际上讲，socket是物理网络地址和逻辑端口号的一个集合，而这个集合可以向另外一个位置的与他具有相同定义的socket进行数据传输。 </p>
        <p>因为socket是由机器地址和端口号来区分/识别的，那么在一个特定的计算机网络上，每一个socket都是以此方式被唯一识别的。这就使得应用程序可以唯一地去定位网络上的另外一个位置的socket。 </p>
        <p>注意：对于同一台机器上的两个socket，他们是完全具备彼此间进行通信的可能的；在这种情况下，两个socket具有相同的主机地址，但是他们拥有不同的端口号。 </p>
        <p>主机地址和端口号的组合，对于不同协议是不同的。在socket的经典应用中，网络通信使用的是IP（Internet Protocol）协议，但是实际上socket是支持很多其它协议的，对于这方面的信息稍后会提到。 </p>
        <p>正如我们将会看到的，不管我们选择怎样的通信协议（传输层），我们都可以使用同一种已成熟的socket API来实现通信。 </p>
        <a name=.E5.8D.8F.E8.AE.AE.E6.A8.A1.E5.9D.97></a>
        <h3><span class=mw-headline>协议模块 </span></h3>
        <p>如上文所述，socket的经典应用是在TCP/IP协议的计算机网络上，使两个逻辑端点之间展开通信活动。最著名的应用TCP/IP的计算机网络，当然就是Internet了。 </p>
        <p>绝大多数socket系统的实现都限定在了TCP/IP网络的通信上。 </p>
        <p>但是，Symbian系统的socket服务组件，就实现了更多的内容；不仅如此，它还为其他组件提供了支持模块插件协议的基础构架。这就使得Symbian公司和它的开发伙伴们大大延长了socket服务组件以及支持socket的应用程序的应用时间。 </p>
        <p>由于新协议和传输层的引入，支持了新的传输&#8216;语言&#8217;或协议的协议组件，从而使得socket服务组件可以随之适应新的应用环境。 </p>
        <p>随着Symbian系统第五版的socket服务组件支持了TCP/IP和红外协议的稽核。在Symbian 6.0版的时候，就增加了蓝牙&#174;无线技术和短信息服务插件。 </p>
        <p>协议模块其实就是标准的Symbian系统动态链接库（DLL）。他们都有共同的UID2--KUidProtocolModule(0x1000004A)来表示他们的类型，并且拥有特殊的扩展名*.PRT。 </p>
        <p>一个关于经典系统的方面，就是socket服务对PLP（Psion Link Protocol）协议也是支持的。PLP被用来进行Symbian系统的手机和运行Microsoft Windows的台式或笔记本计算机之间进行通信。PLP的一个应用就是Symbian Connnect - 目前的被用于名为&#8216;PsiWin&#8217;的Psion计算机。 </p>
        <p>socket服务组件可以以两种方式加载协议模块： </p>
        <ul>
            <li>最通常的做法就是，协议模块会在第一个使用该协议的socket被打开的时候进行加载。
            <li>另外一种做法是，应用程序可以显式地加载协议模块。这种做法的一个好处就在于，当协议加载需要一个比较长的时间的时候，应用程序或用户可以得到相应的提示。使用这种方法调用的API在本文的后面将会进行讨论。 </li>
        </ul>
        <p>要说明的几点：一个协议模块可以包含多种协议实现。比如，在TCPIP.PRT模块中，就包含了UDP、TCP、ICMP、IP以及DNS协议的实现。单个协议的实现可以通过位于\system\data\.的.esk文件进行映射。而每个协议模块都有一个.esk文件来指定该模块所包含的协议，以及每个协议在插件模块中所处的索引位置。 </p>
        <a name=.E4.BC.A0.E8.BE.93.E7.9A.84.E7.8B.AC.E7.AB.8B.E6.80.A7></a>
        <h3><span class=mw-headline>传输的独立性 </span></h3>
        <p>上文已经提到，socket服务组件的插件架构特性可以使得新的协议模块在任何时间被安装到一部Symbian系统的手机当中。 </p>
        <p>这个架构可以使得socket服务组件来实现独立传输层的概念。借助于提供一个通用的核心socket API接口，这种架构就可以处理所有一般性数据传输系统的需求，并且通过添加特定协议的协议模块，socket服务组件就可以被广大应用程序开发者来给自己的产品增添通信功能，从而省下了大量的开发通信子系统的时间。 </p>
        <p>随着时间的发展，新的协议逐步登上历史舞台，协议模块都将会为了适应socket接口而被重写。而应用程序开发者，他们只需要增添协议新近引入的属性或者动作，来支持新的协议即可，Socket服务组件便会使用新的协议，借助操作系统底层的通信组件，来完成通信机制，而并不会影响到上层应用程序开发者的接口和开发。 </p>
        <p>总而言之，socket服务组件可以让应用程序开发者在仅仅维护一套核心API接口的情况下，可以借助操作系统的通信子系统来使用多个协议，从而减少了自己的开发工作量以及开发时间。 </p>
        <a name=.E2.80.9C.E5.AE.A2.E6.88.B7.E7.AB.AF-.E6.9C.8D.E5.8A.A1.E5.99.A8.E2.80.9D.E6.8E.A5.E5.8F.A3></a>
        <h3><span class=mw-headline>&#8220;客户端-服务器&#8221;接口 </span></h3>
        <p>Symbian系统的一个特点就是它具有一个体积很小的微内核（micro-kernel），因此我们只能把必须和硬件设备交互以及进行主机控制的核心服务放在内核端运行。而另外许许多多的系统服务只能以用户模式的服务器线程的形式运行，通常被称为&#8216;系统服务器&#8217;。 </p>
        <p>socket服务组件就是这些&#8216;系统服务器&#8217;中的一个，第三方应用程序就借助公开的客户端API，通过该组件完成通信功能。其中最重要的四个类为： </p>
        <p><br></p>
        <ul>
            <li><strong>RSocketServer</strong>: 这个类是用来建立和socket服务组件之间的连接以及获取必要的资源的。在客户端-服务器架构的定义中，该类表示了应用程序与socket服务组件之间建立连接的会话。所有的其他客户端接口类，在使用中都需要一个被打开的本类的实例来进行操作。 </li>
        </ul>
        <ul>
            <li><strong>RSocket</strong>: 这个类表示了一个socket连接。一个标准的应用程序可能会在不同时间的时候，拥有若干个RSocket的实例在同时进行操作。 </li>
        </ul>
        <ul>
            <li><strong>RHostResolver</strong>: 这个类用来提供主机名称解析服务的接口。 </li>
        </ul>
        <ul>
            <li><strong>RNetDatabase</strong>: 这个类用来提供网络数据库访问的接口。 </li>
        </ul>
        <p><em>RSocket, RHostResolver &amp; RNetDatabase</em> 均表示了一个给定的应用程序与socket服务组件之间进行的会话下的子会话，而应用程序与socket服务组件之间的会话就是一个<em>RSocketServer</em>的实例。 </p>
        <a name=sockets.E6.9C.8D.E5.8A.A1.E5.99.A8.E7.9A.84.E4.B8.BB.E8.A6.81.E7.B1.BB></a>
        <h2><span class=mw-headline>sockets服务器的主要类 </span></h2>
        <p>socket服务组件提供了两个主类，供他的客户端访问内部的API。 </p>
        <ul>
            <li><strong>RSocketServ</strong>: 在每个应用程序线程中，只要需要连接socket请求，他就必须使用一个本类的实例，来为其他连接（会话）提供socket服务。 </li>
        </ul>
        <ul>
            <li><strong>RSocket</strong>: 每一个需要使用socket的应用程序线程，同样也需要一个或多个<em>RSocket</em>对象，这些对象就是子会话了。 </li>
        </ul>
        <p>下面的两个部分将会介绍会话和子会话类（<em>RSocketServ 和 RSocket</em>）的详细内容。 </p>
        <a name=.E4.BD.BF.E7.94.A8RSocketServ.E7.B1.BB></a>
        <h2><span class=mw-headline>使用RSocketServ类 </span></h2>
        <p>RSocketServ类扮演了一个十分重要的角色，因为它是客户端应用程序与socket服务组建之间的连接会话。 </p>
        <p>但是，客户端应用程序并不直接使用这个类来进行数据的发送和接收，或者创建一个远程通信端点；要完成这些任务的话，使用的是RSocket类，这个类将会在稍后进行介绍。 </p>
        <p>RSocketServ可以让客户端应用程序来向socket服务组件发起一些查询，查询的内容包括服务器支持的协议个数以及支持哪些协议，每个支持协议的具体信息等等。 </p>
        <p>希望使用socket的客户端应用程序，都将需要自己创建一个RSocketServ类的实例对象，用这个对象来表示该客户端应用程序和socket服务之间的会话。每一个独立的socket连接，都是一个独立的RSocket类的实例对象。可以说，在一个客户端应用程序中，该程序的RSocketServ类对象就是所有的RSocket类对象的容器。 </p>
        <p>RSocketServ类的两个常用函数就是Connect()和StandardProtocol()。 </p>
        <p><br></p>
        <a name=.E5.BB.BA.E7.AB.8B.E4.B8.80.E4.B8.AA.E8.BF.9E.E6.8E.A5.E5.88.B0sockets.E6.9C.8D.E5.8A.A1.E7.9A.84.E4.BC.9A.E8.AF.9D></a>
        <h3><span class=mw-headline>建立一个连接到sockets服务的会话 </span></h3>
        <p>使用Connect()方法，应用程序就可以建立与socket服务之间的一个会话。它仅仅使用一个参数--该会话所提供的消息通道的个数。 </p>
        <pre> TInt Connect (TUint aMessageSlots); </pre>
        <p>消息数参数被用来限定应用程序向socket服务所同时并发的异步操作的请求通道数。每一个同步请求都将占用一个消息通道，并且请求准备中的异步操作也将占用一个消息通道。 </p>
        <p>一个普通socket进行的读写通信操作，都是异步进行的，也就是说这样的操作要占用两个消息通道。如果socket也可以进行同步操作的话，那么我们其实并不需要指定过多的消息通道，因为同步操作的消息通道是由socket客户端-服务器框架来完成的。对于你的应用程序在同一个时间内会使用到多少个消息通道，这完全是由你来断定的，而在大多数情况下，我们要尽可能的减少同时请求的消息通道数。 </p>
        <p>如果我们不指定任何特定的值，那么系统会使用一个默认值作为消息通道个数的参数：KESockDefaultMessageSlots (0x08)。 </p>
        <a name=.E9.A2.84.E8.BD.BD.E5.85.A5.E5.8D.8F.E8.AE.AE.E6.A8.A1.E5.9D.97></a>
        <h3><span class=mw-headline>预载入协议模块 </span></h3>
        <p>socket服务组件载入协议协议模块的动作是动态进行的，当针对某一个协议的第一个socket被创建的时候，该协议模块在此时才会被载入。尽管如此，载入协议仍然是一件比较费时的操作，RSocketServ提供了一个StartProtocol()函数，来进行协议模块的预载入操作，调用该函数可以在socket连接请求的时候节省载入协议模块的时间。 </p>
        <p>如果你的应用程序需要在程序启动之初就载入协议模块，而并非需要连接的时候才进行载入，那么可以使用下面的函数范例来调用StartProtocol()方法： </p>
        <pre>    void StartProtocol (TUint aFamily, TUint aSockType,
        TUint aProtocol, TRequestStatus&amp; aStatus);
        </pre>
        <p>StartProtocol()函数的参数有：协议族(例如,KAfInet)，使用该协议的socket类型(例如,KSockStream)，协议族中的协议标示(例如,KProtocolInetTcp)，最后一个参数是异步调用的完成状态参数。这些参数的意义将会在下面做以简短介绍。 </p>
        <p>请注意，尽管StartProtocol()函数是一个异步服务，但是它却是一个在操作过程中不能被取消的操作。 </p>
        <a name=.E4.BD.BF.E7.94.A8RSocket.E7.B1.BB></a>
        <h2><span class=mw-headline>使用RSocket类 </span></h2>
        <p>RSocket代表了应用程序的一个socket连接，在一个应用程序中，每一个socket连接都是一个单独的RSocket的实例。事实上，客户端应用程序的代码中使用更多的是RSocket类而并不是RSocketServ类。 </p>
        <p>RSocket是一个提供了许许多多服务的体积庞大的类，这些服务包括： </p>
        <ul>
            <li>连接到服务，无论作为客户端还是服务端
            <li>设置或者查询自己的地址，或者查询远程地址
            <li>从socket读取数据
            <li>向socket写入数据
            <li>其他更多... </li>
        </ul>
        <p>在打开任何socket之前，我们必须有一个激活了的RSocketServ会话。并且，在上述提到的任何服务进行操作之前，我们要确保socket是打开的。作为打开一个socket的一部分，RSocket这个子回话对象（见上文说明）需要同一个socket服务器进行连接，这个服务器就是一个RScoketServ类的实例。 </p>
        <p>下面的章节介绍了RSocket的各种函数，有了这些函数的介绍和帮助我们就可以写出基于socket通信的应用程序来。 </p>
        <a name=.E4.B8.BB.E6.9C.BA.E8.A7.A3.E6.9E.90.E6.9C.8D.E5.8A.A1></a>
        <h2><span class=mw-headline>主机解析服务 </span></h2>
        <a name=.E4.BB.80.E4.B9.88.E6.98.AF.E4.B8.BB.E6.9C.BA.E8.A7.A3.E6.9E.90.3F></a>
        <h3><span class=mw-headline>什么是主机解析? </span></h3>
        <p>在一个由计算机组成的网络里，独立的主机使用不同的地址格式来判断各自是谁，是什么。 </p>
        <p>例如，你的电子邮件有可能保存在一台主机当中，这台主机可能有一个可读的地址，比如pop3.freeserve.net。这个地址尽管对人来说是可读的、是一个具有一定意义的地址，但是对于网络上的计算机来说，并没有任何直接的用处。 </p>
        <p>当你的邮件客户端程序尝试下载你可能会收到的电子邮件的时候，你的电脑就会使用你的电子邮件服务器的地址（先前举例的pop3.freeserve.net）去进行查询，将他们相对应的数字网络地址查询出来。当获得了机器可读的数字网络地址，应用程序才可能建立起连接。在TCP/IP协议族中，地址解析转换是由域名解析服务（Domain Name Service, DNS）进行的。 </p>
        <p>地址解析服务的用处有两个。首先，它可以让计算机网络（在本例中指的是Internet）的用户可以使用一个直接的、有意义的、人们可以理解并且可以记住的的地址来指向某一个网络资源。也许你曾经见过这样的网络地址212.134.93.203、204.71.202.160，但是一般情况下也许你并不会使用这样的数字地址去访问网络，一般情况下你更多使用的是例如www.symbian.com或者www.yahoo.com这样的地址。 </p>
        <p>其次，这种将网络物理地址和用户记忆的网络资源地址进行分割的服务，达到了网络硬件层进行升级或者替换的情况下并不会影响到用户访问的目的。这种机制也从另外一种情况下帮助了大的网络服务提供商，比如微软公司的Hotmail服务，使这些运营商可以在世界各地部署本地服务器，从而让每一个用户获得更快的访问速度，无论用户是在西雅图或者别的任何地方。 </p>
        <a name=.E4.BD.BF.E7.94.A8RHostResolver.E7.B1.BB></a>
        <h3><span class=mw-headline>使用RHostResolver类 </span></h3>
        <p>作为客户端API的一部分，socket服务组件提供了RHostResolver类，用这个类我们可以获得一个通用的主机地址解析服务，这项服务的内部会自己处理相应不同协议的主机地址解析的细节问题。如果我们针对TCP/IP协议族而言，那么RHostResolver类扮演的就是客户端与域名解析服务（DNS）之间进行通信的服务角色。 </p>
        <p>每一个不同的协议，都提供了自己的主机解析服务，这些服务是作为协议模块的一个标准部分实现的。这样的设计就使得客户端可以仅仅访问RHostResolver类，而并不需要关心socket使用的是哪一种协议。 </p>
        <p>RHostResolver接口提供了如下几种功能供客户端应用程序访问，他们是: </p>
        <ul>
            <li>将一个数字网络地址转换为人所能识别的包含一定意义的文本表现形式
            <li>将人读地址转换为相对应的机读数字地址
            <li>读取或者设置本地设备的主机名的方法/函数 </li>
        </ul>
        <p>就像是RSocket一样，RHostResolver类继承自RSubSessionBase。因此，要想使用RHostResolver类，客户端应用程序就必须先进行对socket服务组件的服务器的连接，这个服务组件的服务器就是一个RSocketServ类的实例。 </p>
        <p>RHostResolver类提供了许多主机地址解析服务的函数/方法，每一个函数都提供了两个版本的多态函数--同步和异步操作。 </p>
        <p>请注意，因为这是一个通用的主机地址解析接口，但是并不是所有的协议都提供了主机地址解析服务，所以有些协议可能并没有提供任何主机地址解析服务。 </p>
        <p>如果客户端应用程序尝试使用RHostResolver中的函数去对一个不支持主机地址解析服务的协议请求主机地址解析服务，那么将会得到错误代码KErrNotSupported。 </p>
        <p>在进行任何主机地址解析服务之前，我们要打开一个RHostResolver类的实例。正如前面所提到过的，因为主机解析服务类是一个子会话类，所以在调用RHostResolver::Open()函数之前，该子会话类必须关联一个socket服务组件的服务器会话对象实例。 </p>
        <pre>    TInt Open(RSocketServ&amp; aSocketServer, TUint anAddrFamily,
        TUint aProtocol);
        </pre>
        <p>下一步，我们将会根据上面所示的函数原形，制定我们希望用哪个地址类型来解析的主机地址，地址类型应该是和传递给RSocket::Open()函数的参数一致的。 </p>
        <p>最后，我们还需要指定一个协议来进行主机地址解析服务。如果之前选择的地址类型是协议无关类型的，那么我们可以在这里指定KUndefinedProtocol。 </p>
        <p>其他的RHostResolver类提供的函数如下所示: </p>
        <pre>    TInt GetByName(const TDesC&amp; aName, TNameEntry&amp; aResult);
        TInt GetByAddress(const TSockAddr&amp; anAddr, TNameEntry&amp; aResult);
        TInt GetHostName(TDes&amp; aName);
        TInt SetHostName(const TDesC&amp; aName); // sync only
        TInt Next(TNameEntry&amp; aResult);
        </pre>
        <p>这些函数中的大多数都是可以见名知意的；不过Next()函数例外，我们来进行一些解释：对于有些协议来说，GetByName()和GetByAddress()函数可能会一次找到不止一个结果，比如地址假名被允许的时候。如果这样的话，我们就需要调用Next()函数来返回下一个地址结果。 </p>
        <a name=.E5.9F.9F.E5.90.8D.E6.9C.8D.E5.8A.A1.28DNS.29></a>
        <h3><span class=mw-headline>域名服务(DNS) </span></h3>
        <p>域名解析服务（Domain Name Service,DNS）是TCP/IP协议所提供的主机解析服务。 </p>
        <p>一个标准的DNS查询一般由以下三个步骤组成: </p>
        <ul>
            <li>一个在某一个网络硬件设备（例如一块以太网卡）设备上运行的客户端应用程序，将自己的查询主机请求发送给网络上的另外一台主机--DNS服务器。
            <li>DNS服务器将查询请求进行查询，查询是在庞大的数字地址与主机名称对应列表中进行的，查询到的结果将会被转换成不同的地址格式。
            <li>DNS服务器将地址发送回客户端。 </li>
        </ul>
        <p>请注意，DNS服务可以将文本格式的地址（例如www.symbian.com）解析为数值格式地址（例如212.134.93.203），或者将数值地址（204.71.202.160）解析为文本格式的地址——www.yahoo.com。 </p>
        <p>互联网服务提供商一般都提供了很多DNS服务器（一般都不只一台）来供他们的客户使用。如果没有这些服务器，那么使用互联网对于普通用户来说将是一场灾难。如果没有DNS的话我们将不得不记住我们感兴趣的web站点的32位数字地址，或者使用十分十分冗长难记的地址去给其他人发电子邮件。 </p>
        <p>这里我们需要注意的重要一点是，实际上地址转换这项工作并不是客户端设备进行的，而是待转换地址被发送到了另外一台主机，由另外一台主机进行的解析。所以我们在建立一个使用TPC/IP协议建立连接的时候，就必须提供一个DNS服务器地址，否则一切连接将几乎无法进行。 </p>
        <a name=.E5.9C.A8socket.E4.BB.A3.E7.A0.81.E4.B8.AD.E4.BD.BF.E7.94.A8.E6.B4.BB.E5.8A.A8.E5.AF.B9.E8.B1.A1.EF.BC.88active_objects.EF.BC.89></a>
        <h2><span class=mw-headline>在socket代码中使用活动对象（active objects） </span></h2>
        <p>计算机网络通信，在一般情况下都是使用异步操作的。下面我们先放下谈论已久的socket通信系统，来看看一个打电话过程是如何进行的，这样会有助于我们理解下面要讨论的问题。 </p>
        <p>当一个朋友给你打电话，你的电话机会收到电话打入的电信号，它在收到这个信号后就开始振铃，然后你听到了铃声之后就拿起听筒，开始进行通话，直到挂断电话此次通话结束。 </p>
        <p>当等待电话呼叫的时候，我们可以进行其他任何事情，并不会对我们的生活造成影响。与此的，假如你的朋友给你发送了一个是十分困难的问题让你帮助解决，也许这是一个相当大的难题，你要花一些时间来考虑或者解决，当这个时候，你的朋友可以利用你考虑或者解决的时间，进行他自己的其他活动。 </p>
        <p>上面的电话通信例子，就是一个很好的一部通信系统的例子。 </p>
        <p>当我们使用socket来在两台计算机之间传输数据的时候，我们看到的是一个类似上面打电话例子的异步模型。 </p>
        <p>在一个使用socket进行网络通信的应用程序中，上述异步通信的事件包括： </p>
        <ul>
            <li>连接, 断开连接以及确认请求连接的要求
            <li>接受数据(因为我们并不知道有多少数据要发送过来，所以这个过程是异步的)
            <li>发出数据(因为对于应用程序层来说，我们并不知道底层的硬件需要多长时间才能够将数据发出，所以这个过程也是异步的)
            <li>其他，比如载入协议模块之类的，看似并不是十分明显的异步操作 </li>
        </ul>
        <p>因为我们需要在应用程序中处理这些异步事件，所以我们需要用到Symbian OS的活动对象（Active objects, AOs）来解决这些问题。 </p>
        <p>活动对象的特点有: </p>
        <ul>
            <li>使得应用程序开发者可以很容易的控制对象的生存周期
            <li>在一个单线程程序中完成并非严格意义上的多任务操作
            <li>为Symbian系统提供了效率较高的单线程多任务解决方案，而并不是真正地使用多线程。 </li>
        </ul>
        <p>在Symbian系统中，所有的线程都是通过一个或者多个活动对象，使用一个激活的进度管理器来进行高效率的外部事件处理。 </p>
        <p>一个活动对象，在一个时间内只能处理一个事件源。在实际情况中，活动对象通常也都是被设计为处理一类特定事件的。 </p>
        <p>在稍后的代码示例中，这些代码因为有不同的需求所以使用了不止一个活动对象，无论是客户端还是服务器程序，都使用了不止三个活动对象。其中一个用来处理连接机制，一个用来接收数据，另外一个用来发送数据。 </p>
        <p>下面我们就来看看如合利用活动对象来处理客户端和服务器之间进行socket流式连接的范例。 </p>
        <a name=.E4.BB.A3.E7.A0.81.E7.A4.BA.E4.BE.8B:_.E8.BF.9E.E6.8E.A5sockets></a>
        <h2><span class=mw-headline>代码示例: 连接sockets </span></h2>
        <p>下面一部分就是借助代码的演示来向大家说明如何利用活动对象进行socket连接。这写代码段是从一个进行监听接入连接的&#8216;服务器&#8217;和发送连接请求到服务器的&#8216;客户端&#8217;程序中提取出来的。 </p>
        <a name=.E6.9C.8D.E5.8A.A1.E2.80.98.E7.9B.91.E5.90.AC.E2.80.99.E7.B1.BB.E7.9A.84.E5.AE.9A.E4.B9.89></a>
        <h3><span class=mw-headline>服务&#8216;监听&#8217;类的定义 </span></h3>
        <p>下面的代码是从一个完整的进行&#8216;监听&#8217;（listening）的服务器类定义中取出的一部分。 </p>
        <pre>class CModel&nbsp;: public CActive {
        public:
        void StartEngineL(void);
        private:
        void RunL(void);
        void DoCancel (void);
        private:
        RSocketServ iSession;
        RSocket     iListen, iSocket;
        CRx*        iRxAO; // 用于接收数据的活动对象
        CTx*        iTxAO; // 用于发送数据的活动对象
        };</pre>
        <p>请注意，在成员变量中有两个socket，一个是用来监听和连接的，而另外一个是用来处理和客户端之间进行数据的传输的。 </p>
        <p>在这个类的定义中，还有两个活动对象，他们是iRxAO和iTxAO。这两个活动对象用来在连接到服务之后异步地、分别地处理数据的发送和接收工作。 </p>
        <p>(对上面已经定义的类而言，这个类仅仅接收一个客户端连接，那么请你不要对自己的创造力作任何限制地去想象和学习一下吧，你可以以这个类定义为基础，将他扩展为接收多个客户端连接的服务器吧!) </p>
        <p>下面我们来看看连接过程是如何实现的。 </p>
        <a name=.E5.81.9A.E5.A5.BD.E6.8E.A5.E6.94.B6.E5.AE.A2.E6.88.B7.E7.AB.AF.E8.BF.9E.E6.8E.A5.E7.9A.84.E5.87.86.E5.A4.87></a>
        <h3><span class=mw-headline>做好接收客户端连接的准备 </span></h3>
        <p>首先，在我们的服务器没有进行服务接入请求之前，我们要先创建两个socket，创建方法如下所示： </p>
        <pre>// Need to use two sockets - one to listen for
        // an incoming connection.
        err = iListen.Open(iSession, KAfInet,KSockStream, KUndefinedProtocol);
        User::LeaveIfError(err);
        // The second (blank) socket is required to
        // build the connection &amp; transfer data.
        err = iSocket.Open(iSession);
        User::LeaveIfError(err);</pre>
        <p>一个socket叫做iListen，他扮演的就是&#8216;监听者&#8217;的角色，用来监听是否有来自客户端的接入请求。iListen是一个和协议流关联的对象，在本例中这个协议就是TCP协议，因为我们使用的是Internet地址格式。 </p>
        <p>另外一个socket，叫做iSocket，在现在是被构造为空socket的，它仅仅在客户端连接请求的时候才会被准备好进入工作状态。这个socket就是用来处理来自客户端的任何请求，并且进行数据传输工作的。 </p>
        <p>那么下面，监听socket就可以去进行监听客户端连接请求的工作了。 </p>
        <p>请注意上面例子中使用的两个不同的RSocket::Open()函数的多态。 </p>
        <p>其中第一个，用在iListen成员变量的，它是用来进行客户端请求连接监听的，所以它需要一个本地地址，只有这样连接数据才能本正确地路由到该对象。 </p>
        <p>要设定本地地址，我们需要将一个地址和一个socket进行绑定（bind）操作： </p>
        <pre>// Bind the listening socket to the required
        // port.
        TInetAddr anyAddrOnPort(KInetAddrAny, KTestPort);
        iListen.Bind(anyAddrOnPort);</pre>
        <p>在本例中，我们并没有过多考虑socket的网络地址，因为我们使用的是易于操作的主机地址名称。尽管如此，我们还是需要指定端口号，这样才能完整确定一个绑定地址。 </p>
        <p>这个时候，客户端就可以通过我们的主机的Internet主机地址和端口号（事先在程序中用#define宏定义好了的KTextPort）向我们的主机（服务器）发送请求了。不过有一点，如果我们不向客户端告知我们的主机名称和端口号，那么客户端将永远无法访问到我们的服务器。 </p>
        <p>还要注意，因为我们的socket是使用Internet地址格式协议族进行打开操作的，所以我们调用Bind()函数时送入的函数参数TSockAddr就是一个TInetAddr类型的一个实例。 </p>
        <p>在TInetAddr类中，它除了保存TSockAddr中定义的一般性数据值外，还保存了一个TUint32类型的IP地址数据。在协议族属性中，TInetAddr类提供的永远是KAfInet值，因为该值表示这个地址是一个TCP/IP地址。 </p>
        <p>当完成了socket的建立，绑定了监听socket，我们就几乎完成了所有准备工作，可以相应来自任何客户端的连接请求。 </p>
        <p>下面我们就是需要把接入连接请求创建一个队列，这个时候我们需要调用RScocket::Listen()函数，另外还要注意我们应该使用长度为1的队列，之后我们看到连接是如何进行的时候，就会明白这个队列长度是足够了的。 </p>
        <pre>void CModel::StartEngineL (void)
        {
        &#8230;
        // Listen for incoming connections...
        iListen.Listen(1);
        // and accept an incoming connection.
        // On connection, subsequent data transfer will
        // occur using the socket iSocket
        iListen.Accept(iSocket, iStatus);
        SetActive();
        ...
        }</pre>
        <p>最后，我们调用异步函数RSocket::Accept()来准备接收客户端连接请求。 </p>
        <p>那么我们再来回顾一下继承自活动对象CActive类的CModel类，当一个客户端连接到我们定义的服务器类的时候，CModel::RunL()函数将会被调用。 </p>
        <p>该函数被调用后的过程，请看下一部分。 </p>
        <a name=.E5.A4.84.E7.90.86.E8.BF.9E.E6.8E.A5.E8.AF.B7.E6.B1.82></a>
        <h3><span class=mw-headline>处理连接请求 </span></h3>
        <p>当一个客户端连接请求被收到的时候，最前线的RSocket::Accept()函数执行请求完成，然后活动对象的RunL()函数将会被调用，这一切步骤都是因为CModel类是一个被激活状态的活动对象。 </p>
        <pre>    void CModel::RunL(void)
        {
        if (iStatus==KErrNone)
        {
        // Connection has been established
        NotifyEvent(EEventConnected);
        // Now need to start the receiver AO.
        iRxAO-&gt;RxL(iSocketType);
        }
        else // error condition
        ...
        }
        </pre>
        <p>那么假设现在所有步骤都是正常进行，那么我们获得的完成状态变量就是KErrNone。在上面的范例代码中，我们会向用户界面层传递一个连接建立成功的消息，然后我们启动活动对象，对接收到的数据进行处理，然后连接iSocket进行返回数据的准备。 </p>
        <p>因为我们进行操作的是一个异步系统，所以现在因为客户端和服务器是已经连接的状态，那么客户端可以在任何时间向服务器socket发送数据。所以我们需要在接收到数据之后，尽可能快地进行数据的处理。 </p>
        <p>有一点，在我们进行已连接的socket的数据发送的时候，我们并不会打开活动对象。数据仅仅会在客户端程序或者用户希望发送数据到客户端的时候，才进行操作。 </p>
        <a name=.E4.BD.BF.E7.94.A8.E6.9C.89.E8.BF.9E.E6.8E.A5.E7.9A.84socket></a>
        <h3><span class=mw-headline>使用有连接的socket </span></h3>
        <p>回顾一下我们前面定义的CModel类，我们有一个成员变量，类型为CRx的iRxAO。 </p>
        <p>类CRx是一个继承自CActive的类，他也是一个活动对象。 </p>
        <p>CRx类的成员函数RxL()，定义如下；这个函数向连接到我们的服务器的客户端发出了一个一个异步请求。 </p>
        <pre>    void CRx::RxL ( ) //class CRx derived from CActive
        {
        // Issue read request
        iSocket-&gt;RecvOneOrMore(iDataBuffer, 0, iStatus, iRecvLen);
        SetActive();
        }
        </pre>
        <p>函数RecvOneOrMore()将会在稍后，和其他一些读取以及写入socket的函数一同进行讨论。 </p>
        <p>在接入数据请求完成的时候，CRx::RunL()函数将会被调用，完成后返回的内容有完成状态事件以及新收到的数据内容。 </p>
        <p>那么再来回顾一下CModel类的另外一个成员变量，类型为CTx的iTxAO。 </p>
        <p>类CTx是一个继承自CActive的类，他也是一个活动对象。 </p>
        <p>CTx类的成员函数TxL()，如下所示；他想连接到服务器的客户端进行了一个发送数据的一部请求操作。 </p>
        <pre>    void CTx::TxL (TDesC&amp; aData)
        {
        if (!IsActive())
        {
        // Take a copy of the data to be sent.
        iDataBuffer = aData;
        // Issue write request
        iSocket-&gt;Send(iDataBuffer, 0, iStatus);
        SetActive();
        }
        }
        </pre>
        <p>Send()函数将会在稍后，和其他一些读取以及写入socket的函数一同进行讨论。 </p>
        <p>当数据发送请求完成的时候，CTx::RunL()函数将会被调用，同时返回的内容有发送操作完成的结果状态。 </p>
        <a name=.E4.BC.A0.E8.BE.93.E6.95.B0.E6.8D.AE></a>
        <h2><span class=mw-headline>传输数据 </span></h2>
        <p>现在我们来看看两台网络设备之间，究竟是如何利用socket来进行数据传输的。 </p>
        <p>如我们以前所知，在socket通信中，数据报通信和数据流通信是两种十分不同的通信方式。 </p>
        <p>无论我们使用的是数据报还是数据流的传输方式，每一个独立的数据单元在网络通信的两端被传输的时候都有可能经过十分不同的路由路径，因为在网络通信的双方之间总有着不计其数的子网络，而通信双方对数据单元的路由方向是无法控制的。这种情况是十分普遍而且正常的，由于数据流的传输方式也是以数据报形式为基础的，所以从这个角度来看的话，二者的路由特点是一致的。 </p>
        <p><br></p>
        <a name=.E6.8E.A5.E6.94.B6.E6.95.B0.E6.8D.AE></a>
        <h3><span class=mw-headline>接收数据 </span></h3>
        <a name=.E4.BD.BF.E7.94.A8.E6.97.A0.E8.BF.9E.E6.8E.A5.E7.9A.84sockets></a>
        <h4><span class=mw-headline>使用无连接的sockets </span></h4>
        <p>下面的函数，是RSocket提供的用来接收无连接的socket的接入数据的。 </p>
        <pre>    void RecvFrom(TDes8&amp; aDesc, TSockAddr&amp; anAddr, TUint flags,
        TRequestStatus&amp; aStatus);
        void RecvFrom(TDes8&amp; aDesc, TSockAddr&amp; anAddr, TUint flags,
        TRequestStatus&amp; aStatus, TSockXfrLength&amp; aLen);
        </pre>
        <p>如果应用程序使用的是无连接的socket，那么需要使用RSocket::RecvFrom()这个这个方法来读取从另外一个远程主机发送过来的数据。 </p>
        <p>该函数的第一个参数是一个字符串，是用来保存接收数据的。 </p>
        <p>调用该函数的程序，会在一个完整的数据报接收完成的时候，得到相应的通知。接收数据的长度，就是接收字符串的长度。如果接收数据报的长度要比字符串的最大长度更长，那么接收数据的末尾将被截去。 </p>
        <p>该函书的第二个参数是要进行接收操作的远程主机的地址。这个地址需要是一个根据socket打开方式定义的协议格式相匹配的地址。例如，如果打开socket的时候定义的是TCP/IP协议，那么这个地址需要是一个TInetAddr类型的变量。 </p>
        <p>我们会发现，这个函数有两个版本的重载，他们都进行了同样的操作，方式也一样。唯一不同的是，第二个函数可以将接收数据的长度，显式地返回给调用者。 </p>
        <p>还有一点，一个单独的socket在任何一个时间内，都只有一个状态为等待中的接收操作。 </p>
        <p>上面的方法，只能用于无连接（数据报）类型的socket连接。 </p>
        <a name=.E4.BD.BF.E7.94.A8.E8.BF.9E.E6.8E.A5.E7.9A.84sockets></a>
        <h4><span class=mw-headline>使用连接的sockets </span></h4>
        <p>下面的函数是RSocket提供的用来从已经连接的socket中读取数据的函数原形。 </p>
        <pre>    void Recv(TDes8&amp; aDesc, TUint flags, TRequestStatus&amp; aStatus);
        void Recv(TDes8&amp; aDesc, TUint flags,
        TRequestStatus&amp; aStatus,TSockXfrLength&amp; aLen);
        void RecvOneOrMore(TDes8&amp; aDesc, TUint flags,
        TRequestStatus&amp; aStatus, TSockXfrLength&amp; aLen);
        </pre>
        <p>如果应用程序使用的是已连接的socket，那么应该使用上面的函数来进行远程主机的数据接收工作。 </p>
        <p>和前面的无连接socket类似，这些接收函数的第一个参数，仍然是接收数据要保存的目标字符串变量。 </p>
        <p>Recv()函数会在目标字符串变量被填满或者连接断开的时候完成。在该函数完成调用的时候，读取数据的长度就是字符串的长度，除非在没有读取任何数据连接就断开了。 </p>
        <p>第二个Recv()函数的重载可以显式地获取接收数据的长度，该长度被保存在了类型为TSockXfrLength的函数参数中，这样的话判断接收数据长度就不必关联接收字符串的长度了。 </p>
        <p>最后一个函数RecvOneOrMore()，与Recv()不同，这个函数是会在函数接收到任何数据之后立刻返回的。言外之意，调用RecvOneOrMore()函数会接收到1--n个字节，其中n就是目标字符串的长度。同样地，如果连接被断开，RecvOneOrMore()函数仍然会立刻返回，并且不会返回任何数据。 </p>
        <p>虽然是已连接的socket，但是在发送过程中数据流并不一定都是物理上连续的，尽管从逻辑上看他们是流式的。所以，即便是使用已连接的socket，仍然应用程序--socket的调用者--来进行判断数据流的结束与否，边界切分等工作。 </p>
        <p>注意，由于我们使用的是已连接的socket，那么我们不需要指定接收收据的socket地址，因为已连接的socket是在连接动作发生的时候就已经指定好了传输目标主机地址信息了。 </p>
        <p>在这一部分的前半部分，我们介绍的各种函数都是具有比较高的复杂度的，可能对于应用程序开发者来说并不会具有特别的吸引力。 </p>
        <p>特别地，我们可以注意到所有的函数都以一个参数TUint aFlags作为标示作用，到目前为止还没有对他进行讨论。这个参数的作用是让应用程序可以选择特定协议的指定属性，以此来设置协议接收处理数据的方式。 </p>
        <p>下面介绍的另外一个函数Read()，他将默认标示参数设置为0，并且也去掉了TSockXfrLength类型的参数。如果使用该函数，那么接收数据的长度就只能通过接收目标字符串的长度来获得了。 </p>
        <pre>     void Read(TDes8&amp; aDesc, TRequestStatus&amp; aStatus);
        </pre>
        <p>除了上述的两个例外，这个Read()函数的操作效果就基本同Recv()一样了。 </p>
        <p>注意，这个函数仅仅在已连接的socket通信中是可以使用的。 </p>
        <a name=.E5.8F.91.E9.80.81.E6.95.B0.E6.8D.AE></a>
        <h3><span class=mw-headline>发送数据 </span></h3>
        <a name=.E4.BD.BF.E7.94.A8.E6.9C.AA.E8.BF.9E.E6.8E.A5.E7.9A.84sockets></a>
        <h4><span class=mw-headline>使用未连接的sockets </span></h4>
        <p>下面的函数是RSocket中用来向未连接的socket发送数据的。 </p>
        <pre>    void SendTo(const TDesC8&amp; aDesc, TSockAddr&amp; anAddr, TUint flags,
        TRequestStatus&amp; aStatus);
        void SendTo(const TDesC8&amp; aDesc, TSockAddr&amp; anAddr, TUint flags,
        TRequestStatus&amp; aStatus, TSockXfrLength&amp; aLen);
        </pre>
        <p>如果应用程序连接的是无连接的socket，那么就要使用RSocket::SendTo()函数来向远程主机发送数据。 </p>
        <p>这个函数中的第一个参数是包含了要发送数据内容的字符串，而要发送内容的长度，则是由字符串的长度决定的。 </p>
        <p>当数据发送完成的时候，调用该函数的应用程序将会得到通知。如果你使用的是带有TSockXfrLength类型参数的函数重载，那么已发送的数据的长度，将会在完成的时候被保存在该参数中。 </p>
        <p>第二个参数包含了要发送数据的远程主机的地址，这个地址的格式应该符合socket被打开的时候制定的协议所支持的地址格式，比如，如果我们选择了TCP/IP协议，那么我们就需要使用TInetAddr作为发送主机的地址。 </p>
        <p>第三个参数，TUint类型的标志位，它是一个和协议相关的位标识符，定义了某些需要向协议模块中传递参数的标志信息。 </p>
        <p>需要注意的是，在一个socket连接中，在任意时间最多仅有一个发送操作时处于等待状态的。 </p>
        <p>上述介绍的函数，仅仅可用于无连接的数据报socket使用。 </p>
        <a name=.E4.BD.BF.E7.94.A8.E8.BF.9E.E6.8E.A5.E7.9A.84sockets_2></a>
        <h4><span class=mw-headline>使用连接的sockets </span></h4>
        <p>下面的函数，是RSocket提供的用来向一个已经连接的socket发送数据的。 </p>
        <pre>    void Send(const TDesC8&amp; aDesc, TUint someFlags,
        TRequestStatus&amp; aStatus);
        void Send(const TDesC8&amp; aDesc, TUint someFlags,
        TRequestStatus&amp; aStatus, TSockXfrLength&amp; aLen);
        </pre>
        <p>如果你的应用程序使用的是已经连接的socket，那么可以使用上面的函数来向远程主机发送数据。 </p>
        <p>和上面类似，该函数的第一个参数是包含了要向远程主机发送数据内容的字符串，该字符串的长度就是要发送数据的全部长度。 </p>
        <p>Send函数会在全部数据源发送完成之后，或者连接断开之后返回。 </p>
        <p>第二个函数Send()可以让调用者传递一个TSockXfrLength类型的参数进来，以此来确定发送数据的长度，这样的话传输函数就不必以发送数据的内容的字符串长度来作为原数据的长度了。 </p>
        <p>上面两种函数冲在，都提供了一个TUint someFlags参数，该参数是用来定义和协议相关的标示位的，针对不同协议会有不同的协议标示定义。 </p>
        <p>正如前面提到的SendTo()函数，上面第二个方法中的TSockXfrLength类型的参数，会在异步调用请求完成的时候，被赋予已经发送的数据的长度。 </p>
        <p>请注意，因为我们是在向已经连接的socket发送数据，所以我们并不需要指定目标主机地址。对于已经连接的socket来说，在socket打开的时候，远程主机地址就已经被指定好了。 </p>
        <p>我们目前所提供的函数，可能对于应用程序的开发者来说还是有些过于复杂，并且更深入一些。 </p>
        <p>对于下面提供的Write函数来说，所有的标志标示符都被去除，他们将使用默认值0。另外TSockXfrLength也被去除了，这样的话，发送函数就仅仅从发送数据内容的字符串中获得发送数据的长度了。 </p>
        <pre>    void Write(const TDesC8&amp; aDesc, TRequestStatus&amp; aStatus);
        </pre>
        <p>除了上面说到的两个不同点之外，其它部分都是和Send()函数几乎没有差别的。 </p>
        <p>注意，这里提到的发送数据的函数，都仅仅适用于已经连接的socket。 </p>
        <a name=.E6.80.BB.E7.BB.93></a>
        <h2><span class=mw-headline>总结 </span></h2>
        <p>本文提供了一些Symbian OS的socket服务编写说明，以及如何将通信功能加入到应用程序中。 </p>
        <p>Socket服务组件通过两个主类RSocketServ和RSocket，提供了一个近乎标准Socket API的接口。 RSocketServ是连接到sockets服务的回话进程，而RSocket是连接到sockets服务的子会话。通过这两个类，你可以实现面向连接或者无连接的socket。主机解析服务可以通过RHostResolver类来完成。 </p>
        <p>Socket服务组件的设计是基于协议模块的，不同的插件模块实现了在Socket通信中的不同协议的细节部分。这种设计可以使Socket服务组件可以支持未来的通信协议，而并不对服务组件进行升级。到Symbian OS 6.0为止，被支持的协议包括 TCP/IP（网络控制协议和互联网协议）, IrDA（红外）, SMS（短信） and Bluetooth&#174; （蓝牙无线技术）. </p>
        <p><strong>致谢</strong>: 本文是于2005年从<a class="external text" title=http://www.symbian.com href="http://www.symbian.com/" rel=nofollow><u><font color=#0000ff>www.symbian.com</font></u></a>的开发文章部分引用于此的, 本文的作者是<strong>Gavin Meiklejohn</strong>。目前指向这篇文章的链接已经不再有效，所以此处再次发布这篇十分有价值的文章。 </p>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/57505.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/gtwdaizi/" target="_blank">郭天文</a> 2008-07-30 13:33 <a href="http://www.cppblog.com/gtwdaizi/articles/57505.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[S60]ARM平台独有问题 Writable Static Data in DLLs</title><link>http://www.cppblog.com/gtwdaizi/articles/51908.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Mon, 02 Jun 2008 12:23:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/51908.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/51908.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/51908.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/51908.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/51908.html</trackback:ping><description><![CDATA[<div class=tit>[S60] ARM平台独有问题 Writable Static Data in DLLs</div>
<div class=date>2007-07-08 16:59</div>
<table style="TABLE-LAYOUT: fixed">
    <tbody>
        <tr>
            <td>
            <div class=cnt id=blog_text>在编译arm平台程序的时候，出现如下错误提示：<br><tt>ERROR: Dll 'AppName[UID].APP' has initialised data.<br>或者：<br></tt><tt>ERROR: Dll 'AppName[UID].APP' has uninitialised data.</tt><br><tt>（扩展名APP的应用程序其实也是一个DLL。）<br><br>而在为模拟器编译的时候，这个问题不会出现。这曾经导致我在完成完整的设计，编码和调试后，<br>被迫放弃原有设计。<br><br>从这条错误信息的字面意思是什么也看不出来的。</tt><tt>initialised 和 </tt><tt>uninitialised都一样有问题。<br>其实真正的含义是Dll里存在可写的全局变量。<br><br>大家知道在程序运行的时候，DLL只会被装载一次。在Windows平台，每个进程都有自己独立的DLL空间。也就是说，不同进程装载同一个DLL，互相之间是独立的。只有在一个进程内，才是共享的。但是S60平台的设计是所有进程都共享同一个DLL空间。这样的设计显然是出于节约内存的目的，是很有必要的。但是这样就带来一个问题，那就是DLL里不可以有可写的全局变量，否则就要造成混乱。A进程对变量的改写会直接影响到B进程，这是程序设计者所不愿意看到的。所以，S60平台的编译器就禁止了在DLL内申明可写全局变量。但是全局变量还是可以用的，只要加上const申明即可。<br><br>一般来说，在做DLL设计的时候，的确不鼓励使用可写全局变量。即使是windows平台，DLL的可写全局变量也会在不同模块之间带来问题。当遇到这个编译器错误的时候，应该设法修改设计，回避使用全局变量。<br><br>但是因为APP实际上也是DLL，这就导致连S60的主程序也不能使用可写的全局变量，这个在某些时候就成了问题，全局变量毕竟是一个重要的实现手段。对此，S60提供了线程局部存储(</tt>thread local storage<tt>)来解决问题。<br></tt>TLS的关键是两个函数：<br><tt><tt>void Dll::SetTls(void*)和</tt></tt><tt><tt>void* Dll::Tls()<br>SetTls用于将任意类型的指针保存到线程局部存储中，而Tls()则取出该指针。<br>指针指向在堆上分配的一块内存。一个线程只能有一个局部存储变量。所以，如果你有很多全局变量，就要定义一个结构，把所有的全局变量封装在其中。这是挺别扭的，不过S60 3rd据说就支持dll的可写全局变量了。<br><br>tls样例代码：<br><br>设置<br></tt></tt><tt><tt>GlobalData* p = new GlobalData();<br>if ( p )<br>{<br>&nbsp;&nbsp; Dll::SetTls( p ); <br>}<br><br>使用<br></tt></tt><tt><tt>GlobalData* p = (GlobalData*) Dll::Tls();</tt></tt></div>
            </td>
        </tr>
    </tbody>
</table>
<p>&nbsp;</p>
<div id=Articleti>在Symbian上如何定义全局变量</div>
<p>方法1(推荐)把这个变量定义成AppUi类的私有成员，在创建view时将这个变量传引用（或传指针）到view中，这样view就能随时访问它了。</p>
<p>方法2.把这个变量定义成AppUi类的私有成员，并为它写公共的访问函数<br>// CMyAppUi<br>public: // new methods<br>&nbsp;&nbsp; TInt Share(); // return iShare<br>private:<br>JAVA手机网[www.cnjm.net]&nbsp;&nbsp; TInt iShare;<br>在View里通过下面的方式访问这个变量：<br>// 如果View继承自CAknView<br>CMyAppUi* appUi = static_cast&lt;CMyAppUi*&gt;(AppUi());<br>appUi-&gt;Share(); // :)<br>// 如果View是其它类型<br>CMyAppUi* appUi = static_cast&lt;CMyAppUi*&gt;(CCoeEnv::Static()-&gt;AppUi());<br>appUi-&gt;Share(); // :)<br>方法3.使用单态类，参考诺基亚论坛上的文档：<br>Tip Of The Month: How To Implement A Singleton Class In Symbian OS <br></p>
<p><br><br>&nbsp;</p>
<h1>How to implement a singleton class in Symbian OS &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ID: TTS000222</h1>
<p class=BodyText>Version 1.1<br>Published at <a href="http://www.forum.nokia.com/" target=_blank><u><font color=#0000ff>www.forum.nokia.com</font></u></a> on October 19, 2006.</p>
<h2>Overview</h2>
<p class=BodyText>The singleton pattern is one of the best-known patterns in software engineering. Essentially, a singleton is a class which only allows a single instance of itself to be created, and usually gives simple access to that instance. </p>
<h2>How to use thread local storage (TLS) to implement a singleton class</h2>
<p class=BodyText>In Symbian OS, each DLL that is loaded in each thread has a machine word of thread-specific memory that can be written to and read — but no other static memory, which is why you can't have static class member variables. Since static class member variables are usually used to implement the singleton pattern, in Symbian OS we have to get around this, for instance by using TLS.</p>
<p class=BodyText>The following code demonstrates a singleton object whose <span style="FONT-FAMILY: Courier">NewL</span> function uses TLS to test whether an object of its own type has been created. If it has, it simply returns the pointer stored in TLS, converted to its own type. If not, it instantiates an object of its own type, stores it in TLS, and then returns it.</p>
<p class=BodyText>Note that this assumes that no other class in the DLL that includes this class uses TLS. If this is not the case, you must write a singleton manager class, which uses TLS to store a pointer to a structure of pointers to all the singleton classes that the program needs.</p>
<p class=BodyText>Example 1: Singleton implementation based on TLS</p>
<p class=code>&nbsp;&nbsp;==============</p>
<p class=Codecontinued>&nbsp;&nbsp;CMySingleton.h</p>
<p class=Codecontinued>&nbsp;&nbsp;==============</p>
<p class=Codecontinued>&nbsp;</p>
<p class=Codecontinued>&nbsp;&nbsp;class CMySingleton : public CBase</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p class=Codecontinued>&nbsp;&nbsp;public: // constructor and destructor</p>
<p class=Codecontinued>&nbsp;&nbsp; &nbsp;&nbsp; static CMySingleton* NewL();</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;virtual ~CMySingleton();</p>
<p class=Codecontinued>&nbsp;&nbsp;private: // constructors</p>
<p class=Codecontinued>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;CMySingleton(); // private because of the singleton pattern; it is</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // guaranteed that only NewL will call it</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void ConstructL();</p>
<p class=Codecontinued>&nbsp;&nbsp;public: // other functions</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...</p>
<p class=Codecontinued>&nbsp;&nbsp;private: // other functions</p>
<p class=Codecontinued>&nbsp;&nbsp; &nbsp;&nbsp; ...</p>
<p class=Codecontinued>&nbsp;&nbsp;private: // data</p>
<p class=Codecontinued>&nbsp;&nbsp; &nbsp;&nbsp; ...</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;}</p>
<p class=Codecontinued>&nbsp;</p>
<p class=Codecontinued>&nbsp;&nbsp;================</p>
<p class=Codecontinued>&nbsp;&nbsp;CMySingleton.cpp</p>
<p class=Codecontinued>&nbsp;&nbsp;================</p>
<p class=Codecontinued>&nbsp;</p>
<p class=Codecontinued>&nbsp;&nbsp;CMySingleton::CMySingleton* NewL()</p>
<p class=Codecontinued>&nbsp;&nbsp; &nbsp;&nbsp; {</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;CMySingleton* singleton;</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Check thread local storage:</p>
<p class=Codecontinued>&nbsp;&nbsp; &nbsp;&nbsp; if ( Dll::Tls() == NULL )</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; // TLS is still null, which means that no CMySingleton has</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;// been instantiated yet.&nbsp; Do so now, and return that</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // instance:</p>
<p class=Codecontinued>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; singleton = new ( ELeave ) CMySingleton();</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; CleanupStack::PushL( singleton );</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; singleton-&gt;ConstructL();</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;CleanupStack::Pop( singleton );</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Store a pointer to the new instance in thread local storage:</p>
<p class=Codecontinued>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TInt err = Dll::SetTls( static_cast&lt;TAny*&gt;( singleton ) );</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; if ( err == KErrNone )</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; return singleton;</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else</p>
<p class=Codecontinued>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete instance;</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; User::Leave( err );</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; return NULL;</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p class=Codecontinued>&nbsp;&nbsp; &nbsp;&nbsp; else</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; // CMySingleton has been instantiated once already, so return</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;// that instance:</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;singleton = static_cast&lt;CMySingleton*&gt;( Dll::Tls() );</p>
<p class=Codecontinued>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return singleton;</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p class=Codecontinued>&nbsp;</p>
<h2>TLS on S60 3rd Edition</h2>
<p class=BodyText>Since applications from S60 3rd Edition onwards are implemented as EXE programs, Dll::Tls() is not available anymore. Instead, TLS functionality is implemented in UserSvr class (e32svr.h):</p>
<p class=code>static TInt DllSetTls(TInt aHandle, TAny *aPtr);</p>
<p class=CodeContinued>static TAny *DllTls(TInt aHandle);</p>
<p class=CodeContinued>static void DllFreeTls(TInt aHandle);</p>
<p class=BodyText>Note that EXE programs can contain writeable static data, but this is not recommended to be used except as a last resort.</p>
<h2>Using class CCoeStatic to implement a singleton class</h2>
<p class=BodyText>A simpler way of implementing singletons than using TLS is possible for those classes which use the CCoeEnv class. Since CCoeEnv is a part of the UI control framework, this concerns only applications, not application engines.</p>
<p class=BodyText>This applies also to S60 3rd Edition and later editions.</p>
<p class=BodyText>Example 2: Singleton implementation based on CCoeStatic</p>
<p class=code>&nbsp;&nbsp;==============</p>
<p class=Codecontinued>&nbsp;&nbsp;CMySingleton.h</p>
<p class=Codecontinued>&nbsp;&nbsp;==============</p>
<p class=Codecontinued>&nbsp;</p>
<p class=Codecontinued>&nbsp;&nbsp;/**</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;* Example implementation of a singleton class by means of inheriting</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;* from CCoeStatic.</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;*/</p>
<p class=Codecontinued>&nbsp;&nbsp;class CMySingleton : public CCoeStatic</p>
<p class=Codecontinued>&nbsp;&nbsp; &nbsp;&nbsp; {</p>
<p class=Codecontinued>&nbsp;</p>
<p class=Codecontinued>&nbsp;&nbsp;public: // constructors and destructor&nbsp;&nbsp;&nbsp; </p>
<p class=Codecontinued>&nbsp;</p>
<p class=Codecontinued>&nbsp; &nbsp;&nbsp;&nbsp; /**&nbsp;&nbsp;&nbsp; </p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; * Returns an instance of this class. When called for the first</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * time, a new instance is created and returned.&nbsp; After that,</p>
<p class=Codecontinued>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; * calling InstanceL returns the same instance that was created</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;* earlier.</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp; </p>
<p class=Codecontinued>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; * @return A pointer to a CMySingleton object&nbsp;&nbsp;&nbsp; </p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;*/&nbsp;&nbsp;&nbsp; </p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static CMySingleton* InstanceL();&nbsp;&nbsp;&nbsp; </p>
<p class=Codecontinued>&nbsp;</p>
<p class=Codecontinued>&nbsp;&nbsp;private: // constructor</p>
<p class=Codecontinued>&nbsp;</p>
<p class=Codecontinued>&nbsp;&nbsp; &nbsp;&nbsp; /**&nbsp;&nbsp;&nbsp; </p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;* Default constructor is private because we are using the</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * singleton design pattern.</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp;&nbsp; </p>
<p class=Codecontinued>&nbsp;&nbsp; &nbsp;&nbsp; CMySingleton();&nbsp;&nbsp;&nbsp; </p>
<p class=Codecontinued>&nbsp;</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;...</p>
<p class=Codecontinued>&nbsp;</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p class=Codecontinued>&nbsp;</p>
<p class=Codecontinued>&nbsp;</p>
<p class=Codecontinued>&nbsp;&nbsp;================</p>
<p class=Codecontinued>&nbsp;&nbsp;CMySingleton.cpp</p>
<p class=Codecontinued>&nbsp;&nbsp;================</p>
<p class=Codecontinued>&nbsp;</p>
<p class=Codecontinued>&nbsp;&nbsp;// -------------------------------------------------------------------------</p>
<p class=Codecontinued>&nbsp;&nbsp;// CMySingleton::CMySingleton</p>
<p class=Codecontinued>&nbsp;&nbsp;// C++ default constructor. It is private because we are using the</p>
<p class=Codecontinued>&nbsp;&nbsp;// singleton design pattern.</p>
<p class=Codecontinued>&nbsp;&nbsp;// -------------------------------------------------------------------------</p>
<p class=Codecontinued>&nbsp;&nbsp;CMySingleton::CMySingleton()</p>
<p class=Codecontinued>&nbsp;&nbsp; &nbsp;&nbsp; : CCoeStatic( KUidMySingleton )</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;{</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p class=Codecontinued>&nbsp;</p>
<p class=Codecontinued>&nbsp;&nbsp;// -------------------------------------------------------------------------</p>
<p class=Codecontinued>&nbsp;&nbsp;// CMySingleton::InstanceL</p>
<p class=Codecontinued>&nbsp;&nbsp;// Returns an instance of this class. When called for the first time,</p>
<p class=Codecontinued>&nbsp;&nbsp;// a new instance is created and returned.&nbsp; After that, calling</p>
<p class=Codecontinued>&nbsp;&nbsp;// InstanceL returns the same instance that was created earlier.</p>
<p class=Codecontinued>&nbsp;&nbsp;// Note that the UID passed to CCoeEnv::Static needs to be unique.</p>
<p class=Codecontinued>&nbsp;&nbsp;// -------------------------------------------------------------------------</p>
<p class=Codecontinued>&nbsp;&nbsp;CMySingleton* CMySingleton::InstanceL()</p>
<p class=Codecontinued>&nbsp;&nbsp; &nbsp;&nbsp; {</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;CMySingleton* instance = static_cast&lt;CMySingleton*&gt;</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; ( CCoeEnv::Static( KUidMySingleton ) );</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( !instance )</p>
<p class=Codecontinued>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; instance = new ( ELeave ) CMySingleton;</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CleanupStack::PushL( instance );</p>
<p class=Codecontinued>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; instance-&gt;ConstructL();</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; CleanupStack::Pop();</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }</p>
<p class=Codecontinued>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return instance;</p>
<p class=code>&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/51908.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/gtwdaizi/" target="_blank">郭天文</a> 2008-06-02 20:23 <a href="http://www.cppblog.com/gtwdaizi/articles/51908.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[S60]Symbian学习笔记：Debug On Device[转]</title><link>http://www.cppblog.com/gtwdaizi/articles/48185.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Sat, 26 Apr 2008 06:55:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/48185.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/48185.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/48185.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/48185.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/48185.html</trackback:ping><description><![CDATA[在BREW的开发环境中，没有一个联机调试工具，一直是我觉得相当不方便的事情。在S60平台上做开发，至少这一点是能满足我们的需要。<br><br><span style="FONT-WEIGHT: bold">第一种方法：Carbide C++ v1.2 的 Debug On Device</span><br><br>Carbide C++1.2的pro.以上版本都支持设备调试，实在是一件大快人心的事。<br><br>要实现这个功能，也是相当的方便，当然前提是你用的是Carbide C++ v1.2的Pro.以上版本。<br><br>按正常模式写程序，在模拟器上都弄的差不多了，想放到设备中调试的话，只需要做下面几步：<br>1、先在设备中安装一个软件，安装包在carbide的安装目录下，我机器上的位置是C:\Nokia\Carbide.c++ v1.2\plugins\com.nokia.carbide.trk.support_1.2.0.29\trk\s60，下面有两个 sis文件，因为我要在N73上调试，所以我选择其中的s60_3_0_app_trk_2_7.sisx这个，另一个3_1是用于3rd.FP1手机的。安装后在手机里就有一个TRK应用了。<br><br>2、安装成功后，在手机上启动这个服务TRK，因为我是用的USB线，所以点选项，改成USB，端口是1（这里比较奇怪，明明我的端口应该是COM6）。启动后窗口显示：Status:Connected.<br><br>3、在Carbide C++中，配置一下编译输出目标为Phone Debug(GCCE)，这个很重要，只有DEBUG才行。编译出SISX文件。<br><br>4、打开DEBUG窗口（即debug...），在配置中的第一项&#8220;Symbian OS App Trk&#8220;下建立一个新项。几个窗口的输入如下图所示：<br><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/sharetop/aa.jpg"><br><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/sharetop/bb.jpg"><br><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/sharetop/cc.jpg"><br><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/sharetop/dd.jpg"><br><br>5、点Apply，然后Debug，就可以启动调试。余下的事情与在模拟器中调试就一样了，没啥好说了。<br><br><span style="FONT-WEIGHT: bold">第二种方法：利用S60 SDK自带的Ecmt工具进行DEBUG</span><br><br>如果我们用的是Carbide C++ 的Express版（免费版本）的话，我们没办法做设备联机调试，但是可以用SDK中的工具在程序中将调试信息打印到控制台上。在BREW平台上主要就是依靠这种方式。<br><br>Symbian提供了一个REmct可以用于远程调试，并且它还提供了两个配套工具：手机端的ecmtagent_cpp.sis和PC端的Device Connection。<br><br>这种方式比前一种要稍复杂一点了，因为涉及到代码的修改。<br><br>1、首先同样是在手机上安装一个软件ecmtagent_cpp.sis（不过3rd.的SDK下这个东西不能用，说签名过期之类的错误，只能安装3rd. FP1的SDK下的那个同名sis，唉，也不知道Nokia是咋回事）。<br><br>2、同样在调试前也是要启动手机上的ecmtagent代理，设置成USB连接（不需要选择端口了）。然后看到窗口上显示listening。<br><br>3、在PC上启动那个Device Connection，选择COM6去connect它，状态成为connected。这时发现手机上也显示connected。表明连接成功了。在Device Connection中打开那个Diagnostics工具，所有的调试信息的就是输出到它的窗口里。<br><br>4、最麻烦的是需要修改代码。<br><br>A） 修改mmp，加上这个lib。即：<span style="COLOR: rgb(0,0,255)"><span style="COLOR: rgb(51,153,102)">LIBRARY &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; EcmtClient.lib</span><br><span style="COLOR: rgb(0,0,0)"><br>B)&nbsp;&nbsp; 在要输出调试信息的那个类的h文件中加上：<br>
<div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: rgb(230,230,230) 0% 50%; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 95%; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align=top><span style="COLOR: rgb(0,0,0)">#ifdef&nbsp;_DEBUG<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: rgb(0,0,0)">&lt;</span><span style="COLOR: rgb(0,0,0)">EcmtClient.h</span><span style="COLOR: rgb(0,0,0)">&gt;</span><span style="COLOR: rgb(0,0,0)"><br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align=top></span><span style="COLOR: rgb(0,0,255)">#endif</span><span style="COLOR: rgb(0,0,0)"><br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align=top><br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align=top>...&nbsp;...<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align=top>class CDemoUIAppView : public CCoeControl,MBeating {<br>&nbsp;&nbsp; ... ...<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">private</span><span style="COLOR: rgb(0,0,0)">:<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align=top>#ifdef&nbsp;_DEBUG<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;REcmt&nbsp;iEcmt;<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align=top></span><span style="COLOR: rgb(0,0,255)">#endif</span></div>
</div>
<br>C)&nbsp; 然后在cpp中加上一个初始化与销毁。<br>
<div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: rgb(230,230,230) 0% 50%; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 95%; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align=top><span style="COLOR: rgb(0,0,255)">void</span><span style="COLOR: rgb(0,0,0)">&nbsp;CDemoUIAppView::ConstructL(&nbsp;</span><span style="COLOR: rgb(0,0,255)">const</span><span style="COLOR: rgb(0,0,0)">&nbsp;TRect</span><span style="COLOR: rgb(0,0,0)">&amp;</span><span style="COLOR: rgb(0,0,0)">&nbsp;aRect&nbsp;)<br><img id=_55_134_Open_Image onclick="this.style.display='none'; document.getElementById('_55_134_Open_Text').style.display='none'; document.getElementById('_55_134_Closed_Image').style.display='inline'; document.getElementById('_55_134_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=_55_134_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_55_134_Closed_Text').style.display='none'; document.getElementById('_55_134_Open_Image').style.display='inline'; document.getElementById('_55_134_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=_55_134_Closed_Text style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)">...</span><span id=_55_134_Open_Text><span style="COLOR: rgb(0,0,0)">{<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;CreateWindowL();&nbsp;&nbsp;&nbsp;&nbsp;<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>...&nbsp;...<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>#ifdef&nbsp;_DEBUG<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;iEcmt.Connect();<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;</span><span style="COLOR: rgb(0,0,255)">#endif</span><span style="COLOR: rgb(0,0,0)"><br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: rgb(0,0,0)"><br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align=top><br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align=top>CDemoUIAppView::</span><span style="COLOR: rgb(0,0,0)">~</span><span style="COLOR: rgb(0,0,0)">CDemoUIAppView()<br><img id=_172_227_Open_Image onclick="this.style.display='none'; document.getElementById('_172_227_Open_Text').style.display='none'; document.getElementById('_172_227_Closed_Image').style.display='inline'; document.getElementById('_172_227_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=_172_227_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_172_227_Closed_Text').style.display='none'; document.getElementById('_172_227_Open_Image').style.display='inline'; document.getElementById('_172_227_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=_172_227_Closed_Text style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)">...</span><span id=_172_227_Open_Text><span style="COLOR: rgb(0,0,0)">{<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;...&nbsp;...<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>#ifdef&nbsp;_DEBUG<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;iEcmt.Close();<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;</span><span style="COLOR: rgb(0,0,255)">#endif</span><span style="COLOR: rgb(0,0,0)"><br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></div>
</div>
<br>D) 然后就是在需要输出的地方这样一下：<br>
<div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: rgb(230,230,230) 0% 50%; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 95%; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align=top><span style="COLOR: rgb(0,0,255)">void</span><span style="COLOR: rgb(0,0,0)">&nbsp;CDemoUIAppView::Beat()<br><img id=_29_295_Open_Image onclick="this.style.display='none'; document.getElementById('_29_295_Open_Text').style.display='none'; document.getElementById('_29_295_Closed_Image').style.display='inline'; document.getElementById('_29_295_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=_29_295_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_29_295_Closed_Text').style.display='none'; document.getElementById('_29_295_Open_Image').style.display='inline'; document.getElementById('_29_295_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=_29_295_Closed_Text style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)">...</span><span id=_29_295_Open_Text><span style="COLOR: rgb(0,0,0)">{<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">this</span><span style="COLOR: rgb(0,0,0)">-&gt;</span><span style="COLOR: rgb(0,0,0)">total</span><span style="COLOR: rgb(0,0,0)">++</span><span style="COLOR: rgb(0,0,0)">;<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">if</span><span style="COLOR: rgb(0,0,0)">(</span><span style="COLOR: rgb(0,0,255)">this</span><span style="COLOR: rgb(0,0,0)">-&gt;</span><span style="COLOR: rgb(0,0,0)">total</span><span style="COLOR: rgb(0,0,0)">&gt;</span><span style="COLOR: rgb(0,0,0)">100</span><span style="COLOR: rgb(0,0,0)">)<br><img id=_73_119_Open_Image onclick="this.style.display='none'; document.getElementById('_73_119_Open_Text').style.display='none'; document.getElementById('_73_119_Closed_Image').style.display='inline'; document.getElementById('_73_119_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=_73_119_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_73_119_Closed_Text').style.display='none'; document.getElementById('_73_119_Open_Image').style.display='inline'; document.getElementById('_73_119_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=_73_119_Closed_Text style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)">...</span><span id=_73_119_Open_Text><span style="COLOR: rgb(0,0,0)">{<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">this</span><span style="COLOR: rgb(0,0,0)">-&gt;</span><span style="COLOR: rgb(0,0,0)">total</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)">;<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iHeart</span><span style="COLOR: rgb(0,0,0)">-&gt;</span><span style="COLOR: rgb(0,0,0)">Cancel();<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: rgb(0,0,0)"><br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TBuf</span><span style="COLOR: rgb(0,0,0)">&lt;</span><span style="COLOR: rgb(0,0,0)">16</span><span style="COLOR: rgb(0,0,0)">&gt;</span><span style="COLOR: rgb(0,0,0)">&nbsp;buf;<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buf.Format(KMsgFormat,</span><span style="COLOR: rgb(0,0,255)">this</span><span style="COLOR: rgb(0,0,0)">-&gt;</span><span style="COLOR: rgb(0,0,0)">total);<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iLabel</span><span style="COLOR: rgb(0,0,0)">-&gt;</span><span style="COLOR: rgb(0,0,0)">SetTextL(buf);<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DrawNow();<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>#ifdef&nbsp;_DEBUG<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iEcmt.WriteFormat(KFormattedText,&nbsp;</span><span style="COLOR: rgb(0,0,255)">this</span><span style="COLOR: rgb(0,0,0)">-&gt;</span><span style="COLOR: rgb(0,0,0)">total);<br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: rgb(0,0,255)">#endif</span><span style="COLOR: rgb(0,0,0)"><br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align=top><br><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></div>
</div>
<br>5、编译程序，同样是GCCE下的Phone Debug，自己手工安装到手机里，执行它就可以了。要注意的一点是，因为此时前面的那个ecmtagent正在运行，需要将它切到后台去（不是关闭啊！！！）。在Diagnostics的窗口中就会看到输出的调试信息了。<br><br>最后要补充一点的是，我在尝试这两种调试方法的时候，经常遇到打开端口失败或者连接失败的情况，一般重启一下手机就正常了，不知道是BUG呢还是因为我同时弄了两个代理在手机里照成的冲突，如果你在使用过程中发现不顺了，不妨也重启一下手机吧。</span></span>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/48185.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/gtwdaizi/" target="_blank">郭天文</a> 2008-04-26 14:55 <a href="http://www.cppblog.com/gtwdaizi/articles/48185.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[S60]模拟器配置访问网络</title><link>http://www.cppblog.com/gtwdaizi/articles/47806.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Tue, 22 Apr 2008 04:37:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/47806.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/47806.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/47806.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/47806.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/47806.html</trackback:ping><description><![CDATA[&nbsp; 　　只有S60 &nbsp; 2.0及以前的SDK才需要Ethernet_plug_in。 &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; 　　从S60 &nbsp; 2.1 &nbsp; SDK开始，只要执行SDK安装根目录的"\Epoc32\Tools\"子目录中的"network_config.bat"，即可启动"Emulator &nbsp; network &nbsp; configuration"程序，为仿真器设置了IP地址等配置后，它就能与PC通信，并可以使用PC的网络连接。详细配置方法参见SDK帮助中的"Series &nbsp; 60 &nbsp; Emulator &nbsp; Guide &nbsp; &gt;&gt; &nbsp; Configuring &nbsp; the &nbsp; Emulator"，特别需要注意的是仿真器不能跟PC用同一个IP地址。 &nbsp; <br>&nbsp; &nbsp; <br><clk>&nbsp; 　　配置好以后试着用仿真器上的浏览器打开WAP网站(比如<a href="http://wap.baidu.com/">http://wap.baidu.com/</a>)，如果打得开说明配置成功。</clk><br>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/47806.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/gtwdaizi/" target="_blank">郭天文</a> 2008-04-22 12:37 <a href="http://www.cppblog.com/gtwdaizi/articles/47806.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[S60]symbian基本类型转换</title><link>http://www.cppblog.com/gtwdaizi/articles/47764.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Mon, 21 Apr 2008 13:17:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/47764.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/47764.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/47764.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/47764.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/47764.html</trackback:ping><description><![CDATA[<font face=Verdana size=2>TDesC是所有字符类的祖先<br><br><br>标准C语言<br>Symbian OS<br><br>让一个字符串进入2进制代码<br>Static char hellorom[]=&#8221;hello&#8221;<br>_LIT(khellorom,&#8221;hello&#8221;)<br><br>在栈中获得字符串的指针<br>Const char* helloptr=hellorom<br>TPtrC helloptr=khellorom<br><br>获得在栈中字符串的指针<br>Char hellostack[sizeof(hellorom)];<br><br>Strcpy(hellostack,hellorom);<br>TBufC&lt;5&gt; hellostack=khellorom;<br><br>获得在堆中字符串的指针<br>Char* helloheap=<br><br>(char *)malloc(sizeof(hellorom));<br><br>strcpy(helloheap,hellorom);<br>HBufC* helloheap=<br><br>Khellorom.AllocLC();<br><br><br>a)TPtrC相当于不变的字符串常量.<br><br>b)TPtr相当与String类型。Tbuf相当于char[]。前者与后者的唯一区别是，后者需要指定分配的栈空间大小。<br><br>C)HBufC* 与char*类似。分配的是堆上的空间。<br><br>HBufC* textResource; <br><br>//两种字符串附值方法<br><br>textResource = StringLoader::LoadLC( R_HEWP_TIME_FORMAT_ERROR );<br><br>textResource =iEikonEnv-&gt;AllocReadResourceL(R_EXAMPLE_TEXT_HELLO);<br><br>TBuf&lt;32&gt; timeAsText;<br><br>timeAsText = *textResource;<br><br>/* 数据类型转换*/<br><br><br>TBuf&nbsp;&nbsp;转换为 TPtrC16<br>&nbsp;&nbsp;&nbsp;&nbsp;TBuf&lt;32&gt; tText(_L("2004/11/05 05:44:00"));<br>&nbsp;&nbsp;&nbsp;&nbsp;TPtrC16 tPtrSecond=tText.Mid(17,2);<br><br>TPtrC16 转换为 TBufC16<br>&nbsp;&nbsp;&nbsp;&nbsp;TPtrC16 tPtrSecond=tText.Mid(17,2);<br>&nbsp;&nbsp;&nbsp;&nbsp;TBufC16&lt;10&gt; bufcs(tPtrSecond);<br><br>TBufC16 转换为&nbsp;&nbsp;TPtr16<br>&nbsp;&nbsp;&nbsp;&nbsp;TBufC16&lt;10&gt; bufcs(tPtrSecond);<br>&nbsp;&nbsp;&nbsp;&nbsp;TPtr16 f=bufcs.Des();<br><br>TPtr16 转换为 TBuf<br>&nbsp;&nbsp;&nbsp;&nbsp;TBuf&lt;10&gt; bufSecond;<br>&nbsp;&nbsp;&nbsp;&nbsp;bufSecond.Copy(f);<br><br>TBuf 转换为 TPtr16 <br>&nbsp;&nbsp;&nbsp;&nbsp;TBuf&lt;10&gt; bufSecond(_L("abc"));<br>&nbsp;&nbsp;&nbsp;&nbsp;TPtr16 f;<br>&nbsp;&nbsp;&nbsp;&nbsp;f.Copy(bufSecond);<br><br>TBuf 转换为 TInt<br>&nbsp;&nbsp;&nbsp;&nbsp;TInt aSecond;<br>&nbsp;&nbsp;&nbsp;&nbsp;TLex iLexS(bufSecond);<br>&nbsp;&nbsp;&nbsp;&nbsp;iLexS.Val(aSecond); <br><br>TInt 转换为 TBuf<br>&nbsp;&nbsp;&nbsp;&nbsp;TBuf&lt;32&gt; tbuf;<br>&nbsp;&nbsp;&nbsp;&nbsp;TInt i=200;<br>&nbsp;&nbsp;&nbsp;&nbsp;tbuf.Num(i);<br><br>1.串转换成数字<br>&nbsp;&nbsp; TBuf16&lt;20&gt; buf(_L( "123" ) );<br>&nbsp;&nbsp;&nbsp;&nbsp;TLex lex( buf );<br>&nbsp;&nbsp;&nbsp;&nbsp;TInt iNum;<br>&nbsp;&nbsp;&nbsp;&nbsp;lex.Val( iNum );<br>2.数字转换成串<br>&nbsp;&nbsp; TBuf16&lt;20&gt; buf;<br>&nbsp;&nbsp; TInt iNum = 20;<br>&nbsp;&nbsp; buf.Format( _L( "%d" ) , iNum&nbsp;&nbsp;);<br>3.将symbian串转换成char串<br>&nbsp;&nbsp;&nbsp;&nbsp;char* p = NULL;<br>&nbsp;&nbsp;&nbsp;&nbsp;TBuf8&lt;20&gt; buf( _L( "aaaaa" ) );<br>&nbsp;&nbsp;&nbsp;&nbsp;p = (char *)buf.Ptr();<br><br>4.UTF-8转换成UNICODE<br>&nbsp;&nbsp;&nbsp;&nbsp;CnvUtfConverter::ConvertToUnicodeFromUtf8( iBuf16 , iBuf8 );<br>5.UNICODE转换成UTF-8<br>&nbsp;&nbsp;&nbsp;&nbsp;CnvUtfConverter::ConvertFromUnicodeToUtf8( iBuf8 , iBuf16 ); <br><br><br>6.将char串转换成symbian串<br>&nbsp;&nbsp;&nbsp;&nbsp;char* cc = "aaaa";<br>&nbsp;&nbsp;&nbsp;&nbsp;TPtrC8 a;<br>&nbsp;&nbsp;&nbsp;&nbsp;a.Set( (const TUint8*)cc , strlen(cc) );<br><br>7、将TPtrc8与TPtrc16之间转化<br><br>// Get a iBuf8 from a iBuf16 (data are not modified)<br>TPtrC8 ptr8(reinterpret_cast&lt;const TUint8*&gt;(iBuf16.Ptr()),(iBuf16.Size()*2));<br>iBuf8=ptr8;<br><br>// Get a iBuf16 from a iBuf8 (data are not modified)<br>TPtrC16 ptr16(reinterpret_cast&lt;const TUint16*&gt;(iBuf8.Ptr()),(iBuf8.Size()/2));<br>iBuf16=ptr16;<br><br><br>The second one takes each character and convert it to the other format. The 16-bit to 8-bit conversion may not always succeed in this case:<br><br>Code:<br><br>// Get a iBuf8 from a iBuf16 (data are modified)<br>CnvUtfConverter::ConvertFromUnicodeToUtf8(iBuf8,iBuf16); <br><br>// Get a iBuf16 from a iBuf8 (data are modified)<br>CnvUtfConverter::ConvertToUnicodeFromUtf8(iBuf16,iBuf8); <br><br><br>This second method requires to include the utf.h header and to link against charconv.lib.<br><br>/*memset&nbsp;&nbsp; memcpy&nbsp;&nbsp; strcpy */<br><br>memset主要应用是初始化某个内存空间。用来对一段内存空间全部设置为某个字符。<br>memcpy是用于COPY源空间的数据到目的空间中,用来做内存拷贝可以拿它拷贝任何数据类型的对象。<br>strcpy只能拷贝字符串了，它遇到'\0'就结束拷贝。<br><br><br><br>strcpy <br>原型：extern char *strcpy(char *dest,char *src); <br>用法：#include &lt;string.h&gt;<br>功能：把src所指由NULL结束的字符串复制到dest所指的数组中。<br>说明：src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 返回指向dest的指针。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>memcpy <br>原型：extern void *memcpy(void *dest, void *src, unsigned int count);<br>用法：#include &lt;string.h&gt;<br>功能：由src所指内存区域复制count个字节到dest所指内存区域。<br>说明：src和dest所指内存区域不能重叠，函数返回指向dest的指针。<br><br>memset<br>原型：extern void *memset(void *buffer, int c, int count);<br>用法：#include &lt;string.h&gt;<br>功能：把buffer所指内存区域的前count个字节设置成字符c。<br>说明：返回指向buffer的指针。</font><br>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/47764.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/gtwdaizi/" target="_blank">郭天文</a> 2008-04-21 21:17 <a href="http://www.cppblog.com/gtwdaizi/articles/47764.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[s60]如何进行Express Signed的签名</title><link>http://www.cppblog.com/gtwdaizi/articles/47231.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Sat, 19 Apr 2008 06:56:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/47231.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/47231.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/47231.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/47231.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/47231.html</trackback:ping><description><![CDATA[1. 使用开发者的签名，以及nokia的测试标准对程序进行一系列的标准测试。这个symbian的官方网站都是由相关文档的。这是一个中文的文档，希望对大家有帮助。<a href="http://www.cppblog.com/Files/gtwdaizi/SymbianSignedTestCriteria2.11.1_cn.pdf">/Files/gtwdaizi/SymbianSignedTestCriteria2.11.1_cn.pdf</a><br><br>2.&nbsp;购买publish ID, 国内的朋友可以通过wosign代理来购买, 还是比较方便的, 不过价格比较贵一点, 人民币和美元的汇率都是按照1:10来算的, 这年头美元贬值更赚了. 不过客服态度很好, 声音也很甜美.. &nbsp;哈哈&nbsp; <a href="http://www.wosign.com/">www.wosign.com</a> <br><br>3. 提交之前需要通过nokia的标准化的测试, 这样可以确保通过签名的几率比较大. 测试工具SymbianSigned可以从官网上面下载得到, 安装到手机, 然后, 使用开发者ID和手机的IMIE号生成key和cer对sis进行signsis, 把生成的sis拷贝到手机的symbiansigned的安装目录下, 启动symbiansigned工具会进行一系列测试.<br><br>4. 测试通过后, 使用publish id对原始的sis进行签名, 然后准备readme.txt 和.pkg文件, 打包到zip中提交..提交的流程还是蛮多的, 大概6-7步. 就不详细叙说了..
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/47231.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/gtwdaizi/" target="_blank">郭天文</a> 2008-04-19 14:56 <a href="http://www.cppblog.com/gtwdaizi/articles/47231.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[S60]Symbian 应用软件开发、测试与 S60 平台安全常见问题问答 </title><link>http://www.cppblog.com/gtwdaizi/articles/47241.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Wed, 16 Apr 2008 07:49:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/47241.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/47241.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/47241.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/47241.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/47241.html</trackback:ping><description><![CDATA[<table cellSpacing=0 cellPadding=0 width="96%" align=center border=0>
    <tbody>
        <tr>
            <td height=36>
            <div align=center>&nbsp;</div>
            </td>
        </tr>
        <tr>
            <td>
            <p>&nbsp;&nbsp;&nbsp;&nbsp;本常见问题问答由 WoSign 根据 Forum Nokia(诺基亚开发者论坛)以下文章翻译整理，请同时参考英文原文： <a href="http://forum.nokia.com/main/technical_services/testing/index.html" target=_blank><font color=#0000ff><u>http://forum.nokia.com/main/technical_services/testing/index.html</u></font></a><br><a href="http://forum.nokia.com/main/technical_services/testing/application_testing_faq.html" target=_blank><u><font color=#0000ff>http://forum.nokia.com/main/technical_services/testing/application_testing_faq.html<br></font></u></a><a href="http://seap.forum.nokia.com/main/platforms/s60/faq.html" target=_blank><u><font color=#0000ff>http://seap.forum.nokia.com/main/platforms/s60/faq.html <br></font></u></a><a href="http://seap.forum.nokia.com/main/technical_services/testing/symbian_signed_benefits.html" target=_blank><u><font color=#0000ff>http://seap.forum.nokia.com/main/technical_services/testing/symbian_signed_benefits.html</font></u></a><br>以及 <a href="http://www.wosign.com/FAQ/Symbian_Signed_FAQ.htm"><u><font color=#0000ff>Symbian Signed 认证常见问题问题</font></u></a> </p>
            <p>&nbsp;&nbsp;&nbsp; 软件测试是一个应用软件开发过程中最主要的环节，一般包括模块测试、系统测试、可用性测试和权威认证测试 ( 如： Symbian Signed 认证测试和 Java Veriified 认证测试 ) 。所有通过诺基亚销售渠道推广的移动应用软件都必须通过 Symbian Signed 认证测试或 Java Veriified 认证测试。请同时参考 <a href="http://forum.nokia.com/main/technical_services/testing/testing_documents.html" target=_blank><u><font color=#0000ff>诺基亚测试标准和其他重要文档 </font></u></a>。 </p>
            <p align=left>&nbsp;&nbsp;&nbsp; Symbian Signed 认证已经成为移动应用软件测试和认证的事实工业标准，采用业界广泛接受的软件质量规范来推动基于 Symbian 操作系统的应用软件的开发和内容的开发。 测试和认证主要是为了保证 Symbian 开发平台的安全和最终用户的更加安全。从 Symbian 操作系统 V9.x(S60 第 3 版 ) 开始，&#8220; capability( 能力 ) &#8221;模式限制了许多敏感 API 的访问，一些&#8220;能力&#8221;只能通过 Symbian Signed 认证才能获得，而有些&#8220;能力&#8221;还需要手机厂商的认证。 </p>
            <p align=left>&nbsp;&nbsp;&nbsp; Symbian Signed 认证主要流程如下图所示，首先在<a href="http://www.symbiansigned.com/"><u><font color=#0000ff> Symbiansigned.com</font></u></a> 网上注册用户，再申请购买 <a href="http://www.wosign.com/Products/Publisher_ID_for_Symbian.htm"><u><font color=#0000ff>TC Publisher ID 认证证书</font></u></a>，再签名 SIS 文件，再提交已经签名的文件给 Symbian Signed 指定的测试公司测试，测试通过后从 Symbiansigned 网站取回由测试公司重新签名的文件，就可以部署到手机中安全运行了。<br>&nbsp;&nbsp;&nbsp; 请注意：通过测试取回的文件已经重新使用手机所信任的 Symbian 根证书下颁发的 Symbian Signed 证书签名，请不要再修改此软件，也不得重新使用您的认证证书签名，否则不能正常运行。 </p>
            <p align=center><a href="http://www.wosign.com/Products/Publisher_ID_for_Symbian.htm"><img height=267 src="http://www.wosign.com/FAQ/images/SymbianSigned_process.jpg" width=502 border=0></a></p>
            <p><strong>1. S60 第 3 版的应用软件签名是强制要求吗？ </strong></p>
            <p><strong>答</strong>：是的。 S60 第 3 版的应用软件是必须要数字签名才能运行的，是强制要求。请注意：数字签名与测试认证是两码事，数字签名是必须的，而测试认证不是必须的。您可以使用自签证书 (SDK 生成 ) 签名，或使用 TC Publisher ID(Symbian Signed 认证证书 ) 来签名应用软件。 </p>
            <p><strong><br>2. 自签证书、 Symbian 开发者证书 (Symbian developer certificate) 和 Symbian 认证证书 (TC Publisher ID) 三者有什么不同？签名后的效果有什么不一样？ </strong></p>
            <p><strong>答</strong>：对于 S60 第 3 版，应用软件签名是必须的，否则不能成功安装到手机上。如果应用软件不需要任何能力 (capability) ，则可以使用 SDK 生成自签证书；如果应用软件需要能力，则在软件开发和自测过程中需要申请 Symbian 开发者证书来签名应用软件；而对于最终发布的商用应用软件，有些能力必须通过 Symbian Signed 认证来授权，只有通过 Symbian Signed 认证才能访问某些能力。同时，手机厂商或移动运营商的应用软件市场推广也要求应用软件已经通过 Symbian Signed 认证。 </p>
            <p align=left>三种证书签名后的效果不同在于： </p>
            <p align=left><strong>(1) 使用自签证书签名 </strong></p>
            <p align=left>&nbsp;&nbsp;&nbsp; &#8226;&nbsp; 可以使用 SDK 带的工具来生成自签证书或直接使用 Carbide 中的自签证书；<br>&nbsp;&nbsp;&nbsp; &#8226;&nbsp; 签名后可以安装应用软件，但有警告； <br>&nbsp;&nbsp;&nbsp; &#8226;&nbsp; 只具有有限的能力，仅包括： ReadUserData, WriteUserData, NetworkServices, LocalServices 和 UserEnvironment </p>
            <p align=left><strong>(2) 使用开发者证书签名 </strong></p>
            <p align=left>&nbsp;&nbsp;&nbsp; &#8226;&nbsp; 可以签名 SIS 文件包<br>&nbsp;&nbsp;&nbsp; &#8226;&nbsp; 应用软件具有 14 种能力，可以申请其他能力<br>&nbsp;&nbsp; &nbsp;&#8226;&nbsp; 仅用于开发过程调试，有测试手机数量限制</p>
            <p align=left><strong>(3) 通过 Freeware 认证 </strong></p>
            <p align=left>&nbsp;&nbsp;&nbsp; &#8226;&nbsp; 开发者通过 Symbian Signed Freeware 认证通道提交应用软件获得认证 ( 如果软件通过测试 ) <br>&nbsp;&nbsp;&nbsp; &#8226;&nbsp; 应用软件具有 14 种能力，可以申请其他能力<br>&nbsp;&nbsp;&nbsp; &#8226;&nbsp; 不得用于商业目的&nbsp; </p>
            <p align=left><strong>(4) 通过 Symbian Signed 认证 </strong></p>
            <p align=left>&nbsp;&nbsp;&nbsp; &#8226;&nbsp; 开发者通过 Symbian Signed 认证通道提交应用软件获得认证 ( 如果软件通过测试 ) <br>&nbsp;&nbsp;&nbsp; &#8226;&nbsp; 应用软件可以有所有能力 </p>
            <p align=left><strong>(5) 自我认证 (Self Certified) </strong></p>
            <p align=left>&nbsp;&nbsp;&nbsp; &#8226;&nbsp; 开发者从 Symbian 获得自我认证资格，自己测试和签名应用软件 <br>&nbsp;&nbsp;&nbsp; &#8226;&nbsp; 应用软件可以有所有能力 <br></p>
            <p><strong>3. 为何我需要购买 TC Publisher ID ( Symbian Signed 认证证书 )? </strong></p>
            <p><strong>答</strong>：如果您要申请 Symbian Signed 认证，则一定要先购买<a href="http://www.wosign.com/Products/Publisher_ID_for_Symbian.htm"><u><font color=#0000ff> TC Publisher ID </font></u></a>(免费软件Freeware开发者除外) 。在提交 Test house 测试之前，您需要使用 TC Publisher ID 签名 SIS 文件，用于保证软件确实来自软件开发商和不会在发送过程中被非法篡改。 </p>
            <p>&nbsp;&nbsp;&nbsp; 如果您需要申请支持某些重要的能力的 Symbian 开发者证书，也需要先有 TC Publisher ID 。如果您希望在多款手机上测试您的应用软件，也需要先有 TC Publisher ID( 仅针对 S60 第 3 版 ) 。</p>
            <p><br><strong>4. Symbian Signed 认证证书 (TC Publisher ID) 和 Symbian Signed 测试费用如何？</strong> </p>
            <p align=left><strong>答</strong>： <a href="http://www.wosign.com/Products/Publisher_ID_for_Symbian.htm"><u><font color=#0000ff>Symbian Signed 认证证书</font></u></a> (TC Publisher ID) 费用为 US$200( 人民币 1600 元 )( 原 VeriSign ACS Publisher ID 价格为 US$350/ 人民币 2800 元 ) 。 WoSign 为<a href="http://www.wosign.com/News/WoSign_TrustCenter_PublisherID.htm"><u><font color=#0000ff> TC Trustcenter </font></u></a>唯一指定的中国区销售代理商 <strong>、</strong>辅助身份验证机构和中文技术支持中心。 </p>
            <p align=left>&nbsp;&nbsp;&nbsp; 不同的应用软件测试费用不一样，请参考： <a href="https://www.symbiansigned.com/app/page/overview/testhouses" target=_blank><u><font color=#0000ff>Test House information </font></u></a>有详细的收费说明。此测试费用与其他类似测试服务来讲是非常优惠的，而且 Symbian 正在努力降低此费用，将会推出新的测试工具软件来进一步降低测试费用。 <br>&nbsp;&nbsp;&nbsp; WoSign 推荐用户联系Test House： <a href="http://www.mphasis.com/" target=_blank><u><font color=#0000ff>MphasiS</font></u></a>，主要考虑到3家测试公司中只有该公司在上海有办事处，方便用户中文联系，同时其测试费用也是3家测试公司中最便宜的(网上公开价格为：185欧元，约2000元)。具体联系信息如下：Atlas Wang， Tel: 021-5080 7360， Fax: 021-5080 7362， Email: <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#119;&#97;&#110;&#103;&#46;&#104;&#97;&#111;&#64;&#109;&#112;&#104;&#97;&#115;&#105;&#115;&#46;&#99;&#111;&#109;" target=_blank><u><font color=#0000ff>wang.hao@mphasis.com </font></u></a>。</p>
            <p><br><strong>5. 什么是 Symbian 开发者证书？我什么时候需要开发者证书？</strong> </p>
            <p><strong>答</strong>：如果您需要某些能力并需要在一台手机上测试，则您需要在 Symbian Signed 网站(Request DevCerts)申请 Symbian 开发者证书 ( 仅针对 S60 第 3 版 ) 。请参考Symbian Signed网站提供的 "<a href="http://www.wosign.com/FAQ/Developer_Certificate_Request_Process_v2_chinese.pdf"><u><font color=#0000ff>Symbian开发者证书申请流程</font></u></a>(中文)" 申请开发者证书。请注意： Symbian 开发者证书只能在申请时指定的手机上测试使用。申请条件依据希望在多少台手机上测试和希望获得哪些能力而不同，具体规定如下表： </p>
            <table cellSpacing=0 cellPadding=0 border=1>
                <tbody>
                    <tr>
                        <td width=63>
                        <p align=center><strong>测试手机数量 </strong>Number of IMEIs </p>
                        </td>
                        <td width=157>
                        <p align=center><strong>申请条件 </strong><br>Authentication </p>
                        </td>
                        <td width=359>
                        <p align=center><strong>申请获得的能力 </strong><br>Granted capabilities </p>
                        </td>
                    </tr>
                    <tr>
                        <td height=61>
                        <p align=center>1 </p>
                        </td>
                        <td>
                        <p align=center>Symbian Signed Account </p>
                        </td>
                        <td>
                        <p align=center>LocalServices, ProtServ, UserEnvironment, NetworkServices, Location, ReadUserData, WriteUserData, SW Event, SurroundingsDD, ProtSrv, PowerMgmt, ReadDeviceData, WriteDeviceData, TrustedUI </p>
                        </td>
                    </tr>
                    <tr>
                        <td height=40>
                        <p align=center>2-100 </p>
                        </td>
                        <td>
                        <p align=center>TC Publisher ID and Symbian Signed account </p>
                        </td>
                        <td>
                        <p align=center>As above </p>
                        </td>
                    </tr>
                    <tr>
                        <td height=50>
                        <p align=center>&gt;100 </p>
                        </td>
                        <td>
                        <p align=center>TC Publisher ID, <br>Symbian Signed account <br>and licensee support </p>
                        </td>
                        <td>
                        <p align=center>As above + NetworkControl, MultimediaDD, ComDD, DiskAdmin, AllFiles, DRM &amp; TCB </p>
                        </td>
                    </tr>
                </tbody>
            </table>
            <p align=left><br><strong>6. Symbian Signed 认证证书 (TC Publisher ID) 和 Symbian 开发者证书有效期为多长？ </strong></p>
            <p align=left><strong>答</strong>： TC Publisher ID 有效期为一年，而开发者证书有效期为 6 个月。在申请开发者证书和使用开发者证书签名时，请确保您的 TC Publisher ID 是在有效期内的。您可以双击证书文件 (.cer) 查看证书有效期。如果TC Publisher ID 认证证书已经过期，请重新购买新证书。</p>
            <p align=left><strong><br>7. 我如何知道自签证书签名的应用软件使用了哪些能力？ </strong></p>
            <p align=left><strong>答</strong>：如果应用软件要求某些能力，则在安装过程中会显示如下图示信息(不同的软件可能显示不同的信息)，询问用户是否允许<em>(由于本文从英文原文翻译，没有中文显示信息，请参考您的手机的中文警告信息，以下同)</em>。<br>&nbsp;&nbsp;&nbsp; 是否允许应用软件： <br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; - 使用连接功能 ( 能力 = LocalServices ) <br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; - 读取用户数据 ( 能力 = ReadUserData ) <br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; - 写入用户数据 ( 能力 = WriteUserData) <br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; - 使用照相机或麦克风 ( 能力 = UserEnvironment) <br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; - 网络访问或发起电话呼叫 ( 能力 = NetworkServices) </p>
            <p align=center><img height=172 src="http://www.wosign.com/FAQ/images/Symbian_S60_Sec_FAQ_clip_image001.jpg" width=306> </p>
            <p align=left><strong><br>8. 如果一个应用软件已经签名，如何显示已经签名的应用软件？ </strong></p>
            <p align=left><strong>答</strong>：使用不同的签名证书签名，会显示不同的警告信息： </p>
            <p align=left><strong>(1) 使用自签证书签名 </strong></p>
            <p align=left>显示&#8220;安全警告：应用软件不可信任，也许会损害您的手机&#8221; </p>
            <p align=center><img height=98 src="http://www.wosign.com/FAQ/images/f_clip_image003.jpg" width=270></p>
            <p align=left><strong>(2) 通过 Freeware 认证 </strong></p>
            <p align=left>下图已经涂掉 Freeware 的名称，显示&#8220;此应用软件为免费软件，不得用于商业销售。如果您已经付款购买，请发 Email 到： <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#115;&#121;&#109;&#98;&#105;&#97;&#110;&#115;&#105;&#103;&#110;&#101;&#100;&#64;&#115;&#121;&#109;&#98;&#105;&#97;&#110;&#46;&#99;&#111;&#109;" target=_blank><u><font color=#0000ff>symbiansigned@symbian.com </font></u></a>，并告之您从哪里获得此软件。 &#8221; </p>
            <p align=center><img height=149 src="http://www.wosign.com/FAQ/images/f_clip_image004.jpg" width=270></p>
            <p align=left><strong>(3) 使用开发者证书签名 </strong></p>
            <p align=left>显示&#8220;此应用软件处于开发测试阶段，如果您继续安装此软件可能会带来损害您的手机，要继续安装吗？&#8221;而一旦用户选择继续安装，则不会有其他安全警告。 </p>
            <p align=center><img height=131 src="http://www.wosign.com/FAQ/images/f_clip_image005.jpg" width=256></p>
            <p align=left><strong>(4) 通过 &nbsp;Symbian Signed 认证 </strong></p>
            <p align=left>不仅没有任何安全警告，而且不需要用户确认和同意应用软件中使用的能力，大大简化安装和方便用户使用。</p>
            <p align=center><img height=314 src="http://www.wosign.com/FAQ/images/f_clip_image006.jpg" width=398></p>
            <p align=left><br><strong>9. 我如何知道我的 S60 第 3 版应用软件需要哪些能力？ </strong></p>
            <p align=left><strong>答</strong>：在 S60 第 3 版开发包的帮助文档中有详细说明调用哪些 API 需要什么能力，您可以通过 S60 仿真器来得到确认。当选中&#8220; Enable EPOCWIND,OUT Logging &#8221;和在 epoc.ini 中设置 PlatSecDiagnostics 为 ON 时，仿真器将在 Windows 临时目录中生成一个名为 epocwind.out 的文件，此文件中包含了应用软件所需要的能力信息。 </p>
            <p align=left><strong><br>10. 我的应用软件在访问某些 API 或函数时要求Nokia Vendor ID，如何得到Nokia Vendor ID？ </strong></p>
            <p align=left><strong>答</strong>： Nokia Vendor ID(VID) 用来保护系统的敏感区域，是 NOKIA 专用的，不会对任何其他方开放。也就是说，您不能访问需要 VID 的 API 或函数。 </p>
            <p align=left><br><strong>11. 我的应用软件需要播放和录制音频和视频，需要有 MultimediaDD 能力吗？</strong></p>
            <p align=left><strong>答</strong>：不需要，除非您需要修改缺省的系统权限。 </p>
            <p align=left><br><strong>12. 我的应用软件需要从收件箱中读取附件，需要有 AllFiles 能力吗？ </strong></p>
            <p align=left><strong>答</strong>：不需要。在消息库中有一个类 MmsvAttachmentManager 可以原来完成此任务。 </p>
            <p align=left><br><strong>13. 我的应用软件需要从文件系统中移动 / 删除 / 复制文件，需要有 AllFiles 能力吗？</strong></p>
            <p align=left><strong>答</strong>：从一般目录 ( nondata-caged ) 中移动 / 删除 / 复制文件不需要。只有从 Data-caged 目录 ( 如： /sys/bin, /private, 和 /resource ) 才需要。 </p>
            <p align=left><br><strong>14. 如果要调用 FEP (Front End Processor), MTM (Message Type Module), or browser plug-in ，需要有 哪些 能力吗？</strong></p>
            <p align=left><strong>答</strong>：需要 ALL - TCB (All minus TCB) 能力。 </p>
            <p><strong><br></strong><strong>15. 我无法安装 Symbian SIS 文件到 Symbian OS v9.x 手机上，应该怎么办？ </strong></p>
            <p><strong>答： </strong>如果您的应用软件是通过 Symbian Signed 认证的，请检查 S60 手机上的&#8220;工具&#8221; -&gt; &#8220;设置&#8221; -&gt; &#8220;安全&#8221; -&gt; &#8220;证书管理&#8221;中是否有 Symbian B 根证书，并检查手机日期和时间是否设置正确，同时检查手机 SIM 卡是否插入和工作正常。 </p>
            <p><strong><br>16. 我们应用软件已经通过某款手机 (S60 第 2 版或 S40) 的 Symbian Signed 认证测试，是否可以在其他 S60 或 S40 手机上安装？ </strong></p>
            <p><strong>答</strong>：安装应该是没有问题的。但如果您的应用软件仅通过某款手机的测试，则不能保证在其他手机上工作正常，推荐重新针对其他目标手机做测试。请注意：基于 S60 第 1 版和第 2 版开发的应用软件不能在第 3 版手机上安装，需要使用相应的 SDK 重新编译您的软件。 </p>
            <p align=left><br><strong>17. 什么是 UID ？我如何得到 UID? </strong></p>
            <p align=left><strong>答</strong>： Unique Identifier (UID) 是系统为二进制文件 (EXE 或 DLL) 分配的唯一识别符，是为了防止可执行文件的相互干扰。对于 S60 第 3 版应用软件需要重新申请 UID ，请参考： <a href="http://www.symbiansigned.com/" target=_blank><u><font color=#0000ff>www.symbiansigned.com </font></u></a>-&gt; UIDs </p>
            <p align=left><br><strong>18. 我需要从 protected range 还是 unprotected range 申请 UID? </strong></p>
            <p align=left><strong>答</strong>：下表能解释什么情况下需要什么 UID range ，取决于您的应用软件是使用什么证书签名的： </p>
            <table cellSpacing=0 cellPadding=0 border=1>
                <tbody>
                    <tr>
                        <td width=61 height=39>
                        <p align=center>Signing status </p>
                        </td>
                        <td width=190>
                        <p align=center>Symbian Signed (ready to be submitted to Symbian Signed) </p>
                        </td>
                        <td width=99>
                        <p align=center>DevCert <br>self-signed </p>
                        </td>
                        <td width=227>
                        <p align=center>Other self-signed <br>(e.g. signed with self-created certificate) </p>
                        </td>
                    </tr>
                    <tr>
                        <td height=35>
                        <p align=center>UID range </p>
                        </td>
                        <td width=190>
                        <p align=center>Protected </p>
                        </td>
                        <td width=99>
                        <p align=center>Protected or unprotected </p>
                        </td>
                        <td width=227>
                        <p align=center>Unprotected </p>
                        </td>
                    </tr>
                </tbody>
            </table>
            <p align=left><br><strong>19. 我如何在 S60 第 3 版手机上备份和恢复我的应用软件？ </strong></p>
            <p align=left><strong>答</strong>： S60 第 3 版缺省是不支持备份的，但您可以使用如下办法备份和恢复您的应用软件： </p>
            <p align=left>创建一个 XML 备份注册文件： backup_registration.xml </p>
            <p align=left>&lt;?xml version="1.0" standalone="yes" ?&gt; <br>&lt;backup_registration&gt; <br>&nbsp;&nbsp;&nbsp; &lt;system_backup /&gt; <br>&lt;/backup_registration&gt; </p>
            <p align=left>把 "backup_registration.xml" 包括到您的项目包文件中 project .pkg ： </p>
            <p align=left>"backup_registration.xml"- <br>"!:\private\98765432\backup_registration.xml" </p>
            请注意：把此注册文件放在应用软件的专用保护数据区。 </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/47241.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/gtwdaizi/" target="_blank">郭天文</a> 2008-04-16 15:49 <a href="http://www.cppblog.com/gtwdaizi/articles/47241.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>手机开发平台指南、教程和资料介绍[转载]</title><link>http://www.cppblog.com/gtwdaizi/articles/47094.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Tue, 15 Apr 2008 01:31:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/47094.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/47094.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/47094.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/47094.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/47094.html</trackback:ping><description><![CDATA[<table style="TABLE-LAYOUT: fixed" height="100%" cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td align=left width="40%"><font color=red><strong><font color=red><strong>楼主</strong></font> </strong></font><strong>Posted:</strong>2008-3-22 10:42:55&nbsp;&nbsp;<a title=已记录 href="http://www.imtinewlife.com/BBS/Manage.asp?menu=lookip&amp;ThreadID=412&amp;PostID=865"><img src="http://www.imtinewlife.com/BBS/images/ip.gif" border=0></a></td>
            <td align=right width="60%" height=1><a class=TextButton title="查看 jacky 的个人资料" href="http://www.imtinewlife.com/BBS/Profile.asp?UserName=jacky"><u><font color=#0000ff>信息</font></u></a> <a class=TextButton title="查看 jacky 的个人共享空间" href="http://www.imtinewlife.com/BBS/Blog.asp?BlogUserName=jacky"><u><font color=#0000ff>日志</font></u></a> <a class=TextButton title="发送短讯息给 jacky" href="http://www.imtinewlife.com/BBS/MyFriend.asp?menu=Post&amp;incept=jacky"><u><font color=#0000ff>短讯</font></u></a> <a class=TextButton title="发送电邮给 jacky" href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#108;&#105;&#117;&#113;&#105;&#97;&#110;&#106;&#107;&#64;&#50;&#49;&#99;&#110;&#46;&#99;&#111;&#109;"><u><font color=#0000ff>邮箱</font></u></a> <a class=TextButton title="把 jacky 加入好友" href="http://www.imtinewlife.com/BBS/MyFriend.asp?menu=add&amp;UserName=jacky"><u><font color=#0000ff>好友</font></u></a> <a class=TextButton title="搜索 jacky 发表过的所有主题" href="http://www.imtinewlife.com/BBS/ShowBBS.asp?menu=5&amp;UserName=jacky"><u><font color=#0000ff>搜索</font></u></a> <a class=TextButton title=引用回复这个帖子 href="http://www.imtinewlife.com/BBS/ReTopic.asp?ThreadID=412&amp;PostID=865&amp;quote=True"><u><font color=#0000ff>引用</font></u></a> <a class=TextButton title=回复帖子 href="http://www.imtinewlife.com/BBS/ReTopic.asp?ThreadID=412&amp;PostID=865"><u><font color=#0000ff>回复</font></u></a> </td>
        </tr>
        <tr vAlign=top height=1>
            <td colSpan=2>
            <hr width="100%" SIZE=1>
            </td>
        </tr>
        <tr>
            <td vAlign=top colSpan=2 height="100%">
            <div style="OVERFLOW: auto; WIDTH: 100%">
            <div style="OVERFLOW: auto; WIDTH: 100%"><br>手机可分为智能手机开发和feather phone手机。开发平台可分为开放式平台和封闭式平台，开放式平台包括symbian、windows mobile、linux、Android、BlackBerry、j2me、brew等，支持手机应用程序通过OTA下载和安装；封闭式平台包括MTK、展讯、TI、飞利浦等。下面分别介绍。 <br>1． Symbian： <br>Symbian平台为目前智能手机市场的老大，智能手机全球市场占70%以上，在欧洲和亚洲占绝对优势，只是在美国市场份额少得可怜，希望今年nokia在美国发力，赶上其它智能手机。根据UI风格的不同，Symbian分为s60和UIQ两个平台，其中nokia使用s60平台，索爱和moto采用UIQ平台。Symbian平台由于发展时间较长，又是市场老大，目前中文资料也较多，不像几年前刚接触时只有英文资料。以下书籍值得推荐： <br>《SYMBIAN OS软件开发开发--应用C++开发智能手机应用程序入门》（其中UI部分为UIQ平台）， <br>《Series 60 应用程序开发》（以s60平台为主，重点推荐） <br>《Symbian OS C++手机应用开发 （第2卷）》 <br>另外今年将出来一本有关uiq3.0的新书，值得期待。 <br>关于symbian的开发网站和论坛： <br>诺基亚论坛：最好的symbian论坛， <br><a href="http://discussion.forum.nokia.com/forum/forumdisplay.php?f=6" target=_blank><u><font color=#0000ff>http://discussion.forum.nokia.com/forum/forumdisplay.php?f=6</font></u></a>，其中还有中文论坛。 <br>UIQ官方论坛：<a href="http://developer.uiq.com/" target=_blank><u><font color=#0000ff>http://developer.uiq.com/</font></u></a> <br>Symbian公司中文论坛：<a href="http://developer.symbian.com/forum/forum.jspa?forumID=37" target=_blank><u><font color=#0000ff>http://developer.symbian.com/forum/forum.jspa?forumID=37</font></u></a> <br>NewLC网站：<a href="http://www.newlc.com/" target=_blank><u><font color=#0000ff>http://www.newlc.com/</font></u></a> <br>索爱uiq官方论坛：<a href="http://developer.sonyericsson.com/category.jspa?categoryID=3" target=_blank><u><font color=#0000ff>http://developer.sonyericsson.com/category.jspa?categoryID=3</font></u></a> <br>索爱uiq中文论坛<a href="http://developer.sonyericsson.com/forum.jspa?forumID=133" target=_blank><u><font color=#0000ff>http://developer.sonyericsson.com/forum.jspa?forumID=133</font></u></a> <br><br>2．windows mobile： <br>智能手机全球市场中windows mobile占12%左右市场份额。开发与windows平台类似，所以熟悉windows开发的能很快上手。目前没有较好的针对windows mobile的书，经典书籍《Windows 程序设计（第5版）》对于开发win32程序依然是最好的，经典的书就是牛啊！虽然pocket pc支持MFC，但smartphone不支持，所以为了更好的移植，用win32开发较好。由本书做基础，再参考windows mobile的sdk以及示例代码，应该能很快上手。 <br>关于windows mobile的开发网站和论坛： <br>Windows mobile中文社区：<a href="http://www.winbile.net/BBS/" target=_blank><u><font color=#0000ff>http://www.winbile.net/BBS/</font></u></a> <br>Pocket pc forum：<a href="http://www.windowsmobiledn.com/forum" target=_blank><u><font color=#0000ff>http://www.windowsmobiledn.com/forum</font></u></a>/ <br>微软官方网站：<a href="http://www.microsoft.com/windowsmobile/developers/default.mspx" target=_blank><u><font color=#0000ff>http://www.microsoft.com/windowsmobile/developers/default.mspx</font></u></a> <br><br>3． linux： <br>智能手机全球市场中linux手机仅占可怜的4.4%市场份额。原来moto还出过不少linux手机，如A768、A1200、E680、E2、E6、V8等，07年8月份还信誓旦旦预测60%手机采用Linux OS，但moto后来回购了UIQ的股份，又与微软合作，还加入了google的开放手机联盟，看来要抛弃自己的linux平台了。另外，moto的策略是linux+j2me的模式，虽然采用linux os，但并不对外开放linux的sdk，只有和moto合作的厂家才能获得native linux sdk，所以导致目前linux手机开发的资料和论坛较少。虽然有民间linux高手破解了moto的linux的sdk，可以开发native linux的程序，但native linux的程序不能直接安装在moto的linux手机上，还必须安装一个插件，这对普通用户又是难以跨越的一个门槛。所以个人觉得native linux手机的开发将走向末路。大部分linux手机的ui开发都是基于QT，关于QT开发，可参考《C++ GUI Qt3编程》、《精通Qt4编程》，如果有moto官方的sdk，参考API文档以及一些示例代码，将可以较快上手，如果没有官方的sdk，那就要话很长时间hack了。目前没有很好的关于linux手机开发的论坛，个人推荐陈罡的博客<a href="http://www.cublog.cn/u/26691/" target=_blank><u><font color=#0000ff>http://www.cublog.cn/u/26691/</font></u></a>，内有moto a1200开发随笔，对于熟悉和了解手机native linux开发有很大帮助。 <br><br>4． MTK： <br>MTK最近几年异军突起，近70%的国产手机采用MTK的芯片和平台，黑手机更几乎是MTK的代名词。国内厂家只有夏新没有采用MTK的方案。MTK的模式名为&#8220;Turn-key&#8221;的全面解决方案，厂商采用了这个方案，只需要加一个手机外壳即可成品——这能大大降低了出货时间，一般厂家只修改界面、铃声以及增加一些应用软件。有关MTK平台的介绍，见环球企业家杂志的文章&#8220;国产手机操纵者联发科的秘密&#8221;<a href="http://www.cnbeta.com/articles/45580.htm" target=_blank><u><font color=#0000ff>http://www.cnbeta.com/articles/45580.htm</font></u></a>。 <br>MTK是私有平台，目前没有书籍介绍MTK平台，所以只能从网上查找MTK的资料。以下资料大家可以从网上获得，对于了解MTK很有帮助：《mtk 训练课程.pdf》、《MMI Platform Source Code Training.pdf》主要是MMI界面开发介绍、《MMI Resource &amp; Customization Tool.pdf》MMI资源工具介绍。 <br>最近，MTK平台ＭＭＩ设计牛人ＦＵＧＵＩ自己编写了一本有关mtk平台MMI开发的实例教程，书名为《MMI实例培训教程》（本书大家通过Google下载到），此书深入浅出，全面的介绍了MTK平台MMI开发的各个方面，通过本书，开发人员将能很快进入MTK平台开发领域，实为MTK平台MMI开发的圣经！MTK平台的操作系统为nucleus，有关nucleus的介绍网上有一篇文章《Nucleus实时操作系统分析报告》。MTK平台主要用C语言开发，所以要熟悉MTK开发，首先必须熟悉掌握C语言，MTK的sdk与vc6集成，MMI的各控件和窗口之间通过回调函数实现通讯。 <br>关于MTK的开发网站和论坛： <br>我爱研发网：<a href="http://www.52rd.com/" target=_blank><u><font color=#0000ff>http://www.52rd.com/</font></u></a> 上面几篇文章和书籍都能从本网站找到。 <br>手机研发论坛：<a href="http://www.1mp.cc/bbs/index.asp" target=_blank><u><font color=#0000ff>http://www.1mp.cc/bbs/index.asp</font></u></a> <br><br><br>5． 展讯： <br>展讯平台07年也发展很快，利用MTK下半年PA放大器缺货的机会，趁势而入，抢走mtk很多市场份额。展讯的开发模式和MTK的很类似，基本也是给厂家提供整体解决方案，与MTK的差别见此链接<a href="http://www.chinabyte.com/telecom/267/2507267.shtml" target=_blank><u><font color=#0000ff>http://www.chinabyte.com/telecom/267/2507267.shtml</font></u></a>。国内主要是夏新、联想、文泰等采用展讯平台。展讯平台采用的嵌入式操作系统是threadx，关于threadx的有一本中文书《嵌入式实时操作系统的多线程计算：基于ThreadX和ARM》。同MTK平台一样，为封闭平台，开发语言为C，开发环境为vc6, MMI的各控件和窗口之间与windows类似通过消息进制实现通讯。另外也没有书籍介绍展讯平台，以下资料值得推荐： <br>《Spreadtrum_SAP.ppt》 <br>《MMK_Kernel软件API接口说明书.doc》 <br>《MMK_Window_Table开发说明书.doc》 <br>《展讯平台MMI窗口开发说明书.pdf》 <br>《展讯手机平台软件简介.pdf》 <br>关于展讯的开发网站和论坛： <br>我爱研发网：<a href="http://www.52rd.com/" target=_blank><u><font color=#0000ff>http://www.52rd.com/</font></u></a> 上面几篇文章都能从本网站找到。 <br>手机研发论坛：<a href="http://www.1mp.cc/bbs/index.asp" target=_blank><u><font color=#0000ff>http://www.1mp.cc/bbs/index.asp</font></u></a> <br><br>6． J2ME： <br>J2ME平台为手机上运用最广泛的开放式平台，绝大部分手机均已经支持J2ME了。关于J2ME的书籍数不胜数，个人推荐以下书籍： <br>《j2me技术手册》 <br>《J2ME开发大全》 <br>《J2ME移动应用程序开发》 <br>关于J2ME的开发网站和论坛： <br>J2ME开发网：<a href="http://www.j2medev.com/Index.html" target=_blank><u><font color=#0000ff>http://www.j2medev.com/Index.html</font></u></a> <br>中国Java手机网：<a href="http://www.cnjm.net/" target=_blank><u><font color=#0000ff>http://www.cnjm.net/</font></u></a> <br>以及各手机厂商的官方java论坛 <br><br>7． Brew <br>Brew 的全称是无线二进制运行时环境。Brew平台是高通公司开发的，从无线应用程序开发、设备配置、应用程序分发以及计费和支付的完整端到端解决方案中的无线应用程序开发部分。目前绝大部分CDMA手机都支持Brew平台。学习Brew平台，首先需要熟悉c语言。学习步骤和方法可参考&#8221; BREW高手之路－解析BREW学习过程&#8221;。 <br>学习书籍： <br>《深入BREW手机游戏开发》 <br>《BREW 技术开发与应用》 <br>这些书虽然不够深入，但对于入门还是可以参考的。 <br>关于Brew的开发网站和论坛： <br>Brew官方论坛：<a href="http://brewforums.qualcomm.com/index.php" target=_blank><u><font color=#0000ff>http://brewforums.qualcomm.com/index.php</font></u></a> <br><br>8． Blackberry，Android，iPhone <br>黑莓公司BlackBerry手机和Google的Android手机均只支持java开发。苹果的iPhone不支持第3方开发，只能开发网页，据说将来开放sdk，值得期待。 <br>BlackBerry的开发网站和论坛： <br>BlackBerry开发者指南：<a href="http://www.cnblogs.com/confach/category/36451.html" target=_blank><u><font color=#0000ff>http://www.cnblogs.com/confach/category/36451.html</font></u></a>BlackBerry官方网站：<a href="http://na.blackberry.com/eng/developers/community.jsp" target=_blank><u><font color=#0000ff>http://na.blackberry.com/eng/developers/community.jsp</font></u></a><a href="http://bbs.maxpda.com/forum-184-1.html" target=_blank><u><font color=#0000ff>http://bbs.maxpda.com/forum-184-1.html</font></u></a> <br>Android的开发网站和论坛： <br><a href="http://www.androiddev.net.cn/bbs/" target=_blank><u><font color=#0000ff>http://www.androiddev.net.cn/bbs/</font></u></a> <br><a href="http://www.androidin.com/" target=_blank><u><font color=#0000ff>http://www.androidin.com/</font></u></a><a href="http://www.androidcn.net/" target=_blank><u><font color=#0000ff>http://www.androidcn.net/</font></u></a> <br>iPhone的开发网站和论坛： <br>一群苹果fans成立的网站：<a href="http://apple4.us/" target=_blank><u><font color=#0000ff>http://apple4.us/</font></u></a> <br><a href="http://bbs.maxpda.com/forum-190-1.html" target=_blank><u><font color=#0000ff>http://bbs.maxpda.com/forum-190-1.html</font></u></a> <br><a href="http://lordhong.javaeye.com/blog/153315" target=_blank><u><font color=#0000ff>http://lordhong.javaeye.com/blog/153315</font></u></a> <br><a href="http://lordhong.javaeye.com/blog/152774" target=_blank><u><font color=#0000ff>http://lordhong.javaeye.com/blog/152774</font></u></a> <br><br>9． 其它Feather phone平台 <br>其它feather phone平台，如TI、飞利浦、英飞凌（Infineon）、飞思卡尔（Freescale）、Broadcom、Skyworks等平台，由于平台私有，并且不提供第三方sdk，所以也没有相关资料和文档，希望有了解的朋友介绍一下。</div>
            </div>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/47094.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/gtwdaizi/" target="_blank">郭天文</a> 2008-04-15 09:31 <a href="http://www.cppblog.com/gtwdaizi/articles/47094.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[S60]在程序的导航条中插入文本或图片</title><link>http://www.cppblog.com/gtwdaizi/articles/46743.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Thu, 10 Apr 2008 03:04:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/46743.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/46743.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/46743.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/46743.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/46743.html</trackback:ping><description><![CDATA[<ul>
    <li>开发伙伴平台： </li>
</ul>
<p>S60 3rd Edition </p>
<p><br></p>
<ul>
    <li>详细描述 </li>
</ul>
<p>S60应用程序在前台时，可以设置导航条显示自定义图标或文本。 </p>
<p><br>首先，我们要获得一个状态栏的引用。然后可以从中获得导航栏的引用。应用程序可以使用CAknNavigationDecorator类生成一个基于文本的Navi decorator对象。最后这个对象需要添加到导航栏中以便开始显示： </p>
<pre>//------------------------------------------------------------------------------
&nbsp;
CAknNavigationControlContainer* iNaviPane = 0;
&nbsp;
CAknNavigationDecorator* iNaviDecorator = 0;
&nbsp;
//Get the reference of the status pane
&nbsp;
CEikStatusPane *statusPane = iEikonEnv-&gt;AppUiFactory()-&gt;StatusPane();
&nbsp;
if ( statusPane )
&nbsp;
{
&nbsp;
//Get the reference of the navi pane
&nbsp;
iNaviPane=static_cast&lt;CAknNavigationControlContainer*&gt;(statusPane-&gt;ControlL(
&nbsp;
TUid::Uid(EEikStatusPaneUidNavi)) );
&nbsp;
//Create a Navi decorator object
&nbsp;
iNaviDecorator= iNaviPane-&gt;CreateEditorIndicatorContainerL();
&nbsp;
//Get the reference of the indicator container inside the NaviDecorator
&nbsp;
CAknIndicatorContainer* indiContainer =
&nbsp;
static_cast&lt;CAknIndicatorContainer*&gt;(iNaviDecorator-&gt;DecoratedControl());
&nbsp;
if ( indiContainer &amp;&amp; CEikStatusPaneBase::Current() )
&nbsp;
{
&nbsp;
TBuf&lt;32&gt; msgSize;
&nbsp;
msgSize.Append(_L("Test")); // Text to be displayed
&nbsp;
&nbsp;
indiContainer-&gt;SetIndicatorValueL(
&nbsp;
TUid::Uid( EAknNaviPaneEditorIndicatorMessageLength ), msgSize );
&nbsp;
&nbsp;
indiContainer-&gt;SetIndicatorState(
&nbsp;
TUid::Uid( EAknNaviPaneEditorIndicatorMessageLength ),
&nbsp;
EAknIndicatorStateOn);
&nbsp;
}
&nbsp;
&nbsp;
&nbsp;
//Push the object onto the navi pane.
&nbsp;
iNaviPane-&gt;PushL( *iNaviDecorator );
&nbsp;
}
&nbsp;
//------------------------------------------------------------------------------</pre>
<p><br>下面的这个示例代码，演示了如何在导航栏中显示一个图标： </p>
<pre>//------------------------------------------------------------------------------
&nbsp;
CFbsBitmap* bitmap = NULL;
&nbsp;
CFbsBitmap* mask = NULL;
&nbsp;
CEikStatusPane* statusPane = iEikonEnv-&gt;AppUiFactory()-&gt;StatusPane();
&nbsp;
CAknNavigationControlContainer* naviPane =
&nbsp;
(CAknNavigationControlContainer*)statusPane-&gt;ControlL(
&nbsp;
TUid::Uid(EEikStatusPaneUidNavi));
&nbsp;
// Create an icon
&nbsp;
AknIconUtils::CreateIconLC (bitmap, mask, KIconFile,
&nbsp;
EMbmCarsvgCircle, EMbmCarsvgCircle_mask); //KIconFile is the .mif file
&nbsp;
&nbsp;
TSize size(30,30);
&nbsp;
AknIconUtils::SetSize(bitmap, size); // Sets the size of the extracted image
&nbsp;
//Create a Navi Decorator encapsulation for the image.
&nbsp;
CAknNavigationDecorator* naviDecorator =
&nbsp;
naviPane-&gt;CreateNavigationImageL(bitmap, mask);
&nbsp;
//Push the image onto the navi pane.
&nbsp;
naviPane-&gt;PushL(*naviDecorator);
&nbsp;
//------------------------------------------------------------------------------</pre>
<p><br>需要的头文件及库文件有： </p>
<pre>#include &lt;aknnavi.h&gt;               // for CAknNavigationControlContainer
&nbsp;
#include &lt;eikspane.h&gt;              // for CEikStatusPane
&nbsp;
#include &lt;aknnavide.h&gt;             // for CAknNavigationDecorator
&nbsp;
#include &lt;akniconutils.h&gt;          // for AknIconUtils
&nbsp;
#include &lt;aknindicatorcontainer.h&gt; // for CAknIndicatorContainer
&nbsp;
LIBRARY     aknicon.lib
&nbsp;
LIBRARY     fbscli.lib
&nbsp;
LIBRARY     avkon.lib</pre>
<p><br></p>
<p>注意：程序在前台时这些导航栏上的文字和图标才得以显现，但手机待机时却不会处理。 </p>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/46743.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/gtwdaizi/" target="_blank">郭天文</a> 2008-04-10 11:04 <a href="http://www.cppblog.com/gtwdaizi/articles/46743.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>音频编解码标准</title><link>http://www.cppblog.com/gtwdaizi/articles/41884.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Fri, 25 Jan 2008 05:29:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/41884.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/41884.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/41884.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/41884.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/41884.html</trackback:ping><description><![CDATA[<dd>
<div><br><span style="COLOR: red">PCMU(G.711U)<br></span>类型：Audio<br>制定者：ITU-T<br>所需频宽：64Kbps(90.4)<br>特性：PCMU和PCMA都能提供较好的语音质量，但是它们占用的带宽较高，需要64kbps。<br>优点：语音质量优<br>缺点：占用的带宽较高<br>应用领域：voip<br>版税方式：Free<br>备注：PCMU and PCMA都能够达到CD音质，但是它们消耗的带宽也最多(64kbps)。如果网络带宽比较低，可以选用低比特速率的编码方法，如G.723或G.729，这两种编码的方法也能达到传统长途电话的音质，但是需要很少的带宽（G723需要5.3/6.3kbps，G729需要8kbps）。如果带宽足够并且需要更好的语音质量，就使用PCMU 和 PCMA，甚至可以使用宽带的编码方法G722(64kbps)，这可以提供有高保真度的音质。<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <br><br><span style="COLOR: red">PCMA(G.711A)<br></span>类型：Audio<br>制定者：ITU-T<br>所需频宽：64Kbps(90.4)<br>特性：PCMU和PCMA都能提供较好的语音质量，但是它们占用的带宽较高，需要64kbps。<br>优点：语音质量优<br>缺点：占用的带宽较高<br>应用领域：voip<br>版税方式：Free<br>备注：PCMU and PCMA都能够达到CD音质，但是它们消耗的带宽也最多(64kbps)。如果网络带宽比较低，可以选用低比特速率的编码方法，如G.723或G.729，这两种编码的方法也能达到传统长途电话的音质，但是需要很少的带宽（G723需要5.3/6.3kbps，G729需要8kbps）。如果带宽足够并且需要更好的语音质量，就使用PCMU 和 PCMA，甚至可以使用宽带的编码方法G722(64kbps)，这可以提供有高保真度的音质。</div>
<dt>&nbsp;
<dd>
<div><br><span style="COLOR: red">ADPCM(自适应差分PCM)<br></span>类型：Audio<br>制定者：ITU-T<br>所需频宽：32Kbps<br>特性：ADPCM(adaptive difference pulse code modulation)综合了APCM的自适应特性和DPCM系统的差分特性，是一种性能比较好的波形编码。它的核心想法是：<br>&nbsp; &nbsp;&nbsp; &nbsp; ①利用自适应的思想改变量化阶的大小，即使用小的量化阶(step-size)去编码小的差值，使用大的量化阶去编码大的差值；<br>&nbsp; &nbsp;&nbsp; &nbsp; ②使用过去的样本值估算下一个输入样本的预测值，使实际样本值和预测值之间的差值总是最小。<br>优点：算法复杂度低，压缩比小（CD音质&gt;400kbps），编解码延时最短（相对其它技术）<br>缺点：声音质量一般<br>应用领域：voip<br>版税方式：Free<br>备注：ADPCM (ADPCM Adaptive Differential Pulse Code Modulation), 是一种针对 16bit (或者更高?) 声音波形数据的一种有损压缩算法, 它将声音流中每次采样的 16bit 数据以 4bit 存储, 所以压缩比 1:4. 而压缩/解压缩算法非常的简单, 所以是一种低空间消耗,高质量声音获得的好途径。<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<br><br><span style="COLOR: red">LPC(Linear Predictive Coding，线性预测编码)<br></span>类型：Audio<br>制定者： <br>所需频宽：2Kbps-4.8Kbps<br>特性：压缩比大，计算量大，音质不高，廉价<br>优点：压缩比大,廉价<br>缺点：计算量大，语音质量不是很好，自然度较低<br>应用领域：voip<br>版税方式：Free<br>备注：参数编码又称为声源编码，是将信源信号在频率域或其它正交变换域提取特征参数，并将其变换成数字代码进行传输。译码为其反过程，将收到的数字序列经变换恢复特征参量，再根据特征参量重建语音信号。具体说，参数编码是通过对语音信号特征参数的提取和编码，力图使重建语音信号具有尽可能高的准确性，但重建信号的波形同原语音信号的波形可能会有相当大的差别。如：线性预测编码（LPC）及其它各种改进型都属于参数编码。该编码比特率可压缩到2Kbit/s-4.8Kbit/s，甚至更低，但语音质量只能达到中等，特别是自然度较低。</div>
<dt>&nbsp;
<dd>
<div><br><span style="COLOR: red">CELP(Code Excited Linear Prediction，码激励线性预测编码)<br></span>类型：Audio<br>制定者：欧洲通信标准协会（ETSI）<br>所需频宽：4～16Kbps的速率<br>特性：改善语音的质量：<br>&nbsp; &nbsp;&nbsp; &nbsp; ① 对误差信号进行感觉加权，利用人类听觉的掩蔽特性来提高语音的主观质量；<br>&nbsp; &nbsp;&nbsp; &nbsp; ②用分数延迟改进基音预测，使浊音的表达更为准确，尤其改善了女性语音的质量；<br>&nbsp; &nbsp;&nbsp; &nbsp; ③ 使用修正的MSPE准则来寻找 &#8220;最佳&#8221;的延迟，使得基音周期延迟的外形更为平滑；<br>&nbsp; &nbsp;&nbsp; &nbsp; ④根据长时预测的效率，调整随机激励矢量的大小，提高语音的主观质量；&nbsp; &nbsp;&nbsp; &nbsp; ⑤ 使用基于信道错误率估计的自适应平滑器，在信道误码率较高的情况下也能合成自然度较高的语音。<br>&nbsp; &nbsp;&nbsp; &nbsp; 结论：<br>&nbsp; &nbsp;&nbsp; &nbsp; ① CELP算法在低速率编码环境下可以得到令人满意的压缩效果；<br>&nbsp; &nbsp;&nbsp; &nbsp; ②使用快速算法，可以有效地降低CELP算法的复杂度，使它完全可以实时地实现；<br>&nbsp; &nbsp;&nbsp; &nbsp; ③CELP可以成功地对各种不同类型的语音信号进行编码，这种适应性对于真实环境，尤其是背景噪声存在时更为重要。<br>优点：用很低的带宽提供了较清晰的语音<br>缺点：<br>应用领域：voip<br>版税方式：Free<br>备注：1999年欧洲通信标准协会（ETSI）推出了基于码激励线性预测编码（CELP）的第三代移动通信语音编码标准自适应多速率语音编码器（AMR），其中最低速率为4.75kb/s，达到通信质量。CELP 码激励线性预测编码是Code Excited Linear Prediction的缩写。CELP是近10年来最成功的语音编码算法。<br>&nbsp; &nbsp;&nbsp; &nbsp; CELP语音编码算法用线性预测提取声道参数，用一个包含许多典型的激励矢量的码本作为激励参数，每次编码时都在这个码本中搜索一个最佳的激励矢量，这个激励矢量的编码值就是这个序列的码本中的序号。<br>&nbsp; &nbsp;&nbsp; &nbsp; CELP已经被许多语音编码标准所采用，美国联邦标准FS1016就是采用CELP的编码方法，主要用于高质量的窄带语音保密通信。CELP (Code-Excited Linear Prediction) 这是一个简化的 LPC 算法，以其低比特率著称 (4800-9600Kbps)，具有很清晰的语音品质和很高的背景噪音免疫性。CELP是一种在中低速率上广泛使用的语音压缩编码方案。<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <br><br><span style="COLOR: red">G.711<br></span>类型：Audio<br>制定者：ITU-T<br>所需频宽：64Kbps<br>特性：算法复杂度小，音质一般<br>优点：算法复杂度低，压缩比小（CD音质&gt;400kbps），编解码延时最短（相对其它技术）<br>缺点：占用的带宽较高<br>应用领域：voip<br>版税方式：Free<br>备注：70年代CCITT公布的G.711 64kb/s脉冲编码调制PCM。<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br><br><span style="COLOR: red">G.721</span><br>类型：Audio<br>制定者：ITU-T<br>所需频宽：32Kbps<br>特性：相对于PCMA和PCMU，其压缩比较高，可以提供2：1的压缩比。<br>优点：压缩比大<br>缺点：声音质量一般<br>应用领域：voip<br>版税方式：Free<br>备注：子带ADPCM（SB-ADPCM）技术。G.721标准是一个代码转换系统。它使用ADPCM转换技术，实现64 kb/s A律或&#956;律PCM速率和32 kb/s速率之间的相互转换。</div>
<dt>&nbsp;
<dd>
<div><br><span style="COLOR: red">G.722</span><br>类型：Audio<br>制定者：ITU-T<br>所需频宽：64Kbps<br>特性：G722能提供高保真的语音质量<br>优点：音质好<br>缺点：带宽要求高<br>应用领域：voip<br>版税方式：Free<br>备注：子带ADPCM（SB-ADPCM）技术<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<br><br><span style="COLOR: red">G.723(低码率语音编码算法)<br></span>类型：Audio<br>制定者：ITU-T<br>所需频宽：5.3Kbps/6.3Kbps<br>特性：语音质量接近良，带宽要求低，高效实现，便于多路扩展，可利用C5402片内16kRAM实现53coder。达到ITU-TG723要求的语音质量，性能稳定。可用于IP电话语音信源编码或高效语音压缩存储。<br>优点：码率低，带宽要求较小。并达到ITU-TG723要求的语音质量，性能稳定。<br>缺点：声音质量一般<br>应用领域：voip<br>版税方式：Free<br>备注：G.723语音编码器是一种用于多媒体通信，编码速率为5.3kbits/s和6.3kbit/s的双码率编码方案。G.723标准是国际电信联盟（ITU）制定的多媒体通信标准中的一个组成部分，可以应用于IP电话等系统中。其中，5.3kbits/s码率编码器采用多脉冲最大似然量化技术（MP－MLQ），6.3kbits/s码率编码器采用代数码激励线性预测技术。<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <br><br><span style="COLOR: red">G.723.1(双速率语音编码算法)<br></span>类型：Audio<br>制定者：ITU-T<br>所需频宽：5.3Kbps(22.9)<br>特性：能够对音乐和其他音频信号进行压缩和解压缩，但它对语音信号来说是最优的。G.723.1采用了执行不连续传输的静音压缩，这就意味着在静音期间的比特流中加入了人为的噪声。除了预留带宽之外，这种技术使发信机的调制解调器保持连续工作，并且避免了载波信号的时通时断。<br>优点：码率低，带宽要求较小。并达到ITU-TG723要求的语音质量，性能稳定,避免了载波信号的时通时断。<br>缺点：语音质量一般<br>应用领域：voip<br>版税方式：Free<br>备注：G.723.1算法是 ITU-T建议的应用于低速率多媒体服务中语音或其它音频信号的压缩算法，其目标应用系统包括H.323、H.324等多媒体通信系统 。目前该算法已成为IP电话系统中的必选算法之一。<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <br><br><span style="COLOR: red">G.728<br></span>类型：Audio<br>制定者：ITU-T<br>所需频宽：16Kbps/8Kbps<br>特性：用于IP电话、卫星通信、语音存储等多个领域。G.728是一种低时延编码器，但它比其它的编码器都复杂，这是因为在编码器中必须重复做50阶LPC分析。G.728还采用了自适应后置滤波器来提高其性能。<br>优点：后向自适应，采用自适应后置滤波器来提高其性能<br>缺点：比其它的编码器都复杂<br>应用领域：voip<br>版税方式：Free<br>备注：G.728 16kb/s短延时码本激励线性预测编码（LD-CELP）。1996年ITU公布了G.728 8kb/s的CS－ACELP算法，可以用于IP电话、卫星通信、语音存储等多个领域。16 kbps G.728低时延码激励线性预测。 <br>&nbsp; &nbsp;&nbsp; &nbsp; G.728是低比特线性预测合成分析编码器（G.729和G.723.1）和后向ADPCM编码器的混合体。G.728是LD-CELP编码器，它一次只处理5个样点。对于低速率（56~128 kbps）的综合业务数字网（ISDN）可视电话，G.728是一种建议采用的语音编码器。由于其后向自适应特性，因此G.728是一种低时延编码器，但它比其它的编码器都复杂，这是因为在编码器中必须重复做50阶LPC分析。G.728还采用了自适应后置滤波器来提高其性能。</div>
<dt>&nbsp;
<dd>
<div><br><span style="COLOR: red">G.729<br></span>类型：Audio<br>制定者：ITU-T<br>所需频宽：8Kbps<br>特性：在良好的信道条件下要达到长话质量，在有随机比特误码、发生帧丢失和多次转接等情况下要有很好的稳健性等。这种语音压缩算法可以应用在很广泛的领域中，包括ＩＰ电话、无线通信、数字卫星系统和数字专用线路。<br>&nbsp; &nbsp;&nbsp; &nbsp; G.729算法采用&#8220;共轭结构代数码本激励线性预测编码方案&#8221;（CS-ACELP）算法。这种算法综合了波形编码和参数编码的优点，以自适应预测编码技术为基础，采用了矢量量化、合成分析和感觉加权等技术。<br>&nbsp; &nbsp;&nbsp; &nbsp; G.729编码器是为低时延应用设计的，它的帧长只有10ms，处理时延也是10ms，再加上5ms的前视，这就使得G.729产生的点到点的时延为25ms，比特率为8 kbps。<br>优点：语音质量良，应用领域很广泛，采用了矢量量化、合成分析和感觉加权，提供了对帧丢失和分组丢失的隐藏处理机制<br>缺点：在处理随机比特错误方面性能不好。<br>应用领域：voip<br>版税方式：Free<br>备注：国际电信联盟（ITU-T）于1995年11月正式通过了G.729。 ITU-T建议G.729也被称作&#8220;共轭结构代数码本激励线性预测编码方案&#8221;(CS-ACELP)，它是当前较新的一种语音压缩标准。G.729是由美国、法国、日本和加拿大的几家著名国际电信实体联合开发的。<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br><br><span style="COLOR: red">G.729A<br></span>类型：Audio<br>制定者：ITU-T<br>所需频宽：8Kbps(34.4)<br>特性：复杂性较G.729低，性能较G.729差。<br>优点：语音质量良，降低了计算的复杂度以便于实时实现，提供了对帧丢失和分组丢失的隐藏处理机制<br>缺点：性能较G.729差<br>应用领域：voip<br>版税方式：Free<br>备注：96年ITU-T又制定了G.729的简化方案G.729A，主要降低了计算的复杂度以便于实时实现，因此目前使用的都是G.729A。<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <br><br><span style="COLOR: red">GIPS<br></span>类型：Audio<br>制定者：瑞典Global IP Sound公司<br>所需频宽：<br>特性：GIPS技术可根据带宽状况自动调节编码码率，提供低码率高质量的音频。GIPS的核心技术（网络自适应算法，丢包补偿算法和回声消除算法）可很好地解决语音延迟与回声问题，带来完美音质，提供比电话还清晰的语音通话效果。<br>优点：很好地解决语音延迟与回声问题，带来完美音质，提供比电话还清晰的语音通话效果<br>缺点： 不是Free<br>应用领域：voip<br>版税方式：每年支付一笔使用权费用<br>备注：GIPS音频技术是由来自瑞典的全球顶尖的语音处理高科技公司--"GLOBAL IP SOUND"提供的专用于互联网的语音压缩引擎系统。GIPS技术可根据带宽状况自动调节编码码率，提供低码率高质量的音频。GIPS的核心技术（网络自适应算法，丢包补偿算法和回声消除算法）可很好地解决语音延迟与回声问题，带来完美音质，提供比电话还清晰的语音通话效果。<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <br><br><span style="COLOR: red">Apt-X</span><br>类型：Audio<br>制定者：Audio Processing Technology 公司<br>所需频宽：10Hz to 22.5 kHz，56kbit/s to 576 kbit/s(16 bit 7.5 kHz mono to 24-bit, 22.5kHz stereo)<br>特性：主要用于专业音频领域，提供高品质的音频。其特点是：<br>&nbsp; &nbsp;&nbsp; &nbsp; ①采用4:1:4的压缩与放大方案；<br>&nbsp; &nbsp;&nbsp; &nbsp; ②硬件低复杂度；<br>&nbsp; &nbsp;&nbsp; &nbsp; ③极低的编码延迟；<br>&nbsp; &nbsp;&nbsp; &nbsp; ④由单芯片实现；<br>&nbsp; &nbsp;&nbsp; &nbsp; ⑤单声道或立体声编解码；<br>&nbsp; &nbsp;&nbsp; &nbsp; ⑥只需单设备即可实现22.5kHz的双通道立体声；<br>&nbsp; &nbsp;&nbsp; &nbsp; ⑦高达48kHz的采样频率；<br>&nbsp; &nbsp;&nbsp; &nbsp; ⑧容错性好；<br>&nbsp; &nbsp;&nbsp; &nbsp; ⑨完整的AUTOSYNC&#8482;编解码同步方案；<br>&nbsp; &nbsp;&nbsp; &nbsp; ⑩低功率消耗<br>优点：高品质的音频，硬件复杂度低，设备要求低<br>缺点：不是Free<br>应用领域：voip<br>版税方式：一次性付费<br>备注：子带ADPCM（SB-ADPCM）技术</div>
<dt>&nbsp;
<dd>
<div><br><span style="COLOR: red">NICAM(Near Instantaneous Companded Audio Multiplex 准瞬时压扩音频复用)<br></span>类型：Audio<br>制定者：英国BBC广播公司<br>所需频宽：728Kbps<br>特性：应用范围及其广泛，可用它进行立体声或双语广播<br>优点：应用范围及其广泛，信噪比高，动态范围宽、音质同CD相媲美，故名丽音，因此NICAM又称为丽音<br>缺点：不是Free，频宽要求高<br>应用领域：voip<br>版税方式：一次性付费<br>备注：NICAM也称丽音，它是英文Near-Instantaneously Companded Audio Multiplex的缩写，其含义为准瞬时压扩音频复用，是由英国BBC广播公司开发研究成功的。<br>&nbsp; &nbsp;&nbsp; &nbsp; 通俗地说NICAM技术实际上就是双声道数字声技术，其应用范围及其广泛，最典型的应用便是电视广播附加双声道数字声技术，利用它进行立体声或双语广播，以充分利用电视频道的频谱资源。这是在常规电视广播的基础上无需增加许多投资就可以实现的。在进行立体声广播时，它提高了音频的信号质量，使其接近CD的质量。而且还可以利用NICAM技术进行高速数据广播及其他数据传输的增殖服务，这在当今的信息化社会中似乎就显得尤为重要了！<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <br><br><span style="COLOR: red">MPEG-1 audio layer 1</span><br>类型：Audio<br>制定者：MPEG<br>所需频宽：384kbps（压缩4倍）<br>特性：编码简单，用于数字盒式录音磁带，2声道，VCD中使用的音频压缩方案就是MPEG-1层Ⅰ。<br>优点：压缩方式相对时域压缩技术而言要复杂得多，同时编码效率、声音质量也大幅提高，编码延时相应增加。可以达到&#8220;完全透明&#8221;的声音质量（EBU音质标准）<br>缺点：频宽要求较高<br>应用领域：voip<br>版税方式：Free<br>备注：MPEG-1声音压缩编码是国际上第一个高保真声音数据压缩的国际标准，它分为三个层次：<br>--层1(Layer 1)：编码简单，用于数字盒式录音磁带<br>--层2(Layer 2)：算法复杂度中等，用于数字音频广播(DAB)和VCD等<br>--层3(Layer 3)：编码复杂，用于互联网上的高质量声音的传输，如MP3音乐压缩10倍<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <br><br><span style="COLOR: red">MUSICAM(MPEG-1 audio layer 2,即MP2)</span><br>类型：Audio<br>制定者：MPEG<br>所需频宽：256～192kbps（压缩6～8倍）<br>特性：算法复杂度中等，用于数字音频广播(DAB)和VCD等，2声道，而MUSICAM由于其适当的复杂程度和优秀的声音质量，在数字演播室、DAB、DVB等数字节目的制作、交换、存储、传送中得到广泛应用。<br>优点：压缩方式相对时域压缩技术而言要复杂得多，同时编码效率、声音质量也大幅提高，编码延时相应增加。可以达到&#8220;完全透明&#8221;的声音质量（EBU音质标准）<br>缺点：<br>应用领域：voip<br>版税方式：Free<br>备注：同MPEG-1 audio layer 1<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br><br><span style="COLOR: red">MP3(MPEG-1 audio layer 3)<br></span>类型：Audio<br>制定者：MPEG<br>所需频宽：128～112kbps（压缩10～12倍）<br>特性：编码复杂，用于互联网上的高质量声音的传输，如MP3音乐压缩10倍，2声道。MP3是在综合MUSICAM和ASPEC的优点的基础上提出的混合压缩技术，在当时的技术条件下，MP3的复杂度显得相对较高，编码不利于实时，但由于MP3在低码率条件下高水准的声音质量，使得它成为软解压及网络广播的宠儿。<br>优点：压缩比高，适合用于互联网上的传播<br>缺点：MP3在128KBitrate及以下时，会出现明显的高频丢失<br>应用领域：voip<br>版税方式：Free<br>备注：同MPEG-1 audio layer 1<br><br><span style="COLOR: red">MPEG-2 audio layer</span><br>类型：Audio<br>制定者：MPEG<br>所需频宽：与MPEG-1层1，层2，层3相同<br>特性：MPEG-2的声音压缩编码采用与MPEG-1声音相同的编译码器，层1, 层2和层3的结构也相同，但它能支持5.1声道和7.1声道的环绕立体声。<br>优点：支持5.1声道和7.1声道的环绕立体声<br>缺点：<br>应用领域：voip<br>版税方式：按个收取<br>备注：MPEG-2的声音压缩编码采用与MPEG-1声音相同的编译码器，层1, 层2和层3的结构也相同，但它能支持5.1声道和7.1声道的环绕立体声。</div>
<dt>&nbsp;
<dd>
<div><br><span style="COLOR: red">AAC(Advanced Audio Coding，先进音频编码)<br></span>类型：Audio<br>制定者：MPEG<br>所需频宽：96-128 kbps<br>特性：AAC可以支持1到48路之间任意数目的音频声道组合、包括15路低频效果声道、配音/多语音声道，以及15路数据。它可同时传送16套节目，每套节目的音频及数据结构可任意规定。<br>&nbsp; &nbsp;&nbsp; &nbsp; AAC主要可能的应用范围集中在因特网网络传播、数字音频广播，包括卫星直播和数字AM、以及数字电视及影院系统等方面。AAC使用了一种非常灵活的熵编码核心去传输编码频谱数据。具有48 个主要音频通道，16 个低频增强通道，16 个集成数据流, 16 个配音，16 种编排。<br>优点：支持多种音频声道组合，提供优质的音质<br>缺点： <br>应用领域：voip<br>版税方式：一次性收费<br>备注：AAC于1997年形成国际标准ISO 13818-7。先进音频编码（Advanced Audio Coding--AAC）开发成功，成为继MPEG-2音频标准（ISO/IEC13818-3）之后的新一代音频压缩标准。<br>&nbsp; &nbsp;&nbsp; &nbsp; 在MPEG-2制订的早期，本来是想将其音频编码部分保持与MPEG-1兼容的。但后来为了适应演播电视的要求而将其定义成为一个可以获得更高质量的多声道音频标准。理所当然地，这个标准是不兼容MPEG-1的，因此被称为MPEG-2 AAC。换句话说，从表面上看，要制作和播放AAC，都需要使用与MP3完全不同的工具。<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br><br><span style="COLOR: red">Dolby AC-3<br></span>类型：Audio<br>制定者：美国杜比公司<br>所需频宽：64kbps<br>特性：提供的环绕立体声系统由5个全频带声道加一个超低音声道组成，6个声道的信息在制作和还原过程中全部数字化，信息损失很少，细节丰富，具有真正的立体声效果，在数字电视、DVD和家庭影院中广泛使用。<br>优点：环绕立体声，信息损失很少，细节丰富，具有真正的立体声效果<br>缺点：<br>应用领域：voip<br>版税方式：按个收取<br>备注：杜比数字AC-3（Dolby Digital AC-3）：美国杜比公司开发的多声道全频带声音编码系统，它提供的环绕立体声系统由5个全频带声道加一个超低音声道组成，6个声道的信息在制作和还原过程中全部数字化，信息损失很少，细节丰富，具有真正的立体声效果，在数字电视、DVD和家庭影院中广泛使用。<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<br><br><span style="COLOR: red">ASPEC（Audio Spectral Perceptual Entropy Coding）<br></span>类型：Audio<br>制定者：AT&amp;T<br>所需频宽：64kps<br>特性：音频质量获得显著改善，不过计算复杂度也大大提高，而且在回响、低码率时声音质量严重下降。<br>优点：音频质量获得显著改善<br>缺点：计算复杂度的提高。块边界影响、预计算复杂度的提高。回响、低码率时声音质量严重下降<br>应用领域：voip<br>版税方式：按个收取<br>备注：变换压缩技术<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<br><br><span style="COLOR: red">PAC（Perceptual Audio Coder）<br></span>类型：Audio<br>制定者：AT&amp;T<br>所需频宽：64kps<br>特性：音频质量获得显著改善，不过在回响、低码率时声音质量严重下降。<br>优点：音频质量获得显著改善<br>缺点：块边界影响、预回响、低码率时声音质量严重下降<br>应用领域：voip<br>版税方式：按个收取<br>备注：变换压缩技术<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br><br><span style="COLOR: red">HR</span><br>类型：Audio<br>制定者： 飞利浦<br>所需频宽：8Kbps<br>特性：以增加GSM网络容量为目的,但是会损害语音质量;由于现在网络频率紧缺,一些大的运营商已经在大城市密集地带开通此方式以增加容量。<br>优点：系统容量大<br>缺点：语音质量差<br>应用领域：GSM<br>版税方式：按个收费<br>备注：HF半速率,是一种GSM语音编码方式。</div>
<dt>&nbsp;
<dd>
<div><br><span style="COLOR: red">FR<br></span>类型：Audio<br>制定者：飞利浦<br>所需频宽：13Kbps<br>特性：是一般的GSM手机的通信编码方式,可以获得达到4.1左右Qos的语音通信质量(国际电联规定语音通信质量Qos满分为5)<br>优点：语音质量得到了提高<br>缺点：系统容量降低<br>应用领域：GSM<br>版税方式：按个收费<br>备注：FR全速率，是一种GSM语音编码方式。<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <br><br><span style="COLOR: red">EFR<br></span>类型：Audio<br>制定者：飞利浦<br>所需频宽：13Kbps<br>特性：用于GSM手机基于全速率13Kbps的语音编码和发送,可以获得更好更清晰的语音质量(接近Qos4.7),需要网络服务商开通此项网络功能，手机才能配合实现。<br>优点：音质好<br>缺点：需要网络服务商开通此项网络功能，且系统容量降低<br>应用领域：GSM<br>版税方式：按个收费<br>备注：EFR增强型全速率,一种GSM网络语音的编码方式。</div>
<dt>&nbsp;
<dd>
<div><br><span style="COLOR: red">GSM-AMR(Adaptive Multi-Rate)<br></span>类型：Audio<br>制定者：飞利浦<br>所需频宽：8Kbps(4.75 Kbps~12.2 Kbps)<br>特性： 可以对语音进行替换和消音，平滑噪音，支持间断式传输，对语音进行动态侦查。能在各种网络条件下提供优质的语音效果。<br>优点：音质出色<br>缺点：<br>应用领域：GSM<br>版税方式：按个收费<br>备注：GSM-ASM是一种广泛使用在GPRS和W-CDMA网络上的音频标准。在规范ETSI GSM06.90中对GSM-AMR进行了定义。AMR语音编码是GSM 2+和WCDMA的默认编码标准，是第三代无线通讯系统的语音编码标准。GSM-AMR标准基于ACELP（代数激励线性预测）编码。它能在广泛的传输条件下提供高品质的语音效果。<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<br><br><span style="COLOR: red">EVRC(Enhanced Variable Rate Coder，增强型可变速率编码器)<br></span>类型：Audio<br>制定者：美国Qualcomm通信公司(即高通)<br>所需频宽：8Kbps或13Kbps<br>特性：支持三种码率（9.6 Kbps, 4.8 Kbps 和 1.2 Kbps），噪声抑制，邮件过滤。能在各种网络条件下提供优质的语音效果。<br>优点：音质出色<br>缺点：<br>应用领域：CDMA<br>版税方式：按个收费<br>备注：EVRC编码广泛使用于CDMA网络。EVRC标准遵循规范TIA IS-127的内容。EVRC编码基于RCELP（松弛码激励线性预测）标准。该编码可以以Rate 1（171bits/packet），Rate 1/2（80bits/packet）或是Rate 1/8（16bits/packet）的容量进行操作。在要求下，它也能产生空包（0bits/packet）。</div>
<dt>&nbsp;
<dd>
<div><br><span style="COLOR: red">QCELP(QualComm Code Excited Linear Predictive，受激线性预测编码)<br></span>类型：Audio<br>制定者：美国Qualcomm通信公司(即高通)<br>所需频宽：8k的语音编码算法(可工作于4/4.8/8/9.6Kbps等固定速率上，而且可变速率地工作于800Kbps～9600Kbps之间)<br>特性：使用适当的门限值来决定所需速率。QCELP是一种8k的语音编码算法(可以在8k的速率下提供接近13k的话音压缩质量)。这是一种可变速率话音编码，根据人的说话特性（大家应该能够体会我们日常的沟通和交流时并不是一直保持某种恒定的方式讲话，有间断、有不同的声音频率等都是人的自然表达）而采取的一种优化技术。<br>优点：话音清晰、背景噪声小，系统容量大<br>缺点： 不是Free<br>应用领域：CDMA<br>版税方式：每年支付一笔使用权费用<br>备注：QCELP，即QualComm Code Excited Linear Predictive（QualComm受激线性预测编码）。美国Qualcomm通信公司的专利语音编码算法，是北美第二代数字移动电话（CDMA）的语音编码标准（IS95）。这种算法不仅可工作于4/4.8/8/9.6kbit／s等固定速率上，而且可变速率地工作于800bit／s～9600bit／s之间。QCELP算法被认为是到目前为止效率效率最高的一种算法，它的主要特点之一，是使用适当的门限值来决定所需速率。I&#8216;1限值懈景噪声电平变化而变化，这样就抑制了背景噪声，使得即使在喧闹的环境中，也能得到良好的话音质量， CDMA8Kbit/s的话音近似GSM 13Mbit/s的话音。CDMA采用QCELP编码等一系列技术，具有话音清晰、背景噪声小等优势，其性能明显 优于其他无线移动通信系统，语音质量可以与有线电话媲美。 无线辐射低。</div>
</dd>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/41884.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/gtwdaizi/" target="_blank">郭天文</a> 2008-01-25 13:29 <a href="http://www.cppblog.com/gtwdaizi/articles/41884.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CEikonEnv类功能分析</title><link>http://www.cppblog.com/gtwdaizi/articles/38518.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Fri, 14 Dec 2007 07:04:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/38518.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/38518.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/38518.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/38518.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/38518.html</trackback:ping><description><![CDATA[<p>1.1 继承关系<br><br>CEikonEnv --&gt; CCoeEnv ,MApaAppStarter --&gt;CActive, CBase.<br><br>这个类本身是不能用来被继承的。主要的作用是给所有的 Uikon 的 controls <span><a class=vLink1 id=vad_8 onmouseover="if(typeof(showTitle)!='undefined'){this.title='';window.clearTimeout(hideTO);showTitle(event, this, 8,'');}" title="专业虚拟主机提供商 @Vogate.com" style="FONT-SIZE: 1em" onclick="" onmouseout="if(typeof(showTitle)!='undefined'){mouseIsOverLayer = false; mouseOverWhileLoad = false; hideTO = window.setTimeout('checkIfMouseOverLayer()',500);}" href="http://action.vogate.com/click/click.php?r=http%3A//tag.csdn.net/Article/c960877d-dcf5-48fb-8d5d-53068d8832a1.html&amp;ads_id=3300&amp;site_id=6235007045036118&amp;click=1&amp;url=http%3A//h.kelo8.com&amp;v=0&amp;k=%u63D0%u4F9B&amp;s=http%3A//www.sf.org.cn/Article/symbiandev/200509/232.html&amp;rn=274880" target=_blank><u><font color=#0000ff>提供</font></u></a></span>一个运行的<span><a class=vLink1 id=vad_9 onmouseover="if(typeof(showTitle)!='undefined'){this.title='';window.clearTimeout(hideTO);showTitle(event, this, 9,'');}" title="中国水资讯网.水论坛 @Vogate.com" style="FONT-SIZE: 1em" onclick="" onmouseout="if(typeof(showTitle)!='undefined'){mouseIsOverLayer = false; mouseOverWhileLoad = false; hideTO = window.setTimeout('checkIfMouseOverLayer()',500);}" href="http://action.vogate.com/click/click.php?r=http%3A//tag.csdn.net/Article/c960877d-dcf5-48fb-8d5d-53068d8832a1.html&amp;ads_id=3590&amp;site_id=6235007045036118&amp;click=1&amp;url=http%3A//www.cjk3d.net/news%7C%u65B0%u95FB%u4E2D%u5FC3%uFF1A%u79D1%u7814%u53CA%u5DE5%u7A0B%u76F8%u5173%u65B0%u95FB%3Bhttp%3A//top.cjk3d.net%7C%u4E2D%u56FD%u6C34%u5229%u7F51%u7AD9%u6392%u884C%u699C%3Bhttp%3A//wiki.cjk3d.net%7C%u57FA%u4E8Ewiki%u7684%u6C34%u79D1%u5B66%u77E5%u8BC6%u5E93%3Bhttp%3A//www.cjk3d.net/bbs%7C%u6C34%u8BBA%u575B%uFF1A%u6C34%u79D1%u5B66%u548C%u6C34%u5DE5%u7A0B%u793E%u533A%3Bhttp%3A//model.cjk3d.net%7C%u6C34%u52A8%u529B%u6570%u503C%u6A21%u62DF%uFF1A%u4EE3%u7801%u3001%u8F6F%u4EF6&amp;v=0&amp;k=%u73AF%u5883&amp;s=http%3A//www.sf.org.cn/Article/symbiandev/200509/232.html&amp;rn=869946" target=_blank><u><font color=#0000ff>环境</font></u></a></span>。这些环境包括很多项，比如说环境<span><a class=vLink1 id=vad_4 onmouseover="if(typeof(showTitle)!='undefined'){this.title='';window.clearTimeout(hideTO);showTitle(event, this, 4,'');}" title="" style="FONT-SIZE: 1em" onclick="" onmouseout="if(typeof(showTitle)!='undefined'){mouseIsOverLayer = false; mouseOverWhileLoad = false; hideTO = window.setTimeout('checkIfMouseOverLayer()',500);}" href="http://action.vogate.com/click/click.php?r=http%3A//tag.csdn.net/Article/c960877d-dcf5-48fb-8d5d-53068d8832a1.html&amp;ads_id=3991&amp;site_id=6235007045036118&amp;click=1&amp;url=http%3A//www.ctrip.com/smartlink/smartlink.asp%3Fc%3Dvg%26url%3Dhttp%3A//flights.ctrip.com/Domestic/SearchFlights.aspx&amp;v=0&amp;k=%u5B57%u4F53&amp;s=http%3A//www.sf.org.cn/Article/symbiandev/200509/232.html&amp;rn=947599" target=_blank><u><font color=#0000ff>字体</font></u></a></span>，环境<span><a class=vLink1 id=vad_3 onmouseover="if(typeof(showTitle)!='undefined'){this.title='';window.clearTimeout(hideTO);showTitle(event, this, 3,'');}" title="TCL电视 @Vogate.com" style="FONT-SIZE: 1em" onclick="" onmouseout="if(typeof(showTitle)!='undefined'){mouseIsOverLayer = false; mouseOverWhileLoad = false; hideTO = window.setTimeout('checkIfMouseOverLayer()',500);}" href="http://action.vogate.com/click/click.php?r=http%3A//tag.csdn.net/Article/c960877d-dcf5-48fb-8d5d-53068d8832a1.html&amp;ads_id=312&amp;site_id=6235007045036118&amp;click=1&amp;url=http%3A//www.tclking.com/minisite/b68web/main.htm&amp;v=0&amp;k=%u56FE%u7247&amp;s=http%3A//www.sf.org.cn/Article/symbiandev/200509/232.html&amp;rn=616679" target=_blank><u><font color=#0000ff>图片</font></u></a></span>，<span><a class=vLink1 id=vad_10 onmouseover="if(typeof(showTitle)!='undefined'){this.title='';window.clearTimeout(hideTO);showTitle(event, this, 10,'');}" title="捞财网 @Vogate.com" style="FONT-SIZE: 1em" onclick="" onmouseout="if(typeof(showTitle)!='undefined'){mouseIsOverLayer = false; mouseOverWhileLoad = false; hideTO = window.setTimeout('checkIfMouseOverLayer()',500);}" href="http://action.vogate.com/click/click.php?r=http%3A//tag.csdn.net/Article/c960877d-dcf5-48fb-8d5d-53068d8832a1.html&amp;ads_id=2244&amp;site_id=6235007045036118&amp;click=1&amp;url=http%3A//www.lcw.cc&amp;v=0&amp;k=%u8D44%u6E90&amp;s=http%3A//www.sf.org.cn/Article/symbiandev/200509/232.html&amp;rn=578952" target=_blank><u><font color=#0000ff>资源</font></u></a></span>文件等等。所以 CEikonEnv 提供一系列的工具函数，用于<span><a class=vLink1 id=vad_5 onmouseover="if(typeof(showTitle)!='undefined'){this.title='';window.clearTimeout(hideTO);showTitle(event, this, 5,'');}" title="波导 @Vogate.com" style="FONT-SIZE: 1em" onclick="" onmouseout="if(typeof(showTitle)!='undefined'){mouseIsOverLayer = false; mouseOverWhileLoad = false; hideTO = window.setTimeout('checkIfMouseOverLayer()',500);}" href="http://action.vogate.com/click/click.php?r=http%3A//tag.csdn.net/Article/c960877d-dcf5-48fb-8d5d-53068d8832a1.html&amp;ads_id=3850&amp;site_id=6235007045036118&amp;click=1&amp;url=http%3A//www.chinabird.com/&amp;v=0&amp;k=%u4F7F%u7528&amp;s=http%3A//www.sf.org.cn/Article/symbiandev/200509/232.html&amp;rn=833817" target=_blank><u><font color=#0000ff>使用</font></u></a></span>这些<span><a class=vLink1 id=vad_7 onmouseover="if(typeof(showTitle)!='undefined'){this.title='';window.clearTimeout(hideTO);showTitle(event, this, 7,'');}" title="爱酷吧论坛 @Vogate.com" style="FONT-SIZE: 1em" onclick="" onmouseout="if(typeof(showTitle)!='undefined'){mouseIsOverLayer = false; mouseOverWhileLoad = false; hideTO = window.setTimeout('checkIfMouseOverLayer()',500);}" href="http://action.vogate.com/click/click.php?r=http%3A//tag.csdn.net/Article/c960877d-dcf5-48fb-8d5d-53068d8832a1.html&amp;ads_id=4230&amp;site_id=6235007045036118&amp;click=1&amp;url=http%3A//bbs.acool8.com&amp;v=0&amp;k=%u7A7A%u95F4&amp;s=http%3A//www.sf.org.cn/Article/symbiandev/200509/232.html&amp;rn=545" target=_blank><u><font color=#0000ff>空间</font></u></a></span>。每个 Uikon 的 appication 都有一个由 application framework 提供的 CEikonEnv 的实例，在 application 中可以用<br><br>CEikonEnv::Static() 或者 EikApplication 的宏 iEikonEnv 来使用这个 CEikonEnv 。<br><br>1.2 <span><a class=vLink1 id=vad_6 onmouseover="if(typeof(showTitle)!='undefined'){this.title='';window.clearTimeout(hideTO);showTitle(event, this, 6,'');}" title="TCL @Vogate.com" style="FONT-SIZE: 1em" onclick="" onmouseout="if(typeof(showTitle)!='undefined'){mouseIsOverLayer = false; mouseOverWhileLoad = false; hideTO = window.setTimeout('checkIfMouseOverLayer()',500);}" href="http://action.vogate.com/click/click.php?r=http%3A//tag.csdn.net/Article/c960877d-dcf5-48fb-8d5d-53068d8832a1.html&amp;ads_id=3846&amp;site_id=6235007045036118&amp;click=1&amp;url=http%3A//www.tcl.com&amp;v=0&amp;k=%u529F%u80FD&amp;s=http%3A//www.sf.org.cn/Article/symbiandev/200509/232.html&amp;rn=550026" target=_blank><u><font color=#0000ff>功能</font></u></a></span>分析<br><br>CEikonEnv提供了一系列的功能。包括：<br><br>【Text的处理】<br><br>&#183;<span><a class=vLink1 id=vad_11 onmouseover="if(typeof(showTitle)!='undefined'){this.title='';window.clearTimeout(hideTO);showTitle(event, this, 11,'');}" title="sony&nbsp;tv @Vogate.com" style="FONT-SIZE: 1em" onclick="" onmouseout="if(typeof(showTitle)!='undefined'){mouseIsOverLayer = false; mouseOverWhileLoad = false; hideTO = window.setTimeout('checkIfMouseOverLayer()',500);}" href="http://action.vogate.com/click/click.php?r=http%3A//tag.csdn.net/Article/c960877d-dcf5-48fb-8d5d-53068d8832a1.html&amp;ads_id=413&amp;site_id=6235007045036118&amp;click=1&amp;url=http%3A//www.sony.com.cn/electronics/bravia2006/bravia_index.asp&amp;v=0&amp;k=%u53D6%u5F97&amp;s=http%3A//www.sf.org.cn/Article/symbiandev/200509/232.html&amp;rn=46961" target=_blank><u><font color=#0000ff>取得</font></u></a></span>当前的环境（enviroment）字体：<br>const CFont* font = iEikonEnv-&gt;NormalFont();<br><br>&#183; 取得当前的环境（enviroment）标准符号字体：<br>const CFont* font = iEikonEnv-SymbolFont();<br><br>&#183;类似的字体函数：<br>AnnotationFont() / TitleFont() / LegendFont() /DenseFont() ;<br><br>【AlertWin的处理】<br><br>iEikonEnv-&gt;AlertWin(text);用于显示一个alert windows。<br><br>【Resource readers 和 resource files】<br><br>&#183;根据 resourceId 把资源文件的内容读取到 TBuf 中：<br><br>CEikonEnv 提供了一系列的函数来读取资源文件的内容，<span><a class=vLink1 id=vad_2 onmouseover="if(typeof(showTitle)!='undefined'){this.title='';window.clearTimeout(hideTO);showTitle(event, this, 2,'');}" title="盛大热血传奇 @Vogate.com" style="FONT-SIZE: 1em" onclick="" onmouseout="if(typeof(showTitle)!='undefined'){mouseIsOverLayer = false; mouseOverWhileLoad = false; hideTO = window.setTimeout('checkIfMouseOverLayer()',500);}" href="http://action.vogate.com/click/click.php?r=http%3A//tag.csdn.net/Article/c960877d-dcf5-48fb-8d5d-53068d8832a1.html&amp;ads_id=4147&amp;site_id=6235007045036118&amp;click=1&amp;url=http%3A//tg.sdo.com/730155388&amp;v=0&amp;k=%u57FA%u672C&amp;s=http%3A//www.sf.org.cn/Article/symbiandev/200509/232.html&amp;rn=307108" target=_blank><u><font color=#0000ff>基本</font></u></a></span>的函数用法如下<br><br>TBuf&lt;KAknExFormTitleBufLength&gt; titleText( NULL );<br>iEikonEnv-&gt;ReadResource( titleText, resourceId );<br><br>&#183; 根据　resourceId　把资源文件的内容读取到一个resource reader中：<br><br>这个 resource reader 可以用于后续之用，这个 resource reader 被放置在cleanup stack上。<br>这个 resource reader 的主要作用在可以通过资源文件创建控件，如下：<br><br>CCoeControl::ConstructFromResourceL();<br><br>【Access（访问函数）】<br><br>&#183;在这个范围内主要的函数是：AppUiFactory()。这个函数的主要作用是返回一个<br><br>MEikAppUiFactory 对象指针，This class defines a mixin interface to break <br><br>the dependency of the Uikon Application User Interface on controls。用法如下所示：<br><br>CEikStatusPane* sp = iEikonEnv-&gt;AppUiFactory()-&gt;StatusPane();<br><br>这样就获得了 application 的 status spane，通过这个指针就可以访问其他 sub status spane，如下：<br><br>CAknTitlePane* titlePane = (CAknTitlePane *)sp-&gt;ControlL(TUid::Uid(EEikStatusPaneUidTitle));<br><br>这样，就可以在运行的时候动态更改status spane的内容。<br><br>另外，如果appui继承自CEikAppui，那么可以采用下面的<span><a class=vLink1 id=vad_0 onmouseover="if(typeof(showTitle)!='undefined'){this.title='';window.clearTimeout(hideTO);showTitle(event, this, 0,'');}" title="" style="FONT-SIZE: 1em" onclick="" onmouseout="if(typeof(showTitle)!='undefined'){mouseIsOverLayer = false; mouseOverWhileLoad = false; hideTO = window.setTimeout('checkIfMouseOverLayer()',500);}" href="http://action.vogate.com/click/click.php?r=http%3A//tag.csdn.net/Article/c960877d-dcf5-48fb-8d5d-53068d8832a1.html&amp;ads_id=4137&amp;site_id=6235007045036118&amp;click=1&amp;url=http%3A//tg.sdo.com/730157712%20&amp;v=0&amp;k=%u65B9%u6CD5&amp;s=http%3A//www.sf.org.cn/Article/symbiandev/200509/232.html&amp;rn=653241" target=_blank><u><font color=#0000ff>方法</font></u></a></span>：<br><br>CEikStatusPane *sp = ((CAknAppUi*)iEikonEnv-&gt;EikAppUi())-&gt;StatusPane();<br><br>&#183;Bitmaps 函数<br><br>在seires60中<span><a class=vLink1 id=vad_1 onmouseover="if(typeof(showTitle)!='undefined'){this.title='';window.clearTimeout(hideTO);showTitle(event, this, 1,'');}" title="盛大热血传奇 @Vogate.com" style="FONT-SIZE: 1em" onclick="" onmouseout="if(typeof(showTitle)!='undefined'){mouseIsOverLayer = false; mouseOverWhileLoad = false; hideTO = window.setTimeout('checkIfMouseOverLayer()',500);}" href="http://action.vogate.com/click/click.php?r=http%3A//tag.csdn.net/Article/c960877d-dcf5-48fb-8d5d-53068d8832a1.html&amp;ads_id=4145&amp;site_id=6235007045036118&amp;click=1&amp;url=http%3A//tg.sdo.com/730155388&amp;v=0&amp;k=%u5DF2%u7ECF&amp;s=http%3A//www.sf.org.cn/Article/symbiandev/200509/232.html&amp;rn=3451" target=_blank><u><font color=#0000ff>已经</font></u></a></span>有个bitmapsfunction的namespace，所以这里不讨论这个类别。<br><br>另外，还可以从bitmap中创建ICON文件，作为其他控件的参数。&nbsp;<br><br></p>
<p id=TBPingURL>Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1822893</p>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/38518.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/gtwdaizi/" target="_blank">郭天文</a> 2007-12-14 15:04 <a href="http://www.cppblog.com/gtwdaizi/articles/38518.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>S60 3rd下的图像处理</title><link>http://www.cppblog.com/gtwdaizi/articles/36248.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Wed, 14 Nov 2007 03:41:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/36248.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/36248.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/36248.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/36248.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/36248.html</trackback:ping><description><![CDATA[<p><span style="COLOR: red">&nbsp;&nbsp;以下代码是网上一位仁兄的, 但是我使用测试,怎么都不能得到正确的图像, 我使用的16位的位图, 安装他的步骤无法成功,&nbsp;图像花屏.&nbsp;有没有高手告知一二, 如何解决这个问题.&nbsp;<br><br></span>&nbsp;&nbsp;inline TUint8 GetR( const TUint16 aColor)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;return aColor&gt;&gt;8;<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;inline TUint8 GetG(const TUint16 aColor)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;return aColor;<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;inline TUint8 GetB(const TUint16 aColor)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;return aColor &amp; 0xf;<br>&nbsp;&nbsp;}</p>
<p>CFbsBitmap* CinfoshowContainer::BmpZoomL( CFbsBitmap* aBitmap, TInt aWinth, TInt aHeight)<br>{<br>&nbsp;if( aWinth&gt;0 &amp;&amp; aHeight&gt;0 )<br>&nbsp;{<br>&nbsp;&nbsp;const TInt widtha = aBitmap-&gt;SizeInPixels().iWidth;<br>&nbsp;&nbsp;const TInt heighta = aBitmap-&gt;SizeInPixels().iHeight;<br>&nbsp;&nbsp;TReal WPencent=(TReal)aWinth/widtha;<br>&nbsp;&nbsp;TReal HPencent=(TReal)aHeight/heighta;<br>&nbsp;&nbsp;return BmpZoomL( aBitmap, WPencent, HPencent);<br>&nbsp;}<br>&nbsp;else<br>&nbsp;{<br>&nbsp;&nbsp;return&nbsp;NULL;<br>&nbsp;}</p>
<p>}<br>CFbsBitmap* CinfoshowContainer::BmpZoomL( CFbsBitmap* aBitmap, TReal aPencent ){<br>&nbsp;if(aPencent&gt;0)<br>&nbsp;{<br>&nbsp;&nbsp;return BmpZoomL( aBitmap, aPencent, aPencent );</p>
<p>&nbsp;}<br>&nbsp;else<br>&nbsp;{<br>&nbsp;&nbsp;return&nbsp;NULL;<br>&nbsp;}<br>}<br>CFbsBitmap* CinfoshowContainer::BmpZoomL( CFbsBitmap* aBitmap, TReal aWPencent, TReal aHPencent)<br>{<br>&nbsp;if( aWPencent&gt;0 &amp;&amp; aHPencent&gt;0 )<br>&nbsp;{<br>&nbsp;<br>&nbsp;&nbsp;const TInt widtha = aBitmap-&gt;SizeInPixels().iWidth;<br>&nbsp;&nbsp;const TInt heighta = aBitmap-&gt;SizeInPixels().iHeight;<br>&nbsp;&nbsp;const TInt width = widtha * aWPencent +0.5;<br>&nbsp;&nbsp;const TInt height = heighta * aHPencent +0.5;<br>&nbsp;&nbsp;CFbsBitmap* newbitmap = new(ELeave) CFbsBitmap();<br>&nbsp;&nbsp;User::LeaveIfError(newbitmap-&gt;Create(TSize(width,height), EColor4K/*displayMode*/));</p>
<p>&nbsp;&nbsp;TBitmapUtil bmpUtil1(aBitmap);<br>&nbsp;&nbsp;TBitmapUtil bmpUtil2(newbitmap);<br>&nbsp;&nbsp;bmpUtil1.Begin(TPoint(0,0));<br>&nbsp;&nbsp;bmpUtil2.Begin(TPoint(0,0), bmpUtil1);&nbsp;<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;TUint16* const addr1 = (TUint16*)aBitmap-&gt;DataAddress(); <br>&nbsp;&nbsp;TUint16* const addr2 = (TUint16*)newbitmap-&gt;DataAddress();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;TUint16* p1 = addr1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;TUint16* p2 = addr2;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;const TInt line1 = CFbsBitmap::ScanLineLength(widtha, EColor4K) / 2;&nbsp;<br>&nbsp;&nbsp;const TInt line2 = CFbsBitmap::ScanLineLength(width, EColor4K) / 2;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;TReal xa=0,ya=0;<br>&nbsp;&nbsp;TInt x=0,y=0;<br>&nbsp;&nbsp;const TInt jump = line2 - width;</p>
<p>&nbsp;&nbsp;TUint16* p2end = addr2 + width;</p>
<p>&nbsp;&nbsp;p2end = addr2 + line2*height;<br>&nbsp;&nbsp;while( p2 &lt; p2end)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;TUint16* p2endline = p2 + width; <br>&nbsp;&nbsp;&nbsp;while( p2!=p2endline )<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;xa=x/aWPencent;<br>&nbsp;&nbsp;&nbsp;&nbsp;ya=y/aHPencent;<br>&nbsp;&nbsp;&nbsp;&nbsp;TInt xai = xa;<br>&nbsp;&nbsp;&nbsp;&nbsp;TInt yai = ya;<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;if( xai == widtha -1 )<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if( yai == heighta-1 )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*p2 = *(addr1+line1*yai+xai);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p1=addr1+line1*yai+widtha-1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TUint8 red=GetR(*p1)+(GetR(*(p1+line1))-GetR(*p1))*(ya-yai)+0.5;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TUint8 green=GetG(*p1)+(GetG(*(p1+line1))-GetG(*p1))*(ya-yai)+0.5;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TUint8 blue=GetB(*p1)+(GetB(*(p1+line1))-GetB(*p1))*(ya-yai)+0.5;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*p2 = (red&lt;&lt;8) | (green&amp;0xf0) | blue;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;else<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if( yai == heighta-1 )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p1=addr1+line1*(heighta-1)+xai;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TUint8 red=GetR(*(p1))+(GetR(*(p1+1))-GetR(*(p1)))*(xa-xai)+0.5;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TUint8 green=GetG(*(p1))+(GetG(*(p1+1))-GetG(*(p1)))*(xa-xai)+0.5;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TUint8 blue=GetB(*(p1))+(GetB(*(p1+1))-GetB(*(p1)))*(xa-xai)+0.5;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*p2 = (red&lt;&lt;8) | (green&amp;0xf0) | blue;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p1=addr1+line1*yai+xai;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TUint8 red1=GetR(*(p1))+(GetR(*(p1+1))-GetR(*(p1)))*(xa-xai)+0.5;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TUint8 green1=GetG(*(p1))+(GetG(*(p1+1))-GetG(*(p1)))*(xa-xai)+0.5;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TUint8 blue1=GetB(*(p1))+(GetB(*(p1+1))-GetB(*(p1)))*(xa-xai)+0.5;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p1=addr1+line1*(yai+1)+xai;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TUint8 red2=GetR(*(p1))+(GetR(*(p1+1))-GetR(*(p1)))*(xa-xai)+0.5;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TUint8 green2=GetG(*(p1))+(GetG(*(p1+1))-GetG(*(p1)))*(xa-xai)+0.5;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TUint8 blue2=GetB(*(p1))+(GetB(*(p1+1))-GetB(*(p1)))*(xa-xai)+0.5;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TUint8 red=red1+(red2-red1)*(ya-yai)+0.5;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TUint8 green=green1+(green2-green1)*(ya-yai)+0.5;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TUint8 blue=blue1+(blue2-blue1)*(ya-yai)+0.5;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*p2 = (red&lt;&lt;8) | (green&amp;0xf0) | blue;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;x++;<br>&nbsp;&nbsp;&nbsp;&nbsp;p2++;<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;x=0;<br>&nbsp;&nbsp;&nbsp;y++;<br>&nbsp;&nbsp;&nbsp;p2+=jump;<br>&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;bmpUtil2.End();<br>&nbsp;&nbsp;bmpUtil1.End();<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;return newbitmap;<br>&nbsp;}<br>&nbsp;else<br>&nbsp;{<br>&nbsp;&nbsp;return&nbsp;NULL;<br>&nbsp;}<br>}<br>&nbsp;</p>
<p>使用双线性插值算法实现，支持12位色，缺点是当缩放比例小于0.5时图像较源图偏右下明显。<br>包含3个重载函数，分别是指定宽高，指定整体缩放比例和指定<br><br>可改为支持16位和24位色<br>16位色RGB的获取和合成，tempcolor为象素点的颜色值TUint16型<br><br>TUint8 red= tempcolor&gt;&gt;8;<br>TUint8 green=tempcolor&gt;&gt;3;<br>TUint8 blue=tempcolor &amp; 0x1f;</p>
<p>tempcolor=((TUint16)(red&amp;0xf8)&lt;&lt;8) | ((TUint16)(green&amp;0x3f)&lt;&lt;3) | (blue&amp;0x1f);</p>
<p><br>24位色为3个字节，指针为TUint8*，新图像颜色计算公式示例如下<br>*p2=(*p1)+((*(p1+line1))-(*p1))*(ya-yai)+0.5; //red<br>p1++;<br>p2++;<br>*p2=(*p1)+((*(p1+line1))-(*p1))*(ya-yai)+0.5; //green<br>p1++;<br>p2++;<br>*p2=(*p1)+((*(p1+line1))-(*p1))*(ya-yai)+0.5;//blue<br>p1++;<br>p2++;</p>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/36248.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/gtwdaizi/" target="_blank">郭天文</a> 2007-11-14 11:41 <a href="http://www.cppblog.com/gtwdaizi/articles/36248.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Symbian 中各种提示、输入对话框的使用</title><link>http://www.cppblog.com/gtwdaizi/articles/35962.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Tue, 06 Nov 2007 07:18:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/35962.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/35962.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/35962.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/35962.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/35962.html</trackback:ping><description><![CDATA[<p><strong>1、非阻塞提示框<br><br></strong>symbian定义了几个提示类，分别是：<br>confirm类：CAknConfirmationNote<br>info类：&nbsp;CAknInformationNote<br>warning类：CAknWarningNote<br>error类：CAknErrorNote<br><br>头文件：aknnotewrappers.h<br>lib：&nbsp;avkon.lib&nbsp;&nbsp;&nbsp;eikcdlg.lib&nbsp;&nbsp;&nbsp;eikctl.lib<br><br><strong>Code：<br></strong>TBuf&lt;32&gt; buf;<br>buf.Copy(_L("info note"));<br>CAknInformationNote* iInfoNote = new (ELeave) CAknInformationNote;<br>iInfoNote-&gt;ExecuteLD(buf);<br><br></p>
<p dir=ltr><strong>2、阻塞提示框<br></strong><br>void CEikonEnv::AlertWin(const TDesC&amp; aMsg);<br>void CEikonEnv::AlertWin(const TDesC&amp; aMsg1,const TDesC&amp; aMsg2);<br>static void CEikonEnv::InfoWinL(const TDesC&amp; aFirstLine,const TDesC&amp; aSecondLine);</p>
<p dir=ltr>AlertWin为CEikonEnv类的非静态成员函数，InfoWinL为CEikonEnv类的静态成员函数。<br>AlertWin只能在ui、view和container中使用，使用方法如下：</p>
<p dir=ltr>Code:<br>iEikonEnv-&gt;AlertWin(_L("text"));</p>
<p dir=ltr>InfoWinL可以在任意类中使用，使用方法如下：<br>Code:<br>CEikonEnv::Static()-&gt;InfoWinL(_L("note:"), _L("text"));</p>
<p dir=ltr>为方便使用，常定义宏来使用这类提示框，如： </p>
<p dir=ltr style="MARGIN-RIGHT: 0px">Code:<br>#define DEBUG_DIALOG(x) iEikonEnv-&gt;AlertWin(##x);<br>#define DEBUG_DIALOG1(x) CEikonEnv::Static()-&gt;InfoWinL(_L("note:"), ##x);<br>#define DEBUG_DIALOG2(x,y) CEikonEnv::Static()-&gt;InfoWinL(##x, ##y);<br><br>可以这么使用：<br>TBuf&lt;32&gt; buf;<br>buf.Copy(_L("test"));<br>DEBUG_DIALOG(buf);<br>DEBUG_DIALOG1(buf);<br>DEBUG_DIALOG2(buf,_L("text"));</p>
<p>此类提示框阻塞线程，只有用户按键退出提示框后，后面的程序才能接着运行。<br><br></p>
<p><strong>3、进度条对话框<br></strong><br>进度条对话框类为：<br>CAknProgressDialog <br>头文件：aknprogressdialog.h<br>lib：avkon.lib&nbsp;&nbsp;&nbsp;eikcdlg.lib&nbsp;&nbsp;&nbsp;eikctl.lib</p>
<p><strong>Code:<br></strong><br>//初始化进度条<br>CAknProgressDialog* iProgressDialog;<br>CEikProgressInfo* iProgressInfo;<br>iProgressDialog = new ( ELeave ) CAknProgressDialog( reinterpret_cast<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;CEikDialog**&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( &amp;iProgressDialog ) );<br>iProgressDialog-&gt;SetCallback( this );<br>iProgressDialog-&gt;PrepareLC( R_RESOURCE_PROGRESS_NOTE );&nbsp;&nbsp; //从资源文件构造对话框，资源见下面的定义<br>iProgressInfo = iProgressDialog-&gt;GetProgressInfoL();<br>iProgressInfo-&gt;SetFinalValue( aMaxValue );&nbsp;&nbsp; //设置进度条的最大值（结束值）<br>iProgressDialog-&gt;RunLD();<br>&nbsp;&nbsp;<br>//更新进度条<br>iProgressInfo-&gt;IncrementAndDraw( aStep );&nbsp;&nbsp;</p>
<p>//结束进度条<br>iProgressDialog-&gt;ProcessFinishedL();<br>delete iProgressDialog;<br><br>RESOURCE DIALOG R_RESOURCE_PROGRESS_NOTE&nbsp;&nbsp; //进度条对话框资源<br>&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp; flags = EAknProgressNoteFlags;<br>&nbsp;&nbsp;&nbsp;&nbsp; buttons = R_AVKON_SOFTKEYS_CANCEL;<br>&nbsp;&nbsp;&nbsp;&nbsp; items =<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DLG_LINE<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type = EAknCtNote;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; id = EMagicBoxCtrlIdProgressNote;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; control = AVKON_NOTE<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; layout = EProgressLayout;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; singular_label = "对话框中显示的文字";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; plural_label = "download";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; imagefile = AVKON_BMPFILE_NAME;&nbsp;&nbsp;&nbsp; //第二版中 图标文件为 #define AVKON_BMPFILE_NAME "z:\\system\\data\\avkon.mbm"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; imageid = EMbmAvkonQgn_note_sml;&nbsp;&nbsp; //这两项可更改显示不同图标<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; imagemask = EMbmAvkonQgn_note_sml_mask;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<br>&nbsp;&nbsp;&nbsp;&nbsp; }<br><br><span style="COLOR: red">注意：In Series 60 3rd edition, avkon.mbm was replaced by avkon2.mbm and moved to a different location (and the SDK forgot to mention this and still provides erroneous location).<br>Old entry:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; imagefile = "z:\\system\data\avkon.mbm";<br>New entry:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; imagefile = "z:\\resource\apps\avkon2.mbm";</span></p>
<br>
<p><strong>4、等待对话框<br><br></strong>等待对话框要用到的类：CAknGlobalNote<br>头文件：aknglobalnote.h <br>lib：aknnotify.lib eiksrv.lib</p>
<p><strong>Code:<br></strong><br>//显示等待对话框<br>&nbsp;&nbsp; CAknGlobalNote* globalNote = CAknGlobalNote::NewL();<br>&nbsp;&nbsp; CleanupStack::PushL( globalNote );<br>&nbsp;&nbsp; TInt iWaitNoteId = globalNote-&gt;ShowNoteL( EAknGlobalWaitNote, _L("对话框中显示的文字") );<br>&nbsp;&nbsp; CleanupStack::PopAndDestroy();<br>&nbsp;&nbsp;<br>&nbsp;&nbsp; //结束等待对话框<br>&nbsp;&nbsp; CAknGlobalNote * note = CAknGlobalNote::NewL();<br>&nbsp;&nbsp; CleanupStack::PushL( note );<br>&nbsp;&nbsp; note-&gt;CancelNoteL( iWaitNoteId );<br>&nbsp;&nbsp; CleanupStack::PopAndDestroy();</p>
<p style="COLOR: red"><span style="COLOR: red">注意：</span><br>CAknGlobalNote类除了显示等待对话框外还可显示多种类型的全局对话框，具体类型可通过ShowNoteL的第一个参数指定，可能的类型如下：</p>
<p><br><strong>Code:<br></strong><br>enum TAknGlobalNoteType<br>{<br>EAknGlobalInformationNote = 1,<br>EAknGlobalWarningNote,<br>EAknGlobalConfirmationNote,<br>EAknGlobalErrorNote,<br>EAknGlobalChargingNote,<br>EAknGlobalWaitNote,<br>EAknGlobalPermanentNote,<br>EAknGlobalNotChargingNote,<br>EAknGlobalBatteryFullNote,<br>EAknGlobalBatteryLowNote,<br>EAknGlobalRechargeBatteryNote,<br>EAknCancelGlobalNote,<br>EAknGlobalTextNote<br>};<br></p>
<p><strong>5、询问对话框<br></strong><br>询问对话框用到的类：CAknQueryDialog<br>头文件：AknQueryDialog.h<br>lib：avkon.lib</p>
<p><strong>Code:<br></strong><br>CAknQueryDialog* dlg;<br>dlg = CAknQueryDialog::NewL( CAknQueryDialog::ENoTone );<br>dlg-&gt;PrepareLC( R_RESOURCE_QUERY_DIALOG ); //从资源文件构造对话框，资源见下面的定义<br>TInt ret = dlg-&gt;RunLD();&nbsp;&nbsp; //若用户选择&#8220;是&#8221;，返回非0，选择&#8220;否&#8221;，则返回0</p>
<p>RESOURCE DIALOG R_RESOURCE_QUERY_DIALOG&nbsp;&nbsp; //询问对话框资源<br>&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp; flags = EGeneralQueryFlags;<br>&nbsp;&nbsp;&nbsp;&nbsp; buttons = R_AVKON_SOFTKEYS_YES_NO;&nbsp;&nbsp; //CBA显示&#8220;是&#8221;和&#8220;否&#8221;两个按钮<br>&nbsp;&nbsp;&nbsp;&nbsp; items =<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DLG_LINE<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type = EAknCtQuery;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; id = EGeneralQuery;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; control = AVKON_CONFIRMATION_QUERY&nbsp;&nbsp;&nbsp; //表示这是confirm询问对话框，用户选择&#8220;是&#8221;或&#8220;否&#8221;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; layout = EConfirmationQueryLayout;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; label = "对话框中显示的文字";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<br>&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>此类对话框可以有声音提示，由NewL的const TTone&amp; aTone参数指定，可能的值如下：</p>
<p><strong>Code:<br></strong><br>enum TTone {<br>&nbsp;&nbsp;&nbsp;&nbsp; /// No tone is played <br>&nbsp;&nbsp;&nbsp;&nbsp; ENoTone = 0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp; /// A confirmation tone is played <br>&nbsp;&nbsp;&nbsp;&nbsp; EConfirmationTone = EAvkonSIDConfirmationTone, <br>&nbsp;&nbsp;&nbsp;&nbsp; /// A warning tone is played <br>&nbsp;&nbsp;&nbsp;&nbsp; EWarningTone = EAvkonSIDWarningTone,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp; /// An error tone is played&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp; EErrorTone = EAvkonSIDErrorTone&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp; };</p>
<p>通过定义不同的询问对话框资源，可实现不同的询问对话框，如让用户输入文字的询问对话框资源定义如下：</p>
<p><strong>Code:<br></strong><br>RESOURCE DIALOG R_RESOURCE_DATA_QUERY<br>&nbsp;&nbsp; {<br>&nbsp;&nbsp; flags = EGeneralQueryFlags;<br>&nbsp;&nbsp; buttons = R_AVKON_SOFTKEYS_OK_CANCEL;&nbsp;&nbsp; //CBA按钮显示&#8220;确定&#8221;和&#8220;取消&#8221;<br>&nbsp;&nbsp; items =<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DLG_LINE<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type = EAknCtQuery;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; id = EGeneralQuery;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; control = AVKON_DATA_QUERY&nbsp;&nbsp; //表示这是data询问对话框，需要用户输入内容<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; layout = EDataLayout;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; label = "提示内容";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; control = EDWIN<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flags = EEikEdwinNoHorizScrolling | EEikEdwinResizable;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; width = 30;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lines = 2;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxlength = 159;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<br>&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;<br><br><strong>Code:<br></strong><br>TBuf&lt;128&gt; msg;<br>CAknTextQueryDialog* dlg = new (ELeave) CAknTextQueryDialog(msg,CAknQueryDialog::ENoTone);<br>&nbsp;&nbsp; TInt ret = dlg-&gt;ExecuteLD(R_RESOURCE_DATA_QUERY);</p>
<p>用户输入内容后按&#8220;确定&#8221;，内容就存储到msg中，函数返回非0；按&#8220;取消&#8221;，函数返回0。</p>
<p>这里用到的类是CAknQueryDialog的子类CAknTextQueryDialog。<br>CAknQueryDialog的子类有：</p>
<p><strong>Code:<br></strong><br>CAknFloatingPointQueryDialog&nbsp;&nbsp; //This class should be used when user is reguest to enter a flotaing point number<br>&nbsp;&nbsp; CAknFixedPointQueryDialog&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //...<br>&nbsp;&nbsp; CAknDurationQueryDialog&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //This class should be used when user is reguest to enter duration<br>&nbsp;&nbsp; CAknIpAddressQueryDialog&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //This class should be used when user is reguest to enter IP address,@since 2.1<br>&nbsp;&nbsp; CAknMultiLineDataQueryDialog&nbsp;&nbsp; //Query Dialog with data input on more than one line (2 lines at the moment)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Create using NewL methods and passing parameters as appropriate.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Attention: When deriving from this class, you must call SetDataL during <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; second phase construction.<br>&nbsp;&nbsp; CAknMultiLineIpQueryDialog&nbsp;&nbsp;&nbsp;&nbsp; //...<br>&nbsp;&nbsp; CAknNumberQueryDialog&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //This class should be used when user is reguest to enter number<br>&nbsp;&nbsp; CAknTextQueryDialog&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //This class should be used when user is reguest to enter plain text, secret text, phonenumber or PIN-code<br>CAknTimeQueryDialog&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //This class should be used when user is reguest to enter time or date</p>
<p>使用不同的类，资源文件会有所不同。</p>
<p>另外，在资源中定义EDWIN时，可指定输入发，如： </p>
<p><strong>Code:<br></strong><br>control = EDWIN<br>&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp; flags = EEikEdwinNoHorizScrolling | EEikEdwinResizable;<br>&nbsp;&nbsp;&nbsp;&nbsp; width = 11;<br>&nbsp;&nbsp;&nbsp;&nbsp; lines = 1;<br>&nbsp;&nbsp;&nbsp;&nbsp; maxlength = 11;<br>&nbsp;&nbsp; avkon_flags = EAknEditorFlagFixedCase | <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EAknEditorFlagNoT9 | EAknEditorFlagSupressShiftMenu;&nbsp;&nbsp; //EAknEditorFlagSupressShiftMenu屏蔽切换输入法键<br>&nbsp;&nbsp; allowed_input_modes = EAknEditorNumericInputMode;<br>&nbsp;&nbsp; default_input_mode = EAknEditorNumericInputMode;<br>&nbsp;&nbsp; numeric_keymap = EAknEditorPlainNumberModeKeymap;<br>&nbsp;&nbsp; };</p>
<p>以上写法表示默认输入法为数字，并且屏蔽了输入法切换键，即不能通过输入法切换键来切换输入法。<br></p>
<p><strong><br>6、编辑框<br></strong><br>编辑框使用的类：CEikGlobalTextEditor<br>头文件：eikgted.h</p>
<p><strong>Code:<br></strong><br>CEikGlobalTextEditor* iGKeyEd;<br>TBuf&lt;128&gt; iKeyText;<br>TResourceReader reader;<br>iCoeEnv-&gt;CreateResourceReaderLC( reader, R_RESOURCE_EDITOR );&nbsp;&nbsp; //从资源文件构造编辑框，资源见下面的定义<br>iGKeyEd = new ( ELeave ) CEikGlobalTextEditor;<br>iGKeyEd-&gt;SetContainerWindowL( *this );<br>iGKeyEd-&gt;ConstructFromResourceL( reader );<br>CleanupStack::PopAndDestroy();&nbsp;&nbsp; // Resource reader</p>
<p>//设置编辑框的初始文本和位置，编辑框大小在资源中定义<br>TBuf&lt;32&gt; buf;<br>buf.Copy(_L("demo"));<br>iGKeyEd-&gt;SetTextL(&amp;buf);<br>iGKeyEd-&gt;SetExtent( TPoint(5,2), iGKeyEd-&gt;MinimumSize() );<br>iGKeyEd-&gt;SetFocus(ETrue);<br>// iGKeyEd-&gt;SetReadOnly(ETrue);&nbsp;&nbsp; //设置编辑框为只读<br><br>//使文字居中<br>CParaFormat&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; paraFormat;&nbsp;<br>TParaFormatMask paraFormatMask;<br>paraFormatMask.SetAttrib( EAttAlignment );&nbsp;&nbsp;&nbsp;&nbsp; // set mask<br>paraFormat.iHorizontalAlignment = CParaFormat::ECenterAlign;<br>iGKeyEd-&gt;ApplyParaFormatL( &amp;paraFormat, paraFormatMask );<br>&nbsp;&nbsp;<br>iGKeyEd-&gt;GetText(iKeyText); //获取编辑框中的内容，保存到iKeyText中</p>
<p>RESOURCE GTXTED R_RESOURCE_EDITOR&nbsp;&nbsp; //编辑框资源&nbsp;&nbsp;<br>&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp; flags = EAknEditorFlagDefault;<br>&nbsp;&nbsp;&nbsp;&nbsp; width = 53;<br>&nbsp;&nbsp;&nbsp;&nbsp; height = 16;<br>&nbsp;&nbsp;&nbsp;&nbsp; numlines = 1;<br>&nbsp;&nbsp;&nbsp;&nbsp; textlimit= 1;<br>&nbsp;&nbsp;&nbsp;&nbsp; fontcontrolflags = EGulFontControlAll;<br>&nbsp;&nbsp;&nbsp;&nbsp; fontnameflags = EGulNoSymbolFonts;</p>
<p>//这里也可设置输入法<br>//&nbsp;&nbsp;&nbsp; avkon_flags = EAknEditorFlagFixedCase | <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EAknEditorFlagNoT9 | EAknEditorFlagSupressShiftMenu;&nbsp;&nbsp; //EAknEditorFlagSupressShiftMenu屏蔽切换输入法键<br>//&nbsp;&nbsp;&nbsp;&nbsp; allowed_input_modes = EAknEditorNumericInputMode;<br>//&nbsp;&nbsp;&nbsp;&nbsp; default_input_mode = EAknEditorNumericInputMode;<br>//&nbsp;&nbsp;&nbsp;&nbsp; numeric_keymap = EAknEditorPlainNumberModeKeymap;&nbsp;&nbsp;<br>&nbsp;&nbsp; }</p>
<p style="COLOR: red">注意，要使编辑框正常显示，记得更改container的CountComponentControls和ComponentControl函数，正确处理控件数目和编辑框指针。另外，要使编辑框能正常接收按键事件，要显示调用编辑框的OfferKeyEventL函数，如下：</p>
<p><strong>Code:<br></strong><br>TKeyResponse CMobileGuardSetKeyContainer::OfferKeyEventL( const TKeyEvent&amp; aKeyEvent, TEventCode aType )<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp; return iGKeyEd-&gt;OfferKeyEventL( aKeyEvent, aType );<br>}</p>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/35962.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/gtwdaizi/" target="_blank">郭天文</a> 2007-11-06 15:18 <a href="http://www.cppblog.com/gtwdaizi/articles/35962.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>S60的多线程，活动对象，活动规划器，异步函数</title><link>http://www.cppblog.com/gtwdaizi/articles/34234.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Sun, 14 Oct 2007 14:02:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/34234.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/34234.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/34234.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/34234.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/34234.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Symbian也是多任务操作系统，当然也要用进程、线程完成多任务处理。进程是程序的运行实例，有自己独立的数据空间。线程是进程的执行单元，一个进程至少有一个主线程。多线程可以并发运行采用抢占式完成多任务处理。但是Symbian下不提倡使用多线程，因为Symbian系统是通过客户端/服务器结构来提供对线程资源的访问，这就意味着访问线程需要与内核的服务器程序不断地进行通信，效率低。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在单线程内，配合使用活动对象+异步函数，完全可以模拟多线程并行运行。不同的是，这是一种非抢占式并行运行，即当前活动对象结束之前，其它活动对象不能运行。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 异步函数在执行后立即返回，继续执行它下面的代码。异步操作有后台继续执行，结束后通过信号量表示异步操作结束。同步函数必须函数内所有操作全部执行结束后才能返回，执行下面的代码，否则就阻塞在那里。很显然，实现多任务并行运行必须使用异步函数。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 活动对象是CActive的派生类，设立它的作用就是为了提供一个专门用来调用异步函数的类。因为这个类中专门设有回调函数，使异步函数结束后，能利用这个回调函数进行尾处理。这个函数就是RunL()。在活动对象外面使用异步函数，只能截获信号量，不能直接进入某个回调函数。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 异步函数结束后，是如何进入到正确的回调函数中的呢？系统运行着一个活动调度器(CActiveSchedule)，它能截获异步函数结束后发出的信号量，并根据这个信号量，调用相应的RunL()。问题是如果CActiveSchedule截获了这个信号，但却找不到该调哪个活动对象的RunL()怎么办？这时CActiveSchedule会抛出异常，这种状态叫信号游离，这种状况经常发生，所以使用活动对象应该避免这种情况发生。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 哪些情况会产生游离信号？理解这个问题首先要了解CActiveSchedule如何判断这个信号是不是游离信号。CActiveSchedule判断游离信号的条件是<br>&nbsp;for(I=0;I&lt;NUMBERS_OF_ACTIVE_OBJECT;I++)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IF(ACTIVE_OBJECTS[I].iActive==ETrue&amp;&amp;ACTIVE_OBJECTS[I].iStatus!=KRequestPending)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//由此可见，规则有二<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //规则1 根本就没有这个活动对象<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //规则2 活动对象不是&#8220;活&#8221;的 ACTIVE_OBJECTS[I].RunL();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>}<br>所以有如下情况可能会导致出现游离信号出现<br>1．没有调用CActiveSchedule::Add(this);把活动对象加到活动调度器中。<br>2．没有调用SetActive把活动对象激活。破坏规则（2）<br>3．在活动对象外调用异步函数后，没有用User::WaitForRequest()截获异步函数完成信号量。信号量进入循环却找不到活动对象，破坏规则1。<br>4．同时一个活动对象中同时调用两个异步函数。如：InvokeAsyncFunc1();SetActice();InvokeAsyncFunc2();SetActive();第一个异步函数结束后，执行完回调函数RunL()后，会把iActive置为EFalse,这时第二异步函数的结束信号进入时，却发现活动对象不是&#8220;活&#8221;的，破坏规则2。所以在一个活动对象不能同时调用多个异步函数。
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/34234.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/gtwdaizi/" target="_blank">郭天文</a> 2007-10-14 22:02 <a href="http://www.cppblog.com/gtwdaizi/articles/34234.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]Active Scheduler &amp; Active Object,活动规划器和活动对象</title><link>http://www.cppblog.com/gtwdaizi/articles/34055.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Fri, 12 Oct 2007 10:43:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/34055.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/34055.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/34055.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/34055.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/34055.html</trackback:ping><description><![CDATA[<strong>活动</strong><a id=vad_5 onmouseover="if(typeof(showTitle)!='undefined'){this.title='';window.clearTimeout(hideTO);showTitle(event, this, 5,'');}" title="疯狂园林人 @Vogate.com" onclick="" onmouseout="if(typeof(showTitle)!='undefined'){mouseIsOverLayer = false; mouseOverWhileLoad = false; hideTO = window.setTimeout('checkIfMouseOverLayer()',500);}" href="http://action.vogate.com/click/click.php?r=&amp;ads_id=2479&amp;site_id=6235007045036118&amp;click=1&amp;url=http%3A//www.444.com.cn&amp;v=0&amp;k=%u89C4%u5212&amp;s=http%3A//www.sf.org.cn/Article/symbiandev/200511/14261.html&amp;rn=387196" target=_blank><u><font color=#003399><strong>规划</strong></font></u></a><strong>器 （Active Scheduler） </strong>
<p>由于<a id=vad_3 onmouseover="if(typeof(showTitle)!='undefined'){this.title='';window.clearTimeout(hideTO);showTitle(event, this, 3,'');}" title="" onclick="" onmouseout="if(typeof(showTitle)!='undefined'){mouseIsOverLayer = false; mouseOverWhileLoad = false; hideTO = window.setTimeout('checkIfMouseOverLayer()',500);}" href="http://action.vogate.com/click/click.php?r=&amp;ads_id=3850&amp;site_id=6235007045036118&amp;click=1&amp;url=http%3A//www.chinabird.com/&amp;v=0&amp;k=%u4F7F%u7528&amp;s=http%3A//www.sf.org.cn/Article/symbiandev/200511/14261.html&amp;rn=7506" target=_blank><u><font color=#003399>使用</font></u></a>多线程来处理异步请求比较消耗系统资源，所以<a id=vad_6 onmouseover="if(typeof(showTitle)!='undefined'){this.title='';window.clearTimeout(hideTO);showTitle(event, this, 6,'');}" title="TOMPDA智能手机乐园 @Vogate.com" onclick="" onmouseout="if(typeof(showTitle)!='undefined'){mouseIsOverLayer = false; mouseOverWhileLoad = false; hideTO = window.setTimeout('checkIfMouseOverLayer()',500);}" href="http://action.vogate.com/click/click.php?r=&amp;ads_id=4249&amp;site_id=6235007045036118&amp;click=1&amp;url=http%3A//www.tompda.com&amp;v=0&amp;k=symbian&amp;s=http%3A//www.sf.org.cn/Article/symbiandev/200511/14261.html&amp;rn=518013" target=_blank><u><font color=#003399>symbian</font></u></a> 使用了活动对象（Active Object）来解决异步请求的问题。<br>活动规划器（active scheduler）用于处理由活动对象提出的异步请求。它检测活动对象提出的异步请求，并安排活动对象的请求完成事件的执行顺序。活动规划器仅用一个事件处理线程来规划各个活动对象提出的事件请求，所以它要比多线程<a id=vad_4 onmouseover="if(typeof(showTitle)!='undefined'){this.title='';window.clearTimeout(hideTO);showTitle(event, this, 4,'');}" title="Toyota @Vogate.com" onclick="" onmouseout="if(typeof(showTitle)!='undefined'){mouseIsOverLayer = false; mouseOverWhileLoad = false; hideTO = window.setTimeout('checkIfMouseOverLayer()',500);}" href="http://action.vogate.com/click/click.php?r=&amp;ads_id=4193&amp;site_id=6235007045036118&amp;click=1&amp;url=http%3A//www.toyota.com.cn&amp;v=0&amp;k=%u5B9E%u73B0&amp;s=http%3A//www.sf.org.cn/Article/symbiandev/200511/14261.html&amp;rn=24640" target=_blank><u><font color=#003399>实现</font></u></a>异步请求占用更少的资源。<br>一个活动规划器通常对应到一个线程，CActiveScheduler 类的静态<a id=vad_0 onmouseover="if(typeof(showTitle)!='undefined'){this.title='';window.clearTimeout(hideTO);showTitle(event, this, 0,'');}" title="盛大英雄年代 @Vogate.com" onclick="" onmouseout="if(typeof(showTitle)!='undefined'){mouseIsOverLayer = false; mouseOverWhileLoad = false; hideTO = window.setTimeout('checkIfMouseOverLayer()',500);}" href="http://action.vogate.com/click/click.php?r=&amp;ads_id=4137&amp;site_id=6235007045036118&amp;click=1&amp;url=http%3A//tg.sdo.com/730157712%20&amp;v=0&amp;k=%u65B9%u6CD5&amp;s=http%3A//www.sf.org.cn/Article/symbiandev/200511/14261.html&amp;rn=911351" target=_blank><u><font color=#003399>方法</font></u></a>通常都是针对当前线程中对象的操作。<br>在程序中使用活动对象时，首先应该创建一个活动规划器对象，并把它安装到当前线程，也就是把活动规划器和当前线程关联。 CActiveScheduler::Install()方法可以把活动规划器安装到当前线程， CActiveScheduler::Current() 方法可以<a id=vad_8 onmouseover="if(typeof(showTitle)!='undefined'){this.title='';window.clearTimeout(hideTO);showTitle(event, this, 8,'');}" title="sony&nbsp;tv @Vogate.com" onclick="" onmouseout="if(typeof(showTitle)!='undefined'){mouseIsOverLayer = false; mouseOverWhileLoad = false; hideTO = window.setTimeout('checkIfMouseOverLayer()',500);}" href="http://action.vogate.com/click/click.php?r=&amp;ads_id=413&amp;site_id=6235007045036118&amp;click=1&amp;url=http%3A//www.sony.com.cn/electronics/bravia2006/bravia_index.asp&amp;v=0&amp;k=%u83B7%u53D6&amp;s=http%3A//www.sf.org.cn/Article/symbiandev/200511/14261.html&amp;rn=701714" target=_blank><u><font color=#003399>获取</font></u></a>和当前线程关联的活动规划器。如：</p>
<table cellSpacing=0 cellPadding=5 width="95%" align=center bgColor=#f1f1f1 border=0>
    <tbody>
        <tr>
            <td>CActiveScheduler::Install（CAtv）<br>CActiveScheduler* sco2 =CActiveScheduler::Current();</td>
        </tr>
    </tbody>
</table>
<p>Add()方法可以把活动对象添加到活动规划器中，这样活动规划器就可以处理活动对象所提出的异步请求，当异步请求完成事件发生时调用活动对象的RunL()方法。<br>活动规划器的 Add() 方法把指定的活动对象添加到当前的活动规划器中。但是在某些时候<a id=vad_7 onmouseover="if(typeof(showTitle)!='undefined'){this.title='';window.clearTimeout(hideTO);showTitle(event, this, 7,'');}" title="sony?laptop @Vogate.com" onclick="" onmouseout="if(typeof(showTitle)!='undefined'){mouseIsOverLayer = false; mouseOverWhileLoad = false; hideTO = window.setTimeout('checkIfMouseOverLayer()',500);}" href="http://action.vogate.com/click/click.php?r=&amp;ads_id=300&amp;site_id=6235007045036118&amp;click=1&amp;url=http%3A//www.sonystyle.com.cn/vaio/vaio_home_new.asp%3FidObj%3Dar&amp;v=0&amp;k=%u53EF%u80FD&amp;s=http%3A//www.sf.org.cn/Article/symbiandev/200511/14261.html&amp;rn=247338" target=_blank><u><font color=#003399>可能</font></u></a>需要删除在活动规划器中的活动对象：如果活动对象被销毁，那么同时活动对象就在活动规划器中被删除了，另外使用活动规划器的Deque()方法也可以把活动对象从活动规划器中删除。<br>在调用Add()方法之前必须确认活动规划器已经安装到当前线程，否则将发生E32USER-CBase 44 panic。Add()方法包括一个CActive型的参数， 这是一个指向活动对象的指针，在调用Add()方法时，这个指针不可以为 NULL,否则函数发生 E32USER-CBase 48 panic。另外与要注意的是，在使用Add()方法之前确认活动对象是否已经添加到活动规划器中，如果这个对象已经添加到活动规划器中那么将发生E32USER-CBase 41 panic。<br>CActiveScheduler::Start()方法启动一个在当前活动规划器控制下的的循环等待。而CActiveScheduler::Stop()则可以终止活动规划器的循环等待。活动规划器实际上是构建了一个事件处理的框架，它在循环中使用User::WaitForAnyRequest()等待活动对象的异步请求，当请求事件完成时，就调用一该请求事件相关的活动对象的RunL()方法。活动对象调用RunL()时把它放在TRAP下，这样即使RunL()函数发生Leave活动对象也有可以对它处理，执行一些必要的内存清理。当RunL()发生异常退出之后，首先进入活动对象的RunError()方法，这个方法是一个需方法，有一个默认实现，并返回一个整型的值，如果返回的整形值不是KEeeNone，那么活动规划器将调用自己的Error()方法。Error()方法也有一个默认的实现：发生一个E32USER-CBase 47 panic。</p>
<p><strong>活动对象（Active Object）</strong></p>
<p>CActive类是活动对象（Active Object）的核心类，所有的活动对象类应该从这个类继承。在CActive 中，封装了两个功能：一个是向异步服务提供者发出异步请求；另外一个是处理请完成事件。一个应用程序中可以包含若干个活动对象，并且是它们的都在活动规划器（active scheduler）的控制下运行。<br>活动对象应该包括一个和请求函数相关连的请求对象，请求函数是专门用于完成异步请求的，由于带有请求函数的对象提供了异步服务，所以在SDK的文档里又把他们叫做异步服务提供者（asynchronous service provider）。这里可以举一个<a id=vad_2 onmouseover="if(typeof(showTitle)!='undefined'){this.title='';window.clearTimeout(hideTO);showTitle(event, this, 2,'');}" title="" onclick="" onmouseout="if(typeof(showTitle)!='undefined'){mouseIsOverLayer = false; mouseOverWhileLoad = false; hideTO = window.setTimeout('checkIfMouseOverLayer()',500);}" href="http://action.vogate.com/click/click.php?r=&amp;ads_id=1276&amp;site_id=6235007045036118&amp;click=1&amp;url=http%3A//www.saris.com.cn/event/E258/flashcode/main.htm&amp;v=0&amp;k=%u7B80%u5355&amp;s=http%3A//www.sf.org.cn/Article/symbiandev/200511/14261.html&amp;rn=98140" target=_blank><u><font color=#003399>简单</font></u></a>的例子，RTimer中包括了一些请求函数，如After()、At()等。所以RTimer型的对象是一个异步服务提供者。所以在活动对象中，通常会有一个服务提供者成员，它的作用是提出一个异步请求，并异步完成他们的请求。<br>活动对象的 RunL() 方法用于处理活动对象的请求完成事件。活动对象类作为CActive类的派生类，它必须实现RunL()方法。如果有业务逻辑需要，RunL()可以发出另外一个新的异步请求。当请求结束事件发生时，这个函数被活动规划器调用，也就是说，在活动规划器的WaitForAnyRequest()函数结束以后RunL()函数被调用。WaitForAnyRequest()实际上是对User::WaitForAnyRequest()的调用。<br>在调用活动对象的RunL方法前，活动规划器需要确定，哪一个活动对象拥有最高优先权，然后标记该对象的请求作为请求完成事件。这个优先权是在活动对象构造的时候指定的。RunL运行在活动规划器所设定的TRAP中，如果RunL在执行过程中发生leave那么,那么活动规划器将调用RunError()方法。一旦调用了活动规划器的 Start方法，那么所有的用户代码将运行在活动规划器的某个活动对象的RunL()函数或RunError函数下。<br>活动对象 RunError() 方法用于处理请求结完成事件处理函数RunL() 的异常退出（Leave）。如果活动对象的RunL()函数发生Leave,那么活动规划器将调用活动对象的RunError方法。这样这个发生错误的活动对象就可以完成一些必要的内存清理。如果有派生类实现了这个方法，那么就应该对可能的 leave 做出处理，并返回KErrNone；如果返回了其他的错误码，那么CActiveScheduler类的Error()将被调用。<br>RunError() 方法的默认实现返回一个异常退出码，而一旦发生leave这个异常退出码是一个非KErrNone的值，这样可以认为：一般情况下，活动对象的RunL()方法如果发生leave，那么CActiveScheduler类的Error()将被调用。<br>注意：如果活动对象用于错误处理，那么在他的派生类中应该提供一个比较好的CActiveScheduler Error函数，以便处理那些错误。<br>活动对象的SetActive()方法用于向活动规划器提交一个异步请求。派生类应该在请求发出以后调用这个方法。活动对象也可以通过一定的方法来取消请求，但是这里需要说明的是，取消请求只是让请求提前完成。关于异步请求取消可以使用Cancel()方法。</p>
<p><strong>请求状态（TRequestStatus）<br></strong><br>服务提供者为了完成服务，需要有一个如何完成服务的信息。TRequestStatus 类的对象用于存放为服务提供者定制的请求完成状态。当线程提出请求时，例如RTimer 的After()请求，请求状态对象被作为参数传递到请求函数中。服务完成以后，服务提供者发送信号给服务请求对象的请求信号量并在请求对象中保存一个完成码，通常这个完成码的值是KErrNone或者是其他系统定义的错误码。TRequestStatus 类是密封类，不再被继承。<br></p>
<p>活动规划器和活动对象协同工作</p>
<p>这里的代码和附件中的例子一致，可以下载例子直接在VC6++中调试。活动规划器和活动对象的的协同工作过程如下。首先应该创建一个与当前线程相关的活动规划器：</p>
<table cellSpacing=0 cellPadding=5 width="95%" align=center bgColor=#f1f1f1 border=0>
    <tbody>
        <tr>
            <td>CATV* sco = new(ELeave) CATV();<br>// 推入清理栈<br>CleanupStack::PushL(sco); <br>// 把 sco 活动规划器安装为当前线程的活动对象<br>// 安装以后，sco 活动对象专门处理当前线程的请求事件<br>CActiveScheduler::Install(sco);</td>
        </tr>
    </tbody>
</table>
<p>接着创建一个活动对象，TmCount类是一个从CActive类派生的活动对象类。</p>
<table cellSpacing=0 cellPadding=5 width="95%" align=center bgColor=#f1f1f1 border=0>
    <tbody>
        <tr>
            <td>TmCount* timeCount = TmCount::NewLC(); </td>
        </tr>
    </tbody>
</table>
<p>然后可以从NewLC()方法中看到活动对象构造的具体细节：</p>
<table cellSpacing=0 cellPadding=5 width="95%" align=center bgColor=#f1f1f1 border=0>
    <tbody>
        <tr>
            <td>TmCount* TmCount::NewLC()<br>{<br>console-&gt;Printf(_L("NewLC\n"));<br>// 使用 C++默认构造函数构造<br>TmCount* result = new (ELeave) TmCount(); <br>// 把活动对象推入清理粘<br>CleanupStack::PushL( result ); <br>// 调用两阶段构造函数，构造活动对象内部成员<br>result-&gt;ConstructL(); <br>// 返回活动对象指针<br>return result; <br>};</td>
        </tr>
    </tbody>
</table>
<p>在这个默认的构造函数中，还调用了默认的C++构造函数，这个比较关键，因为正是在这个构造函数中，把活动对象添加到了活动对象，在这个；函数中，还可以定义活动对象的优先权限：</p>
<table cellSpacing=0 cellPadding=5 width="95%" align=center bgColor=#f1f1f1 border=0>
    <tbody>
        <tr>
            <td>
            <p>TmCount::TmCount():CActive(0) // 这里可以设置活动对象的优先级 <br>{ <br>// 把自己加入活动规划器 <br>iTimeCounter=1;<br>CActiveScheduler::Add(this); </p>
            <p>};</p>
            <p>在ConstructL()中，则获得了一个记时器句柄<br>void TmCount::ConstructL()<br>{<br>// 初始化计数器和定时器 <br>iTimeCounter = 0; <br>User::LeaveIfError(iTimer.CreateLocal()); <br>console-&gt;Printf(_L("ConstructL\n"));<br>};</p>
            </td>
        </tr>
    </tbody>
</table>
<p>这样，活动对象构造完成。接着，程序调用活动对象的请求函数。</p>
<table cellSpacing=0 cellPadding=5 width="95%" align=center bgColor=#f1f1f1 border=0>
    <tbody>
        <tr>
            <td>timeCount-&gt;StartL(1);</td>
        </tr>
    </tbody>
</table>
<p>在活动对象的请求函数中：</p>
<table cellSpacing=0 cellPadding=5 width="95%" align=center bgColor=#f1f1f1 border=0>
    <tbody>
        <tr>
            <td>// 活动对象的请求函数<br>void TmCount::StartL(TInt mT) <br>{ <br>// 将请求传递给异步服务提供者，<br>// 异步服务提供者，调用请求函数，<br>// 这里需要注意iStatus 这个参数，它是一个请求状态对象。<br>// 设定定时器状态为每隔mTime秒钟状态完成一次 <br>iTimer.After(iStatus, 10000 * 100 * mT); <br>// 在调用异步请求函数之后调用SteActive()方法，提交异步请求 <br>SetActive(); <br>};</td>
        </tr>
    </tbody>
</table>
<p>异步服务提供者处理请求，当请求处理完成以后，它生成一个事件。活动规划器不断的检查是否有请求完成（是否有请求完成事件发生），如果有请求完成，那么调用与该请求相关联的活动对象的RunL()方法：</p>
<table cellSpacing=0 cellPadding=5 width="95%" align=center bgColor=#f1f1f1 border=0>
    <tbody>
        <tr>
            <td>void TmCountTwo::RunL() <br>{ <br>// 计数器+1以后继续提交延时请求事件 <br>console-&gt;Printf(_L("[2]The Count is -&gt;&gt;%d\n"), iTimeCounter++);<br>// 再次提出异步请求 <br>StartL(1); <br>};</td>
        </tr>
    </tbody>
</table>
<p>在这个方法中又提出了一次异步请求，并使计数器值增加。如果条件符合则可以不再让活动对象提出异步请求，这是一个修改后的RunL()：</p>
<table cellSpacing=0 cellPadding=5 width="95%" align=center bgColor=#f1f1f1 border=0>
    <tbody>
        <tr>
            <td>void TmCount::RunL() <br>{ <br>// 计数器+1以后继续提交延时请求事件 <br>console-&gt;Printf(_L("[1]The Count is -&gt;&gt;%d\n"), iTimeCounter++); <br>// 当记数器值大于等于10时，不再提出异步请求。<br>if (iTimeCounter&lt;10)<br>{<br>StartL(1); <br>}<br>else<br>{<br>//取消请求<br>Cancel();<br>}<br>//User::Leave(9);<br>};</td>
        </tr>
    </tbody>
</table>
<p>如果RunL()在运行过程中发生错误，则RunError()被调用，以下是RunEror（）方法：</p>
<table cellSpacing=0 cellPadding=5 width="95%" align=center bgColor=#f1f1f1 border=0>
    <tbody>
        <tr>
            <td>
            <p>TInt TmCount::RunError(TInt aError)<br>{<br>console-&gt;Printf(_L("[1]Error\n"));<br>//console-&gt;Getch();<br>return 7;<br>};</p>
            <p>如果RunError()方法返回了一个非KErrNone的值那么活动规划器的Error方法将被调用。<br>class CATV :public CActiveScheduler<br>{<br>public :<br>IMPORT_C void Error(TInt anError) const;</p>
            <p>};</p>
            <p>void CATV::Error(TInt anError) const<br>{<br>console-&gt;Printf(_L("Error:%d\n"),anError);<br>//CATV::Stop();<br>};</p>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/34055.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/gtwdaizi/" target="_blank">郭天文</a> 2007-10-12 18:43 <a href="http://www.cppblog.com/gtwdaizi/articles/34055.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>thumb,armi,wins,winc,winscw,分别是什么意思？</title><link>http://www.cppblog.com/gtwdaizi/articles/33257.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Sun, 07 Oct 2007 03:10:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/33257.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/33257.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/33257.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/33257.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/33257.html</trackback:ping><description><![CDATA[thumb和armi都是基于ARM设备的,也就是真机环境:<br>armi可以实现最大数量的真实设备兼容性<br>thumb生成将以稍微降低执行速度为代价而减小代码大小<br><br>wins针对PC,用于VC<br>wincw针对PC,用于CodeWarrior, 其实carbide也是支持的<br>winc 用来实现无GUI的Symbian程序. 它的主要目的是使在PC上面用Symbian应用程序来访问应用文档.
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/33257.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/gtwdaizi/" target="_blank">郭天文</a> 2007-10-07 11:10 <a href="http://www.cppblog.com/gtwdaizi/articles/33257.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转载】RGB，YUV的来历及其相互转换</title><link>http://www.cppblog.com/gtwdaizi/articles/32956.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Sat, 29 Sep 2007 01:40:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/32956.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/32956.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/32956.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/32956.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/32956.html</trackback:ping><description><![CDATA[在视频等相关的应用中，<span><font face=Calibri>YUV</font></span><span>是一个经常出现的格式。本文主要以图解的资料的形式详细描述</span><span><font face=Calibri>YUV</font></span><span>和</span><span><font face=Calibri>RGB</font></span><span>格式的来由，相互关系以及转换方式，并对</span><span><font face=Calibri>C</font></span><span>语言实现的</span><span><font face=Calibri>YUV</font></span><span>转为</span><span><font face=Calibri>RGB</font></span><span>程序进行介绍。</span>
<p><span><span><font face=Calibri>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span><span>人类眼睛的色觉，具有特殊的特性，早在上世纪初，</span><span><font face=Calibri>Young</font></span><span>（</span><span><font face=Calibri>1809</font></span><span>）和</span><span><font face=Calibri>Helmholtz</font></span><span>（</span><span><font face=Calibri>1824</font></span><span>）就提出了视觉的三原色学说，即：视网膜存在三种视锥细胞，分别含有对红、绿、蓝三种光线敏感的视色素，当一定波长的光线作用于视网膜时，以一定的比例使三种视锥细胞分别产生不同程度的兴奋，这样的信息传至中枢，就产生某一种颜色的感觉。</span></p>
<p><font size=3><span><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span><span>70<span>年代以来，由于实验技术的进步，关于视网膜中有三种对不同波长光线特别敏感的视锥细胞的假说，已经被许多出色的<strong>实验所证实</strong>。</span></span><font face="Times New Roman"> </font></font><font face="Times New Roman"></font><font size=3><span>例如：①有人用不超过单个视锥直径的细小单色光束，逐个检查并绘制在体（最初实验是在金鱼和蝾螈等动物进行，以后是人）<strong>视锥细胞的光谱吸收曲线</strong>，发现所有绘制出来的曲线不外三种类型，分别代表了三类光谱吸收特性不同的视锥细胞，一类的吸收峰值在</span><span>420nm<span>处，一类在</span>534nm<span>处，一类在</span>564nm<span>处，差不多正好相当于蓝、绿、红三色光的波长。与上述视觉三原色学说的假设相符。②用微电极记录单个视锥细胞感受器电位的方法，也得到了类似的结果，即不同单色光所引起的不同视锥细胞的超极化型感受器电位的大小也不同，峰值出现的情况符合于三原色学说。</span></span></font></p>
<span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 'Courier New'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 1.0pt"><span style="mso-spacerun: yes"><br><br><br><span lang=ZH style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 'Courier New'; mso-font-kerning: 1.0pt">于是，在彩色显示器</span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">还没有发明的时候，人类已经懂得使用三原色光调配出所有颜色的光。并不是说三原色混合后产生了新的频率的光，而是给人眼睛的感觉是这样。<br><br><br><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">在显示器发明之后，从黑白显示器发展到彩色显示器，人们开始使用发出不同颜色的光的荧光粉（</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>CRT</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">，等离子体显示器），或者不同颜色的滤色片（</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>LCD</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">），或者不同颜色的半导体发光器件（</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>OLED</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">和</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>LED</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">大型全彩显示牌）来形成色彩，无一例外的选择了</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Red,Green,Blue</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">这</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>3</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">种颜色的发光体作为基本的发光单元。通过控制他们发光强度，组合出了人眼睛能够感受到的大多数的自然色彩。</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><o:p></o:p></span>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt"><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><span style="mso-spacerun: yes"><font face=Calibri>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">计算机显示彩色图像的时候也不例外，最终显示的时候，要控制一个像素中</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Red,Green,Blue</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">的值，来确定这个像素的颜色。计算机中无法模拟连续的存储从最暗到最亮的量值，而只能以数字的方式表示。于是，结合人眼睛的敏感程度，使用</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>3</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">个字节（</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>3*8</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">位）来分别表示一个像素里面的</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Red,Green</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">和</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Blue</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">的发光强度数值，这就是常见的</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>RGB</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">格式。我们可以打开画图板，在自定义颜色工具框中，输入</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>r,g,b</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">值，得到不同的颜色。<br><br><br><br><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">但是对于视频捕获和编解码等应用来讲，这样的表示方式数据量太大了。需要想办法在不太影响感觉的情况下，对原始数据的表示方法进行更改，减少数据量。</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt"><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="mso-spacerun: yes">&nbsp;&nbsp;</span></font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">无论中间处理过程怎样，最终都是为了展示给人观看，这样的更改，也是从人眼睛的特性出发，和发明</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>RGB</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">三原色表示方法的出发点是一样的。</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt"><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><span style="mso-spacerun: yes"><font face=Calibri>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">于是我们使用</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Y,Cb,Cr</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">模型来表示颜色。</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Iain</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">的书中写道：</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>The human visual system (HVS) is less sensitive to colour than to luminance (brightness).</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">人类视觉系统（其实就是人的眼睛）对亮度的感觉比对颜色更加敏感。</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt"><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><span style="mso-spacerun: yes"><font face=Calibri>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">在</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>RGB</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">色彩空间中，三个颜色的重要程度相同，所以需要使用相同的分辨率进行存储，最多使用</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>RGB565</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">这样的形式减少量化的精度，但是</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>3</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">个颜色需要按照相同的分辨率进行存储，数据量还是很大的。所以，利用人眼睛对亮度比对颜色更加敏感，将图像的亮度信息和颜色信息分离，并使用不同的分辨率进行存储，这样可以在对主观感觉影响很小的前提下，更加有效的存储图像数据。</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt"><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span>YCbCr</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">色彩空间和它的变形（有时被称为</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>YUV</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">）是最常用的有效的表示彩色图像的方法。</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Y</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">是图像的亮度（</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>luminance/luma</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">）分量，使用以下公式计算，为</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>R,G,B</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">分量的加权平均值：</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt"><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="mso-spacerun: yes">&nbsp;</span>Y = kr R + kgG + kbB<o:p></o:p></font></span></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt"><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><span style="mso-spacerun: yes"><font face=Calibri>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">其中</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>k</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">是权重因数。</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt"><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><span style="mso-spacerun: yes"><font face=Calibri>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">上面的公式计算出了亮度信息，还有颜色信息，使用色差（</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>color difference/chrominance</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">或</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>chroma</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">）来表示，其中每个色差分量为</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>R,G,B</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">值和亮度</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Y</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">的差值：</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt"><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">　　</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Cb = B </font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">－</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Y<o:p></o:p></font></span></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt"><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">　　</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Cr = R </font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">－</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Y <o:p></o:p></font></span></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt; TEXT-INDENT: 23.25pt"><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Cg = G</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">－</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri> Y<o:p></o:p></font></span></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt; TEXT-INDENT: 23.25pt"><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">其中，</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Cb+Cr+Cg</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">是一个常数（其实是一个关于</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Y</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">的表达式），所以，只需要其中两个数值结合</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Y</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">值就能够计算出原来的</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>RGB</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">值。所以，我们仅保存亮度和蓝色、红色的色差值，这就是</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>(Y,Cb,Cr)</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">。</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt; TEXT-INDENT: 23.25pt"><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">相比</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>RGB</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">色彩空间，</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>YCbCr</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">色彩空间有一个显著的优点。</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Y</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">的存储可以采用和原来画面一样的分辨率，但是</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Cb,Cr</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">的存储可以使用更低的分辨率。这样可以占用更少的数据量，并且在图像质量上没有明显的下降。所以，将色彩信息以低于量度信息的分辨率来保存是一个简单有效的图像压缩方法。</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt; TEXT-INDENT: 23.25pt"><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">在</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>COLOUR SPACES .17 ITU-R recommendation BT.601 </font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">中，建议在计算</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Y</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">时，权重选择为</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>kr=0.299,kg=0.587,kb=0.114</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">。于是常用的转换公式如下：</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt; TEXT-INDENT: 22pt; mso-char-indent-count: 2.0"><font face=Calibri size=3>Y = 0.299R + <st1:chmetcnv UnitName="g" SourceValue=".587" HasSpace="False" Negative="False" NumberType="1" TCSC="0" w:st="on">0.587G</st1:chmetcnv> + 0.114B</font></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt; TEXT-INDENT: 22pt; mso-char-indent-count: 2.0"><font size=3><font face=Calibri>Cb = 0.564(B </font><span lang=ZH style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">－</span><font face=Calibri> Y ) </font></font></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt; TEXT-INDENT: 22pt; mso-char-indent-count: 2.0"><font size=3><font face=Calibri>Cr = 0.713(R </font><span lang=ZH style="FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">－</span><font face=Calibri> Y )</font></font></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt; TEXT-INDENT: 22pt; mso-char-indent-count: 2.0"><o:p><font face=Calibri size=3>&nbsp;</font></o:p></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt; TEXT-INDENT: 22pt; mso-char-indent-count: 2.0"><font face=Calibri size=3>R = Y + 1.402Cr</font></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt; TEXT-INDENT: 22pt; mso-char-indent-count: 2.0"><font face=Calibri size=3>G = Y - 0.344Cb - 0.714Cr</font></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt; TEXT-INDENT: 22pt; mso-char-indent-count: 2.0"><font face=Calibri size=3>B = Y + 1.772Cb</font></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0"><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">有了这个公式，我们就能够将一幅</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>RGB</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">画面转换成为</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>YUV</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">画面了，反过来也可以。下面将画面数据究竟是以什么形式存储起来的。</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0"><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">在</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>RGB24</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">格式中，对于宽度为</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>w,</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">高度为</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>h</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">的画面，需要</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>w*h*3</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">个字节来存储其每个像素的</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>rgb</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">信息，画面的像素数据是连续排列的。按照</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>r(0,0),g(0,0),b(0,0);r(0,1),g(0,1),b(0,1);&#8230;;r(w-1,0),g(w-1,0),b(w-1,0);&#8230;;r(w-1,h-1),g(w-1,h-1),b(w-1,h-1)</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">这样的顺序存放起来。</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0"><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">在</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>YUV</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">格式中，以</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>YUV420</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">格式为例。宽度为</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>w</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">高度为</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>h</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">的画面，其亮度</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Y</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">数据需要</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>w*h</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">个字节来表示（每个像素点一个亮度）。而</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Cb</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">和</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Cr</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">数据则是画面中</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>4</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">个像素共享一个</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Cb,Cr</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">值。这样</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Cb</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">用</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>w*h/4</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">个字节，</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Cr</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">用</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>w*h/4</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">个字节。</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0"><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>YUV</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">文件中，把多个帧的画面连续存放。就是</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>YUV YUV YUV&#8230;..</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">这样的不断连续的形式，而其中每个</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>YUV</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">，就是一幅画面。</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0"><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">在这单个</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>YUV</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">中，前</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>w*h</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">个字节是</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Y</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">数据，接着的</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>w*h/4</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">个字节是</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Cb</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">数据，再接着的</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>w*h/4</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">个字节为</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Cr</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">数据。</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0"><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">在由这样降低了分辨率的数据还原出</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>RGB</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">数据的时候，就要依据像素的位置找到它对应的</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Y,Cb,Cr</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">值，其中</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Y</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">值最好找到，像素位置为</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>x,y</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">的话，</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Y</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">数据中第</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>y*width+x</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">个数值就是它的</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Y</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">值。</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Cb</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">和</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Cr</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">由于是每</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>2x2</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">像素的画面块拥有一个，这样</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Cb</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">和</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Cr</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">数据相当于两个分辨率为</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>w/2 * h/2</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">的画面，那么原来画面中的位置为</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>x,y</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">的像素，在这样的低分辨率画面中的位置是</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>x/2,y/2</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">，属于它的</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Cb,Cr</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">值就在这个地方：</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>(y/2)*(width/2)+(x/2)</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">。</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0"><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">为了直观起见，再下面的图中，分别将</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Y</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">画面</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>(Cb,Cr=0)</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">和</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Cb,Cr</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">画面</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>(Y=128)</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">显示出来，可见</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Cb,Cr</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">画面的分辨率是</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Y</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">画面的</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>1/4</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">。但是合成一个画面之后，我们的眼睛丝毫感觉不到</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>4</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">个像素是共用一个</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Cb,Cr</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">的。</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><o:p></o:p></span></p>
<br><br>&nbsp; Cb,Cr<span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">画面</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><o:p></o:p></span>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0"><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">将</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Cb,Cr</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">画面放大观察，里面颜色相同的块都是</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>2x2</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">大小的。</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0in 0in 10pt; TEXT-INDENT: 24pt; mso-char-indent-count: 2.0"><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">附件为</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Windows Mobile</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">上使用公式进行</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>YUV</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">到</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>RGB</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">转换的程序。其中需要注意的是</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>Cb,Cr</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">在计算过程中是会出现负数的，但是从</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>-128</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">到</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>127</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">这些数值都用一个字节表示，读取的时候就映射</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>0</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">到</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>255</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">这个区间，成为了无符号的值，所以要减去</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>128</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">，才能参与公式计算。这样的运算有浮点运算，效率是比较低的，所以要提高效率的话，一般在实用程序中使用整数计算或者查表法来代替。还有，运算后的</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>r,g,b</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">可能会超过</span><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%"><font face=Calibri>0-255</font></span><span lang=ZH style="FONT-SIZE: 12pt; LINE-HEIGHT: 115%; FONT-FAMILY: 宋体; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri">的区间，作一个判断进行调整就可以了。</span></p>
<span style="COLOR: red">&nbsp;&nbsp;&nbsp;&nbsp;不过这里面的YUV TO RGB的算法,效率实在是低,因为里面有了浮点运算,解一帧176*144的图像大概需要400ms左右,这是无法忍受的,如果消除浮点运算,只需要10ms左右,效率的提升真是无法想象.所以大家还是避免在手机上面进行浮点运算.</span></span></span></span></span>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/32956.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/gtwdaizi/" target="_blank">郭天文</a> 2007-09-29 09:40 <a href="http://www.cppblog.com/gtwdaizi/articles/32956.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>