﻿<?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++博客-一针见血-文章分类-Windows Mobile</title><link>http://www.cppblog.com/gtwdaizi/category/5217.html</link><description /><language>zh-cn</language><lastBuildDate>Sat, 21 Feb 2009 18:01:43 GMT</lastBuildDate><pubDate>Sat, 21 Feb 2009 18:01:43 GMT</pubDate><ttl>60</ttl><item><title>[Windows Moible]WM平台下如何关联应用程序与RTSP地址</title><link>http://www.cppblog.com/gtwdaizi/articles/57581.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Thu, 31 Jul 2008 02:02:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/57581.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/57581.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/57581.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/57581.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/57581.html</trackback:ping><description><![CDATA[<p>1. 首先把WM手机通过同步工具同步到PC<br>2. 使用Windows CE Remote Registry Editor 工具打开WM的注册表<br>3. 在注册表中加入以下key-value值<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(1).添加key<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[HKEY_LOCAL_MACHINE\Software\Microsoft\Shell\URLProtocols\rtsp]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (2).添加key-value<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[HKEY_CLASSES_ROOT\rtsp]</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[HKEY_CLASSES_ROOT\rtsp\DefaultIcon]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@=""<a href="file://storage/">\\Storage</a> Card\\Program Files\\guotw\\Mobile.exe" %0"</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[HKEY_CLASSES_ROOT\rtsp\Shell]</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[HKEY_CLASSES_ROOT\rtsp\Shell\Open]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@=""</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[HKEY_CLASSES_ROOT\rtsp\Shell\Open\Command]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@=""<a href="file://storage/">\\Storage</a> Card\\Program Files\\guotw\\Mobile.exe" %1"</p>
4. 测试, 在浏览中任意输入一个rtsp://192.168.0.1:554/test, 那么就会自动启动Mobile这个应用程序了!
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/57581.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-31 10:02 <a href="http://www.cppblog.com/gtwdaizi/articles/57581.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[Windows Mobile]ActiveSync4.5+WM6同步上网的设置问题</title><link>http://www.cppblog.com/gtwdaizi/articles/56762.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Mon, 21 Jul 2008 06:58:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/56762.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/56762.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/56762.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/56762.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/56762.html</trackback:ping><description><![CDATA[多普达的手机与PC(XP homne)通过ActiveSync4.5连接同步成功, 但始终无法连接至Internet, <br>提示：由于发生未知错误0x80072f78，找不到您正在查找的页面。<br><br>解决办法, 如下<br>　在PC的注册表中添加注册表项:<br>&nbsp;&nbsp;&nbsp; [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows CE Services]<br>&nbsp;&nbsp;&nbsp; "AllowLSP"=dword:00000000<br><br>注: 发现在另一台XP professional的机器的注册表中并没有这项, 但也是能成功访问网页, 不知道是不是professional和home的区别导致
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/56762.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-21 14:58 <a href="http://www.cppblog.com/gtwdaizi/articles/56762.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[Windows Mobile]如何使用CBitmapButton</title><link>http://www.cppblog.com/gtwdaizi/articles/54965.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Mon, 30 Jun 2008 08:29:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/54965.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/54965.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/54965.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/54965.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/54965.html</trackback:ping><description><![CDATA[<p>1. 首先把要贴图的按钮的Owner Draw 属相修改为True<br>2. 创建对话框的成员变量bitmapBt<br>3.&nbsp;在OnInitDialog方法中添加如下代码：<br><br>&nbsp;bitmapBt.LoadBitmaps( IDB_UP, IDB_DOWN, IDB_ONDOWN, 0 );</p>
<p>&nbsp;bitmapBt.SubclassDlgItem(IDOK, this);</p>
<p>&nbsp;bitmapBt.SizeToContent();</p>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/54965.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-30 16:29 <a href="http://www.cppblog.com/gtwdaizi/articles/54965.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[Windows Mobile]全屏对话框</title><link>http://www.cppblog.com/gtwdaizi/articles/49723.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Tue, 13 May 2008 07:00:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/49723.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/49723.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/49723.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/49723.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/49723.html</trackback:ping><description><![CDATA[<p>1. 完全全屏<br>在OnInitDialog() 方法中调用如下代码:<br><br>m_bFullScreen = FALSE;<br>CDialog::OnInitDialog();</p>
<p>&nbsp;// Call SHInitDialog with flags for full screen.<br>&nbsp;SHINITDLGINFO shidi;</p>
<p>&nbsp;shidi.dwMask = SHIDIM_FLAGS;<br>&nbsp;shidi.dwFlags = SHIDIF_FULLSCREENNOMENUBAR;<br>&nbsp;shidi.hDlg = m_hWnd;<br>&nbsp;::SHInitDialog(&amp;shidi);</p>
<p>&nbsp;// TODO: Add extra initialization here.<br>&nbsp;//::CommandBar_Show(m_pWndEmptyCB-&gt;m_hWnd, FALSE);</p>
<p>&nbsp;// SHFullScreen fails if dialog box is not foreground.<br>&nbsp;SetForegroundWindow();&nbsp; <br>&nbsp;SHFullScreen(m_hWnd, SHFS_HIDETASKBAR | SHFS_HIDESIPBUTTON);</p>
<p>&nbsp;// Resize the window over the taskbar area.<br>#define MENU_HEIGHT 26<br>&nbsp;RECT rect;<br>&nbsp;GetWindowRect(&amp;rect);<br>&nbsp;rect.top -= MENU_HEIGHT;<br>&nbsp;MoveWindow(&amp;rect, TRUE);<br><br>上面一段代码可以实现完全的全屏, 但是我使用的过程中发现对话框的标题栏消失了..不知道为什么..<br><br>2. 客户区全屏<br><br><span style="COLOR: #3366ff">&nbsp;CHikConfigDlg configDlg;</span></p>
<p style="COLOR: #3366ff">&nbsp;CRect rc;</p>
<p style="COLOR: #3366ff">&nbsp;SetRect( &amp;rc, 0, 0, GetSystemMetrics( SM_CXSCREEN ), GetSystemMetrics( SM_CYSCREEN ) );<br><br>// 用来隐藏菜单栏的</p>
<p style="COLOR: #3366ff">&nbsp;//HWND hCommandBarWnd = ::FindWindowW( _T("menu_worker"), NULL );</p>
<p style="COLOR: #3366ff">&nbsp;//::CommandBar_Show(hCommandBarWnd, FALSE);</p>
<p style="COLOR: #3366ff">&nbsp;::SHFullScreen( configDlg.m_hWnd, SHFS_HIDETASKBAR | SHFS_HIDESTARTICON | SHFS_HIDESIPBUTTON );</p>
<p style="COLOR: #3366ff">&nbsp;::MoveWindow( configDlg.m_hWnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, FALSE );</p>
<p style="COLOR: #3366ff">&nbsp;INT_PTR nResponse = configDlg.DoModal();</p>
<p style="COLOR: #3366ff">&nbsp;if ( nResponse == IDOK )<br>&nbsp;{</p>
<p>&nbsp;}<br></p>
调用上面一段代码, 创建的CHikConfigDlg 对话框就是在客户区内全屏的.
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/49723.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-05-13 15:00 <a href="http://www.cppblog.com/gtwdaizi/articles/49723.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>[Windows Mobile]开发书籍介绍 </title><link>http://www.cppblog.com/gtwdaizi/articles/43399.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Thu, 28 Feb 2008 08:10:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/43399.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/43399.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/43399.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/43399.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/43399.html</trackback:ping><description><![CDATA[<p><font size=2>1、《Microsoft Windows CE 程序设计》 北京大学出版社<br>[美]Doudlas Boling 著<br>该书可以与经典著作《Microsoft Windows 程序设计》相媲美，就象要想在Window平台上开发，必看 《Microsoft Windows 程序设计》一样，如果你想在Windows CE平台上开发，就不得不看《Microsoft Windows CE 程序设计》。<br>该书的CE是CE2.0版本。<br>详细介绍：<a style="COLOR: #0000ff" href="http://www.china-pub.com/computers/common/info.asp?id=3996" target=_blank><u>http://www.china-pub.com/computers/common/info.asp?id=3996</u></a><br></font><span style="FONT-SIZE: 10pt">下载该书的源代码和英语电子书，上下面介绍的FTP：<a href="http://mobile.winfans.net/ccs/forums/89/ShowPost.aspx"><u><font color=#800080>http://mobile.winfans.net/ccs/forums/89/ShowPost.aspx</font></u></a></span><br><br><font size=2>《Programming Microsoft Windows CE .NET, Third Edition》 MS.Press<br>目前市面上没有该书的中译本，不过有个牛人在翻译该书，可以看看他的BLOG：<br></font><a style="COLOR: #0000ff" href="http://blog.csdn.net/tellmenow/" target=_blank><u>http://blog.csdn.net/tellmenow/</u></a><br><br><font size=2>以上两本书，都有英文的电子书和书中例子的源代码。<br><br>2、《EVC高级编程及其应用开发（Embedded Visual C++嵌入式编程）》 <br>中国水利水电出版社<br>汪兵 李存斌 陈鹏等 著<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 该书非常适合初学者，例子介绍得很详细，都是一步一步教你怎么做的。<br>中国水利水电出版社 网上有该书书中例子的源代码。<br>详细介绍：<a style="COLOR: #0000ff" href="http://www.china-pub.com/computers/common/info.asp?id=24402" target=_blank><u>http://www.china-pub.com/computers/common/info.asp?id=24402</u></a></font><br><br><font size=2>3、《Windows Mobile手机应用开发》&nbsp;&nbsp; 人民邮电出版社<br>傅曦 齐宇 徐骏 著<br>该书需要一定的编程基础。<br>网上有该书中的例子源代码。<br>详细介绍：<a style="COLOR: #0000ff" href="http://www.china-pub.com/computers/common/info.asp?id=25574" target=_blank><u>http://www.china-pub.com/computers/common/info.asp?id=25574</u></a></font><br><font size=2>4、《Windows CE应用程序设计》 机械工业出版社<br>田东风 著<br>该书也是不错的入门书籍，书上的例子都不错。以Microsoft eMbedded Visual Tools 3．0为开发工具。<br>详细介绍：<a style="COLOR: #0000ff" href="http://www.china-pub.com/computers/common/info.asp?id=14697" target=_blank><u>http://www.china-pub.com/computers/common/info.asp?id=14697</u></a><br><span style="FONT-SIZE: 10pt">下载该书的源代码，上下面介绍的FTP：<a href="http://mobile.winfans.net/ccs/forums/89/ShowPost.aspx"><u><font color=#800080>http://mobile.winfans.net/ccs/forums/89/ShowPost.aspx</font></u></a></span><br><br>以上的书，本人都多多少少看了一些，其他的书，没有怎么看，也不好推荐。<br>以下的书，也很不错：<br><br>5、《Microsoft .NET Compact Framework 技术内幕&nbsp;》 清华大学出版社<br>Andy Wigley,Stephen Wheelwright 著<br>详细介绍：<a style="COLOR: #0000ff" href="http://www.china-pub.com/computers/common/info.asp?id=14775" target=_blank><u>http://www.china-pub.com/computers/common/info.asp?id=14775</u></a><br>&nbsp; <br>6、《移动设备.NET应用程序设计》 清华大学出版社<br>[英]Andy Wigley;Peter Roxburgh&nbsp; 著<br>详细介绍：<a style="COLOR: #0000ff" href="http://www.china-pub.com/computers/common/info.asp?id=9931" target=_blank><u>http://www.china-pub.com/computers/common/info.asp?id=9931</u></a><br>7、《Windows CE权威指南 》&nbsp;&nbsp;&nbsp;&nbsp; 中国电力出版社<br>&nbsp;[美]CHRIS MUENCH&nbsp; 著<br>详细介绍：<a style="COLOR: #0000ff" href="http://www.china-pub.com/computers/common/info.asp?id=2196" target=_blank><u>http://www.china-pub.com/computers/common/info.asp?id=2196</u></a><br><br>8、《Windows CE.NET系统分析及实验教程》&nbsp; 机械工业出版社<br>&nbsp;&nbsp;陈向群 等&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;著<br>详细介绍：<a style="COLOR: #0000ff" href="http://www.china-pub.com/computers/common/info.asp?id=9701" target=_blank><u>http://www.china-pub.com/computers/common/info.asp?id=9701</u></a><br>9、《Windows CE 程序设计实务：使用eMbedded Visual Basic&nbsp;》<br>中国电力出版社<br>李永隆 健莲科技 著<br>详细介绍：<a style="COLOR: #0000ff" href="http://www.china-pub.com/computers/common/info.asp?id=6588" target=_blank><u>http://www.china-pub.com/computers/common/info.asp?id=6588</u></a><br>10、《Windows CE.net内核定制及应用开发》&nbsp;&nbsp; 电子工业出版社<br>周毓林 宁杨 陆贵强 付林林 著<br>详细介绍：<a style="COLOR: #0000ff" href="http://www.china-pub.com/computers/common/info.asp?id=24208" target=_blank><u>http://www.china-pub.com/computers/common/info.asp?id=24208<br></u></a><br><font size=1><span style="FONT-SIZE: 12pt"><font size=1><span style="FONT-SIZE: 14pt"><font size=2><font size=1><span style="FONT-SIZE: 12pt"><font size=1><span style="FONT-SIZE: 14pt"><font size=1><span style="FONT-SIZE: 12pt"><font size=1><span style="FONT-SIZE: 14pt"><font size=2><font size=1><span style="FONT-SIZE: 12pt"><font size=1>另外：MEDC2005实验用 的HandBook也可以</font><font size=2>上下面介绍的FTP</font></span></font></font></span></font></span></font></span></font><font size=2>：</font><a href="http://mobile.winfans.net/ccs/forums/89/ShowPost.aspx"><font color=#800080 size=2><u>http://mobile.winfans.net/ccs/forums/89/ShowPost.aspx</u></font></a><br></span></font></font><br></span></font></span></font></font>注明：最先发表在：<a style="COLOR: #0000ff" href="http://www.justmobiler.com/319/ShowPost.aspx" target=_blank><u>http://www.justmobiler.com/319/ShowPost.aspx</u></a><br>另外，本人偷懒，上面给出的书籍的详细介绍，都是来自<a style="COLOR: #0000ff" href="http://www.china-pub.com/" target=_blank><u>China-pub</u></a>上的。其实，大家可以去<a style="COLOR: #0000ff" href="http://www.dearbook.com/" target=_blank><u>第二书店</u></a>看看，有时候可以来个互补。本人在这两个网站上都买过书，觉得还可以。至少到目前没有出错过。</p>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/43399.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-02-28 16:10 <a href="http://www.cppblog.com/gtwdaizi/articles/43399.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[Windows Mobile]开发环境搭建指南 [好文转载]</title><link>http://www.cppblog.com/gtwdaizi/articles/43397.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Thu, 28 Feb 2008 08:00:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/43397.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/43397.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/43397.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/43397.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/43397.html</trackback:ping><description><![CDATA[<h2><span><font face=Verdana size=3>内容简介</font></span></h2>
<p><font face=Verdana><font size=2><span>本文描述了如何搭建典型的</span><span>Windows Mobile</span><span>开发环境。介绍了相应的</span><span>IDE</span><span>、</span><span>SDK</span><span>及辅助开发工具的安装及常用配置，并对</span><span>Windows Mobile</span><span>下一代开发环境的发展前景做出展望。本文适合初次接触</span><span>Windows Mobile</span><span>开发的开发人员。</span></font></font></p>
<h2><font face=Verdana><font size=3><span>Windows Mobile</span><span>开发简介</span></font></font></h2>
<p><font face=Verdana><font size=2><span>Windows Mobile</span><span>是微软公司操作系统产品线上重要的一环。与</span><span>Windows 9x/NT/XP/2003</span><span>相比，</span><span>Windows Mobile</span><span>作为完整产品线出现在公众面前的时间非常短，但它的发展却异常迅速，而在这一发展过程中，开发人员提供了绝对关键的推动力。现在，越来越多的开发人员（特别是</span><span>.NET</span><span>开发人员）希望能尽快进入</span><span>Windows Mobile</span><span>的开发领域，而他们所面临的首要问题，除了熟悉</span><span>Windows Mobile</span><span>平台特性之外，便是如何搭建适合的开发环境。因此，本文就将从如何搭建一个</span><span>Windows Mobile</span><span>开发环境入手，对</span><span>Windows Mobile</span><span>平台的开发特性进行概要描述，以期帮助开发人员迅速进入</span><span>Windows Mobile</span><span>开发领域。</span></font></font></p>
<p><font face=Verdana><font size=2><span>在展开本文的内容之前需要说明的一点是，</span><span>Windows Mobile</span><span>平台开发主要包含以下两方面内容：</span></font></font></p>
<p><font face=Verdana><font size=2><span><span>l<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>平台级开发</span></font></font></p>
<p><font face=Verdana><font size=2><span><span>l<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>应用级开发</span></font></font></p>
<p><font face=Verdana><font size=2><span>因为</span><span>Windows Mobile</span><span>平台构建于微软的</span><span>Windows CE</span><span>系列操作系统之上（当前正式商用版本为</span><span>Windows CE .NET 4.21</span><span>），而</span><span>Windows CE</span><span>操作系统具有非常良好的模块化特性，因此开发人员，特别是手机设备厂商，可以通过微软提供的</span><span>Platform Builder</span><span>及</span><span>eMbedded Visual C++</span><span>（以下简称为</span><span>eVC</span><span>）非常方便地定制自己所需的操作系统。这对应的是上面所说的平台级开发。</span></font></font></p>
<p><font face=Verdana><font size=2><span>然而，绝大多数的开发人员并不需要去构建一个全新的、个性化的系统，他们只需要关心如何构建能够运行在</span><span>Windows Mobile</span><span>设备上的应用程序。为此，微软按主要智能设备自身硬件设备特性的不同以及用户体验的差异，定制出了</span><span>Windows CE .NET 4.x</span><span>系列操作系统的两个主要分支，分别安装在不同的</span><span>Windows Mobile</span><span>硬件设备中，从而也就构成了我们通常所说的</span><span>Pocket PC</span><span>和</span><span>Smartphone</span><span>。以下内容中的</span><span>Windows Mobile</span><span>开发，除特指之外，均表示</span><span>Pocket PC/Smartphone</span><span>开发。</span></font></font></p>
<p><font face=Verdana><font size=2><span>本文中提供的大量开发工具，除单独标出的以外，均可在</span><span><a href="http://msdn.microsoft.com/mobility/downloads/default.aspx">http://msdn.microsoft.com/mobility/downloads/default.aspx</a></span><span>下载。</span></font></font></p>
<h2><span><font face=Verdana size=3>迅速搭建开发环境</font></span></h2>
<p><font face=Verdana><font size=2><span>为了进行</span><span>Windows Mobile</span><span>开发，我们需要搭建相应的开发环境。所幸的是，这一环境搭建起来非常简单。</span></font></font></p>
<h3><font face=Verdana><font size=2><span>安装</span><span>Visual Studio .NET 2003</span></font></font></h3>
<p><font face=Verdana><font size=2><span>为了降低</span><span>Windows Mobile</span><span>的开发难度，提高开发人员的开发效率，微软把</span><span>.NET Framework</span><span>移植到了</span><span>Windows Mobile</span><span>设备上，针对</span><span>Windows Mobile</span><span>设备及</span><span>Windows CE .NET</span><span>操作系统设计了</span><span>.NET Compact Framework</span><span>（以下简称</span><span>.NET CF</span><span>）。而</span><span>Visual Studio .NET 2003</span><span>正是开发</span><span>.NET CF</span><span>应用程序的最佳</span><span>IDE</span><span>。在</span><span>Visual Studio .NET 2003</span><span>的安装中默认集成了</span><span>.NET CF 1.0</span><span>，同时提供了</span><span>Pocket PC 2002</span><span>的开发模板，可以直接用来开发</span><span>Pocket PC 2002</span><span>应用程序。</span></font></font></p>
<p><font face=Verdana><font size=2><span>您也可以选择</span><span>Visual Studio 2005</span><span>作为开发工具，目前最高版本为</span><span>Beta 1 Refresh</span><span>。在</span><span>Visual Studio 2005</span><span>中，默认提供了</span><span>Pocket PC/Smartphone 2003 SE</span><span>（第二版）的开发模板，同时将</span><span>Pocket PC 2003 SE</span><span>开发使用</span><span>.NET CF</span><span>版本升级到</span><span>2.0 (beta)</span><span>。</span></font></font></p>
<h3><font face=Verdana><font size=2><span>安装</span><span>eVC (</span><span>可选</span><span>)</span></font></font></h3>
<p><font face=Verdana><font size=2><span>以上环境已经完全可以基于</span><span>.NET CF</span><span>开发</span><span>Windows Mobile</span><span>应用程序。但如果您想使用</span><span>C/C++</span><span>语言来进行</span><span>native</span><span>开发，或者想在</span><span>Windows Mobile</span><span>设备上开发</span><span>COM</span><span>组件及应用，那么可以选择</span><span>eVC</span><span>作为开发工具。目前</span><span>eVC</span><span>的最高版本为</span><span>4.0 + SP4</span><span>，请确保安装了最新的补丁包。</span></font></font></p>
<p><font face=Verdana><font size=2><span>也许您会问：既然已经有了</span><span>Visual Studio .NET</span><span>环境，为什么还要使用</span><span>eVC</span><span>作为开发工具呢？这主要是因为，当前的</span><span>.NET CF</span><span>功能相对而言还很不完整，有很多</span><span>Windows CE .NET</span><span>操作系统的核心功能没有被封装入</span><span>.NET CF</span><span>，如：加密</span><span>/</span><span>解密、网络底层通讯、</span><span>COM</span><span>互操作、</span><span>RAPI</span><span>等等。为了完成上述操作，我们或者使用平台调用</span><span>(P/Invoke)</span><span>以托管方式开发，或者使用</span><span>eVC</span><span>直接针对系统底层进行</span><span>native</span><span>开发。对于</span><span>COM</span><span>互操作，目前</span><span>.NET CF</span><span>还不提供</span><span>COM</span><span>互操作</span><span>(Interop)</span><span>机制，只能使用</span><span>eVC</span><span>进行</span><span>C/C++ COM</span><span>开发。好消息是，在</span><span>.NET CF 2.0</span><span>中将提供功能强大的</span><span>COM</span><span>互操作特性支持，同时也将在</span><span>Visual C++ 2005</span><span>环境中同时提供</span><span>managed</span><span>及</span><span>native</span><span>开发功能，这样所有的开发工作将完全整合在</span><span>Visual Studio 2005</span><span>同一环境中。</span></font></font></p>
<h3><font face=Verdana><font size=2><span>安装</span><span>Pocket PC/Smartphone 2003 SDK</span></font></font></h3>
<p><font face=Verdana><font size=2><span>为了开发</span><span>Pocket PC 2003</span><span>或</span><span>Smartphone 2003</span><span>应用程序，您还需要安装</span><span>Pocket PC 2003 SDK</span><span>或</span><span>Smartphone 2003 SDK</span><span>。值得注意的是，这两款</span><span>SDK</span><span>中所包含的模拟器均为英语环境，如果您想使用简体中文环境的模拟器，请去微软网站上单独下载。</span></font></font></p>
<p><font face=Verdana><font size=2><span>如果您使用</span><span>Visual Studio 2005</span><span>开发</span><span>Windows Mobile</span><span>应用程序，则不需要单独安装相应的</span><span>SDK</span><span>，因为</span><span>SDK</span><span>已经被默认集成至了</span><span>Visual Studio 2005</span><span>环境中。</span></font></font></p>
<h3><font face=Verdana><font size=2><span>SQL Server CE (</span><span>可选</span><span>)</span></font></font></h3>
<p><font face=Verdana><font size=2><span>这是</span><span>Pocket PC</span><span>上推荐使用的嵌入式数据库产品，它与</span><span>SQL Server</span><span>桌面版之间可以实现良好的数据同步及互操作，目前正式版的最新版本为</span><span>2.0</span><span>。在</span><span>SQL Server 2005 Beta 2</span><span>测试版中，包含有</span><span>SQL Server CE 2.0</span><span>的升级版本</span><span>SQL Server 2005 Mobile Edition</span><span>——不过该版本目前只支持</span><span>Pocket PC 2003</span><span>系统。预计</span><span>SQL Server Mobile Edition</span><span>在下一个版本中才能提供对</span><span>Smartphone</span><span>的支持。</span></font></font></p>
<h2><font face=Verdana><font size=3><span>ActiveSync</span><span>环境搭建</span></font></font></h2>
<p><font face=Verdana><font size=2><span>在完成了上述开发环境的搭建之后，您就可以在</span><span>Visual Studio .NET</span><span>中开发和调试应用程序，并在设备</span><span>/</span><span>模拟器中进行部署。但是，如果您还需要进一步执行下述操作，那么请按本节所述继续搭建</span><span>ActiveSync</span><span>环境。可能的执行操作包括（但不限于）：</span></font></font></p>
<p><font face=Verdana><font size=2><span><span>l<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>向设备</span><span>/</span><span>模拟器中复制文件</span></font></font></p>
<p><font face=Verdana><font size=2><span><span>l<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>从设备</span><span>/</span><span>模拟器中删除文件</span></font></font></p>
<p><font face=Verdana><font size=2><span><span>l<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>与设备</span><span>/</span><span>模拟器同步数据</span></font></font></p>
<p><font face=Verdana><font size=2><span><span>l<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>开发和调试包含</span><span>RAPI (Remote API)</span><span>功能的应用</span></font></font></p>
<p><font face=Verdana><font size=2><span><span>l<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>&#8230;&#8230;</span></font></font></p>
<h3><font face=Verdana><font size=2><span>安装</span><span>ActiveSync</span></font></font></h3>
<p><font face=Verdana><font size=2><span>ActiveSync</span><span>是一款管理</span><span>Windows Mobile</span><span>设备连接、与</span><span>PC</span><span>进行数据同步的工具。如果您开发时使用的是真实设备，则最好事先安装</span><span>ActiveSync</span><span>使之与</span><span>PC</span><span>机连接。如果您使用的是模拟器，则除了安装</span><span>ActiveSync</span><span>以外，还需要安装下述工具。</span></font></font></p>
<h3><font face=Verdana><font size=2><span>安装</span><span>Connect Emulator with ActiveSync</span></font></font></h3>
<p><font face=Verdana><font size=2><span>如果您使用的是模拟器软件，除了安装</span><span>ActiveSync</span><span>外，还必须安装</span><span>Connect Emulator with ActiveSync</span><span>这款工具软件。它将使您可以直接通过</span><span>ActiveSync</span><span>连接到模拟器上。</span></font></font></p>
<h2><span><font face=Verdana size=3>辅助工具介绍</font></span></h2>
<p><font face=Verdana><font size=2><span>除了上述基本开发工具以外，在</span><span>Windows Mobile</span><span>开发社区中还存在着大量的辅助工具，包括应用程序框架、工具、控件等等。其中有一些由于定位准确、制作优良、使用方便，已经成为</span><span>Windows Mobile</span><span>开发不可或缺的好助手。以下列出其中的一部分，更多的还存在于</span><span>Windows Mobile</span><span>开发者社区及互联网上，等待着您去发现。</span></font></font></p>
<h3><span><font face=Verdana size=2>OpenNETCF.org Smart Device Framework</font></span></h3>
<p><font face=Verdana><font size=2><span>由几位长年活跃于</span><span>Windows Mobile</span><span>开发者社区的</span><span>MVP</span><span>共同开发的</span><span>OpenNETCF.org Smart Device Framework (</span><span>以下简称为</span><span>SDF)</span><span>，几天前刚刚获得了</span><span>Pocket PC Magazine</span><span>评出的</span><span>2004</span><span>年度最佳</span><span>.NET</span><span>开发框架大奖。熟悉</span><span>SDF</span><span>的开发者都会认为，对于这一奖项，</span><span>OpenNETCF</span><span>的确当之无愧，因为</span><span>SDF</span><span>几乎已经成了</span><span>Windows Mobile</span><span>开发者不可或缺的工具。他们对</span><span>.NET CF</span><span>的不足给出了及时的弥补，在</span><span>SDF</span><span>中，您可以找到</span><span>Configuration</span><span>、</span><span>XML Serialization</span><span>、</span><span> Notification</span><span>、</span><span>Interop Services</span><span>、</span><span>WSE 2.0</span><span>等一系列</span><span>.NET CF</span><span>当前版本尚未提供的功能，以及诸如</span><span>ListBoxEx</span><span>等优秀的控件。更值得一提的是，</span><span>SDF</span><span>是一项完全免费的开源项目。这几位</span><span>MVP</span><span>为整个</span><span>Windows Mobile</span><span>开发者社区所做的贡献也许真的无法用金钱来衡量。</span></font></font></p>
<p><font face=Verdana><font size=2><span>下载地址：</span><span><a href="http://www.opennetcf.org/">http://www.opennetcf.org</a></span><span>。</span></font></font></p>
<h3><span><font face=Verdana size=2>Windows <st1:place w:st="on">Mobile</st1:place> Developer Power Toys</font></span></h3>
<p><font face=Verdana><font size=2><span>这是微软继</span><span>Pocket PC/Smartphone 2003 SDK</span><span>之后为开发人员提供的另一套开发辅助工具集。其中包含不少非常值得一用的优秀工具，如：</span></font></font></p>
<p><font face=Verdana><font size=2><span><span>l<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>ActiveSync Remote Display</span><span>：把连接在</span><span>PC</span><span>上的智能设备影像通过</span><span>PC</span><span>屏幕放大显示</span></font></font></p>
<p><font face=Verdana><font size=2><span><span>l<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>CECopy</span><span>：以命令行的方式向所连接的智能设备传输文件</span></font></font></p>
<p><font face=Verdana><font size=2><span><span>l<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>Hopper</span><span>：用于</span><span>Pocket PC 2003</span><span>的用户输入压力测试工具</span></font></font></p>
<p><font face=Verdana><font size=2><span><span>l<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>PPC Command Shell</span><span>：用于</span><span>Pocket PC 2003</span><span>的命令行工具</span></font></font></p>
<p><font face=Verdana><font size=2><span><span>l<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>TypeIt</span><span>：用于</span><span>Smartphone 2003</span><span>的辅助文字输入工具</span></font></font></p>
<p><font face=Verdana><font size=2><span><span>l<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>&#8230;&#8230;</span></font></font></p>
<h3><span><font face=Verdana size=2>Mobile Application Development Toolkit 2004</font></span></h3>
<p><font face=Verdana><font size=2><span>这是微软近期推出的</span><span>Windows Mobile</span><span>开发工具及资料集，其中包含上述所有产品及工具，以及一系列相关的文档、教程及参考资料。</span></font></font></p>
<h2><span><font face=Verdana size=3>结束语</font></span></h2>
<p><font face=Verdana><font size=2><span>好了，对于如何搭建</span><span>Windows Mobile</span><span>的开发环境就介绍到这里了。可以肯定地说，随着微软公司支持力度的增加和</span><span>Windows Mobile</span><span>开发者社区的成熟，</span><span>Windows Mobile</span><span>开发将面临越来越有利的良好环境。</span></font></font></p>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/43397.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-02-28 16:00 <a href="http://www.cppblog.com/gtwdaizi/articles/43397.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>开发 Windows Mobile 应用程序 FAQ 一</title><link>http://www.cppblog.com/gtwdaizi/articles/43395.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Thu, 28 Feb 2008 07:58:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/43395.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/43395.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/43395.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/43395.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/43395.html</trackback:ping><description><![CDATA[<span class=a14c id=zoom>&nbsp;
<p style="TEXT-INDENT: 2em">问：什么是 Windows Mobile？
<p style="TEXT-INDENT: 2em">答：Windows Mobile 是 Microsoft 用于 Pocket PC 和 Smartphone 的软件平台。Windows Mobile 将熟悉的 Windows 桌面扩展到了个人设备中。
<p style="TEXT-INDENT: 2em">问：Pocket PC 和 Smartphone 之间有什么不同？
<p style="TEXT-INDENT: 2em">答：考虑 Pocket PC 和 Smartphone 的主要使用特性方面。Smartphone 主要是在格式因素和使用两方面作为一种电话设备而设计的。它经过良好的微调，可以用于发出和接收呼叫，并且还可以作为消息处理设备。Pocket PC 主要是作为一种小型个人计算机而设计的，对于查看和管理数据与增强消息处理而言很不错。某些 Pocket PC 设备也具有电话功能。您应当尽量根据目标 Windows Mobile 设备的使用特性来调整您的应用程序。
<p style="TEXT-INDENT: 2em">问：Pocket PC 和 Smartphone 有哪些不同的版本（例如 2002、2003）？
<p style="TEXT-INDENT: 2em">答：Windows Mobile 软件的每个新版本都是在可供开发人员使用的丰富的现有开发平台上构建的，而同时保持了一致的核心，这样应用程序就可以面向各种设备了。目前有三种通用的 Windows Mobile 软件版本：
<p style="TEXT-INDENT: 2em">&#8226; Windows Mobile 2002 软件：运行设备的软件有时称为 Pocket PC 2002 和 Smartphone 2002。新的开发人员功能包括 MAPI 和连接管理器。
<p style="TEXT-INDENT: 2em">&#8226; Windows Mobile 2003 软件：2003 软件版本将 .NET Compact Framework 添加到基于 2003 的设备 ROM。这使得开发人员能够为基于 Windows Mobile 2003 的设备编写托管代码应用程序。其他的新功能包括配置管理器、蓝牙可编程性和 SMS 截获支持。
<p style="TEXT-INDENT: 2em">&#8226; Windows Mobile 2003 Second Edition：Second Edition 版本使得设备制造商能够通过该版本的主要功能（例如，对 Pocket PC 的横向、方形和高分辨率屏幕以及 Smartphone 的 QVGA 屏幕的支持）进行创新。其命名反映了开发平台的一致性，这对于此版本也没有改变，所有支持新屏幕方向和分辨率的 API 始终是平台的一部分。
<p style="TEXT-INDENT: 2em">问：我如何识别不同的软件版本？
<p style="TEXT-INDENT: 2em">答：Pocket PC 和 Smartphone 在 Settings 中都有一个 About 面板。Settings 可以从两种设备的 Start 菜单找到。
<p style="TEXT-INDENT: 2em">根据代码，您可以使用 GetVersionEx 函数查询最高和最低的 OS 版本以及软件的确切内部版本号。
<p style="TEXT-INDENT: 2em">&#8226; Windows Mobile 2002&#8211; OS Version : 3.0
<p style="TEXT-INDENT: 2em">&#8226; Windows Mobile 2003&#8211; OS Version : 4.20
<p style="TEXT-INDENT: 2em">&#8226; Windows Mobile 2003 Second Edition&#8211; OS Version : 4.21
<p style="TEXT-INDENT: 2em">问：为了支持 Windows Mobile 2003 Second Edition 的增强功能（例如高分辨率或横向屏幕），我应该在我的应用程序中做些什么？
<p style="TEXT-INDENT: 2em">答：Windows Mobile 2003 Second Edition 提供了全新的屏幕方向和分辨率，包括针对 Pocket PC 的横向、方形和 VGA 支持以及针对 Smartphone 的 QVGA 支持。这种版本不需要新的 SDK。
<p style="TEXT-INDENT: 2em">1. 阅读Windows Mobile 2003 Second Edition Developer Resources 软件包中白皮书上的最佳做法。
<p style="TEXT-INDENT: 2em">2. 测试您的应用程序，使用 Pocket PC 与 Smartphone 的 Windows Mobile 2003 Second Edition 模拟器。
<p style="TEXT-INDENT: 2em">3. 使应用程序屏幕方向和分辨率保持独立，这样您就可以使用一个代码基以 Windows Mobile 平台上的全部硬件创新为目标了。
<p style="TEXT-INDENT: 2em">下载新的 Windows Mobile Developer 资源包 ，其中包括新的和更新的代码示例及白皮书。
<p style="TEXT-INDENT: 2em">Pocket PC 开发
<p style="TEXT-INDENT: 2em">问：什么工具可用于 Pocket PC 2003 开发？
<p style="TEXT-INDENT: 2em">答：要构建 Pocket PC 2003 本机 C++ 应用程序，您需要 Microsoft&#174; eMbedded Visual C++&#174; 4.0、Microsoft&#174; eMbedded Visual C++&#174; 4.0 Service Pack 3，以及 Pocket PC 2003 软件开发工具包。您可以下载 eMbedded Visual C++ 工具和 Pocket PC 2003 SDK。Windows Mobile 2003 Second Edition 模拟器包使您可以在 Second Edition 设备上测试您的应用程序。注意，Pocket PC 2003 SDK 不支持 Microsoft&#174; eMbedded Visual Basic&#174; 开发。要构建 Pocket PC 2003 托管代码应用程序，您需要 Visual Studio .NET 2003 和 Pocket PC 2003 SDK。
<p style="TEXT-INDENT: 2em">要构建 Pocket PC 移动 Web 应用程序，可以使用 Visual Studio .NET 2003 中的 ASP.NET 移动控件。
<p style="TEXT-INDENT: 2em">问：Pocket PC 2002 应用程序可以在 Pocket PC 2003 设备上工作吗？
<p style="TEXT-INDENT: 2em">答：使用文档化 API 且功能良好的 Pocket PC 2002 应用程序无需重新编译即可在 Pocket PC 2003 设备上运行。
<p style="TEXT-INDENT: 2em">问：为什么 Pocket PC 2003 不再支持 eVB 开发？
<p style="TEXT-INDENT: 2em">答：在 Pocket PC 2003 设备中我们将继续支持 eVB 运行时作为一个可安装的 RAM 组件，这样旧的 eVB 应用程序就能够在新的设备上运行，但是离开 Visual Basic&#174; .NET、Visual C#&#174; .NET 和 Microsoft&#174; .NET Compact Framework 更强大健壮的开发体验，Pocket PC 2003 设备的新 eVB 开发将不受支持。
<p style="TEXT-INDENT: 2em">根据客户的反馈，Pocket PC 2003 设备将在 ROM 中包含 .NET Compact Framework。.NET Compact Framework 是完整的 .NET Framework 的一个子集，是专门为智能设备设计的。它是一种比 Pocket PC 2000 和 Pocket PC 2002 设备中提供的特定于 eVB 运行时的更加全面且与语言无关的应用程序引擎。
<p style="TEXT-INDENT: 2em">问：如何从 eVB 迁移到 Visual Basic .NET？
<p style="TEXT-INDENT: 2em">答：从 eVB 迁移到 Visual Basic .NET 并不容易，但迁移的好处远远超过了成本：
<p style="TEXT-INDENT: 2em">&#8226; 数据类型更丰富：eVB 只有 16 字节的 VARIANT；Visual Basic .NET 使用 .NET Framework 通用类型系统。
<p style="TEXT-INDENT: 2em">&#8226; 执行更快：eVB 需要解释；Visual Basic .NET 在执行前 JIT（实时）编译为本机代码
<p style="TEXT-INDENT: 2em">&#8226; 错误处理更完善：eVB 仅支持&#8220;On Error&#8221;；Visual Basic .NET 支持结构化异常处理
<p style="TEXT-INDENT: 2em">&#8226; 支持结构：eVB 不支持；Visual Basic .NET 支持命名空间、类和结构
<p style="TEXT-INDENT: 2em">&#8226; 面向对象：eVB 是过程性的；Visual Basic .NET 支持完全的 OOP（面向对象编程）
<p style="TEXT-INDENT: 2em">&#8226; 一流公民：eVB 总是想迎头赶上 MFC；Visual Basic .NET 是核心 .NET
<p style="TEXT-INDENT: 2em">&#8226; 本机 XML 支持：eVB 不支持；Visual Basic .NET 支持本机 XML 和 XML Web 服务
<p style="TEXT-INDENT: 2em">&#8226; 数据模型更完善：ADO.NET 远远超过了 ADOCE；它仍是最好的数据模型
<p style="TEXT-INDENT: 2em">&#8226; 执行更安全、更可靠：eVB 是一种脚本语言；Visual Basic .NET 为托管代码
<p style="TEXT-INDENT: 2em">&#8226; 还有许许多多！
<p style="TEXT-INDENT: 2em">同时，还有各种各样的资源（从移植实验到技术文章）可以帮助开发人员进行这种过渡。一个例子就是一篇概述如何从 eVB 迁移到 Visual Basic .NET 及其优点的技术文章： Moving from eMbedded Visual Basic to Visual Basic .NET。
<p style="TEXT-INDENT: 2em">问：我使用什么开发工具来编写基于 .NET Compact Framework 的 Pocket PC 应用程序？
<p style="TEXT-INDENT: 2em">答：Microsoft&#174; Visual Studio&#174; .NET 2003 允许 Visual Basic .NET 或 C# 编程人员创建 Pocket PC 2000、Pocket PC 2002 和 Pocket PC 2003 设备的托管代码应用程序（即那些以 .NET 公共语言运行库为目标的应用程序）。要开发 Pocket PC 2000 和 Pocket PC 2002 设备的托管代码应用程序，您可以使用即装即用的 Visual Studio .NET 2003。在开发过程中，Visual Studio .NET 2003 将会自动地将 .NET Compact Framework 安装到这些设备的 RAM 中。.NET Compact Framework 已经在所有 Pocket PC 2003 设备的 ROM 中，而且 Visual Studio .NET 2003 通过 Pocket PC 2003 SDK 支持它。
<p style="TEXT-INDENT: 2em">问：有什么资源可以用于进行 Windows Mobile 2003 Second Edition 开发？
<p style="TEXT-INDENT: 2em">下载新的 Windows Mobile Developer 资源包 ，其中包括白皮书以及新的和更新的代码示例。该版本不需要全新的 SDK。
<p style="TEXT-INDENT: 2em">可以用新的模拟器软件包测试您的应用程序。
<p style="TEXT-INDENT: 2em">eMbedded Visual C++ 4.0 开发人员应当下载 eMbedded Visual C++ 4.0 Service Pack 3。
<p style="TEXT-INDENT: 2em">Smartphone 开发
<p style="TEXT-INDENT: 2em">问：什么工具可用于 Smartphone 2002 开发？
<p style="TEXT-INDENT: 2em">答：要开始开发 Microsoft Smartphone 2002 应用程序，您需要 eMbedded Visual C++ 3.0 和 Smartphone 2002 SDK。两者都可以在 Windows Mobile Developer 获得。
<p style="TEXT-INDENT: 2em">问：何时可以将 .NET Compact Framework 用于 Smartphone 2002？
<p style="TEXT-INDENT: 2em">答：.NET Compact Framework 的第一个版本重点为成功的 Pocket PC 类别设备提供智能设备编程支持。将 .NET Compact Framework 添加到 Smartphone 的 Smartphone 2003 版本中。没有发布用于 Smartphone 2002 的 .NET Compact Framework 版本的计划。
<p style="TEXT-INDENT: 2em">问：MFC 或 ATL 可用于 Smartphone 2002 开发吗？
<p style="TEXT-INDENT: 2em">答：不可以，Smartphone 2002 不支持 MFC 与 ATL 开发。
<p style="TEXT-INDENT: 2em">问：可以使用 eMbedded Visual Basic 3.0 来构建 Smartphone 2002 应用程序吗？
<p style="TEXT-INDENT: 2em">答：不可以，不支持以 Smartphone 2002 为目标的 eVB 开发。
<p style="TEXT-INDENT: 2em">问：什么工具可用于进行 Microsoft Smartphone 2003 编程？
<p style="TEXT-INDENT: 2em">答：对于 Smartphone 2003 版本，有两种开发选择，或者通过带有 Service Pack 3 的 eMbedded Visual C++ 4.0 开发本机代码，或者通过 Visual Studio .NET 2003 开发托管代码。两种情况都需要下载 Smartphone 2003 SDK。Windows Mobile 2003 Second Edition 模拟器软件包使您可以在 Second Edition 设备上测试应用程序。
<p style="TEXT-INDENT: 2em">eMbedded Visual C++ 4.0 和 Smartphone 2003 SDK 都可以在 Windows Mobile Developer 获得。
<p style="TEXT-INDENT: 2em">问：在 Smartphone 2003 上可以使用 .NET Compact Framework 的哪一个版本？
<p style="TEXT-INDENT: 2em">答：Smartphone 2003 允许开发人员使用 .NET Compact Framework 1.0 Service Pack 1 进行编码。.NET Compact Framework 可以放在 Smartphone 2003 的 ROM 中。.NET Compact Framework 1.0 Service Pack 2 放在 Smartphone 2003 Second Edition 的 ROM 中。
<p style="TEXT-INDENT: 2em">问：Smartphone 2002 应用程序可以在 Smartphone 2003 设备上工作吗？
<p style="TEXT-INDENT: 2em">答：使用文档化 API 且功能良好的 Smartphone 2002 应用程序无需重新编译即可在 Smartphone 2003 设备上运行。
<p style="TEXT-INDENT: 2em">问：什么是示例 Smartphone 2002 设备和 Smartphone 2003 设备？
<p style="TEXT-INDENT: 2em">答：原始的 Orange SPV 与 Orange SPV e100 运行 Windows Mobile 2002。Orange 和 AT&amp;T 上的 MPX200 都是基于 Windows Mobile 2002 的 Smartphone。Orange SPV e200 运行 Windows Mobile 2003。
<p style="TEXT-INDENT: 2em">问：MFC 或 ATL 可用于 Smartphone 2003 开发吗？
<p style="TEXT-INDENT: 2em">答：MFC 不可用于 Smartphone 2003。可以使用 ATL 4.0 进行 Smartphone 2003 开发。有关 ATL 4.0 的更多信息，请参阅 SDK 文档。
<p style="TEXT-INDENT: 2em">问：在何处我可以找到更多有关 Smartphone 应用程序安全模型的信息？
<p style="TEXT-INDENT: 2em">答：为了帮助开发人员了解基于 Windows Mobile 的 Smartphone 应用程序安全模型，我们创作了一本白皮书。请参见 http://msdn.microsoft.com/library/en-us/dnsmtphn2k3/html/smartphone_security.asp。
<p style="TEXT-INDENT: 2em">问：什么是提示模式？
<p style="TEXT-INDENT: 2em">答：OEM 或运营商可以将提示模式包含在他们的 Smartphone 应用程序安全策略中，从而允许用户来决定在安装或运行时是否安装或运行一个应用程序。
<p style="TEXT-INDENT: 2em">问：可以使用 eMbedded Visual Basic 3.0 来构建 Smartphone 2003 应用程序吗？
<p style="TEXT-INDENT: 2em">答：不可以，不支持以 Smartphone 2003 为目标的 eVB 开发。如果您希望利用 Visual Basic 的开发技巧，可以考虑使用 Visual Basic .NET 并以 .NET Compact Framework 为目标。
<p style="TEXT-INDENT: 2em">问：有什么资源可以用于进行 Windows Mobile 2003 Second Edition 开发？
<p style="TEXT-INDENT: 2em">下载新的 Windows Mobile Developer 资源包 ，其中包括白皮书以及新的和更新的代码示例。
<p style="TEXT-INDENT: 2em">可以使用新的模拟器软件包来测试您的应用程序。
<p style="TEXT-INDENT: 2em">eMbedded Visual C++ 4.0 开发人员应当下载用于 eMbedded Visual C++ 4.0 的 Service Pack 3。
<p style="TEXT-INDENT: 2em">移动开发工具
<p style="TEXT-INDENT: 2em">问：什么是 Microsoft eMbedded Visual Tools 3.0？
<p style="TEXT-INDENT: 2em">答：eMbedded Visual Tools 3.0 是一种集成开发环境 (IDE)，移动开发人员用来为基于 Microsoft Windows CE 操作系统的 32 位设备编写软件应用程序。包括完整版的 Microsoft eMbedded Visual C++ 3.0 语言、Microsoft eMbedded Visual Basic 3.0 语言、特定于平台的 SDK、远程工具和文档。
<p style="TEXT-INDENT: 2em">问：eMbedded Visual Tools 3.0 支持什么设备平台？
<p style="TEXT-INDENT: 2em">答：eMbedded Visual Tools 3.0 - 2002 Edition 附带于 Pocket PC 2000、Pocket PC 2002 和 Smartphone 2002 的 SDK，并支持开发自定义的 Windows CE 3.0 设备。
<p style="TEXT-INDENT: 2em">注：Pocket PC 2002 SDK 可以与 eMbedded Visual Basic 3.0 和 eMbedded Visual C++ 3.0 一起使用，但是 Smartphone 2002 SDK 却只受 eMbedded Visual C++ 3.0 支持。
<p style="TEXT-INDENT: 2em">问：什么是 eMbedded Visual C++ 4.0？
<p style="TEXT-INDENT: 2em">答：eMbedded Visual C++ 4.0 是一种强大的开发工具，在为下一代基于 Windows CE 的设备（包括 Pocket PC 2003 和 Smartphone 2003）构建本机代码应用程序时可以为企业提供相当大的好处。这种独立的集成开发环境 (IDE) 带来了新水平的 Windows CE 开发效率，但却没有牺牲灵活性、性能或控制。要使用 eMbedded Visual C++ 工具构建 Pocket PC 2003 与 Smartphone 2003 应用程序，您还需要 eMbedded Visual C++ 4.0 Service Pack 3 和 Pocket PC 2003 以及 Smartphone 2003 SDK。下载 eMbedded Visual C++ 4.0 工具。
<p style="TEXT-INDENT: 2em">问：我可以使用 eMbedded Visual C++ 4.0 开发 Pocket PC 或 Smartphone 应用程序吗？
<p style="TEXT-INDENT: 2em">答：可以使用带有 Service Pack 2 的 eMbedded Visual C++ 4.0 来开发包括 Windows Mobile 2003 Second Edition 在内的 Pocket PC 2003 与 Smartphone 2003 应用程序。也可以用它来开发 Pocket PC 2002 或 Smartphone 2002 应用程序。
<p style="TEXT-INDENT: 2em">问：我可以使用 Windows C
<h1 class=titel>开发 Windows Mobile 应用程序 FAQ </h1>
<p style="TEXT-INDENT: 2em">E Standard SDK 开发 Pocket PC 或 Smartphone 应用程序吗？
<p style="TEXT-INDENT: 2em">答：Windows CE SDK 提供了一个通用的功能子集，使得编写的应用程序能够符合 Standard SDK，以便运行在基于自定义显示的 Windows CE .NET 平台上。为了构建 Pocket PC 和 Smartphone 智能设备应用程序来利用这些平台提供的丰富的设备功能集，需要使用特定于设备的 SDK。
<p style="TEXT-INDENT: 2em">问：eMbedded Visual Tools 3.0 和 Visual Studio .NET 之间有什么不同？
<p style="TEXT-INDENT: 2em">答：eMbedded Visual Tools 3.0 是一种专门针对移动与嵌入式技术开发人员的独立开发环境。对于 Pocket PC 和 Smartphone，可以利用 eMbedded Visual Tools 和适当的平台 SDK 来构建丰富的&#8220;本机代码&#8221;客户端应用程序。Visual Studio .NET 是 Microsoft 的最流行桌面开发工具的最新版本。可以使用 Visual Studio .NET 2003 来构建基于 .NET Compact Framework 的 Pocket PC 智能客户端应用程序。同时，还可以使用 Visual Studio .NET 和 ASP.NET 移动控件构建以各种设备（包括 Pocket PC 和 Smartphone 类别的设备）为目标的基于浏览器的应用程序。 </p>
<h1 class=titel>开发 Windows Mobile 应用程序 FAQ </h1>
</span>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/43395.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-02-28 15:58 <a href="http://www.cppblog.com/gtwdaizi/articles/43395.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>开发 Windows Mobile 应用程序 FAQ 二</title><link>http://www.cppblog.com/gtwdaizi/articles/43396.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Thu, 28 Feb 2008 07:58:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/43396.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/43396.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/43396.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/43396.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/43396.html</trackback:ping><description><![CDATA[<div id=ArticleCnt>
<p>1、Q：新建项目的时候选择哪个项目类型才能创建智能设备的应用程序？</p>
<p>　　A：在Visual Studio的新建项目对话框中选择Visual <a href="http://www.csai.cn/incsearch/search.asp?key=C%23" target=_blank><u><font color=#0000ff>C#</font></u></a>或者<a href="http://www.csai.cn/incsearch/search.asp?key=Visual+Basic" target=_blank><u><font color=#0000ff>Visual Basic</font></u></a>项目类型，选择智能设备模板，然后再选择相应的设备SDK，最后选择&#8220;Device Application&#8221;，就可以创建一个移动设备的应用程序了。</p>
<p>2、Q：托管代码与本地代码有哪些区别？</p>
<p>　　A：托管代码是指使用<a href="http://www.csai.cn/incsearch/search.asp?key=%2ENET" target=_blank><u><font color=#0000ff>.NET</font></u></a><clk>&nbsp;Compact Framework<nobr oncontextmenu="return false;" onmousemove=kwM(11); id=key0 onmouseover="kwE(event,11, this);" style="COLOR: #6600ff; BORDER-BOTTOM: #6600ff 1px dotted; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="return kwC(event,11);" onmouseout="kwL(event, this);" target="_blank">开发</nobr>的程序代码，可执行文件被编译成IL，执行时需要有.NET的运行时环境。而本地代码指用</clk><a href="http://www.csai.cn/incsearch/search.asp?key=C%2B%2B" target=_blank><u><font color=#0000ff>C++</font></u></a>等语言开发的程序代码，可执行文件被编译成与CPU指令集有关的机器码，可以直接运行。&nbsp;</p>
<p>3、Q：能不能简要介绍一下Magneto里面对OTA和MMS的支持？</p>
<p>　　A：Magneto对OTA有很好的支持，SDK文档的通讯部分中，有针对OTA的专门介绍。MMS的应用程序基本都是由第三方开发的，因为MMS是基于WAP协议的，而Magneto本身对WAP的支持也很好，具体的协议也可以在SDK文档里找到。</p>
<p><clk>4、Q：请问用Visual Basic <nobr oncontextmenu="return false;" onmousemove=kwM(8); id=key9 onmouseover="kwE(event,8, this);" style="COLOR: #6600ff; BORDER-BOTTOM: #6600ff 1px dotted; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="return kwC(event,8);" onmouseout="kwL(event, this);" target="_blank">.NET</nobr>开发PDA数据库程序能不能使用ADO.NET？</clk></p>
<p>　　A：Visual Basic .NET开发PDA数据库不需要引用System.data.oledb，只需要引用System.Data.SqlServerCe命名空间就可以了。该命名空间中的数据库操作类和ADO.NET是基本一致的。可以用它们来开发针对SQL Server CE的应用程序。</p>
<p>5、Q：在Visual C++2005中，可以使用.Net Compact Framework吗？</p>
<p>　　A：不能，现在.NET Compact Framework只支持C#和VB.NET，而不支持C++/CLI。但是在VS.NET 2005中可以用C++来开发Native代码来支持移动设备。&nbsp;</p>
<p>6、Q：从什么地方可以得到Smartphone开发环境？</p>
<p>　　A：Smartphone的SDK可以在<a href="http://www.csai.cn/incsearch/search.asp?key=%CE%A2%C8%ED" target=_blank><u><font color=#0000ff>微软</font></u></a>网站上找到，而Visual Studio 2005 Beta 2可以通过参加微软活动的方式获得。MEDC 2005的参加者都获得了VS.NET 2005和<a href="http://www.csai.cn/incsearch/search.asp?key=Windows" target=_blank><u><font color=#0000ff>Windows</font></u></a> Mobile 5 SDK的开发光盘。&nbsp;</p>
<p>7、Q：托管性的代码执行效率怎么样？和使用Visual C++编写的代码相比较。</p>
<p>　　A：托管代码的执行效率肯定不如本地代码高，但是托管代码也有一些好处是无法取代的。</p>
<p>8、Q：是否可以使用Visual Studio .NET 2003来开发能够运行在Windows Mobile 2005上的应用程序？</p>
<p>　　A：首先更正一下，Windows Mobile最新一代的<a href="http://www.csai.cn/incsearch/search.asp?key=%B2%D9%D7%F7%CF%B5%CD%B3" target=_blank><u><font color=#0000ff>操作系统</font></u></a>叫做Windows Mobile 5，而不是Windows Mobile 2005。是的，使用VS.NET 2003开发的应用程序是可以在Windows Mobile 5上正常运行的，因为Windows Mobile 5 ROM中内置了.NET Compact Framewrok 1.0 SP3。&nbsp;</p>
<p>9、Q：PDA上不能用Pocket Access么？SQL CE太大了。</p>
<p>　　A：可以使用Pocket Access来开发Windows Mobile上的应用程序。可以采用C++调用OLEDB或者ADOCE的方式来访问Pocket Access数据库。</p>
<p>10、Q：Visual Studio 2005的新功能是否只在Windows Mobile 5里受到支持，2003是否支持？</p>
<p>　　A：新功能分两个部分，一部分是.NET Compact Framework 2.0中提供的的新功能，这部分的功能可以被Windows Mobile 2003支持，但必须安装.NET Compact Framework 2.0；而另一部分是Windows Mobile 5的特有功能。.NET Compact Framework 2.0和Windows Mobile 5开发文档的&#8220;What&#8217;s New&#8221;部分，分别描述了这两方面的新特性。</p>
<p><clk>11、Q：请问如何在模拟器里面配置连接到移动<nobr oncontextmenu="return false;" onmousemove=kwM(7); id=key8 onmouseover="kwE(event,7, this);" style="COLOR: #6600ff; BORDER-BOTTOM: #6600ff 1px dotted; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="return kwC(event,7);" onmouseout="kwL(event, this);" target="_blank">网络</nobr>？</clk></p>
<p>　　A：模拟器如果需要连接移动网络的话，必须有专门的硬件提供支持。可以在开发PC的串口上连一个GPRS的模拟器，SDK文档中对此有专门的说明。</p>
<p>12、Q：SQL CE可以像Pocket Access那样仅使用一个文件就能运行么？是否需要像PC上那样安个<a href="http://www.csai.cn/incsearch/search.asp?key=%B7%FE%CE%F1%C6%F7" target=_blank><u><font color=#0000ff>服务器</font></u></a>才能使用？</p>
<p>　　A：不会的，只需要在Windows Mobile上安装SQL Server CE的支持库，也就是就是一些DLL文件。而SQL Server CE的库文件是一个单独的文件，不需要安装一个服务器。</p>
<p>13、Q：开发好的程序通过什么方式部署到<a href="http://www.csai.cn/incsearch/search.asp?key=%CA%D6%BB%FA" target=_blank><u><font color=#0000ff>手机</font></u></a>上？对手机有什么要求？</p>
<p>　　A：开发的程序需要打包成cab文件部署到手机上。除了通过ActiveSync安装外，还可以通过网络<a href="http://www.csai.cn/incsearch/search.asp?key=%CF%C2%D4%D8" target=_blank><u><font color=#0000ff>下载</font></u></a>、<a href="http://www.csai.cn/incsearch/search.asp?key=%B4%E6%B4%A2" target=_blank><u><font color=#0000ff>存储</font></u></a>卡运行等方式来安装应用程序。对手机的要求是，必须和开发程序的目标<a href="http://www.csai.cn/incsearch/search.asp?key=%C6%BD%CC%A8" target=_blank><u><font color=#0000ff>平台</font></u></a>相兼容。比如为Windows Mobile 5开发的应用程序，可能就没办法很好地运行在Windows Mobile2003平台上。</p>
<p>14、Q：在模拟器上面开发程序，和真实环境有区别么？需要注意一些什么？</p>
<p>　　A：模拟器的仿真度十分高，Windows Mobile 5的模拟器甚至可以支持ARM指令，所以基本不会遇到兼容性的问题。但是对于一些需要连接外部设备的应用场景，比如前边说的<a href="http://www.csai.cn/incsearch/search.asp?key=%CE%DE%CF%DF" target=_blank><u><font color=#0000ff>无线</font></u></a>网络，还有GPS设备等，就需要用到实际设备了。</p>
<p>15、Q：当开发国际化应用程序时，应该特别注意哪些方面？</p>
<p>　　A：对于国际化的应用程序，.NET本身就已经提供了非常好的支持。可以把用户界面的文字保存在相应的<a href="http://www.csai.cn/incsearch/search.asp?key=%D7%CA%D4%B4" target=_blank><u><font color=#0000ff>资源</font></u></a><clk>文件中，然后由应用程序判断操作<nobr oncontextmenu="return false;" onmousemove=kwM(2); id=key3 onmouseover="kwE(event,2, this);" style="COLOR: #6600ff; BORDER-BOTTOM: #6600ff 1px dotted; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="return kwC(event,2);" onmouseout="kwL(event, this);" target="_blank">系统</nobr>的语言版本来调用相应的文字。</clk></p>
<p>16、Q：用.NET开发Pocket PC程序需要考虑设备具体使用的是哪种CPU吗？</p>
<p>　　A：不必。无论是在虚拟机上的x86指令集，还是实际设备上的ARM指令集，对.NET Compact Framework程序的运行来说都一样。&nbsp;</p>
<p>17、Q：Windows Mobile 5 是否支持通过语音控制新的开发程序？</p>
<p>　　A：现在还不支持。&nbsp;</p>
<p>18、Q：可以在vwd2005 bata2中开发Pocket PC程序吗？Pocket PC是否具有浏览器？</p>
<p>　　A：可以，Pocket PC平台是内置浏览器的。&nbsp;</p>
<p>19、Q：Visual Studio 2005的Mobile开发，支持Mobile 2003的设备吗？</p>
<p>　　A：支持，VS 2005本身就自带Windows Mobile 2003的SDK。</p>
<p>20、Q：Windows Mobile 5.0 for Smartphone较之前的版本有何明显的区别？对于测试这一领域，我们需要注意些什么？</p>
<p>　　A：Windows Mobile 5的Smartphone平台更多的变化是在API层面，比如对数据库的支持、对GPS API的支持等， Windows Mobile 5 SDK文档中对此有详细地说明。</p>
<p>21、Q：对开发来说CDMA和GPRS的数据传输是透明的吗？</p>
<p><clk>　　A：对于<nobr oncontextmenu="return false;" onmousemove=kwM(6); id=key7 onmouseover="kwE(event,6, this);" style="COLOR: #6600ff; BORDER-BOTTOM: #6600ff 1px dotted; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="return kwC(event,6);" onmouseout="kwL(event, this);" target="_blank">软件开发</nobr>来说数据传输是透明的，CDMA和GPRS对于上层应用程序来说，只要支持HTTP协议或者TCP/IP协议就可以进行数据传输的操作。&nbsp;</clk></p>
<p>22、Q：Visual Studio .NET能否支持Nokia的S60系列系统开发？</p>
<p>　　A：可以，Visual C++能支持Nokia S60的开发。&nbsp;</p>
<p>23、Q：Pocket PC与Mobile开发的主要区别在哪里？</p>
<p><clk>　　A：Window Mobile是微软<nobr oncontextmenu="return false;" onmousemove=kwM(1); id=key2 onmouseover="kwE(event,1, this);" style="COLOR: #6600ff; BORDER-BOTTOM: #6600ff 1px dotted; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="return kwC(event,1);" onmouseout="kwL(event, this);" target="_blank">公司</nobr>基于Windows CE.NET的一个平台。它包含Pocket PC和Smartphone两个版本。&nbsp;</clk></p>
<p>24、Q：SDE从哪里可以下载？Pocket PC 2005的模拟器可以从哪里下载？</p>
<p>　　A：SDE是早期用来开发移动设备程序的VS扩展，目前网上似乎很难找到。其实不用安装它，安装所需版本的Pocket PC或者Smartphone的SDK即可。各个版本的Windows Mobile开发的SDK和模拟器的地址可以从这篇Blog上下载（http：//twodays.cnblogs.com/archive/2005/06/30/184107.htm）。&nbsp;</p>
<p>25、Q：.NET Compact Framework 2.0能装在Windows Mobile 2003上吗?</p>
<p>　　A：可以。.NET Compact Framework 2.0必须手动安裝到Windows Mobile 2003的机器上。</p>
<p><clk>26、Q：请问有没有好的Windows Mobile<nobr oncontextmenu="return false;" onmousemove=kwM(3); id=key4 onmouseover="kwE(event,3, this);" style="COLOR: #6600ff; BORDER-BOTTOM: #6600ff 1px dotted; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="return kwC(event,3);" onmouseout="kwL(event, this);" target="_blank">编程</nobr>的网站或者论坛？</clk></p>
<p>　　A：OpenNETCF.org、<a href="http://www.devbuzz.com/"><u><font color=#0000ff>www.devbuzz.com</font></u></a>、<a href="http://www.codeproject.com/"><u><font color=#0000ff>www.codeproject.com</font></u></a>、<a href="http://www.msdn.com/mobility/"><u><font color=#0000ff>www.msdn.com/mobility/</font></u></a>、<a href="http://www.pocketpcdn.com/"><u><font color=#0000ff>www.pocketpcdn.com</font></u></a></p>
<p>27、Q：Windows Mobile 2003上的.NET Compact Framework能升级到.NET Compact Framework 2.0吗？</p>
<p>　　A：可以。.NET Compact Framework 2.0必须手动安裝到Windows Mobile 2003的机器上。</p>
<p>28、Q：请问编写WML文件与使用.NET Compact Framework进行开发有什么联系和区别？</p>
<p>　　A：WML是能够利用WAP浏览器进行浏览的文件，是一种基于<a href="http://www.csai.cn/incsearch/search.asp?key=Web" target=_blank><u><font color=#0000ff>Web</font></u></a>的开发方式。.NET Compact Framework是在设备上运行的程序，是基于应用的开发方式。</p>
<p>29、Q：在使用.NET Compact Framework 1.0进行开发时，用EVC直接调用Native代码与使用C#通过P/Invoke在性能上有什么差别？在.NET Compact Framework 2.0上，用C++直接调用和用C#通过P/Invoke又如何呢？</p>
<p>　　A：用EVC調用Native API的效率，会比使用.NET Compact Framework通过P/Invoke调用Native API要高，这是.NET Compact Framework本身的特性。在从托管代码中调用Native API时，其内部会进行一些额外的类型转换动作，这会导致效率的降低。</p>
<p><clk>30、Q：有没有支持<nobr oncontextmenu="return false;" onmousemove=kwM(5); id=key6 onmouseover="kwE(event,5, this);" style="COLOR: #6600ff; BORDER-BOTTOM: #6600ff 1px dotted; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="return kwC(event,5);" onmouseout="kwL(event, this);" target="_blank">显示</nobr></clk><a href="http://www.csai.cn/incsearch/search.asp?key=HTML" target=_blank><u><font color=#0000ff>HTML</font></u></a>文本的控件？</p>
<p>　　A：WebBrowser控件可以用于HTML文本。</p>
<p><clk>31、Q：CAB安装后会在Pocket PC上自动生成&#8220;卸载程序&#8221;，如何<nobr oncontextmenu="return false;" onmousemove=kwM(0); id=key1 onmouseover="kwE(event,0, this);" style="COLOR: #6600ff; BORDER-BOTTOM: #6600ff 1px dotted; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="return kwC(event,0);" onmouseout="kwL(event, this);" target="_blank">制作</nobr>安装包，才能不自动产生&#8220;卸载程序&#8221;？</clk></p>
<p>　　A：利用VS 2005建立Smart Device Cab Project，在Solution Explorer的Cab Project上点击鼠标右键选择Property，即可看到有一个选项为NoUninstall，默认为False，改为True就可以了。</p>
<p>32、Q：OpenNETCF能运行在.NET Framework 1.1环境下吗？其中的控件可以与.NET Framework 1.1控件混合使用吗？怎样在Visual Studio .NET 2003中加入OpenNETCF控件？</p>
<p><clk>　　A：当初在<nobr oncontextmenu="return false;" onmousemove=kwM(4); id=key5 onmouseover="kwE(event,4, this);" style="COLOR: #6600ff; BORDER-BOTTOM: #6600ff 1px dotted; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="return kwC(event,4);" onmouseout="kwL(event, this);" target="_blank">设计</nobr>NET Compact Framework 1.0/1.1时，由于考虑到移动设备的资源有限，所以有些原本.NET Framework 1.1中已经提供的类和控件就被删除了，OpenNETCF Smart Device Framework主要是针对.NET Compact Framework 1.0/1.1中没有的功能，开发出来的类似的类型和额外的功能，以弥补.NET Compact Framework 1.0/1.1不足之处。这套Framework主要是供.NET Compact Framework</clk><a href="http://www.csai.cn/incsearch/search.asp?key=%B3%CC%D0%F2%BF%AA%B7%A2" target=_blank><u><font color=#0000ff>程序开发</font></u></a>所用，除了少部份针对PC与Pocket PC的同步功能所编写的类之外，大部分都是在.NET Compact Framework上执行的，一般不支持.NET Framework。OpenNETCF的Smart Device Framework安装完毕之后，可以在VS 2003左侧的工具箱中看到OpenNETCF的控件，可以直接拖放来使用。</p>
</div>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/43396.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-02-28 15:58 <a href="http://www.cppblog.com/gtwdaizi/articles/43396.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于在命令行参数中文件路径有空格的问题</title><link>http://www.cppblog.com/gtwdaizi/articles/43374.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Thu, 28 Feb 2008 03:34:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/43374.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/43374.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/43374.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/43374.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/43374.html</trackback:ping><description><![CDATA[<p>可以使用以下方法来解决文件路径中有空格的问题<br><br>&nbsp;CCommandLineInfo cmdInfo;</p>
<p>&nbsp;CString cmdLineStr = GetCommandLine();<br><br>获取整个命令行, 然后人工的对这个命令行字符串进行解析..</p>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/43374.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-02-28 11:34 <a href="http://www.cppblog.com/gtwdaizi/articles/43374.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CString 操作指南</title><link>http://www.cppblog.com/gtwdaizi/articles/42953.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Tue, 19 Feb 2008 09:30:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/42953.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/42953.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/42953.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/42953.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/42953.html</trackback:ping><description><![CDATA[<p>原文出处：<a href="http://www.codeproject.com/string/cstringmgmt.asp" target=_blank><u><font color=#0000ff>codeproject：CString Management</font></u></a><br><br><br>通过阅读本文你可以学习如何有效地使用 CString。<br><br>　　CString 是一种很有用的数据类型。它们很大程度上简化了MFC中的许多操作，使得MFC在做字符串操作的时候方便了很多。不管怎样，使用CString有很多特殊的技巧，特别是对于纯C背景下走出来的程序员来说有点难以学习。这篇文章就来讨论这些技巧。<br>　　使用CString可以让你对字符串的操作更加直截了当。这篇文章不是CString的完全手册，但囊括了大部分常见基本问题。<br><br>这篇文章包括以下内容： </p>
<ol>
    <li>
    <p align=left><a href="http://blog.csdn.net/pinping1314/archive/2005/04/21/357260.aspx#CString 对象的连接"><u><font color=#800080>CString 对象的连接</font></u></a> </p>
    <li><a href="http://blog.csdn.net/pinping1314/archive/2005/04/21/357260.aspx#格式化字符串"><u><font color=#800080>格式化字符串（包括 int 型转化为 CString ）</font></u></a>
    <li><a href="http://blog.csdn.net/pinping1314/archive/2005/04/21/357260.aspx#CString 型转化成 int 型"><u><font color=#800080>CString 型转化成 int 型</font></u></a>
    <li><a href="http://blog.csdn.net/pinping1314/archive/2005/04/21/357260.aspx#CString 型和 char* 类型的相互转化"><u><font color=#800080>CString 型和 char* 类型的相互转化</font></u></a><br>
    <dir>
    <li><a href="http://blog.csdn.net/pinping1314/archive/2005/04/21/357260.aspx#char* 转化为 CString"><u><font color=#800080>char* 转化成 CString</font></u></a>
    <li><a href="http://blog.csdn.net/pinping1314/archive/2005/04/21/357260.aspx#CString转化成char* 之一"><u><font color=#800080>CString 转化成 char* 之一：使用LPCTSTR强制转化</font></u></a>
    <li><a href="http://blog.csdn.net/pinping1314/archive/2005/04/21/357260.aspx#CString转化成char* 之二"><u><font color=#800080>CString 转化成 char* 之二：使用CString对象的GetBuffer方法</font></u></a>
    <li><a href="http://blog.csdn.net/pinping1314/archive/2005/04/21/357260.aspx#CString to char * 之三"><font color=#800080><u>CString 转化成 char* 之三: 和控件的接口</u></font></a></li>
    </dir>
    <li><a href="http://blog.csdn.net/pinping1314/archive/2005/04/21/357260.aspx#CString 型转化成 BSTR 型"><u><font color=#800080>CString 型转化成 BSTR 型</font></u></a>；
    <li><a href="http://blog.csdn.net/pinping1314/archive/2005/04/21/357260.aspx#BSTR 型转化成 CString 型"><u><font color=#800080>BSTR 型转化成 CString 型</font></u></a>；
    <li><a href="http://blog.csdn.net/pinping1314/archive/2005/04/21/357260.aspx#VARIANT 型转化成 CString 型"><u><font color=#800080>VARIANT 型转化成 CString 型</font></u></a>；
    <li><a href="http://blog.csdn.net/pinping1314/archive/2005/04/21/357260.aspx#载入字符串表资源"><u><font color=#800080>载入字符串表资源</font></u></a>；
    <li><a href="http://blog.csdn.net/pinping1314/archive/2005/04/21/357260.aspx#CString 和临时对象"><u><font color=#800080>CString 和临时对象</font></u></a>；
    <li><a href="http://blog.csdn.net/pinping1314/archive/2005/04/21/357260.aspx#CString的效率"><u><font color=#800080>CString 的效率</font></u></a>；
    <li><a href="http://blog.csdn.net/pinping1314/archive/2005/04/21/357260.aspx#总结"><u><font color=#800080>总结</font></u></a> </li>
</ol>
<p>下面我分别讨论。<br><br><img alt="" src="http://www.vckbase.com/document/image/paragraph.gif"> 1、<strong><a name="CString 对象的连接">CString 对象的连接</a></strong><br><br>　　能体现出 CString 类型方便性特点的一个方面就字符串的连接，使用 CString 类型，你能很方便地连接两个字符串，正如下面的例子：</p>
<pre>CString gray("Gray");CString cat("Cat");CString graycat = gray + cat;</pre>
<p>要比用下面的方法好得多：</p>
<pre>char gray[] = "Gray";char cat[] = "Cat";char * graycat = malloc(strlen(gray) + strlen(cat) + 1);strcpy(graycat, gray);strcat(graycat, cat);</pre>
<p><img alt="" src="http://www.vckbase.com/document/image/paragraph.gif"> 2、<strong><a name=格式化字符串>格式化字符串</a></strong><br><br>　　与其用 sprintf() 函数或 wsprintf() 函数来格式化一个字符串，还不如用 CString 对象的Format()方法：</p>
<pre>CString s;s.Format(_T("The total is %d"), total);</pre>
<p>　　用这种方法的好处是你不用担心用来存放格式化后数据的缓冲区是否足够大，这些工作由CString类替你完成。<br>　　格式化是一种把其它不是字符串类型的数据转化为CString类型的最常用技巧，比如，把一个整数转化成CString类型，可用如下方法：</p>
<pre>CString s;s.Format(_T("%d"), total);</pre>
<p>　　我总是对我的字符串使用_T()宏，这是为了让我的代码至少有Unicode的意识，当然，关于Unicode的话题不在这篇文章的讨论范围。_T()宏在8位字符环境下是如下定义的：</p>
<pre>#define _T(x) x // 非Unicode版本（non-Unicode version）</pre>
<p>而在Unicode环境下是如下定义的：</p>
<pre>#define _T(x) L##x // Unicode版本（Unicode version）</pre>
<p>所以在Unicode环境下，它的效果就相当于：</p>
<pre>s.Format(L"%d", total);</pre>
<p>　　如果你认为你的程序可能在Unicode的环境下运行，那么开始在意用 Unicode 编码。比如说，不要用 sizeof() 操作符来获得字符串的长度，因为在Unicode环境下就会有2倍的误差。我们可以用一些方法来隐藏Unicode的一些细节，比如在我需要获得字符长度的时候，我会用一个叫做DIM的宏，这个宏是在我的dim.h文件中定义的，我会在我写的所有程序中都包含这个文件：</p>
<pre>#define DIM(x) ( sizeof((x)) / sizeof((x)[0]) )</pre>
　　这个宏不仅可以用来解决Unicode的字符串长度的问题，也可以用在编译时定义的表格上，它可以获得表格的项数，如下：<br>
<pre>class Whatever { ... };Whatever data[] = {   { ... },    ...   { ... },};for(int i = 0; i &lt; DIM(data); i++) // 扫描表格寻找匹配项。</pre>
　　这里要提醒你的就是一定要注意那些在参数中需要真实字节数的API函数调用，如果你传递字符个数给它，它将不能正常工作。如下：
<pre>TCHAR data[20];lstrcpyn(data, longstring, sizeof(data) - 1); // WRONG!lstrcpyn(data, longstring, DIM(data) - 1); // RIGHTWriteFile(f, data, DIM(data), &amp;bytesWritten, NULL); // WRONG!WriteFile(f, data, sizeof(data), &amp;bytesWritten, NULL); // RIGHT</pre>
<p>造成以上原因是因为lstrcpyn需要一个字符个数作为参数，但是WriteFile却需要字节数作为参数。<br>同样需要注意的是有时候需要写出数据的所有内容。如果你仅仅只想写出数据的真实长度，你可能会认为你应该这样做：</p>
<pre>WriteFile(f, data, lstrlen(data), &amp;bytesWritten, NULL); // WRONG</pre>
<p>但是在Unicode环境下，它不会正常工作。正确的做法应该是这样：</p>
<pre>WriteFile(f, data, lstrlen(data) * sizeof(TCHAR), &amp;bytesWritten, NULL); // RIGHT</pre>
<p>　　因为WriteFile需要的是一个以字节为单位的长度。（可能有些人会想&#8220;在非Unicode的环境下运行这行代码，就意味着总是在做一个多余的乘1操作，这样不会降低程序的效率吗？&#8221;这种想法是多余的，你必须要了解编译器实际上做了什么，没有哪一个C或C++编译器会把这种无聊的乘1操作留在代码中。在Unicode环境下运行的时候，你也不必担心那个乘2操作会降低程序的效率，记住，这只是一个左移一位的操作而已，编译器也很乐意为你做这种替换。）<br>　　使用_T宏并不是意味着你已经创建了一个Unicode的程序，你只是创建了一个有Unicode意识的程序而已。如果你在默认的8-bit模式下编译你的程序的话，得到的将是一个普通的8-bit的应用程序（这里的8-bit指的只是8位的字符编码，并不是指8位的计算机系统）；当你在Unicode环境下编译你的程序时，你才会得到一个Unicode的程序。记住，CString 在 Unicode 环境下，里面包含的可都是16位的字符哦。<br><br><img alt="" src="http://www.vckbase.com/document/image/paragraph.gif"> 3、<strong><a name="CString 型转化成 int 型">CString 型转化成 int 型</a></strong><br><br>　　把 CString 类型的数据转化成整数类型最简单的方法就是使用标准的字符串到整数转换例程。<br>　　虽然通常你怀疑使用_atoi()函数是一个好的选择，它也很少会是一个正确的选择。如果你准备使用 Unicode 字符，你应该用_ttoi()，它在 ANSI 编码系统中被编译成_atoi()，而在 Unicode 编码系统中编译成_wtoi()。你也可以考虑使用_tcstoul()或者_tcstol()，它们都能把字符串转化成任意进制的长整数（如二进制、八进制、十进制或十六进制），不同点在于前者转化后的数据是无符号的（unsigned），而后者相反。看下面的例子：</p>
<pre>CString hex = _T("FAB");CString decimal = _T("4011");ASSERT(_tcstoul(hex, 0, 16) == _ttoi(decimal));</pre>
<p><img alt="" src="http://www.vckbase.com/document/image/paragraph.gif"> 4、<strong><a name="CString 型和 char* 类型的相互转化">CString 型和 char* 类型的相互转化</a></strong><br><br>　　这是初学者使用 CString 时最常见的问题。有了 C++ 的帮助，很多问题你不需要深入的去考虑它，直接拿来用就行了，但是如果你不能深入了解它的运行机制，又会有很多问题让你迷惑，特别是有些看起来没有问题的代码，却偏偏不能正常工作。<br>比如，你会奇怪为什么不能写向下面这样的代码呢：</p>
<pre>CString graycat = "Gray" + "Cat";</pre>
<p>或者这样：</p>
<pre>CString graycat("Gray" + "Cat");</pre>
<p>　　事实上，编译器将抱怨上面的这些尝试。为什么呢？因为针对CString 和 LPCTSTR数据类型的各种各样的组合，&#8220; +&#8221; 运算符 被定义成一个重载操作符。而不是两个 LPCTSTR 数据类型，它是底层数据类型。你不能对基本数据（如 int、char 或者 char*）类型重载 C++ 的运算符。你可以象下面这样做：</p>
<pre>CString graycat = CString("Gray") + CString("Cat");</pre>
<p>或者这样：</p>
<pre>CString graycat = CString("Gray") + "Cat";</pre>
<p>研究一番就会发现：&#8220; +&#8221;总是使用在至少有一个 CString 对象和一个 LPCSTR 的场合。<br><br>注意，编写有 Unicode 意识的代码总是一件好事，比如：</p>
<pre>CString graycat = CString(_T("Gray")) + _T("Cat");</pre>
<p>这将使得你的代码可以直接移植。<br><br><em><strong><a name="char* 转化为 CString">char* 转化为 CString</a></strong></em><br><br>　　现在你有一个 char* 类型的数据，或者说一个字符串。怎么样创建 CString 对象呢？这里有一些例子：</p>
<pre>char * p = "This is a test";</pre>
<p>或者象下面这样更具有 Unicode 意识：</p>
<pre>TCHAR * p = _T("This is a test")</pre>
<p>或</p>
<pre>LPTSTR p = _T("This is a test");</pre>
<p>你可以使用下面任意一种写法：</p>
<pre>CString s = "This is a test"; // 8-bit onlyCString s = _T("This is a test"); // Unicode-awareCString s("This is a test"); // 8-bit onlyCString s(_T("This is a test")); // Unicode-awareCString s = p;CString s(p);</pre>
<p>　　用这些方法可以轻松将常量字符串或指针转换成 CString。需要注意的是，字符的赋值总是被拷贝到 CString 对象中去的，所以你可以象下面这样操作：</p>
<pre>TCHAR * p = _T("Gray");CString s(p);p = _T("Cat");s += p;</pre>
<p>结果字符串肯定是&#8220;GrayCat&#8221;。<br><br>CString 类还有几个其它的构造函数，但是这里我们不考虑它，如果你有兴趣可以自己查看相关文档。<br><br>事实上，CString 类的构造函数比我展示的要复杂，比如：</p>
<pre>CString s = "This is a test"; </pre>
<p>　　这是很草率的编码，但是实际上它在 Unicode 环境下能编译通过。它在运行时调用构造函数的 MultiByteToWideChar 操作将 8 位字符串转换成 16 位字符串。不管怎样，如果 char * 指针是网络上传输的 8 位数据，这种转换是很有用的。<br><br><em><strong><a name="CString转化成char* 之一">CString 转化成 char* 之一</a>：</strong></em>强制类型转换为 LPCTSTR；<br><br>　　这是一种略微硬性的转换，有关&#8220;正确&#8221;的做法，人们在认识上还存在许多混乱，正确的使用方法有很多，但错误的使用方法可能与正确的使用方法一样多。<br>　　我们首先要了解 CString 是一种很特殊的 C++ 对象，它里面包含了三个值：一个指向某个数据缓冲区的指针、一个是该缓冲中有效的字符记数以及一个缓冲区长度。 有效字符数的大小可以是从0到该缓冲最大长度值减1之间的任何数（因为字符串结尾有一个NULL字符）。字符记数和缓冲区长度被巧妙隐藏。<br>　　除非你做一些特殊的操作，否则你不可能知道给CString对象分配的缓冲区的长度。这样，即使你获得了该0缓冲的地址，你也无法更改其中的内容，不能截短字符串，也 绝对没有办法加长它的内容，否则第一时间就会看到溢出。<br>　　LPCTSTR 操作符（或者更明确地说就是 TCHAR * 操作符）在 CString 类中被重载了，该操作符的定义是返回缓冲区的地址，因此，如果你需要一个指向 CString 的 字符串指针的话，可以这样做：</p>
<p>&#160;</p>
<pre>CString s("GrayCat");LPCTSTR p = s;</pre>
<p>　　它可以正确地运行。这是由C语言的强制类型转化规则实现的。当需要强制类型转化时，C++规测容许这种选择。比如，你可以将（浮点数）定义为将某个复数 （有一对浮点数）进行强制类型转换后只返回该复数的第一个浮点数（也就是其实部）。可以象下面这样：</p>
<pre>Complex c(1.2f, 4.8f);float realpart = c;</pre>
<p>如果(float)操作符定义正确的话，那么实部的的值应该是1.2。<br>　　这种强制转化适合所有这种情况，例如，任何带有 LPCTSTR 类型参数的函数都会强制执行这种转换。 于是，你可能有这样一个函数（也许在某个你买来的DLL中）：</p>
<pre>BOOL DoSomethingCool(LPCTSTR s);</pre>
<p>你象下面这样调用它：</p>
<pre>CString file("c:\\myfiles\\coolstuff")BOOL result = DoSomethingCool(file);</pre>
<p>　　它能正确运行。因为 DoSomethingCool 函数已经说明了需要一个 LPCTSTR 类型的参数，因此 LPCTSTR 被应用于该参数，在 MFC 中就是返回的串地址。<br><br>如果你要格式化字符串怎么办呢？</p>
<pre>CString graycat("GrayCat");CString s;s.Format("Mew! I love %s", graycat);</pre>
<p>　　注意由于在可变参数列表中的值（在函数说明中是以&#8220;...&#8221;表示的）并没有隐含一个强制类型转换操作符。你会得到什么结果呢？<br>　　一个令人惊讶的结果，我们得到的实际结果串是：</p>
<pre>"Mew! I love GrayCat"。</pre>
<p>　　因为 MFC 的设计者们在设计 CString 数据类型时非常小心， CString 类型表达式求值后指向了字符串，所以这里看不到任何象 Format 或 sprintf 中的强制类型转换，你仍然可以得到正确的行为。描述 CString 的附加数据实际上在 CString 名义地址之后。<br>　　有一件事情你是不能做的，那就是修改字符串。比如，你可能会尝试用&#8220;,&#8221;代替&#8220;.&#8221;（不要做这样的，如果你在乎国际化问题，你应该使用十进制转换的 National Language Support 特性，），下面是个简单的例子：</p>
<pre>CString v("1.00"); // 货币金额，两位小数LPCTSTR p = v;p[lstrlen(p) - 3] = '','';</pre>
<p>　　这时编译器会报错，因为你赋值了一个常量串。如果你做如下尝试，编译器也会错：</p>
<pre>strcat(p, "each");</pre>
<p>　　因为 strcat 的第一个参数应该是 LPTSTR 类型的数据，而你却给了一个 LPCTSTR。<br><br>　　不要试图钻这个错误消息的牛角尖，这只会使你自己陷入麻烦！<br><br>　　原因是缓冲有一个计数，它是不可存取的（它位于 CString 地址之下的一个隐藏区域），如果你改变这个串，缓冲中的字符计数不会反映所做的修改。此外，如果字符串长度恰好是该字符串物理限制的长度（梢后还会讲到这个问题），那么扩展该字符串将改写缓冲以外的任何数据，那是你无权进行写操作的内存（不对吗？），你会毁换坏不属于你的内存。这是应用程序真正的死亡处方。</p>
<p><em><strong><a name="CString转化成char* 之二">CString转化成char* 之二</a>：</strong></em>使用 CString 对象的 GetBuffer 方法；<br><br>　　如果你需要修改 CString 中的内容，它有一个特殊的方法可以使用，那就是 GetBuffer，它的作用是返回一个可写的缓冲指针。 如果你只是打算修改字符或者截短字符串，你完全可以这样做：</p>
<pre>CString s(_T("File.ext"));LPTSTR p = s.GetBuffer();LPTSTR dot = strchr(p, ''.''); // OK, should have used s.Find...if(p != NULL)*p = _T(''\0'');s.ReleaseBuffer();</pre>
<p>　　这是 GetBuffer 的第一种用法，也是最简单的一种，不用给它传递参数，它使用默认值 0，意思是：&#8220;给我这个字符串的指针，我保证不加长它&#8221;。当你调用 ReleaseBuffer 时，字符串的实际长度会被重新计算，然后存入 CString 对象中。<br>　　必须强调一点，在 GetBuffer 和 ReleaseBuffer 之间这个范围，一定不能使用你要操作的这个缓冲的 CString 对象的任何方法。因为 ReleaseBuffer 被调用之前，该 CString 对象的完整性得不到保障。研究以下代码：</p>
<pre>CString s(...);LPTSTR p = s.GetBuffer();//... 这个指针 p 发生了很多事情int n = s.GetLength(); // 很糟D!!!!! 有可能给出错误的答案!!!s.TrimRight(); // 很糟!!!!! 不能保证能正常工作!!!!s.ReleaseBuffer(); // 现在应该 OKint m = s.GetLength(); // 这个结果可以保证是正确的。s.TrimRight(); // 将正常工作。</pre>
<p>　　假设你想增加字符串的长度，你首先要知道这个字符串可能会有多长，好比是声明字符串数组的时候用：</p>
<pre>char buffer[1024];</pre>
<p>表示 1024 个字符空间足以让你做任何想做得事情。在 CString 中与之意义相等的表示法：</p>
<pre>LPTSTR p = s.GetBuffer(1024);</pre>
<p>　　调用这个函数后，你不仅获得了字符串缓冲区的指针，而且同时还获得了长度至少为 1024 个字符的空间（注意，我说的是&#8220;字符&#8221;，而不是&#8220;字节&#8221;，因为 CString 是以隐含方式感知 Unicode 的）。<br>　　同时，还应该注意的是，如果你有一个常量串指针，这个串本身的值被存储在只读内存中，如果试图存储它，即使你已经调用了 GetBuffer ，并获得一个只读内存的指针，存入操作会失败，并报告存取错误。我没有在 CString 上证明这一点，但我看到过大把的 C 程序员经常犯这个错误。<br>　　C 程序员有一个通病是分配一个固定长度的缓冲，对它进行 sprintf 操作，然后将它赋值给一个 CString：</p>
<pre>char buffer[256];sprintf(buffer, "%......", args, ...); // ... 部分省略许多细节CString s = buffer;</pre>
<p>虽然更好的形式可以这么做：</p>
<pre>CString s;s.Format(_T("%...."), args, ...);</pre>
<p>如果你的字符串长度万一超过 256 个字符的时候，不会破坏堆栈。<br><br>　　另外一个常见的错误是：既然固定大小的内存不工作，那么就采用动态分配字节，这种做法弊端更大：</p>
<pre>int len = lstrlen(parm1) + 13  lstrlen(parm2) + 10 + 100;char * buffer = new char[len];sprintf(buffer, "%s is equal to %s, valid data", parm1, parm2);CString s = buffer;......delete [] buffer;</pre>
<p>它可以能被简单地写成：</p>
<pre>CString s;s.Format(_T("%s is equal to %s, valid data"), parm1, parm2);</pre>
<p>　　需要注意 sprintf 例子都不是 Unicode 就绪的，尽管你可以使用 tsprintf 以及用 _T() 来包围格式化字符串，但是基本 思路仍然是在走弯路，这这样很容易出错。<br><br><em><strong><a name="CString to char * 之三">CString to char * 之三</a>：</strong></em>和控件的接口；<br><br>　　我们经常需要把一个 CString 的值传递给一个控件，比如，CTreeCtrl。MFC为我们提供了很多便利来重载这个操作，但是 在大多数情况下，你使用&#8220;原始&#8221;形式的更新，因此需要将墨某个串指针存储到 TVINSERTITEMSTRUCT 结构的 TVITEM 成员中。如下：</p>
<pre>TVINSERTITEMSTRUCT tvi;CString s;// ... 为s赋一些值。tvi.item.pszText = s; // Compiler yells at you here// ... 填写tvi的其他域HTREEITEM ti = c_MyTree.InsertItem(&amp;tvi);</pre>
<p>　　为什么编译器会报错呢？明明看起来很完美的用法啊！但是事实上如果你看看 TVITEM 结构的定义你就会明白，在 TVITEM 结构中 pszText&nbsp;成员的声明如下：</p>
<pre>LPTSTR pszText;int cchTextMax;</pre>
<p>　　因此，赋值不是赋给一个 LPCTSTR 类型的变量，而且编译器无法知道如何将赋值语句右边强制转换成 LPCTSTR。好吧，你说，那我就改成这样：</p>
<pre>tvi.item.pszText = (LPCTSTR)s; //编译器依然会报错。</pre>
<p>　　编译器之所以依然报错是因为你试图把一个 LPCTSTR 类型的变量赋值给一个 LPTSTR 类型的变量，这种操作在C或C++中是被禁止的。你不能用这种方法 来滥用常量指针与非常量指针概念，否则，会扰乱编译器的优化机制，使之不知如何优化你的程序。比如，如果你这么做：</p>
<pre>const int i = ...;//... do lots of stuff... = a[i]; // usage 1// ... lots more stuff... = a[i]; // usage 2</pre>
<p>　　那么，编译器会以为既然 i 是 const ，所以 usage1和usage2的值是相同的，并且它甚至能事先计算好 usage1 处的 a[i] 的地址，然后保留着在后面的 usage2 处使用，而不是重新计算。如果你按如下方式写的话：</p>
<pre>const int i = ...;int * p = &amp;i;//... do lots of stuff... = a[i]; // usage 1// ... lots more stuff(*p)++; // mess over compiler''s assumption// ... and other stuff... = a[i]; // usage 2</pre>
<p>　　编译器将认为 i 是常量，从而 a[i] 的位置也是常量，这样间接地破坏了先前的假设。因此，你的程序将会在 debug 编译模式（没有优化）和 release 编译模式（完全优化）中反映出不同的行为，这种情况可不好，所以当你试图把指向 i 的指针赋值给一个 可修改的引用时，会被编译器诊断为这是一种伪造。这就是为什么（LPCTSTR）强制类型转化不起作用的原因。<br>　　为什么不把该成员声明成 LPCTSTR 类型呢？因为这个结构被用于读写控件。当你向控件写数据时，文本指针实际上被当成 LPCTSTR，而当你从控件读数据 时，你必须有一个可写的字符串。这个结构无法区分它是用来读还是用来写。<br><br>因此，你会常常在我的代码中看到如下的用法：</p>
<pre>tvi.item.pszText = (LPTSTR)(LPCTSTR)s;</pre>
<p>　　它把 CString 强制类型转化成 LPCTSTR，也就是说先获得改字符串的地址，然后再强制类型转化成 LPTSTR，以便可以对之进行赋值操作。 注意这只有在使用 Set 或 Insert 之类的方法才有效！如果你试图获取数据，则不能这么做。<br>　　如果你打算获取存储在控件中的数据，则方法稍有不同，例如，对某个 CTreeCtrl 使用 GetItem 方法，我想获取项目的文本。我知道这些 文本的长度不会超过 MY_LIMIT，因此我可以这样写：</p>
<pre>TVITEM tvi;// ... assorted initialization of other fields of tvitvi.pszText = s.GetBuffer(MY_LIMIT);tvi.cchTextMax = MY_LIMIT;c_MyTree.GetItem(&amp;tvi);s.ReleaseBuffer();</pre>
<p>　　可以看出来，其实上面的代码对所有类型的 Set 方法都适用，但是并不需要这么做，因为所有的类 Set 方法（包括 Insert方法）不会改变字符串的内容。但是当你需要写 CString 对象时，必须保证缓冲是可写的，这正是 GetBuffer 所做的事情。再次强调： 一旦做了一次 GetBuffer 调用，那么在调用 ReleaseBuffer 之前不要对这个 CString 对象做任何操作。<br><br><img alt="" src="http://www.vckbase.com/document/image/paragraph.gif"> 5、<strong><a name="CString 型转化成 BSTR 型">CString 型转化成 BSTR 型</a></strong><br><br>　　当我们使用 ActiveX 控件编程时，经常需要用到将某个值表示成 BSTR 类型。BSTR 是一种记数字符串，Intel平台上的宽字符串（Unicode），并且 可以包含嵌入的 NULL 字符。<br><br>你可以调用 CString 对象的 AllocSysString 方法将 CString 转化成 BSTR：</p>
<pre>CString s;s = ... ; // whateverBSTR b = s.AllocSysString();</pre>
<p>　　现在指针 b 指向的就是一个新分配的 BSTR 对象，该对象是 CString 的一个拷贝，包含终结 NULL字符。现在你可以将它传递给任何需要 BSTR 的接口。通常，BSTR 由接收它的组件来释放，如果你需要自己释放 BSTR 的话，可以这么做：</p>
<pre>::SysFreeString(b);</pre>
<p>　　对于如何表示传递给 ActiveX 控件的字符串，在微软内部曾一度争论不休，最后 Visual Basic 的人占了上风，BSTR（&#8220;Basic String&#8221;的首字母缩写）就是这场争论的结果。<br><br><img alt="" src="http://www.vckbase.com/document/image/paragraph.gif"> 6、<strong><a name="BSTR 型转化成 CString 型">BSTR 型转化成 CString 型</a></strong><br><br>　　由于 BSTR 是记数 Unicode 字符串，你可以用标准转换方法来创建 8 位的 CString。实际上，这是 CString 内建的功能。在 CString 中 有特殊的构造函数可以把 ANSI 转化成 Unicode，也可以把Unicode 转化成 ANSI。你同样可以从 VARIANT 类型的变量中获得 BSTR 类型的字符串，VARIANT 类型是 由各种 COM 和 Automation (自动化)调用返回的类型。<br><br>例如，在一个ANSI程序中：</p>
<pre>BSTR b;b = ...; // whateverCString s(b == NULL ? L"" : b)</pre>
<p>　　对于单个的 BSTR 串来说，这种用法可以工作得很好，这是因为 CString 有一个特殊的构造函数以LPCWSTR（BSTR正是这种类型） 为参数，并将它转化成 ANSI 类型。专门检查是必须的，因为 BSTR 可能为空值，而 CString 的构造函数对于 NULL 值情况考虑的不是很周到，（感谢 Brian Ross 指出这一点!）。这种用法也只能处理包含 NUL 终结字符的单字符串；如果要转化含有多个 NULL 字符 串，你得额外做一些工作才行。在 CString 中内嵌的 NULL 字符通常表现不尽如人意，应该尽量避免。<br>　　根据 C/C++ 规则，如果你有一个 LPWSTR，那么它别无选择，只能和 LPCWSTR 参数匹配。<br><br>在 Unicode 模式下，它的构造函数是：</p>
<pre>CString::CString(LPCTSTR);</pre>
<p>正如上面所表示的，在 ANSI 模式下，它有一个特殊的构造函数：</p>
<pre>CString::CString(LPCWSTR); </pre>
<p>　　它会调用一个内部的函数将 Unicode 字符串转换成 ANSI 字符串。（在Unicode模式下，有一个专门的构造函数，该函数有一个参数是LPCSTR类型——一个8位 ANSI 字符串 指针，该函数将它加宽为 Unicode 的字符串！）再次强调：一定要检查 BSTR 的值是否为 NULL。<br>　　另外还有一个问题，正如上文提到的：BSTRs可以含有多个内嵌的NULL字符，但是 CString 的构造函数只能处理某个串中单个 NULL 字符。 也就是说，如果串中含有嵌入的 NUL字节，CString 将会计算出错误的串长度。你必须自己处理它。如果你看看 strcore.cpp 中的构造函数，你会发现 它们都调用了lstrlen，也就是计算字符串的长度。<br>　　注意从 Unicode 到 ANSI 的转换使用带专门参数的 ::WideCharToMultiByte，如果你不想使用这种默认的转换方式，则必须编写自己的转化代码。<br>　　如果你在 UNICODE 模式下编译代码，你可以简单地写成：<br></p>
<pre>CString convert(BSTR b){    if(b == NULL)        return CString(_T(""));    CString s(b); // in UNICODE mode    return s;}</pre>
　　如果是 ANSI 模式，则需要更复杂的过程来转换。注意这个代码使用与 ::WideCharToMultiByte 相同的参数值。所以你 只能在想要改变这些参数进行转换时使用该技术。例如，指定不同的默认字符，不同的标志集等。
<pre>CString convert(BSTR b){    CString s;    if(b == NULL)       return s; // empty for NULL BSTR#ifdef UNICODE    s = b;#else    LPSTR p = s.GetBuffer(SysStringLen(b) + 1);     ::WideCharToMultiByte(CP_ACP,            // ANSI Code Page                          0,                 // no flags                          b,                 // source widechar string                          -1,                // assume NUL-terminated                          p,                 // target buffer                          SysStringLen(b)+1, // target buffer length                          NULL,              // use system default char                          NULL);             // don''t care if default used    s.ReleaseBuffer();#endif    return s;}</pre>
　　我并不担心如果 BSTR 包含没有映射到 8 位字符集的 Unicode 字符时会发生什么，因为我指定了::WideCharToMultiByte 的最后两个参数为 NULL。这就是你可能需要改变的地方。 <br><br><img alt="" src="http://www.vckbase.com/document/image/paragraph.gif"> 7、<strong><a name="VARIANT 型转化成 CString 型">VARIANT 型转化成 CString 型</a></strong><br><br>　　事实上，我从来没有这么做过，因为我没有用 COM/OLE/ActiveX 编写过程序。但是我在microsoft.public.vc.mfc 新闻组上看到了 Robert Quirk 的一篇帖子谈到了这种转化，我觉得把他的文章包含在我的文章里是不太好的做法，所以在这里多做一些解释和演示。如果和他的文章有相孛的地方可能是我的疏忽。<br>　　VARIANT 类型经常用来给 COM 对象传递参数，或者接收从 COM 对象返回的值。你也能自己编写返回 VARIANT 类型的方法，函数返回什么类型 依赖可能（并且常常）方法的输入参数（比如，在自动化操作中，依赖与你调用哪个方法。IDispatch::Invoke 可能返回（通过其一个参数）一个 包含有BYTE、WORD、float、double、date、BSTR 等等 VARIANT 类型的结果，（详见 MSDN 上的 VARIANT 结构的定义）。在下面的例子中，假设 类型是一个BSTR的变体，也就是说在串中的值是通过 bsrtVal 来引用，其优点是在 ANSI 应用中，有一个构造函数会把 LPCWCHAR 引用的值转换为一个 CString（见 BSTR-to-CString 部分）。在 Unicode 模式中，将成为标准的 CString 构造函数，参见对缺省::WideCharToMultiByte 转换的告诫，以及你觉得是否可以接受（大多数情况下，你会满意的）。
<pre>VARIANT vaData;vaData = m_com.YourMethodHere();ASSERT(vaData.vt == VT_BSTR);CString strData(vaData.bstrVal);</pre>
<p>你还可以根据 vt 域的不同来建立更通用的转换例程。为此你可能会考虑：<br></p>
<pre>CString VariantToString(VARIANT * va){    CString s;    switch(va-&gt;vt)      { /* vt */       case VT_BSTR:          return CString(vaData-&gt;bstrVal);       case VT_BSTR | VT_BYREF:          return CString(*vaData-&gt;pbstrVal);       case VT_I4:          s.Format(_T("%d"), va-&gt;lVal);          return s;       case VT_I4 | VT_BYREF:          s.Format(_T("%d"), *va-&gt;plVal);       case VT_R8:          s.Format(_T("%f"), va-&gt;dblVal);          return s;       ... 剩下的类型转换由读者自己完成       default:          ASSERT(FALSE); // unknown VARIANT type (this ASSERT is optional)          return CString("");      } /* vt */}</pre>
<img alt="" src="http://www.vckbase.com/document/image/paragraph.gif"> 8、<strong><a name=载入字符串表资源>载入字符串表资源</a></strong><br><br>　　如果你想创建一个容易进行语言版本移植的应用程序，你就不能在你的源代码中直接包含本土语言字符串 （下面这些例子我用的语言都是英语，因为我的本土语是英语），比如下面这种写法就很糟：
<pre>CString s = "There is an error";</pre>
<p>　　你应该把你所有特定语言的字符串单独摆放（调试信息、在发布版本中不出现的信息除外）。这意味着向下面这样写比较好：</p>
<pre>s.Format(_T("%d - %s"), code, text);</pre>
<p>　　在你的程序中，文字字符串不是语言敏感的。不管怎样，你必须很小心，不要使用下面这样的串：</p>
<pre>// fmt is "Error in %s file %s"// readorwrite is "reading" or "writing"s.Format(fmt, readorwrite, filename); </pre>
<p>　　这是我的切身体会。在我的第一个国际化的应用程序中我犯了这个错误，尽管我懂德语，知道在德语的语法中动词放在句子的最后面，我们的德国方面的发行人还是苦苦的抱怨他们不得不提取那些不可思议的德语错误提示信息然后重新格式化以让它们能正常工作。比较好的办法（也是我现在使用的办法）是使用两个字符串，一个用 于读，一个用于写，在使用时加载合适的版本，使得它们对字符串参数是非敏感的。也就是说加载整个格式，而不是加载串&#8220;reading&#8221;，&#8220;writing&#8221;：</p>
<pre>// fmt is "Error in reading file %s"// "Error in writing file %s"s.Format(fmt, filename);</pre>
<p>　　一定要注意，如果你有好几个地方需要替换，你一定要保证替换后句子的结构不会出现问题，比如在英语中，可以是主语-宾语，主语-谓语，动词-宾语的结构等等。<br>　　在这里，我们并不讨论 FormatMessage，其实它比 sprintf/Format 还要有优势，但是不太容易和CString 结合使用。解决这种问题的办法就是我们按照参数出现在参数表中的位置给参数取名字，这样在你输出的时候就不会把他们的位置排错了。<br>　　接下来我们讨论我们这些独立的字符串放在什么地方。我们可以把字符串的值放入资源文件中的一个称为 STRINGTABLE 的段中。过程如下：首先使用 Visual Studio 的资源编辑器创建一个字符串，然后给每一个字符串取一个ID，一般我们给它取名字都以 IDS_开头。所以如果你有一个信息，你可以创建一个字符串资源然后取名为 IDS_READING_FILE，另外一个就取名为 IDS_WRITING_FILE。它们以下面的形式出现在你的 .rc 文件中：</p>
<pre>STRINGTABLEIDS_READING_FILE "Reading file %s"IDS_WRITING_FILE "Writing file %s"END</pre>
<p><strong>注意：</strong>这些资源都以 Unicode 的格式保存，不管你是在什么环境下编译。他们在Win9x系统上也是以Unicode 的形式存在，虽然 Win9x 不能真正处理 Unicode。<br>然后你可以这样使用这些资源：<br>// 在使用资源串表之前，程序是这样写的：<br></p>
<pre>   CString fmt;      if(...)        fmt = "Reading file %s";     else       fmt = "Writing file %s";  ...    // much later  CString s;  s.Format(fmt, filename); </pre>
// 使用资源串表之后，程序这样写：
<pre>    CString fmt;        if(...)           fmt.LoadString(IDS_READING_FILE);        else           fmt.LoadString(DS_WRITING_FILE);    ...      // much later    CString s;    s.Format(fmt, filename);</pre>
　　现在，你的代码可以移植到任何语言中去。LoadString 方法需要一个字符串资源的 ID 作为参数，然后它从 STRINGTABLE 中取出它对应的字符串，赋值给 CString 对象。 CString 对象的构造函数还有一个更加聪明的特征可以简化 STRINGTABLE 的使用。这个用法在 CString::CString 的文档中没有指出，但是在 构造函数的示例程序中使用了。（为什么这个特性没有成为正式文档的一部分，而是放在了一个例子中，我记不得了！）——【<strong>译者注</strong>：从这句话看，作者可能是CString的设计者。其实前面还有一句类似的话。说他没有对使用GetBuffer(0)获得的指针指向的地址是否可读做有效性检查 】。这个特征就是：如果你将一个字符串资源的ID强制类型转换为 LPCTSTR，将会隐含调用 LoadString。因此，下面两个构造字符串的例子具有相同的效果，而且其 ASSERT 在debug模式下不会被触发：
<pre>CString s;s.LoadString(IDS_WHATEVER);CString t( (LPCTSTR)IDS_WHATEVER );ASSERT(s == t);//不会被触发，说明s和t是相同的。</pre>
<p>　　现在，你可能会想：这怎么可能工作呢？我们怎么能把 STRINGTABLE ID 转化成一个指针呢？很简单：所有的字符串 ID 都在1~65535这个范围内，也就是说，它所有的高位都是0，而我们在程序中所使用的指针是不可能小于65535的，因为程序的低 64K 内存永远也不可能存在的，如果你试图访问0x00000000到0x0000FFFF之间的内存，将会引发一个内存越界错误。所以说1~65535的值不可能是一个内存地址，所以我们可以用这些值来作为字符串资源的ID。<br>　　我倾向于使用 MAKEINTRESOURCE 宏显式地做这种转换。我认为这样可以让代码更加易于阅读。这是个只适合在 MFC 中使用的标准宏。你要记住，大多数的方法即可以接受一个 UINT 型的参数，也可以接受一个 LPCTSTR 型的参数，这是依赖 C++ 的重载功能做到的。C++重载函数带来的 弊端就是造成所有的强制类型转化都需要显示声明。同样，你也可以给很多种结构只传递一个资源名。</p>
<pre>CString s;s.LoadString(IDS_WHATEVER);CString t( MAKEINTRESOURCE(IDS_WHATEVER));ASSERT(s == t);</pre>
<p>　　告诉你吧：我不仅只是在这里鼓吹，事实上我也是这么做的。在我的代码中，你几乎不可能找到一个字符串，当然，那些只是偶然在调试中出现的或者和语言无关的字符串除外。<br><br><img alt="" src="http://www.vckbase.com/document/image/paragraph.gif"> 9、<strong><a name="CString 和临时对象">CString 和临时对象</a></strong><br><br>　　这是出现在 microsoft.public.vc.mfc 新闻组中的一个小问题，我简单的提一下，这个问题是有个程序员需要往注册表中写入一个字符串，他写道：<br>　　我试着用 RegSetValueEx() 设置一个注册表键的值，但是它的结果总是令我困惑。当我用char[]声明一个变量时它能正常工作，但是当我用 CString 的时候，总是得到一些垃圾："&amp;Yacute;&amp;Yacute;&amp;Yacute;&amp;Yacute;...&amp;Yacute;&amp;Yacute;&amp;Yacute;&amp;Yacute;&amp;Yacute;&amp;Yacute;"为了确认是不是我的 CString 数据出了问题，我试着用 GetBuffer，然后强制转化成 char*，LPCSTR。GetBuffer 返回的值是正确的，但是当我把它赋值给 char* 时，它就变成垃圾了。以下是我的程序段：</p>
<pre>char* szName = GetName().GetBuffer(20);RegSetValueEx(hKey, "Name", 0, REG_SZ,              (CONST BYTE *) szName,             strlen (szName + 1));</pre>
<p>这个 Name 字符串的长度小于 20，所以我不认为是 GetBuffer 的参数的问题。<br><br>真让人困惑，请帮帮我。<br><br>亲爱的 Frustrated，<br><br>你犯了一个相当微妙的错误，聪明反被聪明误，正确的代码应该象下面这样：<br></p>
<pre>CString Name = GetName();RegSetValueEx(hKey, _T("Name"), 0, REG_SZ,                     (CONST BYTE *) (LPCTSTR)Name,                    (Name.GetLength() + 1) * sizeof(TCHAR));</pre>
　　为什么我写的代码能行而你写的就有问题呢？主要是因为当你调用 GetName 时返回的 CString 对象是一个临时对象。参见：《C++ Reference manual》&#167;12.2<br>　　在一些环境中，编译器有必要创建一个临时对象，这样引入临时对象是依赖于实现的。如果编译器引入的这个临时对象所属的类有构造函数的话，编译器要确保这个类的构造函数被调用。同样的，如果这个类声明有析构函数的话，也要保证这个临时对象的析构函数被调用。<br>　　编译器必须保证这个临时对象被销毁了。被销毁的确切地点依赖于实现.....这个析构函数必须在退出创建该临时对象的范围之前被调用。<br>　　大部分的编译器是这样设计的：在临时对象被创建的代码的下一个执行步骤处隐含调用这个临时对象的析构函数，实现起来，一般都是在下一个分号处。因此，这个 CString 对象在 GetBuffer 调用之后就被析构了（顺便提一句，你没有理由给 GetBuffer 函数传递一个参数，而且没有使用ReleaseBuffer 也是不对的）。所以 GetBuffer 本来返回的是指向这个临时对象中字符串的地址的指针，但是当这个临时对象被析构后，这块内存就被释放了。然后 MFC 的调试内存分配器会重新为这块内存全部填上 0xDD，显示出来刚好就是&#8220;&amp;Yacute;&#8221;符号。在这个时候你向注册表中写数据，字符串的内容当然全被破坏了。<br>　　我们不应该立即把这个临时对象转化成 char* 类型，应该先把它保存到一个 CString 对象中，这意味着把临时对象复制了一份，所以当临时的 CString 对象被析构了之后，这个 CString 对象中的值依然保存着。这个时候再向注册表中写数据就没有问题了。<br>　　此外，我的代码是具有 Unicode 意识的。那个操作注册表的函数需要一个字节大小，使用lstrlen(Name+1) 得到的实际结果对于 Unicode 字符来说比 ANSI 字符要小一半，而且它也不能从这个字符串的第二个字符起开始计算，也许你的本意是 lstrlen(Name) + 1（OK，我承认，我也犯了同样的错误！）。不论如何，在 Unicode 模式下，所有的字符都是2个字节大小，我们需要处理这个问题。微软的文档令人惊讶地对此保持缄默：REG_SZ 的值究竟是以字节计算还是以字符计算呢？我们假设它指的是以字节为单位计算，你需要对你的代码做一些修改来计算这个字符串所含有的字节大小。<br><br><img alt="" src="http://www.vckbase.com/document/image/paragraph.gif"> 10、<strong><a name=CString的效率>CString 的效率</a></strong><br><br>　　CString 的一个问题是它确实掩藏了一些低效率的东西。从另外一个方面讲，它也确实可以被实现得更加高效，你可能会说下面的代码：
<pre>CString s = SomeCString1;s += SomeCString2;s += SomeCString3;s += ",";s += SomeCString4;</pre>
<p>比起下面的代码来，效率要低多了：</p>
<pre>char s[1024];lstrcpy(s, SomeString1);lstrcat(s, SomeString2);lstrcat(s, SomeString 3);lstrcat(s, ",");lstrcat(s, SomeString4);</pre>
<p>　　总之，你可能会想，首先，它为 SomeCString1 分配一块内存，然后把 SomeCString1 复制到里面，然后发现它要做一个连接，则重新分配一块新的足够大的内存，大到能够放下当前的字符串加上SomeCString2，把内容复制到这块内存 ，然后把 SomeCString2 连接到后面，然后释放第一块内存，并把指针重新指向新内存。然后为每个字符串重复这个过程。把这 4 个字符串连接起来效率多低啊。事实上，在很多情况下根本就不需要复制源字符串（在 += 操作符左边的字符串）。<br>　　在 VC++6.0 中，Release 模式下，所有的 CString 中的缓存都是按预定义量子分配的。所谓量子，即确定为 64、128、256 或者 512 字节。这意味着除非字符串非常长，连接字符串的操作实际上就是 strcat 经过优化后的版本（因为它知道本地的字符串应该在什么地方结束，所以不需要寻找字符串的结尾；只需要把内存中的数据拷贝到指定的地方即可）加上重新计算字符串的长度。所以它的执行效率和纯 C 的代码是一样的，但是它更容易写、更容易维护和更容易理解。<br>　　如果你还是不能确定究竟发生了怎样的过程，请看看 CString 的源代码，strcore.cpp，在你 vc98的安装目录的 mfc\src 子目录中。看看 ConcatInPlace 方法，它被在所有的 += 操作符中调用。<br><br>啊哈！难道 CString 真的这么"高效"吗？比如，如果我创建</p>
<pre>CString cat("Mew!");</pre>
<p>　　然后我并不是得到了一个高效的、精简的5个字节大小的缓冲区（4个字符加一个结束字符），系统将给我分配64个字节，而其中59个字节都被浪费了。<br>　　如果你也是这么想的话，那么就请准备好接受再教育吧。可能在某个地方某个人给你讲过尽量使用少的空间是件好事情。不错，这种说法的确正确，但是他忽略了事实中一个很重要的方面。<br>　　如果你编写的是运行在16K EPROMs下的嵌入式程序的话，你有理由尽量少使用空间，在这种环境下，它能使你的程序更健壮。但是在 500MHz, 256MB的机器上写 Windows 程序，如果你还是这么做，它只会比你认为的&#8220;低效&#8221;的代码运行得更糟。<br>　　举例来说。字符串的大小被认为是影响效率的首要因素，使字符串尽可能小可以提高效率，反之则降低效率，这是大家一贯的想法。但是这种想法是不对的，精确的内存分配的后果要在程序运行了好几个小时后才能体现得出来，那时，程序的堆中将充满小片的内存，它们太小以至于不能用来做任何事，但是他们增加了你程序的内存用量，增加了内存页面交换的次数，当页面交换的次数增加到系统能够忍受的上限，系统则会为你的程序分配更多的页面，直到你的程序占用了所有的可用内存。由此可见，虽然内存碎片是决定效率的次要因素，但正是这些因素实际控制了系统的行为，最终，它损害了系统的可靠性，这是令人无法接受的。<br>　　记住，在 debug 模式下，内存往往是精确分配的，这是为了更好的排错。<br>　　假设你的应用程序通常需要连续工作好几个月。比如，我常打开 VC++，Word，PowerPoint，Frontpage，Outlook Express，Fort&#233; Agent，Internet Explorer和其它的一些程序，而且通常不关闭它们。我曾经夜以继日地连续用 PowerPoint 工作了好几天（反之，如果你不幸不得不使用像 Adobe FrameMaker 这样的程序的话，你将会体会到可靠性的重要；这个程序机会每天都要崩溃4~6次，每次都是因为用完了所有的空间并填满我所有的交换页面）。所以精确内存分配是不可取的，它会危及到系统的可靠性，并引起应用程序崩溃。<br>　　按量子的倍数为字符串分配内存，内存分配器就可以回收用过的内存块，通常这些回收的内存块马上就可以被其它的 CString 对象重新用到，这样就可以保证碎片最少。分配器的功能加强了，应用程序用到的内存就能尽可能保持最小，这样的程序就可以运行几个星期或几个月而不出现问题。<br>　　题外话：很多年以前，我们在 CMU 写一个交互式系统的时候，一些对内存分配器的研究显示出它往往产生很多内存碎片。Jim Mitchell，现在他在 Sun Microsystems 工作，那时侯他创造了一种内存分配器，它保留了一个内存分配状况的运行时统计表，这种技术和当时的主流分配器所用的技术都不同，且较为领先。当一个内存块需要被分割得比某一个值小的话，他并不分割它，因此可以避免产生太多小到什么事都干不了的内存碎片。事实上他在内存分配器中使用了一个浮动指针，他认为：与其让指令做长时间的存取内存操作，还不如简单的忽略那些太小的内存块而只做一些浮动指针的操作。（His observation was that the long-term saving in instructions by not having to ignore unusable small storage chunks far and away exceeded the additional cost of doing a few floating point operations on an allocation operation.）他是对的。<br>　　永远不要认为所谓的&#8220;最优化&#8221;是建立在每一行代码都高速且节省内存的基础上的，事实上，高速且节省内存应该是在一个应用程序的整体水平上考虑的。在软件的整体水平上，只使用最小内存的字符串分配策略可能是最糟糕的一种方法。<br>　　如果你认为优化是你在每一行代码上做的那些努力的话，你应该想一想：在每一行代码中做的优化很少能真正起作用。你可以看我的另一篇关于优化问题的文章《Your Worst Enemy for some thought-provoking ideas》。<br>　　记住，+= 运算符只是一种特例，如果你写成下面这样：</p>
<pre>CString s = SomeCString1 + SomeCString2 + SomeCString3 + "," + SomeCString4;</pre>
<p>则每一个 + 的应用会造成一个新的字符串被创建和一次复制操作。<br><br><img alt="" src="http://www.vckbase.com/document/image/paragraph.gif"> <strong><a name=总结>总结</a></strong><br><br>　　以上是使用 CString 的一些技巧。我每天写程序的时候都会用到这些。CString 并不是一种很难使用的类，但是 MFC 没有很明显的指出这些特征，需要你自己去探索、去发现。<br></p>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/42953.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-02-19 17:30 <a href="http://www.cppblog.com/gtwdaizi/articles/42953.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>windows mobile下获取应用的安装路径</title><link>http://www.cppblog.com/gtwdaizi/articles/42888.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Mon, 18 Feb 2008 08:28:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/42888.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/42888.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/42888.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/42888.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/42888.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;TCHAR cPath[MAX_PATH];&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;CString filePath;</p>
<p>&nbsp;&nbsp;&nbsp;GetModuleFileName( NULL, cPath, MAX_PATH );</p>
<p>&nbsp;&nbsp;&nbsp;filePath = cPath;</p>
<p>&nbsp;&nbsp;&nbsp;filePath = filePath.Left(filePath.ReverseFind('\\'));</p>
<p>&nbsp;&nbsp;&nbsp;AfxMessageBox(filePath);&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; strPath为你想得到的EXE文件路径<br></p>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/42888.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-02-18 16:28 <a href="http://www.cppblog.com/gtwdaizi/articles/42888.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows CE开发常见问题解答(转载)</title><link>http://www.cppblog.com/gtwdaizi/articles/42884.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Mon, 18 Feb 2008 07:32:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/42884.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/42884.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/42884.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/42884.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/42884.html</trackback:ping><description><![CDATA[<p>1.怎样在一个控件获得焦点时打开软键盘？</p>
<p>比如一个EditBox获得焦点后，这个时候自动打开软键盘，这样可以方便用户输入——SIPINFO、SHSIPINFO、SIPSETINFO、SIPGETINFO里面有些参数弄不明白 </p>
<p>//隐藏输入面板 <br>BOOL LowerSip() <br>{ <br>BOOL fRes = FALSE; <br>SIPINFO si; <br>memset( &amp;si, 0, sizeof( si ) ); <br>si.cbSize = sizeof( si ); <br>if( SHSipInfo( SPI_GETSIPINFO, 0, &amp;si, 0 ) ) <br>{ <br>si.fdwFlags &amp;= ~SIPF_ON; <br>fRes = SHSipInfo( SPI_SETSIPINFO, 0, &amp;si, 0 ); <br>} <br>return fRes; <br>} </p>
<p>//升起输入面板 <br>BOOL RaiseSip( void ) <br>{ <br>BOOL fRes = FALSE; <br>SIPINFO si; <br>memset( &amp;si, 0, sizeof( si ) ); <br>si.cbSize = sizeof( si ); <br>if( SHSipInfo( SPI_GETSIPINFO, 0, &amp;si, 0 ) ) <br>{ <br>si.fdwFlags |= SIPF_ON; <br>fRes = SHSipInfo( SPI_SETSIPINFO, 0, &amp;si, 0 ); <br>} <br>return fRes; <br>} <br>再试试下面这些： <br>//SHSipPreference(m_hWnd, SIP_UP);//弹出输入面板 <br>//SHSipPreference(m_hWnd, SIP_DOWN);//隐藏输入面板(有一个时延) <br>//SHSipPreference(m_hWnd, SIP_FORCEDOWN );//隐藏输入面板(立即) <br>//SHSipPreference(m_hWnd, SIP_UNCHANGED ); <br>//一般只用在调用SIP_DOWN时的的后面，使这个命令无效 </p>
<p>--------------------------------------------------------------------------------</p>
<p>2.WinCE下字符串-数字转化的问题！</p>
<p>在VC6.0下，把#include &lt;stdlib.h&gt;、#include &lt;stdio.h&gt;两个文件包括进去后，下面这段代码一点问题没有, <br>CString str1,str2; <br>str1="123"; <br>str2="123.4"; <br>int i; <br>float j; <br>i=atoi(str1); <br>j=atof(str2); <br>但是在EVC3.0里面，却出现了问题：提示atof没有定义，atoi也不能正常转化。 </p>
<p>用wcstoi,wcstof, wcstol和wcstod </p>
<p>--------------------------------------------------------------------------------</p>
<p>3. 我新拿了一个Pocket Pc，编了几个程序，但发现对话框都只能全屏显示，这是为什么？</p>
<p>一般在Pocket PC中所有的对话框都是全屏显示，这是操作系统规定的行为。但如使用系统自定义的信息提示框，则不是全屏显示。如： Afxmessagebox所激发的提示框就是如此。 <br>可以重载WM_INITDIALOG消息 <br>MSDN： <br>The DialogBox macro uses the CreateWindowEx function to create the dialog box. DialogBox then sends a WM_INITDIALOG message to the dialog box procedure. The function displays the dialog box (regardless of whether the template specifies the WS_VISIBLE style), disables the owner window, and starts its own message loop to retrieve and dispatch messages for the dialog box. </p>
<p>就是说当对话框窗口创建完以后，会发出一个WM_INITDIALOG 消息，你只要在自己的窗口消息处理函数里对这个消息进行处理，就可以了 <br>比如： </p>
<p>case WM_INITDIALOG: <br>// Create a Done button and size it. <br>shidi.dwMask = SHIDIM_FLAGS; <br>shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN; <br>shidi.hDlg = hDlg; <br>SHInitDialog(&amp;shidi); <br>InitOptionDlg(hDlg); <br>return TRUE; </p>
<p>主要就是修改shidi.dwFlags ，看看ABOUT的窗口消息处理吧 <br>补充： SHINITDLGINFO shidi; <br>SHINITDLGINFO shidi; <br>上面说的是在纯API的程序中的方法 <br>对于MFC创建的DIALOG程序，可以这样： </p>
<p>BOOL CXXXDlg::OnInitDialog() <br>{ </p>
<p>SHINITDLGINFO shidi; <br>HWND hDlg = m_hWnd; <br>// Create a Done button and size it. <br>shidi.dwMask = SHIDIM_FLAGS; <br>shidi.dwFlags = SHIDIF_SIPDOWN ; <br>shidi.hDlg = hDlg; <br>SHInitDialog(&amp;shidi); <br>//InitOptionDlg(hDlg); <br>//CDialog::OnInitDialog(); <br>&#8230;&#8230; </p>
<p>} </p>
<p>--------------------------------------------------------------------------------</p>
<p>4.在eVC基于MFC的程序中如何将ToolBar栏隐藏</p>
<p>关于ToolBar的隐藏： <br>首先，如果你是用MFC向导创建的工程，则默认会生成ToolBar，我要说的是，干掉它！自己来创建。：） <br>First，声明CToolBar成员变量： <br>CToolBar * d_pToolbar2; <br>然后&#8230;&#8230; <br>static UINT BASED_CODE Toolbar2Buttons[] = <br>{ <br>// 下面是工具栏对应菜单的ID，工具栏图标是我弄的一个Bitmap，其ID为IDR_ADD_TOOLBAR <br>ID_FILE_NEW, <br>ID_FILE_OPEN, <br>ID_FILE_SAVE, <br>ID_SEPARATOR, <br>ID_EDIT_CUT, <br>ID_EDIT_COPY, <br>ID_EDIT_PASTE, <br>ID_SEPARATOR, <br>ID_TRANS_DICT, <br>ID_TOOLBAR_SHOW, //这是新加入的菜单项，点击隐藏工具栏，再点击就显示工具栏 <br>}; <br>然后&#8230;&#8230; <br>在CMainFrame的OnCreate()中加入： <br>OnToolbarCreate(); <br>然后&#8230;&#8230; <br>void CMainFrame::OnToolbarCreate() <br>{ <br>// Should only get here if we don't have a toolbar. <br>ASSERT(d_pToolbar2 == 0); <br>// Create C++ object and WinAPI window. <br>d_pToolbar2 = new CToolBar(); <br>d_pToolbar2-&gt;Create(this, WS_CHILD | CBRS_BOTTOM | <br>CBRS_SIZE_FIXED | CBRS_FLOATING, <br>0x9100); <br>// Get bitmap and connect to tool items. <br>d_pToolbar2-&gt;LoadBitmap(IDR_ADD_TOOLBAR); <br>d_pToolbar2-&gt;SetButtons(Toolbar2Buttons, <br>sizeof(Toolbar2Buttons)/sizeof(UINT)); <br>// Make toolbar dockable. <br>d_pToolbar2-&gt;EnableDocking(CBRS_ALIGN_ANY); <br>EnableDocking(CBRS_ALIGN_ANY); <br>DockControlBar(d_pToolbar2); <br>} <br>然后&#8230;&#8230; <br>void CMainFrame::OnToolbarShow() <br>{ <br>ASSERT(d_pToolbar2 != 0); </p>
<p>// Query current visibility. <br>BOOL bVisible = (d_pToolbar2-&gt;GetStyle() &amp; WS_VISIBLE); </p>
<p>// Show or hide. <br>int nShow = (bVisible) ? SW_HIDE : SW_SHOWNORMAL; <br>d_pToolbar2-&gt;ShowWindow(nShow); </p>
<p>// Reconfigure remaining toolbar items. <br>RecalcLayout(); </p>
<p>// Store visibility state for later. <br>d_bToolbarVisible = (!bVisible); <br>} </p>
<p>void CMainFrame::OnUpdateToolbarShow(CCmdUI* pCmdUI) <br>{ <br>//This function is signed for checking the menu 'Edit|Show Toolbar' <br>pCmdUI-&gt;Enable(d_pToolbar2 != 0); <br>int nCheck = (d_bToolbarVisible) ? 1 : 0; <br>pCmdUI-&gt;SetCheck(nCheck); <br>} </p>
<p>ＯＫ，默认情况下ToolBar是隐藏的，点击菜单中的新加入的隐藏/显示工具栏命令即可来回切换了。 </p>
<p>--------------------------------------------------------------------------------</p>
<p>5.如何制作pocket Pc 下的安装程序？</p>
<p>在C:\Windows CE Tools\wce300\MS Pocket PC\support\ActiveSync\windows ce application installation 下面有例子. <br>也有其它第三方的安装工具，比如installshield。 </p>
<p>--------------------------------------------------------------------------------</p>
<p>6.怎样在主界面中显示一幅图片 </p>
<p>我做了一个小程序， 想在主界面中显示一幅图片，我的图片是.JPG格式的，如果需要转换，用什么工具？ </p>
<p>把JPG图转为BMP图咯，网上有不少这样的程序。 <br>然后用LoadBitmap、SelectObject、StretchBlt等语句把BMP图显示到VIEW中。 </p>
<p><br>--------------------------------------------------------------------------------</p>
<p>7. 请问，在WinCE下如何截获所有鼠标和键盘的消息?</p>
<p>wince下只能用三种钩子 <br>#define WH_JOURNALRECORD 0 <br>#define WH_JOURNALPLAYBACK 1 <br>#define WH_KEYBOARD_LL 20 </p>
<p>--------------------------------------------------------------------------------</p>
<p>8.在Pocket PC下用eVC作的对话框能否做成不是全屏的？</p>
<p>在MFC中 </p>
<p>m_bFullScreen = FALSE;</p>
<p><br>--------------------------------------------------------------------------------</p>
<p>9.如何将char 类型的中文字符串转换成Unicode的字符串?</p>
<p>MultiByteToWideChar，在仿真器中无效;你也可以通过其他方法；用wcsprintf这个函数</p>
<p><br>--------------------------------------------------------------------------------</p>
<p>10. evc单文档界面中，菜单左边总有一个"new"，如何将其去掉？</p>
<p>在MainFrm的OnCreate内找到这个： <br>m_wndCommandBar.m_bShowSharedNewButton = TRUE; <br>把TRUE改为FALSE </p>
<p>--------------------------------------------------------------------------------</p>
<p>11.Edit出现上下文菜单问题？ </p>
<p>近来我看了一下SDK带的Sample中的Npp，其中它有一个功能就是在EDIT上出现上下文菜单，可是当我仿照它在自己的项目中添加此功能时，即在资源中添加CONTROL "",IDC_STATIC,"SIPPREF",NOT WS_VISIBLE,-10,-10、,6,6，在模拟器中正常，但在PDA中不能显示包含Edit的对话框。而Npp可以在两者正常显示。我又在Npp中增加一个对话框，也相应的改变资源，结果是在模拟器和PDA中都能正常显示。 </p>
<p>调用SHInitExtraControls()应该在构造函数，不应在OnInitDialog中。如果在OnInitDialog中调用，包含EDIT的对话框将不显示。 <br>事实上在XXXApp::InitInstance函数中调用更好，这样只需调用一次，就万事大吉。 </p>
<p>--------------------------------------------------------------------------------</p>
<p>12. 如何将.mdb数据库转换为.cdb数据库 </p>
<p>如何将.mdb数据库转换为.cdb数据库，在没有实际PDA,只有Pocket PC Emuliation和EVB的情况下。 <br>Pocket PC Emuliation运行时为何提示&#8220;存储器不足，无法完成操作&#8221;？ </p>
<p>此问题微软已经给出了答案。 <br>在SDK文档中有一个叫做device的例子程序，它就是将tdb文件转化成cdb文件的，而还有一个desktop的程序，它是将mdb文件转化成tdb文件的。 </p>
<p><br>--------------------------------------------------------------------------------</p>
<p>13.请问如何用EVC建立和调用DLL </p>
<p>我按照帮助中用MFC开发DLL的例子做，但是另外一个程序调用的时候的时候却出现连接错误，说找不到那个函数。后来看了EVC的例子spintest之后也是这样。 </p>
<p>和在WINDOWS下的一样 <br>是不是LINK2001 ERROR？ <br>你如果是隐式调用（就是不用LOADLIBRARY（）的），要把你的DLL的LIB文件在PROJECT--&gt;SETTINGS---&gt;LINK---&gt;INPUT里指明。 </p>
<p>--------------------------------------------------------------------------------</p>
<p>14.编辑框如何自动会换行 ?</p>
<p>请教,Plam中的table控件,在Wince上怎么做? <br>就是编辑框自动会换行.当你输入的内容超过一行,自动切换到下一行,下面的内容自动往下滚。 </p>
<p>勾选编辑控件的MultiLine，如果想输入回车换行，再勾选want renturn </p>
<p>--------------------------------------------------------------------------------</p>
<p>15.是否在adoce,pocket access中的update语句不能执行？</p>
<p>ADOCE不能直接执行UPDATE语句，但ADOCE有Update方法，你可用它实现。</p>
<p><br>--------------------------------------------------------------------------------</p>
<p>16.请问如何在Windows CE中实现BC++中的inport(...)与outportb(...)函数功能？</p>
<p>CE下，可以用WINDOWS API函数来对端口操作。 比较简单。 <br>API一般只要用到CreateFile（打开端口，串口操作和文件操作只有一点不同就是打开方式不同，所以第三个参数要用 OPEN_EXISTING ） <br>COMMTIMEOUTS、DCB两个结构是存放设置参数的，可以改 <br>WriteFile、WriteFile（读写端口） <br>因为串口通讯用的是异步通讯，所以下面两句比较重要 <br>SetCommMask（指定监视的端口事件） <br>WaitCommEvent（等待端口事件） </p>
<p>--------------------------------------------------------------------------------</p>
<p>17. 如何显示一个对话框让用户选择一个目录而不是文件</p>
<p>没有标准的函数处理这个，你只好自己实现活使用第三方的解决方案。</p>
<p><br>--------------------------------------------------------------------------------</p>
<p>18.有没有办法(API)激活或禁止电源保存模式？</p>
<p>参看SystemIdleTimerReset()的安装文档。创建一个包含象睡眠的无限循环的线程，然后调用SystemIdleTimerReset()。也许有一种中断线程的办法就是程序退出。</p>
<p><br>--------------------------------------------------------------------------------</p>
<p>19. Windows CE的文件名最小程度是多少？</p>
<p>在windef.h定义了MAX_PATH，普遍应该是260个字符。</p>
<p>20.&nbsp;我使用CFileDialog创建了一个浏览按钮，默认目录始终是显示"All Folders"和在"\My Device\My do***ents"下。怎样改变初始目录到"\My Device"。使用fileDlg.m_ofn.lpstrInitialDir = TEXT("<a href="file://My/"><u><font color=#0000ff>file://My/</font></u></a> Device");，但是没有改变默认显示的目录。<br>lpstrInitialDir指向一个指定初始文件目录的字符串。如果为NULL，将使用系统的根目录。尽量尝试一下lpstrInitialDir为NULL。</p>
<p><br>--------------------------------------------------------------------------------</p>
<p>21.在Pocket PC任务栏上可能有X和OK按钮吗？</p>
<p>不可能，至少没有象WisBar的第三方工具。</p>
<p><br>--------------------------------------------------------------------------------</p>
<p>22.如何禁止用户改变日期和时间？有可能实现吗？</p>
<p>你可能用自己的程序替代\windows\clock.exe，但是，它们可以通过另外的程序处理这个。同样，在同步时ActiveSync改变设备的时间与PC匹配。</p>
<p><br>--------------------------------------------------------------------------------</p>
<p>23.&nbsp; 我有一个xscal cpu的ipaq 3970设备，但是在eMbedded Visual C++ 3.0上没有目标类型。我应该在EVC3.0上使用什么类型。这个问题也发生在安装程序Cabwiz.exe上。</p>
<p>你可以使用ARM类型。XScal基于ARM体系。</p>
<p><br>--------------------------------------------------------------------------------</p>
<p>24.&nbsp; 如何使程序在后台运行？</p>
<p>最小化程序将使程序进入后台，因此只要在程序启动时最小化，那么它将运行在后台。</p>
<p>补充:还可以做成service。<br>--------------------------------------------------------------------------------</p>
<p>25.&nbsp; 我准备去掉SIP按钮。我在OnInitDialog事件中使用SHFullScreen。然而SIP按钮仍然可见，忘记做什么了吗？</p>
<p>代码如下： </p>
<p>// SHFullScreen fails if dialog box is not foreground. <br>SetForegroundWindow(); <br>// Go to the full screen mode <br>SHFullScreen(m_hWnd, SHFS_HIDESIPBUTTON | SHFS_HIDESTARTICON); </p>
<p><br>不能在OnInitDialog中使用SHFullScreen，因为对话框还没有可见。你应该传递一个自定义消息，在那个消息调用这个函数。 </p>
<p>也许下面这段代码会有用： </p>
<p>void PFCSipButtonShow( BOOL bShow ) <br>{ <br>HWND hWnd = ::FindWindow( _T( "MS_SIPBUTTON" ), NULL ); <br>if (hWnd == NULL) <br>return; </p>
<p>if (bShow) <br>::ShowWindow( hWnd, SW_SHOW ); <br>else <br>::ShowWindow( hWnd, SW_HIDE ); </p>
<p>} // PFCSipButtonShow </p>
<p><br>--------------------------------------------------------------------------------</p>
<p>26.&nbsp;如何在Pocket PC2002模拟器上安装Pocket PC程序？</p>
<p>PPC2002模拟器没有模拟ARM处理器，因此你必须有x86 CPU的二进制文件和相应的安装程序。只需使用文件浏览器复制cab文件到模拟器，然后执行它。商业程序的安装包通常不包含x86的二进制程序。如果你没有x86处理器的程序发布版本，你不能做这个安装。如果程序是你自己的，你可以创建一个x86的版本，之后创建一个安装CAB。</p>
<p><br>--------------------------------------------------------------------------------</p>
<p>27.&nbsp; 如何在eVC程序中读取普通的图标文件？</p>
<p>在PC程序中使用ExtractIconEx()，但是在Pocket 设备好象不工作。缺少了什么？PC图标文件在Pocket PC环境是非法的？或者需要转换格式？ </p>
<p>不幸的是，在Pocket PC上没有API去读取图标。因此，你不得不手工解析图标文件。 </p>
<p>--------------------------------------------------------------------------------</p>
<p>28.&nbsp;如何绘制一个透明的圆呢？</p>
<p>我想使用eVC++和GDI在Pocket PC 2002上绘制一个圆。我使用它绘制了直线，它处理的很好： </p>
<p>hbrOld =(HBRUSH) SelectObject(hDC, CreatePatternBrush(RGB(0,255,0))); <br>hpnOld =(HPEN) SelectObject(hDC, CreatePen(PS_SOLID, 2, RGB(255,0,0))); <br>Ellipse( hDC, 10, 10, 20, 20); <br>DeleteObject( SelectObject (hDC, hbrOld) ); <br>DeleteObject( SelectObject (hDC, hpnOld) ); </p>
<p>但是如何绘制一个透明的圆呢？有PS_NULL这样画笔类型吗？ </p>
<p>可以使用GetStockObject()得到一个NULL_BRUSH或HOLLOW_BRUSH（这两个是相同的）。然后用SelectObject选择它，就象你已经做的那样。 </p>
<p>--------------------------------------------------------------------------------</p>
<p>29.&nbsp; 假定我知道程序的名称，关闭运行着的eVC的程序使用什么API?</p>
<p>如果你知道程序的名称，并且假定与主窗口的名称相同，那么你可以使用FindWindow得到那个窗口的句柄，然后传送WM_CLOSE消息到那个窗口。 </p>
<p>HWND hwnd = FindWindow(NULL, _T("APPLICATION NAME")); <br>if ( hwnd) <br>PostMessage(hwnd, WM_DESTROY, 0, 0); </p>
<p><br>--------------------------------------------------------------------------------</p>
<p>30.&nbsp; 如何从PC设置PDA的时间？</p>
<p>最简单的办法是写一个自定义的RAPI函数，通过CeRapi调用设备的SetSystemTime.</p>
<p><br>--------------------------------------------------------------------------------</p>
<p>31.&nbsp; 怎样使用WriteBinary，我不明白第二个参数(LPBYTE):</p>
<p>BOOL CVORegistry::WriteBinary(LPCTSTR pcszKey, LPBYTE pData, DWORD cbData) </p>
<p>第二个参数是指向包含你想写到注册表的二进制数据的缓冲。 </p>
<p>BYTE data[] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef }; <br>extern CVORegistry reg; <br>reg.WriteData(_T("BinaryData"), data, sizeof(data)); </p>
<p>--------------------------------------------------------------------------------</p>
<p>32.&nbsp; Windows CE支持钩子API吗？这样我们可以监视需要的时间。如果支持，用法也象Windows 2000那样吗？</p>
<p>坏消息：CE不支持钩子。<br>系统不支持，我们还是可以想其他办法的&#8230;&#8230;<img alt="Stick out tongue" src="http://www.winbile.net/BBS/emoticons/emotion-4.gif"><br><br>--------------------------------------------------------------------------------</p>
<p>33.&nbsp; 我不能使用Pocket PC上CDialog的TitleBar，我能用静态文本框控件替代，使之与TitleBar相似。有办法显示TitleBar吗？</p>
<p>大多数Pocket PC上的对话框是全屏的，没有自己的主题栏，而是使用系统任务栏。你可以创建一个非全屏对话框（象消息框那样）。</p>
<p><br>--------------------------------------------------------------------------------</p>
<p>34.&nbsp; 如何在程序中关闭（suspend）Pocekt PC？</p>
<p>方法1：虚拟关机键 <br>::keybd_event(VK_OFF, 0, 0, 0); <br>::keybd_event(VK_OFF, 0, KEYEVENTF_KEYUP, 0); </p>
<p>方法2：调用未公开函数PowerOffSystem() <br>extern "C" __declspec(dllimport) void PowerOffSystem(); </p>
<p><br>--------------------------------------------------------------------------------</p>
<p>35.&nbsp; 如何在程序中重启（soft reset）Pocket PC？</p>
<p>#include <br>#define IOCTL_HAL_REBOOT CTL_CODE(FILE_DEVICE_HAL, 15, METHOD_BUFFERED, FILE_ANY_ACCESS) <br>extern "C" __declspec(dllimport) BOOL KernelIoControl( <br>DWORD dwIoControlCode, <br>LPVOID lpInBuf, <br>DWORD nInBufSize, <br>LPVOID lpOutBuf, <br>DWORD nOutBufSize, <br>LPDWORD lpBytesReturned); <br>BOOL ResetPocketPC() <br>{ <br>return KernelIoControl(IOCTL_HAL_REBOOT, NULL, 0, NULL, 0, NULL); <br>} </p>
<p><br>--------------------------------------------------------------------------------</p>
<p>36.&nbsp;如何在程序中硬启动（hardware reset）Pocekt PC？</p>
<p>注意：使用此段代码会将您的Pocket PC的用户数据全部清空。 </p>
<p>#include <br>#define IOCTL_HAL_REBOOT CTL_CODE(FILE_DEVICE_HAL, 15, METHOD_BUFFERED, FILE_ANY_ACCESS) <br>extern "C" __declspec(dllimport)void SetCleanRebootFlag(void); <br>extern "C" __declspec(dllimport) BOOL KernelIoControl( <br>DWORD dwIoControlCode, <br>LPVOID lpInBuf, <br>DWORD nInBufSize, <br>LPVOID lpOutBuf, <br>DWORD nOutBufSize, <br>LPDWORD lpBytesReturned); <br>BOOL HardResetPocketPC() <br>{ <br>SetCleanRebootFlag(); <br>return KernelIoControl(IOCTL_HAL_REBOOT, NULL, 0, NULL, 0, NULL); <br>} </p>
<p><br>--------------------------------------------------------------------------------</p>
<p>37.&nbsp; 以下方法信息不全，无法使用：</p>
<p>1.系统不认识VK_OFF<br>2.使用哪个dll 和 lib文件？</p>
<p><br>&#183;&nbsp; 如何在程序中关闭（suspend）Pocekt PC？</p>
<p>方法1：虚拟关机键 <br>::keybd_event(VK_OFF, 0, 0, 0); <br>::keybd_event(VK_OFF, 0, KEYEVENTF_KEYUP, 0); </p>
<p>方法2：调用未公开函数PowerOffSystem() <br>extern \"C\" __declspec(dllimport) void PowerOffSystem(); </p>
<p>关闭（suspend) <br>方法1： <br>//虚拟关机键 <br>::keybd_event(VK_OFF, 0, 0, 0); <br>::keybd_event(VK_OFF, 0, KEYEVENTF_KEYUP, 0); </p>
<p>方法2： <br>//调用未公开函数PowerOffSystem() <br>extern "C" __declspec(dllimport) void PowerOffSystem(); <br></p>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/42884.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-02-18 15:32 <a href="http://www.cppblog.com/gtwdaizi/articles/42884.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>开发识别屏幕方向的应用程序 </title><link>http://www.cppblog.com/gtwdaizi/articles/41705.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Wed, 23 Jan 2008 03:30:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/41705.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/41705.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/41705.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/41705.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/41705.html</trackback:ping><description><![CDATA[<div class=topic>
<div class=majorTitle xmlns:msxsl="urn:schemas-microsoft-com:xslt"></div>
<div class=title xmlns:msxsl="urn:schemas-microsoft-com:xslt"><strong>开发识别屏幕方向的应用程序</strong> </div>
<!--content type: DocStudio. Transform: psdk2mtps.xslt.-->
<div id=mainSection>
<div id=mainBody>
<div>
<div>发布日期 : 8/17/2004<span> | </span>更新日期 : 8/17/2004</div>
<p>Microsoft</p>
<p>适用范围：<br>Windows Mobile&#8482; 2003 第二版软件<br>基于 Windows Mobile&#8482; 的 Pocket PC</p>
<p><strong>摘要：</strong>了解基于 Windows Mobile 的设备如何在横竖向模式下显示、该功能的后台情况、为该功能开发移动应用程序的相关信息、开发者指南中新的建议和示例。</p>
<p>请从 Microsoft 下载中心下载 <a id=ctl00_rs1_mainContentContainer_ctl01 onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl01',this);" href="http://download.microsoft.com/download/e/2/7/e279edc4-7513-45b0-bd5c-39d935a4a8ae/Windows%20Mobile%20Sample%20-%20Crossword.msi"><u><font color=#800080>Crossword.msi</font></u></a>。</p>
<h5>本页内容</h5>
<p><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#EWAA"><img alt=引言 src="http://msdn2.microsoft.com/zh-cn/library/ms839354.arrow_px_down(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#EWAA"><u><font color=#800080>引言</font></u></a> <br><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#ETAA"><img alt=更改屏幕方向 src="http://msdn2.microsoft.com/zh-cn/library/ms839354.arrow_px_down(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#ETAA"><u><font color=#800080>更改屏幕方向</font></u></a> <br><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#EQAA"><img alt=应用程序窗口如何识别屏幕方向 src="http://msdn2.microsoft.com/zh-cn/library/ms839354.arrow_px_down(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#EQAA"><u><font color=#800080>应用程序窗口如何识别屏幕方向</font></u></a> <br><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#ENAA"><img alt=刷新屏幕内容 src="http://msdn2.microsoft.com/zh-cn/library/ms839354.arrow_px_down(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#ENAA"><u><font color=#800080>刷新屏幕内容</font></u></a> <br><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#EKAA"><img alt=RelayoutDialog src="http://msdn2.microsoft.com/zh-cn/library/ms839354.arrow_px_down(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#EKAA"><u><font color=#800080>RelayoutDialog</font></u></a> <br><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#EHAA"><img alt=原有应用程序的特性 src="http://msdn2.microsoft.com/zh-cn/library/ms839354.arrow_px_down(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#EHAA"><u><font color=#800080>原有应用程序的特性</font></u></a> <br><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#EEAA"><img alt=安装警告消息 src="http://msdn2.microsoft.com/zh-cn/library/ms839354.arrow_px_down(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#EEAA"><u><font color=#800080>安装警告消息</font></u></a> <br><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#EBAA"><img alt=结论 src="http://msdn2.microsoft.com/zh-cn/library/ms839354.arrow_px_down(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#EBAA"><u><font color=#800080>结论</font></u></a> <br></p>
<h3 id=EWAA>引言</h3>
<p>Windows Mobile 2003 第二版软件为 Pocket PC 引入了新的功能，使基于 Windows Mobile 的设备可在横竖向两种模式下显示。在有些设备中，横向是默认的显示模式。此外，用户将能在使用中让屏幕在两种方向之间切换，而不必重新设置设备。</p>
<p>本文提供了有关该功能的后台信息、并介绍了开发适用于横竖向屏幕的移动应用程序的相关信息。此外，还向开发者提供了新的指南（包括一些建议和示例）供参考。</p>
<div><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#mainSection"><img alt="" src="http://msdn2.microsoft.com/zh-cn/library/ms839354.arrow_px_up(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#mainSection"><u><font color=#800080>返回页首</font></u></a> <br></div>
<h3 id=ETAA>更改屏幕方向</h3>
<p>通常，屏幕方向仅在用户使用&#8220;屏幕方向&#8221;控制面板，或按下某硬件按钮来旋转屏幕时才改变。</p>
<p>此外，应用程序也可通过 <strong>ChangeDisplaySettingsEx</strong> 函数以编程方式更改屏幕方向。该函数使用方法见 MSDN 中&#8220;Rotating the Content of the Screen&#8221;（旋转屏幕内容的方向）一文。例如，如果使用的应用程序只能在竖向模式下操作，则可通过编程改变屏幕方向。但是，如果屏幕方向的改变很突然，通过编程改变屏幕方向会让用户搞不清楚。应用程序应始终要求用户在旋转屏幕前确认显示模式。</p>
<p>为了在竖向模式下显示，将 <em>dmDisplayOrientation</em> 字段中的 <strong>DEVMODE</strong> 结构设置为 DMDO_0。对于右手横向模式，使用 DMDO_270。对于左手横向模式，使用 DMDO_90。</p>
<div><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#mainSection"><img alt="" src="http://msdn2.microsoft.com/zh-cn/library/ms839354.arrow_px_up(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#mainSection"><u><font color=#800080>返回页首</font></u></a> <br></div>
<h3 id=EQAA>应用程序窗口如何识别屏幕方向</h3>
<p>屏幕方向如果改变，或当&#8220;输入面板&#8221;出现时，应用程序的所有全屏顶层窗口都要适应新的取向。</p>
<p><strong>注意：</strong> <strong></strong>如果窗口的上、左、右坐标在工作区域边界之上或之外，该窗口被认为是全屏窗口。工作区域是标题栏下的整个屏幕区域。顶层窗口是无父窗口的窗口，即有一个 <strong>NULL</strong> 父窗口。</p>
<p>如果窗口大小改变，窗口将收到 <strong>WM_SIZE</strong> 通知。<strong>WM_SIZE</strong> 消息的 <em>lParam</em> 参数的低位字指定了客户端区域的新宽度，高位字指定了客户端区域的新高度。应用程序应识别窗口大小的改变，并相应地更新窗口布局。此外，也应重新确定所包含任何子窗口的布局。</p>
<p>如果应用程序没有全屏窗口，它收不到 <strong>WM_SIZE</strong> 通知。相反，它应在 <em>wParam</em> 参数设置为 <strong>SETTINGCHANGE_RESET</strong> 时监听 <strong>WM_SETTINGCHANGE</strong>消息。</p>
<p><strong>注意：</strong> 如果应用程序有顶层窗口，或使用 <strong>SHHandleWMSettingChange</strong>、<strong>SHInitDialog</strong> 和 <strong>SHFullScreen</strong> 方法创建了窗口，它会同时收到 <strong>WM_SIZE</strong> 和 <strong>WM_SETTINGCHANGE</strong> 消息。但是，如果应用程序创建了子窗口，子窗口收不到 <strong>WM_SIZE</strong> 消息，即使子窗口是全屏窗口。</p>
<p>以下 <strong>WindowProc</strong> 模板的代码示例利用了 <strong>WM_SIZE</strong> 和 <strong>WM_SETTINGCHANGE</strong> 消息。</p>
<pre>&nbsp;&nbsp;&nbsp;&nbsp;switch (uMessage)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case WM_SIZE:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 重新计算所有子窗口的布局；重新设置
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 列出视图和编辑框的大小，重新确定按钮、
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 静态文字和其他控件的位置。
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case WM_SETTINGCHANGE:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (SETTINGCHANGE_RESET == wParam) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 屏幕方向改变。此时
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 执行 WM_SIZE 不能执行的处理，
// 如重新调整全屏子窗口的大小，对
// 顶层窗口调用 MoveWindow 等等。
// 如果不需要处理 WM_SETTINGCHANGE 消息，可以
// 忽略它。
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
</pre>
<div><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#mainSection"><img alt="" src="http://msdn2.microsoft.com/zh-cn/library/ms839354.arrow_px_up(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#mainSection"><u><font color=#800080>返回页首</font></u></a> <br></div>
<h3 id=ENAA>刷新屏幕内容</h3>
<p>使用 Windows Mobile 2003 第二版软件时，Pocket PC 的最小显示区域是 240 个像素高和 240 个像素宽。编程人员应保证应用程序在最低配置下可用。常见问题是，菜单在竖向显示模式下可能符合要求，但在横向显示模式不符合要求。如果这样，需要在两个菜单之间重新排列菜单项。</p>
<p>刷新应用程序的屏幕内容时，可以使用下列 4 个编程选项： </p>
<ul>
    <li>
    <p>调整内容适应窗口大小 </p>
    <li>
    <p>更改内容 </p>
    <li>
    <p>更改布局 </p>
    <li>
    <p>设计所有布局通用的 240x240 正方形。</p>
    </li>
</ul>
<p><strong>表</strong> <strong>1</strong> 显示了各方法（调整内容适应窗口大小有两个示例）在 Pocket PC 的 Windows Mobile 软件中刷新屏幕内容的示例：</p>
<table>
    <strong>表 1：竖向图与横向图的屏幕刷新选项</strong>
    <tbody>
        <tr>
            <th>
            <p>屏幕刷新选项</p>
            </th>
            <th>
            <p>竖向</p>
            </th>
            <th>
            <p>横向</p>
            </th>
        </tr>
        <tr>
            <td>
            <p>调整内容适应窗口大小</p>
            <p>重新调整日历网格单元的大小以适用工作区域。</p>
            </td>
            <td>&nbsp;
            <p><img alt=screen_orientation_awareness01 src="http://msdn2.microsoft.com/zh-cn/library/ms839354.screen_orientation_awareness01(zh-cn,MSDN.10).gif"> </p>
            </td>
            <td>&nbsp;
            <p><img alt=screen_orientation_awareness02 src="http://msdn2.microsoft.com/zh-cn/library/ms839354.screen_orientation_awareness02(zh-cn,MSDN.10).gif"> </p>
            </td>
        </tr>
        <tr>
            <td>
            <p>调整内容适应窗口大小</p>
            <p>&#8220;内存&#8221;设置控制面板将列表框重新设置为最大尺寸，然后重新确定它四周所有界面元素的位置。</p>
            </td>
            <td>&nbsp;
            <p><img alt=screen_orientation_awareness03 src="http://msdn2.microsoft.com/zh-cn/library/ms839354.screen_orientation_awareness03(zh-cn,MSDN.10).gif"> </p>
            </td>
            <td>&nbsp;
            <p><img alt=screen_orientation_awareness04 src="http://msdn2.microsoft.com/zh-cn/library/ms839354.screen_orientation_awareness04(zh-cn,MSDN.10).gif"> </p>
            </td>
        </tr>
        <tr>
            <td>
            <p>更改内容。</p>
            <p>&#8220;日历&#8221;在横向显示模式下一次只显示 8 个月份。</p>
            </td>
            <td>&nbsp;
            <p><img alt=screen_orientation_awareness05 src="http://msdn2.microsoft.com/zh-cn/library/ms839354.screen_orientation_awareness05(zh-cn,MSDN.10).gif"> </p>
            </td>
            <td>&nbsp;
            <p><img alt=screen_orientation_awareness06 src="http://msdn2.microsoft.com/zh-cn/library/ms839354.screen_orientation_awareness06(zh-cn,MSDN.10).gif"> </p>
            </td>
        </tr>
        <tr>
            <td>
            <p>更改布局。</p>
            <p>在横向显示模式下，Windows Media Player 的按钮出现在视频内容的一侧，不是在下端。</p>
            </td>
            <td>&nbsp;
            <p><img alt=screen_orientation_awareness07 src="http://msdn2.microsoft.com/zh-cn/library/ms839354.screen_orientation_awareness07(zh-cn,MSDN.10).gif"> </p>
            </td>
            <td>&nbsp;
            <p><img alt=screen_orientation_awareness08 src="http://msdn2.microsoft.com/zh-cn/library/ms839354.screen_orientation_awareness08(zh-cn,MSDN.10).gif"> </p>
            </td>
        </tr>
        <tr>
            <td>
            <p>设计正方形。</p>
            <p>日历&#8220;选项&#8221;对话框的整个内容在两种取向模式下都显示在 240x240 的正方形区域内。</p>
            </td>
            <td>&nbsp;
            <p><img alt=screen_orientation_awareness09 src="http://msdn2.microsoft.com/zh-cn/library/ms839354.screen_orientation_awareness09(zh-cn,MSDN.10).gif"> </p>
            </td>
            <td>&nbsp;
            <p><img alt=screen_orientation_awareness10 src="http://msdn2.microsoft.com/zh-cn/library/ms839354.screen_orientation_awareness10(zh-cn,MSDN.10).gif"> </p>
            </td>
        </tr>
    </tbody>
</table>
<table>
    <tbody>
    </tbody>
</table>
<p>请记住，要尽可能的设计通用布局，这样应用程序可处理任意尺寸和任何宽高比的显示内容。这意味着尽可能避免分开设计横竖向模式。如果必须设计不同的横竖向布局模式，不要简单地因屏幕宽度大于屏幕高度，而假设应用程序能在横向模式下显示。例如，设备屏幕宽可能有 321 个像素，而屏幕高有 320 个像素。在这样的设备上，应用程序也许能以横竖向两种模式显示，应选择应用程序最适用或首选的模式，这可能是竖向模式。</p>
<div><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#mainSection"><img alt="" src="http://msdn2.microsoft.com/zh-cn/library/ms839354.arrow_px_up(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#mainSection"><u><font color=#800080>返回页首</font></u></a> <br></div>
<h3 id=EKAA>RelayoutDialog</h3>
<p>在 CrosswordSample 应用程序中，有一个函数是 <strong>RelayoutDialog</strong>，它可帮助重新设置、重新定位对话框中的子控件。例如，假设对话框有两个对话模板，一个用于横向，一个用于竖向。如果这两个模板中的控件相同，且有相同的控件 ID，则可使用下列代码作为 <strong>WM_SIZE</strong> 处理程序：</p>
<pre>case WM_SIZE:
RelayoutDialog(g_hInst, hDlg, InWideMode() ?
MAKEINTRESOURCE(IDD_TOOLS_OPTIONS_1_WIDE) :
MAKEINTRESOURCE(IDD_TOOLS_OPTIONS_1));
</pre>
<p><strong>注意：</strong> 定义为 <strong>IDC_STATIC</strong> 的控件具有相同的控件 ID，所以如果有多个 <strong>IDC_STATIC</strong>控件，应当把它们重命名为 <strong>IDC_STATIC_1</strong>、<strong>IDC_STATIC_2</strong>等。</p>
<p>如果静态控件在新布局中也发生了变换，<strong>RelayoutDialog</strong> 会同时更新静态控件的文本和位图。</p>
<div><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#mainSection"><img alt="" src="http://msdn2.microsoft.com/zh-cn/library/ms839354.arrow_px_up(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#mainSection"><u><font color=#800080>返回页首</font></u></a> <br></div>
<h3 id=EHAA>原有应用程序的特性</h3>
<p>当用户在基于 Windows Mobile 2003 第二版的 Pocket PC 上运行旧应用程序时，用户还保留了以往在竖向模式下的经验，但竖向模式与横向模式的经验将有所不同。在横向模式下，对话框的下半部分可能跑出屏幕底线之外。为了解决这个问题，系统将显示一个垂直滚动条，允许用户滚动屏幕。只有存在常出现于竖向屏幕底部的控件时，才出现垂直滚动条。如果不出现，则不出现滚动条。</p>
<p>应用程序是否是&#8220;原有&#8221;应用程序，取决于可执行文件头中的子系统版本。默认情况下，使用 Windows Mobile 2003 SDK 编译的应用程序中的子系统版本号为 4.20 或更低版本号，在将来版本的 Pocket PC SDK 中子系统版本号为 4.21 或更高版本号。子系统版本号为 4.20 或低于 4.20 时被认为是旧应用程序，可以看见滚动条。</p>
<p>知道了这种特性，用户就能通过滚动条看见隐藏的图像（假设不能直接看见的图像和控件）。此外，您仍可以使用这种技术快速存储或检索图像，但应在屏幕的左侧完成这项工作。</p>
<p>理想情况下，对话框不应需要滚动条。为此，最好的方法是：使对话框控件在竖向模式下不被&#8220;输入面板&#8221;覆盖，故最好设计 240x240 的最低分辨率。</p>
<div><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#mainSection"><img alt="" src="http://msdn2.microsoft.com/zh-cn/library/ms839354.arrow_px_up(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#mainSection"><u><font color=#800080>返回页首</font></u></a> <br></div>
<h3 id=EEAA>安装警告消息</h3>
<p>当在基于 Windows Mobile 的可旋转屏幕的 Pocket PC 上安装了旧应用程序时，将出现以下消息，如<strong>图</strong> <strong>11</strong> 所示：</p>
<p><img alt=screen_orientation_awareness11 src="http://msdn2.microsoft.com/zh-cn/library/ms839354.screen_orientation_awareness11(zh-cn,MSDN.10).gif"> </p>
<div><strong>图</strong> <strong>11</strong> <strong>：安装警告消息</strong> </div>
<p>这个对话告诉用户，他们要使用的应用程序程序可能无法识别正方形屏幕旋转，因此不能在横向模式下正确显示。只有 <strong>VersionMin</strong> 值（它指定应用程序支持的最低操作系统版本号）低于 4.21，才显示这个对话。</p>
<p>由于将 <strong>VersionMin</strong> 设置为 4.21 将阻止把应用程序安装在基于旧 Windows Mobile 的 Pocket PC 上，所以建议把<strong>BuildMax</strong> 值（不常用）设置为表 2 中的值，禁用此消息：</p>
<table>
    <strong>表 2：BuildMax 值</strong>
    <tbody>
        <tr>
            <th></th>
            <th></th>
        </tr>
        <tr>
            <td>
            <p>0xA0000000</p>
            </td>
            <td>
            <p>应用程序支持正方形屏幕（240x240 像素）。</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>0xC0000000</p>
            </td>
            <td>
            <p>应用程序支持屏幕旋转。</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>0xE0000000</p>
            </td>
            <td>
            <p>应用程序支持正方形屏幕旋转。</p>
            </td>
        </tr>
    </tbody>
</table>
<table>
    <tbody>
    </tbody>
</table>
<p>这些参数可通过编辑 INF 文件的 [CEDevice] 部分（cabwiz 用来生成 CAB 文件）来更改。有关 INF 文件格式的详细信息，请参阅 MSDN 文档。</p>
<div><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#mainSection"><img alt="" src="http://msdn2.microsoft.com/zh-cn/library/ms839354.arrow_px_up(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#mainSection"><u><font color=#800080>返回页首</font></u></a> <br></div>
<h3 id=EBAA>结论</h3>
<p>开发基于 Windows Mobile 2003 第二版软件的 Pocket PC 的应用程序，要求取消关于屏幕方向的假设。使用本文提供的简单指南，您可以编写安装和运行于竖向、横向和正方形屏幕上的应用程序。</p>
<p>&#160;</p>
<div><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#mainSection"><img alt=返回页首 src="http://msdn2.microsoft.com/zh-cn/library/ms839354.arrow_px_up(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839354.aspx#mainSection"><u><font color=#800080>返回页首</font></u></a> </div>
</div>
</div>
</div>
</div>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/41705.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-23 11:30 <a href="http://www.cppblog.com/gtwdaizi/articles/41705.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]Windows Mobile开发资源介绍</title><link>http://www.cppblog.com/gtwdaizi/articles/40697.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Tue, 08 Jan 2008 03:53:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/40697.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/40697.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/40697.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/40697.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/40697.html</trackback:ping><description><![CDATA[<p><font size=3><span>目前</span><span><font face=Calibri>Windows Mobile</font></span><span>的开发资源已经非常多了，我们在这里试着对这些资源进行一个归纳，使第一次进入</span><span><font face=Calibri>Windows Mobile</font></span><span>领域的开发者能够更容易得找到有用的开发资源。</span></font></p>
<h2><span><font face=Cambria>Windows Mobile</font></span><span>是什么</span></h2>
<p><font size=3><span><font face=Calibri>Windows Mobile</font></span><span>是微软为智能手机和</span><span><font face=Calibri>PDA</font></span><span>提供的操作系统，在</span><span><font face=Calibri>Windows Mobile 5.0</font></span><span>之前分为</span><span><font face=Calibri>Pocket PC</font></span><span>和</span><span><font face=Calibri>Smartphone</font></span><span>两种版本，</span><span><font face=Calibri>Pocket PC</font></span><span>中包括</span><span><font face=Calibri>PDA</font></span><span>版本和带电话功能的</span><span><font face=Calibri>Phone Edition</font></span><span>。在</span><span><font face=Calibri>Windows Mobile 6.0</font></span><span>中分为三类：</span><span><font face=Calibri>Professional</font></span><span>，即</span><span><font face=Calibri>Pocket PC Phone Edition; Standard, </font></span><span>即</span><span><font face=Calibri>Smartphone</font></span><span>；</span><span><font face=Calibri>Classic</font></span><span>，即无电话功能的</span><span><font face=Calibri>Pocket PC</font></span><span>。</span></font></p>
<p><font size=3><span><font face=Calibri>Windows Mobile</font></span><span>是基于</span><span><font face=Calibri>Windows CE</font></span><span>操作系统开发的针对智能手机和</span><span><font face=Calibri>PDA</font></span><span>的操作系统平台。所以</span><span><font face=Calibri>Windows Mobile</font></span><span>的硬件与应用程序都是由相关的标准要求，符合标准才能够运行</span><span><font face=Calibri>Windows Mobile</font></span><span>操作系统。</span></font></p>
<h2><span>获取开发工具</span></h2>
<p><font size=3><span>目前</span><span><font face=Calibri>Windows Mobile</font></span><span>的主流开发平台</span><span><font face=Calibri>/</font></span><span>语言分为两种：</span><span><font face=Calibri>.NET</font></span><span>（包括</span><span><font face=Calibri>C#</font></span><span>和</span><span><font face=Calibri>VB.NET</font></span><span>）和</span><span><font face=Calibri>C++</font></span><span>。微软已经将这两种开发语言的支持加入到</span><span><font face=Calibri>Visual Studio</font></span><span>中。</span><span><font face=Calibri>Visual Studio 2005</font></span><span>和</span><span><font face=Calibri>2008</font></span><span>均内置了</span><span><font face=Calibri>Windows Mobile</font></span><span>的</span><span><font face=Calibri>SDK</font></span><span>，可以直接开发</span><span><font face=Calibri>Windows Mobile</font></span><span>应用程序。</span><span><font face=Calibri>Visual Studio</font></span><span>也支持安装最新版本的</span><span><font face=Calibri>Windows Mobile SDK</font></span><span>。</span></font></p>
<p><font size=3><span>如果想用</span><span><font face=Calibri>Visual Studio</font></span><span>开发</span><span><font face=Calibri>Windows Mobile</font></span><span>应用程序的话，必须已经获取了</span><span><font face=Calibri>Visual Studio Professional</font></span><span>或以上版本。</span></font></p>
<p><font size=3><span>除了</span><span><font face=Calibri>Visual Studio</font></span><span>外，我们还可以使用免费的</span><span><font face=Calibri>eMbedded Visual C++ 4.0</font></span><span>来开发</span><span><font face=Calibri>C++</font></span><span>应用程序。在安装</span><span><font face=Calibri>SP4</font></span><span>版本后，可以支持基于</span><span><font face=Calibri>Windows CE 5.0</font></span><span>设备的应用开发（目前</span><span><font face=Calibri>Windows Mobile 5.0</font></span><span>和</span><span><font face=Calibri>6.0</font></span><span>均基于</span><span><font face=Calibri>Windows CE 5.0</font></span><span>）。下载地址如下：</span></font></p>
<p><span><a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=1DACDB3D-50D1-41B2-A107-FA75AE960856&amp;displaylang=en"><font face=Calibri color=#0000ff size=3>http://www.microsoft.com/downloads/details.aspx?FamilyId=1DACDB3D-50D1-41B2-A107-FA75AE960856&amp;displaylang=en</font></a></span></p>
<p><font size=3><span><font face=Calibri>eMbedded Visual C++ 4.0 SP4</font></span><span>下载地址：</span></font></p>
<p><span><a href="http://www.microsoft.com/downloads/details.aspx?familyid=4A4ED1F4-91D3-4DBE-986E-A812984318E5&amp;displaylang=en"><font face=Calibri color=#0000ff size=3>http://www.microsoft.com/downloads/details.aspx?familyid=4A4ED1F4-91D3-4DBE-986E-A812984318E5&amp;displaylang=en</font></a></span></p>
<p><font size=3><span>在安装完成开发工具后，还需要根据不同的目标设备安装不同版本的</span><span><font face=Calibri>Windows Mobile SDK</font></span><span>。我们可以在</span><span><font face=Calibri>MSDN</font></span><span>网站的下载中查询&#8220;</span><span><font face=Calibri>Windows Mobile x.0 SDK</font></span><span>&#8221;，或者直接去下面链接中查找：</span></font></p>
<p><span><a href="http://msdn2.microsoft.com/en-us/windowsmobile/bb264327.aspx"><font face=Calibri color=#0000ff size=3>http://msdn2.microsoft.com/en-us/windowsmobile/bb264327.aspx</font></a></span></p>
<p><font size=3><span>比如，</span><span><font face=Calibri>Windows Mobile 6.0 SDK</font></span><span>的下载地址：</span></font></p>
<p><span><a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=06111a3a-a651-4745-88ef-3d48091a390b&amp;DisplayLang=en"><font face=Calibri color=#0000ff size=3>http://www.microsoft.com/downloads/details.aspx?FamilyID=06111a3a-a651-4745-88ef-3d48091a390b&amp;DisplayLang=en</font></a></span></p>
<p><font size=3><span>如果要开发中文版的应用程序，还需要安装单独的本地化模拟器映像文件。</span><span><font face=Calibri>Windows Mobile 6.0</font></span><span>的语言映像文件下载链接如下：</span></font></p>
<p><span><a href="http://www.microsoft.com/downloads/details.aspx?familyid=38C46AA8-1DD7-426F-A913-4F370A65A582&amp;displaylang=en"><font face=Calibri color=#0000ff size=3>http://www.microsoft.com/downloads/details.aspx?familyid=38C46AA8-1DD7-426F-A913-4F370A65A582&amp;displaylang=en</font></a></span></p>
<p><font size=3><span>除此之外，我们还需要安装</span><span><font face=Calibri>ActiveSync 4.5</font></span><span>，来使开发环境与</span><span><font face=Calibri>Windows Mobile</font></span><span>设备相连接。在</span><span><font face=Calibri>Vista</font></span><span>中</span><span><font face=Calibri>Windows Mobile Device Center</font></span><span>与</span><span><font face=Calibri>ActiveSync</font></span><span>的功能相同。</span></font></p>
<p><font size=3><span>如果使用</span><span><font face=Calibri>.NET Compact Framework</font></span><span>来开发应用程序，还需要保证目标设备上安装了</span><span><font face=Calibri>.NET CF</font></span><span>的</span><span><font face=Calibri>CLR</font></span><span>，如果没有目标设备安装</span><span><font face=Calibri>.NET CF</font></span><span>，可以下载单独的</span><span><font face=Calibri>.NET CF</font></span><span>再发布包：</span></font></p>
<p><span><a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=9655156b-356b-4a2c-857c-e62f50ae9a55"><font face=Calibri color=#0000ff size=3>http://www.microsoft.com/downloads/details.aspx?FamilyID=9655156b-356b-4a2c-857c-e62f50ae9a55</font></a></span></p>
<h2><span>网络资源</span></h2>
<p><font size=3><span><font face=Calibri>Windows Mobile</font></span><span>开发中心</span></font></p>
<p><span><a href="http://msdn2.microsoft.com/en-us/windowsmobile/default.aspx"><font face=Calibri color=#0000ff size=3>http://msdn2.microsoft.com/en-us/windowsmobile/default.aspx</font></a></span></p>
<p><span><font face=Calibri size=3>&nbsp;</font></span></p>
<p><font size=3><span><font face=Calibri>Windows Mobile</font></span><span>产品主页</span></font></p>
<p><span><a href="http://www.microsoft.com/windowsmobile/"><font face=Calibri color=#0000ff size=3>http://www.microsoft.com/windowsmobile/</font></a></span></p>
<p><span><a href="http://www.microsoft.com/china/windowsmobile"><font face=Calibri color=#0000ff size=3>http://www.microsoft.com/china/windowsmobile</font></a></span></p>
<p><span><font face=Calibri size=3>&nbsp;</font></span></p>
<p><font size=3><span><font face=Calibri>Windows Mobile</font></span><span>移动解决方案联盟</span></font></p>
<p><span><a href="http://www.wmisv.com.cn/"><font face=Calibri color=#0000ff size=3>http://www.wmisv.com.cn/</font></a></span></p>
<p><span><font face=Calibri size=3>&nbsp;</font></span></p>
<p><span><font face=Calibri size=3>Pocket PC Developer Network</font></span></p>
<p><font size=3><span>老牌</span><span><font face=Calibri>Pocket PC</font></span><span>开发者网站，在</span><span><font face=Calibri>EVC</font></span><span>和</span><span><font face=Calibri>EVB</font></span><span>时代曾经是开发者唯一的选择，不过后来风头逐渐被</span><span><font face=Calibri>OpenNETCF</font></span><span>盖过，但目前依旧是最完整的开发文章目录</span></font></p>
<p><span><a href="http://www.pocketpcdn.com/"><font face=Calibri color=#0000ff size=3>http://www.pocketpcdn.com/</font></a></span></p>
<p><span><font face=Calibri size=3>&nbsp;</font></span></p>
<p><span><font face=Calibri size=3>Smartphone Developer Network</font></span></p>
<p><font size=3><span><font face=Calibri>Pocket PC Developer Network</font></span><span>的姊妹网站</span></font></p>
<p><span><a href="http://www.smartphonedn.com/"><font face=Calibri color=#0000ff size=3>http://www.smartphonedn.com/</font></a></span></p>
<p><span><font face=Calibri size=3>&nbsp;</font></span></p>
<p><span><font face=Calibri size=3>Code Project</font></span></p>
<p><font size=3><span>综合性开发者网站，其中</span><span><font face=Calibri>CE</font></span><span>开发和</span><span><font face=Calibri>.NET CF</font></span><span>开发部分由许多值得借鉴的示例代码</span></font></p>
<p><span><a href="http://www.codeproject.com/KB/mobile/"><font face=Calibri size=3>http://www.codeproject.com/KB/mobile/</font></a></span></p>
<p><span><font face=Calibri size=3>&nbsp;</font></span></p>
<p><span><font face=Calibri size=3>DEVBUZZ.COM</font></span></p>
<p><font size=3><span>老牌</span><span><font face=Calibri>Embedded Visual Basic</font></span><span>开发网站，转型</span><span><font face=Calibri>.NET CF</font></span><span>后，仍然有一些开发资源值的一看</span></font></p>
<p><span><a href="http://www.devbuzz.com/"><font face=Calibri color=#0000ff size=3>http://www.devbuzz.com/</font></a></span></p>
<h2><span>开发资源</span></h2>
<p><span><font face=Calibri size=3>OpenNETCF</font></span></p>
<p><font size=3><span>著名的开源类库，早先由多位</span><span><font face=Calibri>MVP</font></span><span>发起，进行公司化运作，后被</span><span><font face=Calibri>Novell</font></span><span>收购，先为咨询公司。</span><span><font face=Calibri>OpenNETCF</font></span><span>的最新版本仍可以免费使用，但不提供源代码。</span></font></p>
<p><span><a href="http://www.opennetcf.com/"><font face=Calibri size=3>http://www.opennetcf.com/</font></a></span></p>
<p><span><font face=Calibri size=3>&nbsp;</font></span></p>
<p><span><font face=Calibri size=3>InTheHand</font></span></p>
<p><font size=3><span>著名的开源类库，</span><span><font face=Calibri>32feet.NET</font></span><span>是以</span><span><font face=Calibri>Bluetooth</font></span><span>和</span><span><font face=Calibri>IrDA</font></span><span>开发为主的</span><span><font face=Calibri>Shared Source</font></span><span>类库。</span></font></p>
<p><span><a href="http://inthehand.net/"><font face=Calibri color=#0000ff size=3>http://inthehand.net/</font></a></span></p>
<p><span><font face=Calibri size=3>&nbsp;</font></span></p>
<p><span><font face=Calibri size=3>Mobile Line of Business Solution Accelerator</font></span></p>
<p><span><font size=3>由微软开发的一套移动商业软件开发指导包</font></span></p>
<p><span><a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=80A5C2C5-4F9B-4C1A-BFF6-2A3C6B68D15B&amp;displaylang=en"><font face=Calibri color=#0000ff size=3>http://www.microsoft.com/downloads/details.aspx?FamilyId=80A5C2C5-4F9B-4C1A-BFF6-2A3C6B68D15B&amp;displaylang=en</font></a></span></p>
<p><span><font face=Calibri size=3>&nbsp;</font></span></p>
<p><span><font face=Calibri size=3>Mobile Client Software Factory</font></span></p>
<p><font size=3><span>微软开发的一套软件工厂框架，将设计模式应用于</span><span><font face=Calibri>Mobile</font></span><span>软件开发</span></font></p>
<p><span><a href="http://msdn2.microsoft.com/en-us/library/aa480471.aspx"><font face=Calibri color=#0000ff size=3>http://msdn2.microsoft.com/en-us/library/aa480471.aspx</font></a></span></p>
<p><span><font size=3>下载地址：</font></span></p>
<p><span><a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=F9176708-9F57-4C0F-97FB-F9C65A9BBF22&amp;displaylang=en"><font face=Calibri color=#0000ff size=3>http://www.microsoft.com/downloads/details.aspx?FamilyID=F9176708-9F57-4C0F-97FB-F9C65A9BBF22&amp;displaylang=en</font></a></span></p>
<p><span><font face=Calibri size=3>&nbsp;</font></span></p>
<h2><span>开发社区</span></h2>
<p><span><font size=3>中文的开发论坛：</font></span></p>
<p><span><span><font size=3>l</font>&nbsp;</span></span><span><font size=3>微软移动开发者论坛</font></span></p>
<p><font size=3><span>微软的官方开发者论坛，目前的版主是微软最有价值专家（</span><span><font face=Calibri>MVP</font></span><span>）。</span></font></p>
<p><span><a href="http://forums.microsoft.com/china/default.aspx?ForumGroupID=459&amp;SiteID=15"><font face=Calibri color=#0000ff size=3>http://forums.microsoft.com/china/default.aspx?ForumGroupID=459&amp;SiteID=15</font></a></span></p>
<p><span><span><font size=3>l</font>&nbsp;</span></span><font size=3><span><font face=Calibri>CSDN</font></span><span>嵌入式开发论坛</span></font></p>
<p><font size=3><span>最大的开发者社区，硬件</span><span><font face=Calibri>/</font></span><span>嵌入式开发板块中包括&#8220;嵌入开发（</span><span><font face=Calibri>WinCE</font></span><span>）&#8221;板块和移动平台板块中包括&#8220;</span><span><font face=Calibri>Windows Mobile</font></span><span>&#8221;板块</span></font></p>
<p><span><a href="http://community.csdn.net/"><font face=Calibri size=3>http://community.csdn.net/</font></a></span></p>
<p><span><span><font size=3>l</font>&nbsp;</span></span><font size=3><span><font face=Calibri>Windows Mobile</font></span><span>开发者社区</span></font></p>
<p><font size=3><span><font face=Calibri>CSIP</font></span><span>创建的开发者讨论社区</span></font></p>
<p><span><a href="http://www.winbile.net/BBS/"><font face=Calibri color=#0000ff size=3>http://www.winbile.net/BBS/</font></a></span></p>
<p><span><span><font size=3>l</font>&nbsp;</span></span><font size=3><span>马宁的</span><span><font face=Calibri>Windows Mobile</font></span><span>开发研究</span></font></p>
<p><span><a href="http://groups.csdn.net/aawolf_Mobile"><font face=Calibri color=#0000ff size=3>http://groups.csdn.net/aawolf_Mobile</font></a></span></p>
<p><span><span><font size=3>l</font>&nbsp;</span></span><font size=3><span>博客园的</span><span><font face=Calibri>Windows Mobile</font></span><span>应用开发团队博客</span></font></p>
<p><span><font face=Calibri size=3>s</font><a href="http://mobiledev.cnblogs.com/"><font face=Calibri color=#0000ff size=3>http://mobiledev.cnblogs.com/</font></a></span></p>
<p><span><font face=Calibri size=3>&nbsp;</font></span></p>
<p><span><font size=3>英文论坛：</font></span></p>
<p><span><span><font size=3>l</font>&nbsp;</span></span><font size=3><span><font face=Calibri>MSDN</font></span><span>开发者社区：</span><span><font face=Calibri>Smart Device Development</font></span></font></p>
<p><span><a href="http://forums.microsoft.com/MSDN/default.aspx?ForumGroupID=11&amp;SiteID=1"><font face=Calibri color=#0000ff size=3>http://forums.microsoft.com/MSDN/default.aspx?ForumGroupID=11&amp;SiteID=1</font></a></span></p>
<h2><span><font face=Cambria>&nbsp;Webcast </font></span></h2>
<p><span><span><font size=3>l</font>&nbsp;</span></span><font size=3><span>中文</span><span><font face=Calibri>MSDN</font></span><span>与</span><span><font face=Calibri>TechNet Webcast</font></span></font></p>
<p><font size=3><span><font face=Calibri>Windows</font></span><span>移动开发系列课程</span></font></p>
<p><span><a href="http://www.microsoft.com/china/msdn/events/webcasts/shared/webcast/Series/WindowsMobile.aspx"><font face=Calibri color=#0000ff size=3>http://www.microsoft.com/china/msdn/events/webcasts/shared/webcast/Series/WindowsMobile.aspx</font></a></span></p>
<p><font size=3><span><font face=Calibri>Windows Mobile </font></span><span>技术开发黄金周</span></font></p>
<p><span><a href="http://www.microsoft.com/china/msdn/events/webcasts/shared/webcast/Series/Mobilegoldenweek.aspx"><font face=Calibri color=#0000ff size=3>http://www.microsoft.com/china/msdn/events/webcasts/shared/webcast/Series/Mobilegoldenweek.aspx</font></a></span></p>
<p><font size=3><span><font face=Calibri>Windows Mobile 2nd </font></span><span>开发黄金周</span></font></p>
<p><span><a href="http://www.microsoft.com/china/msdn/events/webcasts/shared/webcast/Series/Mobilegoldenweek2nd.aspx"><font face=Calibri color=#0000ff size=3>http://www.microsoft.com/china/msdn/events/webcasts/shared/webcast/Series/Mobilegoldenweek2nd.aspx</font></a></span></p>
<p><font size=3><span><font face=Calibri>Windows Mobile 3rd </font></span><span>技术开发黄金周</span></font></p>
<p><span><a href="http://www.microsoft.com/china/msdn/events/webcasts/shared/webcast/Series/mobile3rd.aspx"><font face=Calibri color=#0000ff size=3>http://www.microsoft.com/china/msdn/events/webcasts/shared/webcast/Series/mobile3rd.aspx</font></a></span></p>
<p><font size=3><span><font face=Calibri>TechNet Windows </font></span><span>移动系列课程</span></font></p>
<p><span><a href="http://www.microsoft.com/china/technet/webcasts/class/mobile.mspx"><font face=Calibri color=#0000ff size=3>http://www.microsoft.com/china/technet/webcasts/class/mobile.mspx</font></a></span></p>
<p><span><span><font size=3>l</font>&nbsp;</span></span><font size=3><span>英文</span><span><font face=Calibri>Webcast</font></span><span>和</span><span><font face=Calibri>Virtual Labs</font></span></font></p>
<p><span><font face=Calibri size=3>Windows Mobility Marvels</font></span></p>
<p><font size=3><span>主要针对的是</span><span><font face=Calibri>Windows Mobile</font></span><span>开发者，包括</span><span><font face=Calibri>Webcast</font></span><span>和</span><span><font face=Calibri>Virtual Labs</font></span></font></p>
<p><span><a href="http://www.microsoft.com/events/series/msdnmobility.aspx"><font face=Calibri color=#0000ff size=3>http://www.microsoft.com/events/series/msdnmobility.aspx</font></a></span></p>
<p><font size=3><span><font face=Calibri>Windows Mobility Marvels</font></span><span>部分课程下载</span></font></p>
<p><span><a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=08e4391d-e07d-41fe-b2b8-aa4225281347&amp;DisplayLang=en"><font face=Calibri color=#0000ff size=3>http://www.microsoft.com/downloads/details.aspx?FamilyID=08e4391d-e07d-41fe-b2b8-aa4225281347&amp;DisplayLang=en</font></a></span></p>
<p><span><font face=Calibri size=3>&nbsp;</font></span></p>
<p><span><font face=Calibri size=3>Windows Mobile Solutions</font></span></p>
<p><font size=3><span>针对</span><span><font face=Calibri>IT Pro</font></span><span>和</span><span><font face=Calibri>Windows Mobile</font></span><span>用户的</span><span><font face=Calibri>Webcast</font></span><span>系列</span></font></p>
<p><span><a href="http://www.microsoft.com/events/series/msecmobility.aspx"><font face=Calibri color=#0000ff size=3>http://www.microsoft.com/events/series/msecmobility.aspx</font></a></span></p>
<h2><span><font face=Cambria>BLOG</font></span></h2>
<p><span><span><font size=3>l</font>&nbsp;</span></span><font size=3><span><font face=Calibri>Windows Mobile</font></span><span>产品组英文</span><span><font face=Calibri>BLOG</font></span></font></p>
<p><span><font face=Calibri size=3>Windows Mobile Team Blog</font></span></p>
<p><span><a href="http://blogs.msdn.com/windowsmobile/"><font face=Calibri color=#0000ff size=3>http://blogs.msdn.com/windowsmobile/</font></a></span></p>
<p><span><font face=Calibri size=3>.NET Compact Framework Team Blog</font></span></p>
<p><span><a href="http://blogs.msdn.com/netcfteam/"><font face=Calibri color=#0000ff size=3>http://blogs.msdn.com/netcfteam/</font></a></span></p>
<p><span><font face=Calibri size=3>Visual Studio For Device</font></span></p>
<p><span><a href="http://blogs.msdn.com/vsdteam/"><font face=Calibri color=#0000ff size=3>http://blogs.msdn.com/vsdteam/</font></a></span></p>
<p><span><font face=Calibri size=3>SQL Server Compact</font></span></p>
<p><span><a href="http://blogs.msdn.com/SQLServerCompact/"><font face=Calibri color=#0000ff size=3>http://blogs.msdn.com/SQLServerCompact/</font></a></span></p>
<p><span><font face=Calibri size=3>&nbsp;</font></span></p>
<p><span><span><font size=3>l</font>&nbsp;</span></span><font size=3><span>产品组成员</span><span><font face=Calibri>BLOG</font></span></font></p>
<p><font size=3><span><font face=Calibri>Mike Hall</font></span><span>的</span><span><font face=Calibri>BLOG</font></span></font></p>
<p><span><a href="http://blogs.msdn.com/mikehall/"><font face=Calibri color=#0000ff size=3>http://blogs.msdn.com/mikehall/</font></a></span></p>
<p><span><font face=Calibri size=3>Rob Tiffany's Windows Mobile Accelerator</font></span></p>
<p><font size=3><span>主要研究领域为</span><span><font face=Calibri>SQL CE</font></span><span>和</span><span><font face=Calibri>BOL Accelerator</font></span></font></p>
<p><span><a href="http://blogs.msdn.com/robtiffany/"><font face=Calibri color=#0000ff size=3>http://blogs.msdn.com/robtiffany/</font></a></span></p>
<p><span><font face=Calibri size=3>David Kline</font></span></p>
<p><font size=3><span><font face=Calibri>.NET Compact Framework</font></span><span>应用领域</span></font></p>
<p><span><a href="http://blogs.msdn.com/davidklinems/"><font face=Calibri color=#0000ff size=3>http://blogs.msdn.com/davidklinems/</font></a></span></p>
<p><span><font face=Calibri size=3>Steve Lasker's Web Log</font></span></p>
<p><font size=3><span><font face=Calibri>SQL CE</font></span><span>和</span><span><font face=Calibri>Sync Service for ADO.NET</font></span></font></p>
<p><span><a href="http://blogs.msdn.com/stevelasker/"><font face=Calibri color=#0000ff size=3>http://blogs.msdn.com/stevelasker/</font></a></span></p>
<p><span><font face=Calibri size=3>Steven Pratschner's .Net CF WebLog</font></span></p>
<p><font size=3><span><font face=Calibri>.NET Compact Framework CLR</font></span><span>运行机制</span></font></p>
<p><span><a href="http://blogs.msdn.com/stevenpr/"><font face=Calibri color=#0000ff size=3>http://blogs.msdn.com/stevenpr/</font></a></span></p>
<p><span><font face=Calibri size=3>&nbsp;</font></span></p>
<p><span><span><font size=3>l</font>&nbsp;</span></span><font size=3><span>英文开发者</span><span><font face=Calibri>BLOG</font></span></font></p>
<p><span><font face=Calibri size=3>OpenNETCF Blogs</font></span></p>
<p><font size=3><span>以开发</span><span><font face=Calibri>OpenNETCF</font></span><span>开源类库闻名的公司，拥有多位重量级</span><span><font face=Calibri>MVP</font></span><span>的</span><span><font face=Calibri>BLOG</font></span></font></p>
<p><span><a href="http://blog.opennetcf.org/"><font face=Calibri color=#0000ff size=3>http://blog.opennetcf.org/</font></a></span></p>
<p><span><font face=Calibri size=3>In the hand Blogs</font></span></p>
<p><font size=3><span>另一个以开发</span><span><font face=Calibri>InTheHand</font></span><span>开源类库闻名的开发者</span><span><font face=Calibri>BLOG</font></span></font></p>
<p><span><a href="http://inthehand.net/blogs/"><font face=Calibri color=#0000ff size=3>http://inthehand.net/blogs/</font></a></span></p>
<p><span><font face=Calibri size=3>&nbsp;</font></span></p>
<p><span><span><font size=3>l</font>&nbsp;</span></span><font size=3><span>中文开发者</span><span><font face=Calibri>BLOG</font></span></font></p>
<p><font size=3><span>马宁的移动开发</span><span><font face=Calibri>BLOG</font></span></font></p>
<p><span><a href="http://blog.csdn.net/aawolf"><font face=Calibri size=3>http://blog.csdn.net/aawolf</font></a></span></p>
<p><font size=3><span>张欣的</span><span><font face=Calibri>BLOG</font></span></font></p>
<p><span><a href="http://twodays.cnblogs.com/"><font face=Calibri color=#0000ff size=3>http://twodays.cnblogs.com/</font></a></span></p>
<p><font size=3><span>黎波的</span><span><font face=Calibri>BLOG</font></span></font></p>
<p><span><a href="http://www.cnblogs.com/upto/"><font face=Calibri color=#0000ff size=3>http://www.cnblogs.com/upto/</font></a></span></p>
<p><span><font face=Calibri size=3>&nbsp;</font></span></p>
<h2><span>开发图书</span></h2>
<h2><span><a href="http://www.amazon.com/gp/reader/0735624178/ref=sib_dp_pt/103-3824260-4233467#reader-link"><img id=prodImage onmouseover="sitb_showLayer('bookpopover'); return false;" onmouseout="sitb_doHide('bookpopover'); return false;" height=240 alt="Programming Windows&#194;&#174; Embedded CE 6.0 Developer Reference (PRO-Developer)" src="http://ecx.images-amazon.com/images/I/41v8ebqpiBL._BO2,204,203,200_PIsitb-dp-500-arrow,TopRight,45,-64_OU01_AA240_SH20_.jpg" width=240 border=0></a></span></h2>
<p><span><a href="http://www.amazon.com/gp/product/images/0735624178/ref=dp_image_0/103-8143305-4291852?ie=UTF8&amp;n=283155&amp;s=books" target=AmazonHelp><span><font size=5></font></span></a></span></p>
<p><strong><span><font size=3>Programming Windows&#174; Embedded CE 6.0 Developer Reference</font></span></strong></p>
<p><font size=3><span>作者：</span><span><font face=Calibri>Douglas Boling</font></span></font></p>
<p><font size=3><span>出版社</span><span><font face=Calibri>: Microsoft Press; 4 edition (October 10, 2007) </font></span></font></p>
<p><font size=3><span>语言</span><span><font face=Calibri>: English </font></span></font></p>
<p><span><font face=Calibri size=3>ISBN-10: 0735624178</font></span></p>
<p><span><font face=Calibri size=3>&nbsp;</font></span></p>
<p><span>
<table cellSpacing=0 cellPadding=0 width=240 border=0>
    <tbody>
        <tr>
            <td id=prodImageCell width=240 height=240><a onclick="return amz_js_PopWin(this.href,'AmazonHelp','width=700,height=600,resizable=1,scrollbars=1,toolbar=0,status=1');" href="http://www.amazon.com/gp/product/images/0321174038/ref=dp_image_0/103-3824260-4233467?ie=UTF8&amp;n=283155&amp;s=books" target=AmazonHelp><img id=prodImage height=240 alt=".NET Compact Framework Programming with C# (Microsoft .NET Development Series)" src="http://ecx.images-amazon.com/images/I/519cg1grVjL._AA240_.jpg" width=240 border=0></a></td>
        </tr>
        <tr>
            <td>&nbsp;</td>
        </tr>
    </tbody>
</table>
</span></p>
<p><span><a href="http://www.amazon.com/gp/product/images/0321174038/sr=8-3/qid=1196919912/ref=dp_image_0/103-8143305-4291852?ie=UTF8&amp;n=283155&amp;s=books&amp;qid=1196919912&amp;sr=8-3" target=AmazonHelp><span><font size=3><font face=Calibri></font></font></span></a></span></p>
<p><strong><span><font size=3>.NET Compact Framework Programming with C#</font></span></strong></p>
<p><span><font face=Calibri size=3>Paul Yao , David Durant</font></span></p>
<p><font size=3><span>出版社</span><span><font face=Calibri>: Addison-Wesley Professional (June 3, 2004) </font></span></font></p>
<p><font size=3><span>语言</span><span><font face=Calibri>: English </font></span></font></p>
<p><span><font face=Calibri size=3>ISBN-10: 0321174038</font></span></p>
<p><span><font face=Calibri size=3>&nbsp;
<table cellSpacing=0 cellPadding=0 width=240 border=0>
    <tbody>
        <tr>
            <td id=prodImageCell width=240 height=240><a href="http://www.amazon.com/gp/reader/0735623589/ref=sib_dp_pt/103-3824260-4233467#reader-link"><img id=prodImage onmouseover="sitb_showLayer('bookpopover'); return false;" onmouseout="sitb_doHide('bookpopover'); return false;" height=240 alt="Microsoft&#174; Mobile Development Handbook" src="http://ecx.images-amazon.com/images/I/41ZYn2WdtIL._BO2,204,203,200_PIsitb-dp-500-arrow,TopRight,45,-64_OU01_AA240_SH20_.jpg" width=240 border=0></a></td>
        </tr>
        <tr>
            <td>&nbsp;</td>
        </tr>
    </tbody>
</table>
</font></span></p>
<p><span><a href="http://www.amazon.com/gp/product/images/0735623589/sr=8-1/qid=1196919912/ref=dp_image_0/103-8143305-4291852?ie=UTF8&amp;n=283155&amp;s=books&amp;qid=1196919912&amp;sr=8-1" target=AmazonHelp><span><font size=3><font face=Calibri></font></font></span></a></span></p>
<p><strong><span><font size=3></font></span></strong></p>
<p><strong><span><font size=3>Microsoft Mobile Development Handbook</font></span></strong></p>
<p><font size=3><span>作者：</span><span><font face=Calibri>Andy Wigley, Daniel Moth, Peter Foot</font></span></font></p>
<p><font size=3><span>出版社</span><span><font face=Calibri>: Microsoft Press (May 30, 2007) </font></span></font></p>
<p><font size=3><span>语言</span><span><font face=Calibri>: English </font></span></font></p>
<p><span><font face=Calibri size=3>ISBN-10: 0735623589</font></span></p>
<p><span><font face=Calibri size=3>&nbsp;</font></span></p>
<p><span><a href="http://www.amazon.com/gp/reader/0735617252/ref=sib_dp_pt/103-8143305-4291852#reader-link"><span><font size=3><font face=Calibri></font></font></span></a></span></p>
<p><strong><span><font size=3>
<table cellSpacing=0 cellPadding=0 width=240 border=0>
    <tbody>
        <tr>
            <td id=prodImageCell width=240 height=240><a href="http://www.amazon.com/gp/reader/0735617252/ref=sib_dp_pt/103-3824260-4233467#reader-link"><img id=prodImage onmouseover="sitb_showLayer('bookpopover'); return false;" onmouseout="sitb_doHide('bookpopover'); return false;" height=240 alt="Microsoft .NET Compact Framework (Core Reference)" src="http://ecx.images-amazon.com/images/I/41CD702K7YL._BO2,204,203,200_PIsitb-dp-500-arrow,TopRight,45,-64_OU01_AA240_SH20_.jpg" width=240 border=0></a></td>
        </tr>
        <tr>
            <td>&nbsp;<span id=prodImageCaption><br></span></td>
        </tr>
    </tbody>
</table>
</font></span></strong></p>
<p><strong><span><font size=3>Microsoft .NET Compact Framework (Core Reference)</font></span></strong></p>
<p><font size=3><span>作者：</span><span><font face=Calibri>Andy Wigley, Stephen Wheelwright, Robert Burbidge, Rory MacLoed, Mark Sutton</font></span></font></p>
<p><font size=3><span>出版社</span><span><font face=Calibri>: Microsoft Press; 1 edition (January 22, 2003) </font></span></font></p>
<p><font size=3><span>语言</span><span><font face=Calibri>: English </font></span></font></p>
<p><span><font face=Calibri size=3>ISBN-10: 0735617252</font></span></p>
<p><span><font face=Calibri size=3>&nbsp;</font></span></p>
<p><span><a href="javascript:moreup(14775,%22Microsoft%20.NET%20Compact%20Framework技术内幕%22,9)"><span><font size=3><font face=Calibri></font></font></span></a></span></p>
<p><font size=3><span><a href='javascript:moreup(14775,"Microsoft .NET Compact Framework技术内幕",9)' href_cetemp='javascript:moreup(14775,"Microsoft .NET Compact Framework技术内幕",9)'><strong><img alt="Microsoft .NET Compact Framework技术内幕" onerror=jp.oe(this); src="http://images.china-pub.com/ebook10000-15000/14775/zcover.jpg" onload=jp.w(this); border=0 s="1" mysrc="/ebook10000-15000/14775" n="-1"></strong>&nbsp;</a></span></font></p>
<p><font size=3><strong><span>Microsoft .NET Compact Framework</span></strong><strong><span>技术内幕</span></strong><strong></strong></font></p>
<p><font size=3><span>原</span><font face=Calibri> </font><span>书</span><font face=Calibri> </font><span>名：</span><span><font face=Calibri> Microsoft .NET Compact Framework&nbsp;</font></span></font></p>
<p><font size=3><span>原出版社：</span><span><font face=Calibri> Microsoft Press&nbsp;</font></span></font></p>
<p><font size=3><span>作</span><font face=Calibri> </font><span>者：</span><span><font face=Calibri>Andy Wigley,Stephen Wheelwright&nbsp;</font></span></font></p>
<p><font size=3><span>译</span><font face=Calibri> </font><span>者：</span><font face=Calibri> </font><span>罗兵</span><font face=Calibri> </font><span>徐雅骥</span><font face=Calibri> </font><span>江楠</span><span><span><font face=Calibri>&nbsp; </font></span></span></font></p>
<p><font size=3><span>出</span><font face=Calibri> </font><span>版</span><font face=Calibri> </font><span>社：</span><font face=Calibri> </font><span>清华大学出版社</span></font></p>
<p><font size=3><span>书</span><font face=Calibri> </font><span>号：</span><span><font face=Calibri> 7302072280&nbsp;</font></span></font></p>
<p><font size=3><span>出版日期：</span><span><font face=Calibri> 2003 </font></span><span>年</span><span><font face=Calibri>9</font></span><span>月</span></font></p>
<p><span><font face=Calibri size=3>&nbsp;</font></span></p>
<p><span><font face=Calibri size=3>&nbsp;<a href='javascript:moreup(32836,".NET Compact Framework移动开发指南",9)' href_cetemp='javascript:moreup(32836,".NET Compact Framework移动开发指南",9)'><img alt=".NET Compact Framework移动开发指南" onerror=jp.oe(this); src="http://images.china-pub.com/ebook30001-35000/32836/zcover.jpg" onload=jp.w(this); border=0 s="1" mysrc="/ebook30001-35000/32836" n="-1">&nbsp;</a></font></span><span><font face=Calibri size=3>&nbsp;</font></span></p>
<p><span><font face=Calibri size=3>&nbsp;</font></span></p>
<p><span><a href="javascript:moreup(32836,%22.NET%20Compact%20Framework移动开发指南%22,9)"><span><font size=3><font face=Calibri></font></font></span></a></span></p>
<p><font size=3><strong><span>.NET Compact Framework</span></strong><strong><span>移动开发指南</span></strong><strong></strong></font></p>
<p><font size=3><span>作</span><font face=Calibri> </font><span>者：颜友宁</span><font face=Calibri> </font></font></p>
<p><font size=3><span>出</span><font face=Calibri> </font><span>版</span><font face=Calibri> </font><span>社：清华大学出版社</span><font face=Calibri> </font><span>北京科海电子出版社</span></font></p>
<p><font size=3><span>书</span><font face=Calibri> </font><span>号：</span><span><font face=Calibri> 7302140855&nbsp;</font></span></font></p>
<p><font size=3><span>出版日期：</span><span><font face=Calibri> 2006 </font></span><span>年</span><span><font face=Calibri>11</font></span><span>月</span></font></p>
<p><span><font face=Calibri size=3>&nbsp;</font></span></p>
<p><span><a href='javascript:moreup(30739,%22.NET精简框架程序设计：C#版",9)' href_cetemp='javascript:moreup(30739,%22.NET精简框架程序设计：C#版",9)'><span><font size=3><font face=Calibri></font></font></span></a></span></p>
<p><font size=3><span><a href='javascript:moreup(30739,".NET精简框架程序设计：C#版",9)' href_cetemp='javascript:moreup(30739,".NET精简框架程序设计：C#版",9)'><strong><img alt=.NET精简框架程序设计：C#版 onerror=jp.oe(this); src="http://images.china-pub.com/ebook30001-35000/30739/zcover.jpg" onload=jp.w(this); border=0 s="1" mysrc="/ebook30001-35000/30739" n="-1"></strong>&nbsp;</a></span></font></p>
<p><font size=3><strong><span>.NET</span></strong><strong><span>精简框架程序设计：</span></strong><strong><span>C#</span></strong><strong><span>版</span></strong><strong></strong></font></p>
<p><font size=3><span>原</span><font face=Calibri> </font><span>书</span><font face=Calibri> </font><span>名：</span><span><font face=Calibri> .NET Compact Framework Programming with C#&nbsp;</font></span></font></p>
<p><font size=3><span>原出版社：</span><span><font face=Calibri> Addison-Wesley/Pearson&nbsp;</font></span></font></p>
<p><font size=3><span>作</span><font face=Calibri> </font><span>者：（美）</span><span><font face=Calibri>Paul Yao,David Durant</font></span></font></p>
<p><font size=3><span>译</span><font face=Calibri> </font><span>者：</span><font face=Calibri> </font><span>刘新军</span><font face=Calibri> </font><span>盛泉</span><font face=Calibri> </font><span>李辛鹤</span><span><span><font face=Calibri>&nbsp; </font></span></span></font></p>
<p><font size=3><span>出</span><font face=Calibri> </font><span>版</span><font face=Calibri> </font><span>社：</span><font face=Calibri> </font><span>电子工业出版社</span></font></p>
<p><font size=3><span>书</span><font face=Calibri> </font><span>号：</span><span><font face=Calibri> 712102716X&nbsp;</font></span></font></p>
<p><font size=3><span>出版日期：</span><span><font face=Calibri> 2006 </font></span><span>年</span><span><font face=Calibri>6</font></span><span>月</span></font></p>
<p><span><font face=Calibri size=3>&nbsp;</font></span></p>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/40697.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-08 11:53 <a href="http://www.cppblog.com/gtwdaizi/articles/40697.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows Mobile中如何建立GPRS连接以便Socket能正常通信</title><link>http://www.cppblog.com/gtwdaizi/articles/39578.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Tue, 25 Dec 2007 06:51:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/39578.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/39578.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/39578.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/39578.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/39578.html</trackback:ping><description><![CDATA[<span>&nbsp;
<p><span>【版<span><span>&nbsp;&nbsp; </span></span>本】</span></p>
<p><st1:chsdate year="1899" month="12" day="30" islunardate="False" isrocdate="False" w:st="on"><span>1.0.0</span></st1:chsdate></p>
<p><span>【操作系统】</span></p>
<p><span>Windows Mobile 5.0</span></p>
<p><span>【作<span><span>&nbsp;&nbsp; </span></span>者】</span></p>
<p><span>谢红伟&#183;<span>chrys </span>&#183;<span><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#99;&#104;&#114;&#121;&#115;&#64;&#49;&#54;&#51;&#46;&#99;&#111;&#109;">chrys@163.com</a> </span>&#183;<span><a href="http://www.howa.com.cn/">http://www.howa.com.cn</a></span></span></p>
<p><span>【开发日期】</span></p>
<p><span>2007-12-11 01:23:56</span></p>
<p>&#160;</p>
<p><font size=3><span>最近编写一个医疗项目的程序，需要用</span><span><font face="Times New Roman"> Windows Mobile </font></span><span>来做通信处理，需要将手机端的数据通过</span><span><font face="Times New Roman">GPRS</font></span><span>传送至公网上的一个服务器上。数据传输我采用的是</span><span><font face="Times New Roman">socket</font></span><span>，用数据线</span><span><font face="Times New Roman">+ActiveSync</font></span><span>调试通过，数据传输正常，在准备将软件提交给质检部门的时候，用真正的</span><span><font face="Times New Roman">GPRS</font></span><span>来做通信测试时，问题出来了，连接始终建立不了，但用手机的</span><span><font face="Times New Roman">IE</font></span><span>浏览器却能正常打开网页，而且奇怪的是只要用</span><span><font face="Times New Roman">IE</font></span><span>浏览器成功访问过一次网页，我的</span><span><font face="Times New Roman"> socket </font></span><span>就能正常进行数据通信，看来传说中的</span><span><font face="Times New Roman">GPRS</font></span><span>常连接被我误解了。</span></font></p>
<p><font size=3><span>手机开通</span><span><font face="Times New Roman">GPRS</font></span><span>以后，我们的</span><span><font face="Times New Roman">socket </font></span><span>程序还不能直接建立网络连接，需要用连接管理器来获取当前可用连接，并自动选择一个最佳的连接途径，然后启用这个连接，在连接启动成功以后再用</span><span><font face="Times New Roman">socket </font></span><span>进行网络连接方可正常进行。大概</span><span><font face="Times New Roman">GPRS</font></span><span>拨号和连接过程就是在这里自动进行的吧。源代码中封装了一个连接管理的类和测试代码，可以清楚地看到</span><span><font face="Times New Roman">Windows Mobile </font></span><span>在</span><span><font face="Times New Roman">socket </font></span><span>编程之前到底需要做什么样的操作。</span></font></p>
<p><span><font face="Times New Roman" size=3>&nbsp;</font></span></p>
<p><span><font size=3>首先需要枚举当前可用的连接</font></span></p>
<p><span><font size=3><font face="Times New Roman">void CConnectManager::EnumNetIdentifier ( OUT CStringArray &amp;StrAry )</font></font></span></p>
<p><span><font size=3><font face="Times New Roman">{</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>CONNMGR_DESTINATION_INFO networkDestInfo = {0};</font></font></span></p>
<p><span><font face="Times New Roman" size=3>&nbsp;</font></span></p>
<p><font size=3><span><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>// </font></span><span>得到网络列表</span></font></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>for ( DWORD dwEnumIndex=0; ; dwEnumIndex++ )</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>memset ( &amp;networkDestInfo, 0, sizeof(CONNMGR_DESTINATION_INFO) );</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if ( ConnMgrEnumDestinations ( dwEnumIndex, &amp;networkDestInfo ) == E_FAIL )</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>break;</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>StrAry.Add ( networkDestInfo.szDescription );</font></font></span></p>
<p><span><font face="Times New Roman"><font size=3><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</font></font></span></p>
<p><span><font face="Times New Roman"><font size=3>}</font></font></span></p>
<p><span><font face="Times New Roman" size=3>&nbsp;</font></span></p>
<p><font size=3><span>接下来找到&#8220;</span><span><font face="Times New Roman">Internet</font></span><span>&#8221;这个连接，可用远程</span><span><font face="Times New Roman">URL</font></span><span>映射的方式来完成，这样可以让系统自动选取一个最好的连接。</span></font></p>
<p><span><font size=3><font face="Times New Roman">int CConnectManager::MapURLAndGUID ( LPCTSTR lpszURL, OUT GUID &amp;guidNetworkObject, OUT CString *pcsDesc/*=NULL*/ )</font></font></span></p>
<p><span><font size=3><font face="Times New Roman">{</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if ( !lpszURL || lstrlen(lpszURL) &lt; 1 )</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return FALSE;</font></font></span></p>
<p><span><font face="Times New Roman" size=3>&nbsp;</font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>memset ( &amp;guidNetworkObject, 0, sizeof(GUID) );</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>int nIndex = 0;</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>HRESULT hResult = ConnMgrMapURL ( lpszURL, &amp;guidNetworkObject, (DWORD*)&amp;nIndex );</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if ( FAILED(hResult) )</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>nIndex = -1;</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>DWORD dwLastError = GetLastError ();</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>AfxMessageBox ( _T("Could not map a request to a network identifier") );</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>else</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if ( pcsDesc )</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>CONNMGR_DESTINATION_INFO DestInfo = {0};</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if ( SUCCEEDED(ConnMgrEnumDestinations(nIndex, &amp;DestInfo)) )</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>*pcsDesc = DestInfo.szDescription;</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</font></font></span></p>
<p><span><font face="Times New Roman" size=3>&nbsp;</font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return nIndex;</font></font></span></p>
<p><span><font size=3><font face="Times New Roman">}</font></font></span></p>
<p><span><font face="Times New Roman" size=3>&nbsp;</font></span></p>
<p><span><font size=3>以下代码是用来启用指定编号的连接</font></span></p>
<p><span><font size=3><font face="Times New Roman">BOOL CConnectManager::EstablishConnection ( DWORD dwIndex )</font></font></span></p>
<p><span><font size=3><font face="Times New Roman">{</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ReleaseConnection ();</font></font></span></p>
<p><span><font face="Times New Roman" size=3>&nbsp;</font></span></p>
<p><font size=3><span><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>// </font></span><span>得到正确的连接信息</span></font></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>CONNMGR_DESTINATION_INFO DestInfo = {0};</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>HRESULT hResult = ConnMgrEnumDestinations(dwIndex, &amp;DestInfo);</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>BOOL bRet = FALSE;</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if(SUCCEEDED(hResult))</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</font></font></span></p>
<p><font size=3><span><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>// </font></span><span>初始化连接结构</span></font></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>CONNMGR_CONNECTIONINFO ConnInfo;</font></font></span></p>
<p><span><font face="Times New Roman" size=3>&nbsp;</font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ZeroMemory(&amp;ConnInfo, sizeof(ConnInfo));</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ConnInfo.cbSize = sizeof(ConnInfo);</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ConnInfo.dwParams = CONNMGR_PARAM_GUIDDESTNET;</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ConnInfo.dwFlags = CONNMGR_FLAG_PROXY_HTTP | CONNMGR_FLAG_PROXY_WAP | CONNMGR_FLAG_PROXY_SOCKS4 | CONNMGR_FLAG_PROXY_SOCKS5;</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ConnInfo.dwPriority = CONNMGR_PRIORITY_USERINTERACTIVE;</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ConnInfo.guidDestNet = DestInfo.guid;</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ConnInfo.bExclusive<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>= FALSE; </font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ConnInfo.bDisabled = FALSE;</font></font></span></p>
<p><span><font face="Times New Roman" size=3>&nbsp;</font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>DWORD dwStatus = 0;</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>hResult = ConnMgrEstablishConnectionSync(&amp;ConnInfo, &amp;m_hConnection, 10*1000, &amp;dwStatus );</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if(FAILED(hResult))</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>m_hConnection = NULL;</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>else bRet = TRUE;</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</font></font></span></p>
<p><span><font face="Times New Roman" size=3>&nbsp;</font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return bRet;</font></font></span></p>
<p><span><font size=3><font face="Times New Roman">}</font></font></span></p>
<p><span><font face="Times New Roman" size=3>&nbsp;</font></span></p>
<p><span><font size=3>为了确保连接是否真正可用，需要检测连接状态，在规定的时间内如果未取得&#8220;连接成功&#8221;的状态，则认为连接未能正常启用，可能需要配置手机的连接管理器界面</font></span></p>
<p><span><font size=3><font face="Times New Roman">BOOL CConnectManager::WaitForConnected ( int nTimeoutSec, DWORD *pdwStatus/*=NULL*/ )</font></font></span></p>
<p><span><font size=3><font face="Times New Roman">{</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>DWORD dwStartTime = GetTickCount ();</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>BOOL bRet = FALSE;</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>while ( GetTickCount ()-dwStartTime &lt; (DWORD)nTimeoutSec * 1000 )</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if ( m_hConnection )</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>DWORD dwStatus = 0;</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>HRESULT hr = ConnMgrConnectionStatus ( m_hConnection, &amp;dwStatus );</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if ( pdwStatus ) *pdwStatus = dwStatus;</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if ( SUCCEEDED(hr) )</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if ( dwStatus == CONNMGR_STATUS_CONNECTED )</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>bRet = TRUE;</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>break;</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Sleep ( 100 );</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</font></font></span></p>
<p><span><font face="Times New Roman" size=3>&nbsp;</font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return bRet;</font></font></span></p>
<p><span><font size=3><font face="Times New Roman">}</font></font></span></p>
<p><span><font face="Times New Roman" size=3>&nbsp;</font></span></p>
<p><font size=3><span>至此，我们的连接启用工作已经做完了，我们可以用我们熟悉的</span><span><font face="Times New Roman"> socket </font></span><span>来编写网络通信程序了。下面是一个测试</span><span><font face="Times New Roman"> socket </font></span><span>测试网络连接是否能正常建立的例子：</span></font></p>
<p><span><font size=3><font face="Times New Roman">SetWaitCursor ();</font></font></span></p>
<p><span><font size=3><font face="Times New Roman">CSocket sock;</font></font></span></p>
<p><span><font size=3><font face="Times New Roman">sock.Create ();</font></font></span></p>
<p><span><font size=3><font face="Times New Roman">if ( sock.Connect ( _T("www.baidu.com"), 80 ) )</font></font></span></p>
<p><span><font size=3><font face="Times New Roman">{</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>RestoreCursor ();</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>AfxMessageBox ( _T("Connect to www.baidu.com successfully"), MB_ICONINFORMATION );</font></font></span></p>
<p><span><font size=3><font face="Times New Roman">}</font></font></span></p>
<p><span><font size=3><font face="Times New Roman">else</font></font></span></p>
<p><span><font size=3><font face="Times New Roman">{</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>RestoreCursor ();</font></font></span></p>
<p><span><font size=3><font face="Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>AfxMessageBox ( _T("Connect to www.baidu.com failed") );</font></font></span></p>
<p><span><font size=3><font face="Times New Roman">}</font></font></span></p>
<p><span><font face="Times New Roman" size=3>&nbsp;</font></span></p>
<p><font size=3><span><font face="Times New Roman">GPRSDemo.exe </font></span><span>的使用</span></font></p>
<p><span><font size=3>程序启动以后出现如下界面：</font></span></p>
<p align=center><span><font size=3></font></span></p>
<p><span><font face="Times New Roman" size=3>&nbsp;<img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/chrys2000/屏幕截图_2007-12-11%2002_30_10.jpg"></font></span></p>
<p><font size=3><span>连接可用性</span><font face="Times New Roman"> <span>&#8211; </span></font><span>检测连接管理器是否可用</span></font></p>
<p><font size=3><span>映射</span><span><font face="Times New Roman">URL &#8211; </font></span><span>是让系统自动寻找一个最好的连接</span></font></p>
<p><font size=3><span>枚举网络标识符</span><font face="Times New Roman"> <span>&#8211; </span></font><span>将当前系统中所有可用的连接都会被枚举出来</span></font></p>
<p><font size=3><span>连接网络</span><font face="Times New Roman"> <span>&#8211; </span></font><span>将枚举出来的连接选中的那个连接进行连接启用操作。</span></font></p>
<p><font size=3><span>连接状态</span><font face="Times New Roman"> <span>&#8211; </span></font><span>表示可以获取到当前连接的状态；</span></font></p>
<p><font size=3><span>连接到公网测试</span><font face="Times New Roman"> </font><span><font face="Times New Roman">&#8211; </font></span><span>利用</span><font face="Times New Roman"> <span><a href="http://www.baidu.com/">www.baidu.com</a>&nbsp;</span></font><span>来测试连接是否已经正常启动。</span></font></p>
<p><span><font face="Times New Roman" size=3>&nbsp;</font></span></p>
<p><span><font size=3>操作步骤：</font></span></p>
<p><font size=3><span>可以直接按&#8220;枚举网络标识符&#8221;，程序将所有当前在用的网络枚举出来并添加到</span><span><font face="Times New Roman"> ListBox </font></span><span>控件中；</span></font></p>
<p><font size=3><span>连接网络。选择一个连接（例如：</span><span><font face="Times New Roman">Internet</font></span><span>），按&#8220;连接网络&#8221;按钮，当提示</span><font face="Times New Roman"> <span>Connection net successfully </span></font><span>表示连接已经正常启用了。</span></font></p>
<p><font size=3><span>按&#8220;连接到公网测试&#8221;按钮，软件自动和</span><font face="Times New Roman"> <span><a href="http://www.baidu.com/">www.baidu.com</a> </span></font><span>进行连接测试。</span></font></p>
<p><font size=3></font>&nbsp;</p>
<p><font size=3><span><a href="http://www.pudn.com/downloads94/sourcecode/embed/detail373151.html" target=_blank>源代码下载地址：http://www.pudn.com/downloads94/sourcecode/embed/detail373151.html</a></span></font></p>
</span>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/39578.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-25 14:51 <a href="http://www.cppblog.com/gtwdaizi/articles/39578.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WaitForMultipleObjects用法探索</title><link>http://www.cppblog.com/gtwdaizi/articles/39556.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Tue, 25 Dec 2007 03:09:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/39556.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/39556.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/39556.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/39556.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/39556.html</trackback:ping><description><![CDATA[<p><font size=3><span><font face="Times New Roman">WaitForMultipleObjects</font></span><span>是</span><span><font face="Times New Roman">Windows</font></span><span>中的一个功能非常强大的函数，几乎可以等待</span><span><font face="Times New Roman">Windows</font></span><span>中的所有的内核对象（关于该函数的描述和例子见</span><span><font face="Times New Roman">MSDN</font></span><span>，）。但同时该函数在用法上却需要一定的技巧。</span></font></p>
<pre><font size=3><font color=#660000><strong><span>原型</span></strong><span>：</span></font></font><strong><span>DWORD</span></strong><span> <strong>WaitForMultipleObjects(</strong></span></pre>
<pre><span>&nbsp;<strong>DWORD</strong> <em><span><span><span><u>nCount</u></span></span></span></em><strong>,</strong></span></pre>
<pre><span>&nbsp;<strong>const HANDLE*</strong> <em><span><span><span><u>lpHandles</u></span></span></span></em><strong>,</strong></span></pre>
<pre><span>&nbsp;<strong>BOOL</strong> <em><span><span><span><u>bWaitAll</u></span></span></span></em><strong>,</strong></span></pre>
<pre><span>&nbsp;<strong>DWORD</strong> <u><em><span><span><span>dwMilliseconds</span></span></span></em><strong></strong></u></span></pre>
<pre><strong><span>);</span></strong></pre>
<p><span><font face="Times New Roman" size=3>&nbsp;</font></span></p>
<p><font size=3><span>当</span><span><font face="Times New Roman">WaitForMultipleObjects</font></span><span>等到多个内核对象的时候，如果它的</span></font><em><span>bWaitAll </span></em><font size=3><span>参数设置为</span><span><font face="Times New Roman">false</font></span><span>。其返回值减去</span><span><font face="Times New Roman">WAIT_OBJECT_0 </font></span><span>就是参数</span></font><em><span>lpHandles</span></em><span><font size=3>数组的序号。如果同时有多个内核对象被出发，这个函数返回的只是其中序号最小的那个。</font></span></p>
<p><font size=3><span>问题就在这里，我们如何可以获取所有被同时触发的内核对象。举个例子：我们需要在一个线程中处理从完成端口、数据库、和可等待定时器来的数据。一个典型的实现方法就是：用</span><span><font face="Times New Roman">WaitForMultipleObjects</font></span><span>等待所有的这些事件。如果完成端口，数据库发过来的数据量非常大，可等待定时器时间也只有几十毫秒。那么这些事件同时触发的几率可以说非常大，我们不希望丢弃任何一个被触发的事件。那么如何能高效地实现这一处理呢？</span></font></p>
<p><font size=3><font face=宋体><span>MSDN</span>中有一句非常重要的描述，它可以说是<span>WaitForMultipleObjects</span>用法的精髓：</font></font><span>The function modifies the state of some types of synchronization objects. Modification occurs only for the object or objects whose signaled state caused the function to return. For example, the count of a semaphore object is decreased by one. When <em>bWaitAll</em> is FALSE, and multiple objects are in the signaled state, the function chooses one of the objects to satisfy the wait; the states of the objects not selected are unaffected</span><span>.</span></p>
<p><font size=3><span>多个内核对象被触发时，</span><span><font face="Times New Roman">WaitForMultipleObjects</font></span><span>选择其中序号最小的返回。而</span><span><font face="Times New Roman">WaitForMultipleObjects</font></span><span>它只会改变使它返回的那个内核对象的状态。</span></font></p>
<p><span><font size=3>这儿又会产生一个问题，如果序号最小的那个对象频繁被触发，那么序号比它大的内核对象将得不到被处理的机会。</font></span></p>
<p><font size=3><span>为了解决这一问题，可以采用双</span><span><font face="Times New Roman">WaitForMultipleObjects</font></span><span>检测机制来实现。见下面的例子：</span></font></p>
<p>
<table cellSpacing=0 cellPadding=0 width=612 border=0>
    <tbody>
        <tr>
            <td vAlign=top width=612>
            <p align=left><span>DWORD WINAPI ThreadProc(LPVOID lpParameter)</span></p>
            <p align=left><span>{</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp; </span>DWORD dwRet = 0;</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp; </span><span>int</span><span>&nbsp;&nbsp; </span>nIndex = 0;</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp; </span><span>while</span>(1)</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp; </span>{</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>dwRet = WaitForMultipleObjects(nCount,pHandles,<span>false</span>,INFINITE);</span></p>
            <p align=left>&nbsp;</p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>switch</span>(dwRet)</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>case</span> WAIT_TIMEOUT:</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>break</span>;</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>case</span> WAIT_FAILED:</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>return</span> 1;</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>default</span>:</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>nIndex = dwRet - WAIT_OBJECT_0;</span></p>
            <p align=left>&nbsp;</p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ProcessHanlde(nIndex++);</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>//</span></span><span>同时检测其他的事件</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>while</span>(nIndex &lt; nCount)</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>dwRet = WaitForMultipleObjects(nCount - nIndex,&amp;pHandles[nIndex],<span>false</span>,0);</span></p>
            <p align=left>&nbsp;</p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>switch</span>(dwRet)</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>case</span> WAIT_TIMEOUT:</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>nIndex = nCount; <span>//</span></span><span>退出检测<span>,</span>因为没有被触发的对象了<span>.</span></span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>break</span>;</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>case</span> WAIT_FAILED:</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>return</span> 1;</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>default</span>:</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>nIndex = dwRet - WAIT_OBJECT_0;</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>ProcessHanlde(nIndex++);</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>break</span></span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>break</span>;</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp; </span>}</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp; </span><span>return</span> 0;</span></p>
            <p><span>}</span></p>
            </td>
        </tr>
    </tbody>
</table>
<strong><font color=#000066 size=5></font></strong></p>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/39556.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-25 11:09 <a href="http://www.cppblog.com/gtwdaizi/articles/39556.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Using WinInet HTTP functions in Full Asynchronous Mode</title><link>http://www.cppblog.com/gtwdaizi/articles/39107.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Thu, 20 Dec 2007 05:49:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/39107.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/39107.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/39107.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/39107.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/39107.html</trackback:ping><description><![CDATA[<h2>Introduction</h2>
<p>If you have ever dug into the MSDN for WinInet API, you noticed that it can be used asynchronously and that it is the recommended way to use it.</p>
<p>If then you decide to use it, you won&#8217;t find any explanation of how to use it asynchronously. And no samples are available anywhere on Internet. After a long research and lots of testing, I finally managed to reconstruct a big part of the (voluntary?) missing documentation.</p>
<p>Why asynchronous is better? Because it can handle timeouts correctly. Just what&#8217;s missing in WinInet under IE5.5.</p>
<p>If you try to use <code>TerminateThread</code> or <code>CloseHandle</code> functions to handle timeouts (these methods are given in MSDN articles), you&#8217;ll fall into unrecoverable leaks of all kinds.</p>
<p>This has been tested successfully with: IE4.01SP3, IE5.0, IE5.01, IE5.5SP1 under WinNT4 on mono and multiprocessor machines, under a stressed environment (15 concurrent instances running non-stop for 12 hours on multi-proc NT server machines).</p>
<h2>Theory</h2>
<p>To use WinInet functions in full asynchronous mode, you must do things in the right order:</p>
<ol>
    <li>Use <code>INTERNET_FLAG_ASYNC</code> to open the session
    <li>Set a status callback using <code>InternetSetStatusCallback</code>
    <li>Open the connection using <code>InternetOpenUrl</code>
    <li>If <code>InternetOpenUrl</code> returned <code>NULL</code> and <code>GetLastError</code> is <code>ERROR_IO_PENDING</code>:
    <ul>
        <li>wait for the <code>INTERNET_STATUS_HANDLE_CREATED</code> notification in the callback, and save the connection Handle.
        <li>wait for the <code>INTERNET_STATUS_REQUEST_COMPLETE</code> notification in the callback before going further. </li>
    </ul>
    <li>Extract the content-length from the header and set up an <code>INTERNET_BUFFERS</code> structure:
    <ul>
        <li><code>dwStructSize</code> = <code><span class=code-keyword>sizeof</span>(INTERNET_BUFFERS)</code>
        <li><code>lpvBuffer</code> = your allocated buffer
        <li><code>dwBufferLength</code> = its length </li>
    </ul>
    <li>Use <code>InternetReadFileEx</code> with the <code>IRF_ASYNC</code> flag to read the remaining data asynchronously. Don&#8217;t use <code>InternetReadFile</code> since it is a synchronous function.
    <li>If <code>InternetReadFileEx</code> returned <code>False</code> and <code>GetLastError</code> is <code>ERROR_IO_PENDING</code>: wait for the <code>INTERNET_STATUS_REQUEST_COMPLETE</code> notification in the callback before going further.
    <p>Warning: <code>INTERNET_BUFFERS</code> members are modified asynchronously (only the <code>dwBufferLength</code> member and the content of the buffer).</p>
    <li>If the <code>dwBufferLength</code> member is not 0, move the <code>lpvBuffer</code> pointer from this amount and subtract this amount from the buffer length so <code>dwBufferLength</code> reflects the remaining size <code>lpvBuffer</code> points to, then loop to 6.
    <li>Close the connection handle with <code>InternetCloseHandle</code> and wait for <code>INTERNET_STATUS_HANDLE_CLOSING</code> and the facultative <code>INTERNET_STATUS_REQUEST_COMPLETE</code> notification (sent only if an error occurs &#8211; like a sudden closed connection -, you must test the cases). </li>
</ol>
<p>At this state, you can either begin a new connection process or close the session handle. But before closing it, you should un-register the callback function.</p>
<h2>Detail</h2>
<p>After the theory, let&#8217;s look at some code for some of the points:</p>
<h4>1&amp;2: Create the connection using INTERNET_FLAG_ASYNC and setup the callback func:</h4>
<pre>m_Session = InternetOpen(AGENT_NAME, INTERNET_OPEN_TYPE_PRECONFIG,
NULL, NULL, INTERNET_FLAG_ASYNC);
InternetSetStatusCallback( m_Session,
(INTERNET_STATUS_CALLBACK)InternetCallbackFunc );</pre>
<h4>3&amp;4: Open the connection using InternetOpenUrl and wait for INTERNET_STATUS_REQUEST_COMPLETE</h4>
<p>Use the <code>lParam</code> to send a session identifier to your callback. I always use the <code><span class=code-keyword>this</span></code> pointer of my class for it. I assume you know how to handle callbacks.</p>
<pre>InternetOpenUrl( m_Session, uurl, NULL, <span class=code-digit>0</span>,
INTERNET_FLAG_RELOAD | INTERNET_FLAG_PRAGMA_NOCACHE |
INTERNET_FLAG_NO_CACHE_WRITE, (LPARAM)<span class=code-keyword>this</span> );</pre>
<p>The callback will receive a lots of messages then. Here are their orders along with the <code>dwInternetStatus</code> value:</p>
<pre>[openUrl] InternetStatus: <span class=code-digit>60</span> INTERNET_STATUS_HANDLE_CREATED
**At <span class=code-keyword>this</span> point you can save the HINTERNET handle <span class=code-keyword>using</span> code like <span class=code-keyword>this</span> <span class=code-keyword>in</span> your callback:
INTERNET_ASYNC_RESULT* res = (INTERNET_ASYNC_RESULT*)lpvStatusInformation;
m_hHttpFile = (HINTERNET)(res-<span class=code-keyword>&gt;</span>dwResult);
[openUrl] InternetStatus: <span class=code-digit>10</span>
[openUrl] InternetStatus: <span class=code-digit>11</span>
[openUrl] InternetStatus: <span class=code-digit>20</span>
[openUrl] InternetStatus: <span class=code-digit>21</span>
[openUrl] InternetStatus: <span class=code-digit>30</span>
[openUrl] InternetStatus: <span class=code-digit>31</span>
[openUrl] InternetStatus: <span class=code-digit>40</span>
[openUrl] InternetStatus: <span class=code-digit>41</span>
[openUrl] InternetStatus: <span class=code-digit>100</span> INTERNET_STATUS_REQUEST_COMPLETE</pre>
<h4>5: Extract the content-length and set up the INTERNET_BUFFERS structure</h4>
<p>Once you have the handle, try to call <code>HttpQueryInfo</code> with <code>HTTP_QUERY_CONTENT_LENGTH</code> to get the size of the data to retrieve. This function can fail if the content-length field is not in the HTTP header.</p>
<p>Set up the <code>INTERNET_BUFFERS</code> structure.</p>
<pre lang=text>INTERNET_BUFFERS ib = { sizeof(INTERNET_BUFFERS) };
ib.lpvBuffer = your allocated buffer
ib.dwBufferLength = its length</pre>
<p>The <code>dwBufferTotal</code> is provided for your own use and is never modified by WinInet (as far as I know). I use it to store the total size of the received data.</p>
<h4>6&amp;7&amp;8 Read the remaining data in a loop</h4>
<p>Use <code>InternetReadFileEx</code> with the <code>IRF_ASYNC</code> flag to read the remaining data asynchronously. Don&#8217;t use <code>InternetReadFile</code> since it is a synchronous function. You must loop on <code>InternetReadFileEx</code> while the <code>ib.dwBufferLength</code> is not 0. Before each iteration you must adjust the <code>lpvBuffer</code> pointer and reset the <code>dwBufferLength</code> members of <code>ib</code>: add the received length to the pointer and set <code>dwBufferLength</code> to your remaining buffer size.</p>
<pre><span class=code-comment>//</span><span class=code-comment>Start the pump
</span>BOOL bOk = InternetReadFileEx( m_hHttpFile, &amp;ib, IRF_ASYNC, (LPARAM)<span class=code-keyword>this</span> );
<span class=code-keyword>if</span>(!bOk &amp;&amp; GetLastError()==ERROR_IO_PENDING)
wait...
<span class=code-comment>//</span><span class=code-comment>Pump
</span><span class=code-keyword>while</span>( bOk &amp;&amp; ib.dwBufferLength!=0 )
{
(adjust ib values)
bOk = InternetReadFileEx( m_hHttpFile, &amp;ib, IRF_ASYNC, (LPARAM)<span class=code-keyword>this</span> );
<span class=code-keyword>if</span>(!bOk &amp;&amp; GetLastError()==ERROR_IO_PENDING)
wait...
}</pre>
<p>Your callback should receive these notifications (maybe more than once):</p>
<pre lang=text>[connect] InternetStatus: 40 (receiving response)
[connect] InternetStatus: 41 (response received)
[connect] InternetStatus: 50
[connect] InternetStatus: 51
and maybe
[connect] InternetStatus: 100 INTERNET_STATUS_REQUEST_COMPLETE</pre>
<p>The last is received only if <code>GetLastError()</code> returned <code>ERROR_IO_PENDING</code>. If you stored the total data size (in bytes) in the <code>dwBufferTotal</code> member, use it to set the final &#8220;0&#8221; in your string buffer (if it&#8217;s a string).</p>
<pre>buf[ib.dwBufferTotal] = <span class=code-digit>0</span>;</pre>
<h4>9 Close the connection handle</h4>
<pre>InternetCloseHandle( m_httpFile );</pre>
<p>The callback will receive this notification when the handle is closed:</p>
<pre lang=text>[connect] InternetStatus: 70 INTERNET_STATUS_HANDLE_CLOSING</pre>
<p>In most error cases, the connection is closed unexpectedly. If it happens you&#8217;ll receive a 70 followed by a 100 (<code>INTERNET_STATUS_REQUEST_COMPLETE</code>). This can happen anywhere during the process.</p>
<h4>10 Before closing the m_Session handle</h4>
<p>You must deregister the callback:</p>
<pre>InternetSetStatusCallback( m_Session, NULL );</pre>
<p>This should help those who tried to go through asynchronous mode in WinInet! Sorry, there are no attached files but you should be able to use the functions and create nice classes now. If you liked this article please add an entry in <a href="http://www.softlion.com/" target=_blank><u><font color=#0000ff>my guestbook</font></u></a> and buy me a license of my shareware.</p>
<h2>Bibliography</h2>
<ul>
    <li><a href="http://msdn.microsoft.com/workshop/networking/wininet/reference/functions/InternetReadFileEx.asp" target=_blank><u><font color=#0000ff>Microsoft website</font></u></a>
    <li>Q176420: <a href="http://support.microsoft.com/support/kb/articles/Q176/4/20.ASP" target=_blank><u><font color=#0000ff>BUG: InternetSetOption Does Not Set Timeout Values</font></u></a>
    <li>Q176176: <a href="http://support.microsoft.com/support/kb/articles/Q176/1/76.ASP" target=_blank><u><font color=#0000ff>FIX: InternetOpenUrl Does Not Work When Called Asynchronously</font></u></a>
    <li>Q238425: INFO: WinInet Not Supported for Use in Services
    <li>Q190542: INFO: Using WinInet APIs in a System Service to access SSL sites
    <li><a href="news://microsoft.public.inetsdk.programming.wininet/" target=_blank><u><font color=#0000ff>Microsft Newsgroup</font></u></a> </li>
</ul>
<!-- Article Ends --><!-- Main Page Contents End -->
<h2>About the Author</h2>
<table cellSpacing=5 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr vAlign=top>
            <td id=ctl00_AboutAuthorRptr_ctl00_AboutAuthor_memberPhotoTable style="WIDTH: 155px" vAlign=top><strong><a id=ctl00_AboutAuthorRptr_ctl00_AboutAuthor_memberProfileLink href="http://www.codeproject.com/script/Membership/Profiles.aspx?mid=31"><u><font color=#0000ff>Benjamin Mayrargue</font></u></a></strong><br><br>
            <center><u><font color=#0000ff></font></u></center><br><span class=SmallText id=ctl00_AboutAuthorRptr_ctl00_AboutAuthor_memberType></span></td>
            <td><br>
            <table>
                <tbody>
                    <tr id=ctl00_AboutAuthorRptr_ctl00_AboutAuthor_locationRow>
                        <td class=SmallText>Location: </td>
                        <td width="100%"><span class=SmallText id=ctl00_AboutAuthorRptr_ctl00_AboutAuthor_memberLocation><img height=11 alt="United States" src="http://www.codeproject.com/script/Geo/Images/US.gif" width=16> United States</span></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br>
<table id=ctl00_PopularArticlesRow cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr vAlign=top>
            <td style="WIDTH: 100%">
            <h2>Other popular Internet / Network articles:</h2>
            <ul>
                <li><a href="http://www.codeproject.com/KB/IP/AsyncSocketServerandClien.aspx"><u><font color=#0000ff>An Asynchronous Socket Server and Client</font></u></a>
                <div class=SmallText>An asynchronous socket server and client with encryption and compression.</div>
                <li><a href="http://www.codeproject.com/KB/IP/ndk.aspx"><u><font color=#0000ff>Network Development Kit 2.0</font></u></a>
                <div class=SmallText>Network Development Kit is a set of simple classes for a client-server architecture.</div>
                <li><a href="http://www.codeproject.com/KB/IP/drvfltip.aspx"><u><font color=#0000ff>Developing Firewalls for Windows 2000/XP</font></u></a>
                <div class=SmallText>An article about developing Firewalls for Windows 2000/XP.</div>
                <li><a href="http://www.codeproject.com/KB/IP/socketsincs.aspx"><u><font color=#0000ff>Asynchronous socket communication</font></u></a>
                <div class=SmallText>An article on using sockets to communicate in a non-blocking manner. The sample works through building a simple chat client and server.</div>
                <li><a href="http://www.codeproject.com/KB/IP/serversocket.aspx"><u><font color=#0000ff>Multi-threaded Client/Server Socket Class</font></u></a>
                <div class=SmallText>A multi-threaded based Client/Server Socket Communication class</div>
                </li>
            </ul>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/39107.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-20 13:49 <a href="http://www.cppblog.com/gtwdaizi/articles/39107.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WM工具栏的使用</title><link>http://www.cppblog.com/gtwdaizi/articles/39088.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Thu, 20 Dec 2007 01:36:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/39088.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/39088.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/39088.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/39088.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/39088.html</trackback:ping><description><![CDATA[<p>/////////////////////////////////////////////////////////////////////////////<br>CFileAssociationDlg.h<br>////////////////////////////////////////////////////////////////////////////<br><br>//申明状态栏变量<br>CStatusBar m_status;&nbsp; <br><br>/////////////////////////////////////////////////////////////////////////////<br>CFileAssociationDlg.cpp<br>////////////////////////////////////////////////////////////////////////////<br><br>// 创建状态栏中要显示的内容, 通过创建String资源实现, 这里使用数组indicators存储资源的ID<br>static UINT BASED_CODE indicators[] = <br>{<br>&nbsp;ID_INDICATOR_NISH, <br>&nbsp;ID_INDICATOR_TIME<br>};<br><br><span style="COLOR: #0000ff">/*<br>virtual BOOL Create(<br>&nbsp;&nbsp; CWnd* pParentWnd,<br>&nbsp;&nbsp; DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_TOP,<br>&nbsp;&nbsp; UINT nID = AFX_IDW_STATUS_BAR <br>);<br>创建状态栏, 并把创建的状态栏与m_status绑定<br>*/</span><br>&nbsp;m_status.Create(this);<br><br><span style="COLOR: #0000ff">// 通过数组指针指定状态栏要显示内容, indicators表示数组指针, 2 表示indicators指向的数组的元素个数</span><br>&nbsp;m_status.SetIndicators(indicators, 2);</p>
<p><span style="COLOR: #0000ff">// 获取客户区大小</span>&nbsp;<br>&nbsp;CRect rect;<br>&nbsp;GetClientRect(&amp;rect);<br>&nbsp;<br><span style="COLOR: #0000ff">// 由于状态栏由多个方块组成, SetPaneInfo用来设置每个方块的属性<br></span><span style="COLOR: #0000ff">// SBPS_NORMAL正常type, SBPS_STRETCH两边伸展, 填充未使用的区域</span><br>m_status.SetPaneInfo(0, ID_INDICATOR_NISH, SBPS_NORMAL, rect.Width() - 100);<br>&nbsp;m_status.SetPaneInfo(1,ID_INDICATOR_TIME,SBPS_STRETCH ,0);</p>
<p><span style="COLOR: #0000ff">//&nbsp;设置状态栏属性</span><br>&nbsp;m_status.SetBarStyle(CBRS_ALIGN_TOP| CBRS_FLYBY | CBRS_SIZE_DYNAMIC);<br>&nbsp;//::SetBkColor((m_status.GetStatusBarCtrl().GetDC()),RGB(180,180,180));&nbsp;<br><br><span style="COLOR: #0000ff">// 画状态栏在屏幕上<br></span>&nbsp;RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,&nbsp;ID_INDICATOR_TIME);<br><br><span style="COLOR: red"><strong>以下内容为[转]</strong></span><br></p>
<p><strong><img height=16 src="http://www.vckbase.com/document/image/paragraph.gif" width=14> Q:如何在对话框中加入工具条</strong></p>
<p>在 OnInitDialog 中加入下面代码： </p>
<pre>BOOL CYourDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Create the toolbar. To understand the meaning of the styles used, you
// can take a look at the MSDN for the Create function of the CToolBar class.
ToolBar.Create(this, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_TOOLTIPS |CBRS_FLYBY | CBRS_BORDER_BOTTOM);
// I have assumed that you have named your toolbar''s resource as IDR_TOOLBAR1.
// If you have given it a different name, change the line below to accomodate
// that by changing the parameter for the LoadToolBar function.
ToolBar.LoadToolBar(IDR_TOOLBAR1);
CRect rcClientStart;
CRect rcClientNow;
GetClientRect(rcClientStart);
// To reposition and resize the control bar
RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST,0, reposQuery, rcClientNow);
CPoint ptOffset(rcClientNow.left - rcClientStart.left,rcClientNow.top-rcClientStart.top);
CRect rcChild;
CWnd* pwndChild = GetWindow(GW_CHILD);
while (pwndChild)
{
pwndChild-&gt;GetWindowRect(rcChild);
ScreenToClient(rcChild);
rcChild.OffsetRect(ptOffset);
pwndChild-&gt;MoveWindow(rcChild, FALSE);
pwndChild = pwndChild-&gt;GetNextWindow();
}
CRect rcWindow;
GetWindowRect(rcWindow);
rcWindow.right += rcClientStart.Width() - rcClientNow.Width();
rcWindow.bottom += rcClientStart.Height() - rcClientNow.Height();
MoveWindow(rcWindow, FALSE);
// And position the control bars
RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);
return TRUE;  // return TRUE  unless you set the focus to a control
}
</pre>
<p><strong><img height=16 src="http://www.vckbase.com/document/image/paragraph.gif" width=14> Q:如何改变对话框的形状？</strong><br><br>可用下面一些函数： <br>CreatePolygonRgn<br>CreateRectRgn<br>CreateRoundRectRgn 等. </p>
<pre>  CRgn m_rgn;  // Put this in your dialog''s header file. i.e. a member variable
// This Gets the size of the Dialog: This piece of code is to be placed in the
// OnInitDialog Function of your dialog.
CRect rcDialog
GetClientRect(rcDialog);
// The following code Creates the area and assigns it to your Dialog
m_rgn.CreateEllipticRgn(0, 0, rcDialog.Width(), rcDialogHeight());
SetWindowRgn(GetSafeHwnd(), (HRGN) m_rgn, TRUE);
</pre>
<p><strong><img height=16 src="http://www.vckbase.com/document/image/paragraph.gif" width=14> Q：如何实现非客户区移动？</strong><br><br>可用下面二种方法</p>
<pre>// Handler for WM_LBUTTONDOWN message
void CYourDialog::OnLButtonDown(UINT nFlags, CPoint point)
{
CDialog::OnLButtonDown(nFlags, point);
PostMessage( WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM( point.x, point.y));
}
// Handler for WM_NCHITTEST message
LONG CYourDialog::OnNcHitTest( UINT uParam, LONG lParam )
{
int xPos = LOWORD(lParam);
int yPos = HIWORD(lParam);
UINT nHitTest = CDialog::OnNcHitTest(CSize(xPos, yPos));
return (nHitTest == HTCLIENT) ? HTCAPTION : nHitTest;
}
</pre>
<p><br><strong><img height=16 src="http://www.vckbase.com/document/image/paragraph.gif" width=14> Q:如何使对话框初始为最小化状态？</strong><br><br>在 OnInitDialog 中加入下面代码：</p>
<pre>SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE, NULL);</pre>
<p><strong><img height=16 src="http://www.vckbase.com/document/image/paragraph.gif" width=14> Q:如何限定对话框大小范围？</strong><br><br>在 WM_SIZING中加入下面代码：</p>
<pre>void CYourDialog::OnSizing(UINT fwSide, LPRECT pRect)
{
if(pRect-&gt;right - pRect-&gt;left &lt;=200)
pRect-&gt;right = pRect-&gt;left + 200;
if(pRect-&gt;bottom - pRect-&gt;top &lt;=200)
pRect-&gt;bottom = pRect-&gt;top + 200;
CDialog::OnSizing(fwSide, pRect);
}
</pre>
<p><strong><img height=16 src="http://www.vckbase.com/document/image/paragraph.gif" width=14> Q:如何在对话框中加入状态条？</strong><br><br>定义 CStatusBar 变量：</p>
<pre>CStatusBar m_StatusBar;</pre>
<p>定义状态条指定状态：</p>
<pre>static UINT BASED_CODE indicators[] =
{
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM
};
</pre>
<p>在 OnInitDialog 中加入下面代码： </p>
<pre>  m_StatusBar.CreateEx(this,SBT_TOOLTIPS,WS_CHILD|WS_VISIBLE|CBRS_BOTTOM,AFX_IDW_STATUS_BAR);
// Set the indicators namely caps and nums lock status
m_StatusBar.SetIndicators(indicators,sizeof(indicators)/sizeof(UINT));
CRect rect;
GetClientRect(&amp;rect);
m_StatusBar.SetPaneInfo(0,ID_INDICATOR_CAPS,SBPS_NORMAL,rect.Width()/2);
m_StatusBar.SetPaneInfo(1,ID_INDICATOR_NUM,SBPS_STRETCH ,rect.Width()/2);
RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,ID_INDICATOR_NUM);
m_StatusBar.GetStatusBarCtrl().SetBkColor(RGB(180,180,180));
</pre>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/39088.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-20 09:36 <a href="http://www.cppblog.com/gtwdaizi/articles/39088.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WM下给Dialog添加菜单</title><link>http://www.cppblog.com/gtwdaizi/articles/39030.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Wed, 19 Dec 2007 07:40:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/39030.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/39030.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/39030.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/39030.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/39030.html</trackback:ping><description><![CDATA[<p>如何在WM平台下, 给创建的Dialog添加菜单,&nbsp;以下这段代码添加在CFileAssociationDlg::OnInitDialog()方法内, CFileAssociationDlg是你要创建的对话框.<br>&nbsp;<br><span style="COLOR: #3366ff">// 创建SHMENUBARINFO结构体</span><br>SHMENUBARINFO&nbsp;&nbsp; mbi;&nbsp;<br><br><span style="COLOR: #3366ff">//&nbsp;初始化, 每个字节都置为0</span><br>&nbsp;ZeroMemory(&amp;mbi,&nbsp;&nbsp; sizeof(SHMENUBARINFO));&nbsp;&nbsp;&nbsp;<br><br><span style="COLOR: #3366ff">// 设置结构体SHMENUBARINFO的长度</span><br>&nbsp;mbi.cbSize&nbsp;&nbsp; =&nbsp;&nbsp; sizeof(SHMENUBARINFO);&nbsp;&nbsp;&nbsp;<br><br><span style="COLOR: #3366ff">// 设置控制菜单的窗口,即CFileAssociationDlg对话框</span><br>&nbsp;mbi.hwndParent&nbsp;&nbsp; =&nbsp;&nbsp; this-&gt;m_hWnd;&nbsp;&nbsp;&nbsp;<br><br><span style="COLOR: #3366ff">// IDR_HELLO_MENU为资源文件中的Menu ID, 需要创建该菜单</span><br>&nbsp;mbi.nToolBarId&nbsp;&nbsp; =&nbsp;&nbsp; IDR_HELLO_MENU;&nbsp;&nbsp;&nbsp;<br><br><span style="COLOR: #3366ff">// 应用程序的实例</span><br>&nbsp;mbi.hInstRes&nbsp;&nbsp; =&nbsp;&nbsp; AfxGetInstanceHandle();&nbsp;&nbsp;&nbsp;<br><br><span style="COLOR: #3366ff">// Bitmap identifier used to load the bitmap resource for buttons with images from the instance specified by <strong>hInstRes</strong><em>.</em></span>&nbsp;<br>&nbsp;mbi.nBmpId = 0;<br><br><span style="COLOR: #3366ff">// Number of images in the bitmap referred to by <strong>nBmpId</strong><em>.</em></span> <br>&nbsp;mbi.cBmpImages = 0;&nbsp;<br><br><span style="COLOR: #3366ff">// 设置菜单属性, 这里需要注意的是<font color=#ff0000>SHCMBF_HMENU , </font><font color=#000000><span style="COLOR: #ff0000">SHCMBF_HIDESIPBUTTON</span><span style="COLOR: #3366ff">属性</span>, <span style="COLOR: #3366ff">前者必须要有, 否则菜单会创建失败, 后者只应用于Mobile<br>// 平台, 用来隐藏输入法菜单</span></font></span><br>&nbsp;mbi.dwFlags = SHCMBF_COLORBK | SHCMBF_HMENU | SHCMBF_HIDESIPBUTTON;<br><br><span style="COLOR: #3366ff">// 创建菜单</span><br>&nbsp;if(SHCreateMenuBar(&amp;mbi))<br>&nbsp;{<br>&nbsp;&nbsp;<br>&nbsp;}</p>
<p>&nbsp;else<br>&nbsp;{<br>&nbsp;&nbsp;::DestroyWindow(m_hWnd);<br>&nbsp;&nbsp;PostQuitMessage(1);<br>&nbsp;&nbsp;return(-1);<br>&nbsp;}</p>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/39030.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-19 15:40 <a href="http://www.cppblog.com/gtwdaizi/articles/39030.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows mobile平台下的文件类型注册(一)</title><link>http://www.cppblog.com/gtwdaizi/articles/38827.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Tue, 18 Dec 2007 14:04:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/38827.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/38827.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/38827.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/38827.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/38827.html</trackback:ping><description><![CDATA[<font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Windows Mobile既然跟桌面Windows都系出同源，当然很多东西都一样。我们修改注册表的目的是通过修改和变更一些系统的默认数据，更好的优化系统，使系统达到一个相对较好的运行状态。如果想自行做些小修改对注册表有一定的了解是非常必备的，因为这会牵扯到整个系统的运作，一旦修改错误可能会使系统运行不正常，甚至是无法运行，最后只能硬启。<br><br>　　我们先对注册表有个大致的了解。注册表大致上可以分为四组：<br><br>　　HKEY_CLASSES_ROOT：<br>　　用来放置一些资料的定义，如副档名的关联，资料的类别之类的东西。<br><br>　　HKEY_CURRENT_USER：<br>　　这个区域是放置一些每个使用者共用的资料及设定，因为Windows Mobile依然架构是跟NT相近，有区分All User或User的分别，这里就是纪录这些东西。 <br><br>　　HKEY_LOCAL_MACHINE：<br>　　此区是放置系统的设定，不论软体或硬体都是放在这，如同它LOCAL MACHINE的含义一样。<br><br>　　HKEY_USERS：<br>　　用来存放使用者自己的一些资料，除非有写程序，否则一般都是没有在用的。</font><br><br>1. 如何实现文件与应用程序的关联<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;首先我们来看看windows xp中如何实现文件的关联的:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(1)打开[我的电脑]-&gt;[工具]-&gt;[文件夹选项]-&gt;[文件类型]选项, 如下图:<br><img style="WIDTH: 369px; HEIGHT: 457px" height=457 alt="" src="http://www.cppblog.com/images/cppblog_com/gtwdaizi/file.jpg" width=369 align=left border=0><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>新建一个后缀hik<br><img height=106 alt="" src="http://www.cppblog.com/images/cppblog_com/gtwdaizi/file_ext.jpg" width=365 border=0><br>然后更改打开方式, 我这里设置为QQ<br><img style="WIDTH: 364px; HEIGHT: 392px" height=392 alt="" src="http://www.cppblog.com/images/cppblog_com/gtwdaizi/file_ext_qq.jpg" width=364 border=0><br>至此就完成了一个文件类型到应用程序的关联, 现在我们可以打开注册表看看<br>在HKEY_CLASS_ROOT下面找到.hik, 可能大家还不了解ft000005是什么意思, 我也搞不太清楚, 应该是一个注册表的索引, 搜索一下ft00005<br><img height=118 alt="" src="http://www.cppblog.com/images/cppblog_com/gtwdaizi/register1.jpg" width=529 border=0><br><br>在HKEY_USERS---Microsoft---Windows---Explorer---FileExts---.HIK,里面就定义了关联的应用程序<br><img height=74 alt="" src="http://www.cppblog.com/images/cppblog_com/gtwdaizi/register2.jpg" width=586 border=0><br><br>创建一个.hik后缀的文件, 双击, 就可以发现带开了QQ.<br><br>这种方式是通过windows xp的文件夹选项来注册文件类型的, 若要在代码中需要注册文件类型, 采用这种方式显然行不通, 所以接下来要寻求如何通过代码来创建注册表中的键值对.<br>待续........<br>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/38827.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-18 22:04 <a href="http://www.cppblog.com/gtwdaizi/articles/38827.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows mobile平台下的文件类型注册(二) </title><link>http://www.cppblog.com/gtwdaizi/articles/38952.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Tue, 18 Dec 2007 14:04:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/38952.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/38952.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/38952.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/38952.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/38952.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;上文是使用的文件夹选项中的设置来注册文件类型, 其实我们可以手动的修改注册表来达到这个效果, 在此就直接介绍一下在windows mobile下面如何直接通过修改注册表来注册文件类型了.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.打开windows mobile的注册表<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这是需要解决的第一个问题, 如何浏览并修改windows mobile的注册表, 作为windows mobile的开发人员, 大多数人会选择microsoft visual studio.<br></p>
<img height=183 alt="" src="http://www.cppblog.com/images/cppblog_com/gtwdaizi/remote_register.jpg" width=439 border=0><br>&nbsp;在Visual Studio Remote Tools中有个remote registry editor工具, 打开这小家伙, 注意在此之前首先需要使用同步工具建立与mobile手机的连接, 关于如何连接请点击<a title=这里 href="http://www.cppblog.com/gtwdaizi/articles/32838.html">这里</a>.<br><br><img height=327 alt="" src="http://www.cppblog.com/images/cppblog_com/gtwdaizi/register_connector.jpg" width=288 border=0><br>选中Windows Mobile5.0 Pocket PC Device, 连接成功后就可以看到注册表项了, 在HKEY_CLASSES_ROOT下面, 创建一个key命名为.hik, 如下图, data值设置为hik.Document<br><img height=140 alt="" src="http://www.cppblog.com/images/cppblog_com/gtwdaizi/register_hik.jpg" width=471 border=0><br>然后在创建一个key,命名为hik.Document<br><img height=83 alt="" src="http://www.cppblog.com/images/cppblog_com/gtwdaizi/register_hikdoc.jpg" width=485 border=0><br>在hik.Document下创建子键DefaultIcon, 值为"\Program Files\FileAssociation\FileAccociation.exe" , 1&nbsp;这个键表示应用程序对应的图标.<br><br>继续在hik.Document下创建shell子键, 在创建open子键, 在创建command子键, 值为"\Program Files\FileAssociation\FileAccociation.exe" , 1&nbsp;&nbsp; 这个路径就是.hik后缀的文件对应的应用程序的路径, 后面的1表示传递给应用的命令行参数为双击的.hik文件的路径.<br><br>到此手动增加文件类型的注册就完毕了, 可以创建一个.hik的文件测试一下.<br>下一篇将讲述如何使用windows mobile的函数来进行文件类型的注册.<br>待续......<br><br><br><br>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/38952.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-18 22:04 <a href="http://www.cppblog.com/gtwdaizi/articles/38952.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Smartphone 应用程序安全与代码签名模型开发人员实用指南</title><link>http://www.cppblog.com/gtwdaizi/articles/38707.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Mon, 17 Dec 2007 03:14:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/38707.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/38707.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/38707.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/38707.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/38707.html</trackback:ping><description><![CDATA[<div class=title xmlns:msxsl="urn:schemas-microsoft-com:xslt">Smartphone 应用程序安全与代码签名模型开发人员实用指南 </div>
<!--content type: DocStudio. Transform: psdk2mtps.xslt.-->
<div id=mainSection>
<div id=mainBody>
<div>
<div>发布日期 : 2/28/2005<span> | </span>更新日期 : 2/28/2005</div>
<p>James Pratt<br>Microsoft</p>
<p>适用于：<br>Microsoft&#174; Windows&#174; Powered Smartphone 2002<br>Windows Mobile&#8482; 2003 software for Smartphones<br>Windows Mobile 2003 Second Edition software for Smartphones<br>Microsoft ActiveSync&#174;<br>Microsoft Visual Studio&#174; .NET 2003<br>Microsoft eMbedded Visual C++&#174; version 3.0<br>Microsoft eMbedded Visual C++ version 4.0</p>
<p><strong>摘要：</strong>本文介绍应用程序开发人员必须了解的有关 Smartphone 应用程序安全模型的内容、以及当某款基于 Windows Mobile 的 Smartphone 推向市场时移动运营商所拥有的不同策略选择。</p>
<h5>本页内容</h5>
<p><a href="http://msdn2.microsoft.com/zh-cn/library/ms839377.aspx#EGAA"><img alt=摘要 src="http://msdn2.microsoft.com/zh-cn/library/ms839377.arrow_px_down(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839377.aspx#EGAA"><u><font color=#800080>摘要</font></u></a> <br><a href="http://msdn2.microsoft.com/zh-cn/library/ms839377.aspx#EFAA"><img alt=应用程序安全背景 src="http://msdn2.microsoft.com/zh-cn/library/ms839377.arrow_px_down(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839377.aspx#EFAA"><u><font color=#800080>应用程序安全背景</font></u></a> <br><a href="http://msdn2.microsoft.com/zh-cn/library/ms839377.aspx#EEAA"><img alt=代码签名实践 src="http://msdn2.microsoft.com/zh-cn/library/ms839377.arrow_px_down(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839377.aspx#EEAA"><u><font color=#800080>代码签名实践</font></u></a> <br><a href="http://msdn2.microsoft.com/zh-cn/library/ms839377.aspx#EDAA"><img alt=小结 src="http://msdn2.microsoft.com/zh-cn/library/ms839377.arrow_px_down(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839377.aspx#EDAA"><u><font color=#800080>小结</font></u></a> <br><a href="http://msdn2.microsoft.com/zh-cn/library/ms839377.aspx#ECAA"><img alt="附录 A：受保护的注册表项" src="http://msdn2.microsoft.com/zh-cn/library/ms839377.arrow_px_down(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839377.aspx#ECAA"><u><font color=#800080>附录 A：受保护的注册表项</font></u></a> <br><a href="http://msdn2.microsoft.com/zh-cn/library/ms839377.aspx#EBAA"><img alt="附录 B：特权 API 列表" src="http://msdn2.microsoft.com/zh-cn/library/ms839377.arrow_px_down(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839377.aspx#EBAA"><u><font color=#800080>附录 B：特权 API 列表</font></u></a> <br></p>
<h3 id=EGAA>摘要</h3>
<p>Microsoft&#8482; 基于 Windows Mobile 的 Smartphone 是根据数字代码签名实现应用程序安全模型的。希望以基于 Windows Mobile 的 Smartphone 为目标的应用程序开发人员需要了解 Smartphone 应用程序安全模型、以及当某款基于 Windows Mobile 的 Smartphone 推向市场时移动运营商所拥有的不同策略选择。</p>
<p>如果您是一位了解构建 Pocket PC 或 Smartphone 应用程序的 Smartphone 开发人员，并且还在构建 Pocket PC 和/或 Smartphone 安装包 (.cab)，本文将提供您所需的一切，以帮助您了解 Smartphone 应用程序安全模型、特权与非特权应用程序的不同之处、如何确定您的应用程序是否需要特权信任、如何配置进行 Smartphone 开发的开发环境，以及如何通过代码签名供应商进行应用程序签名。</p>
<div><a href="http://msdn2.microsoft.com/zh-cn/library/ms839377.aspx#mainSection"><img alt="" src="http://msdn2.microsoft.com/zh-cn/library/ms839377.arrow_px_up(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839377.aspx#mainSection"><u><font color=#800080>返回页首</font></u></a> <br></div>
<h3 id=EFAA>应用程序安全背景</h3>
<p><a onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl01',this);" href="http://msdn.microsoft.com/mobility/windowsmobile/partners/mobile2market/faq.aspx"><em><u><font color=#0000ff>Mobile2Market FAQ</font></u></em></a> 提供了一个非常不错的针对应用程序安全与代码签名的高级指南。在阅读本文之前，您可能希望阅读 Mobile2Market FAQ，以便为您提供有价值的背景知识。</p>
<p><strong>数字代码签名</strong> </p>
<p>数字代码签名是一种验证数字内容来源的方式。在 Windows Mobile 领域中，有时会将它与徽标认证混淆。徽标认证是验证某个 Windows Mobile 应用程序是否符合一组实现 Windows Mobile 应用程序的指导原则的过程。当前的指导原则可以在 <a onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl02',this);" href="http://msdn.microsoft.com/mobility/windowsmobile/partners/mobile2market/"><em><u><font color=#0000ff>Mobile2Market 站点</font></u></em></a>上找到。经过认证的应用程序在应用程序中和它的包装上都标有&#8220;Designed for Windows Mobile&#8221;徽标。&#8220;Designed for Windows Mobile&#8221;徽标不担保应用程序是由它声明的软件供应商构建的，也不担保如果它由该软件供应商构建，它没有在软件供应商发出它和您接收到它的这段时间内遭到恶意篡改。而代码签名确实提供了这些担保。</p>
<p>让人感到不解的是，数字代码签名既使用数字证书，又有一个单独的徽标认证程序。其实，这两者有完全不同的目的和目标。</p>
<p><strong>究竟为什么要进行数字代码签名？</strong> </p>
<p>数字代码签名不是基于 Windows Mobile 的 Smartphone 所独有的。每次 Microsoft&#174; Internet Explorer 询问您是否希望安装 Active X&#174; 控件，然后询问您是否希望&#8220;信任来自 X 公司的内容&#8221;时，应用程序是在要求您决定是否信任内容提供商。Internet Explorer 断言相关的包在签名后没有更改过。如果您信任该来源，那么您就可以信任该应用程序，因为它来源于一个经过验证的源。代码签名将验证数字内容的来源以及自从它签名后没有更改过的事实。</p>
<p><strong>用于</strong> <strong>Smartphone </strong><strong>的</strong> <strong>Windows </strong><strong>Mobile</strong> <strong></strong><strong>软件的应用程序安全</strong> </p>
<p>通过禁止用户从一个未知源安装应用程序，基于 Windows Mobile 的 Smartphone 应用程序安全可以帮助保护最终用户的 Smartphone 设备的完整性。</p>
<p>应用程序安全是一种通过代码签名实施的策略决策。在移动运营商将电话推向市场之前，他们会做出策略决策。移动运营商在任何时候都可以更改策略决策。</p>
<p>基于 Windows Mobile 的 Smartphone 实现了周边安全和运行时安全。周边安全控件可以<em>安装</em> 在设备上。运行时安全控件可以在设备上<em>执行</em>。例如，您只需安装一种铃声或一个主屏幕，然而您需要安装并执行一个应用程序。如果您创建内容并安装在没有包含任何可执行组件的设备上，则您只需考虑周边安全。如果您在创建一些可执行的东西（例如应用程序或组件），那么您需要考虑周边安全和运行时安全。</p>
<p>Smartphone 包含三个不同的证书存储区：一个非特权执行信任存储区、一个特权执行信任存储区和一个安装信任存储区。证书存储区包含安装在电话上的数字证书的公共部分。证书的公共版可以用来验证应用程序的数字签名，但不能用来对应用程序进行签名。</p>
<p><strong>什么时候我需要拥有超越非特权执行模式的特权？</strong> </p>
<p>大多数应用程序只需要非特权执行模式，例如游戏和有助于提高工作效率的个人应用程序。如果您计划在应用程序中完成以下某件事情，您可能需要特权执行模式，因此应当使用特权证书进行签名： </p>
<ul>
    <li>
    <p>修改系统注册表项（参阅<a onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl03',this);" href="http://msdn.microsoft.com/mobility/understanding/gettingstarted/windowsmobile/default.aspx?pull=/library/en-us/dnsmtphn2k3/html/smartphone_security.asp"><em><u><font color=#0000ff>附录 A</font></u></em></a>） </p>
    <li>
    <p>访问 SMS 子系统（SmsXXX 函数） </p>
    <li>
    <p>进行或截获电话呼叫并访问其他的 exTAPI API </p>
    <li>
    <p>访问 SIM 管理子系统（SimXXX 函数） </p>
    <li>
    <p>直接通过无线电接口层访问无线电设备（不通过 Smartphone SDK 提供） </p>
    <li>
    <p>使用低级系统 API，例如 Kernel IOControl </p>
    <li>
    <p>编写用来插入到系统进程或者特权进程的组件，例如 DLL。一个常见的例子是 Microsoft ActiveSync&#174; 服务提供程序，它作为设备端 ActiveSync 应用程序应归类为特权应用程序。 </p>
    <p><strong>注</strong> <a onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl04',this);" href="http://msdn.microsoft.com/mobility/understanding/gettingstarted/windowsmobile/default.aspx?pull=/library/en-us/dnsmtphn2k3/html/smartphone_security.asp"><em><u><font color=#0000ff>附录 B</font></u></em></a> 包含了需要特权访问的 API 列表。</p>
    </li>
</ul>
<p><strong>特权与非特权执行模式</strong> </p>
<p>Smartphone 应用程序安全模型的设计很灵活，可以满足各种移动运营商的网络的需要。特权与非特权应用程序的概念指的是给定应用程序访问设备上的功能和 API 的权限级别： </p>
<ul>
    <li>
    <p><strong>特权信任</strong>应用程序可以完全访问系统和 API。在特权证书存储区进行证书签名的应用程序以这种执行特权运行。 </p>
    <li>
    <p><strong>非特权信任</strong>应用程序可以有限访问系统和 API。在非特权证书存储区进行证书签名的应用程序以这种执行特权运行。 </p>
    <li>
    <p><strong>不受信任</strong>应用程序不允许加载到 Smartphone 并且不能访问系统或 API。 </p>
    </li>
</ul>
<p>由运营商选择 Smartphone 安全策略。这种策略可能允许不受信任的应用程序以非特权访问模式运行，也可能需要对应用程序进行数字签名。下一节讨论安全策略矩阵。</p>
<p><strong>什么是可能的安全策略？</strong> </p>
<p>对于安装应用程序（周边安全），运营商的策略选择很简单： </p>
<ul>
    <li>
    <p>允许安装未经签名的安装包 </p>
    <li>
    <p>不允许安装未经签名的安装包 </p>
    </li>
</ul>
<p>在 Smartphone 2003 中，有另外一种模式，这种模式询问用户是否希望安装应用程序。</p>
<p>对于执行应用程序（运行时安全），移动运营商必须选择是否允许应用程序或组件以特权和非特权信任模式运行。下表显示了需要通过其进行签名才能运行的证书类型（取决于策略）。在 Smartphone 2002 中：</p>
<table>
    <tbody>
        <tr>
            <th>
            <p>策略</p>
            </th>
            <th>
            <p>执行模式</p>
            </th>
            <th>
            <p>执行模式</p>
            </th>
        </tr>
        <tr>
            <td>&nbsp;
            <p>&#160;</p>
            </td>
            <td>
            <p>非特权</p>
            </td>
            <td>
            <p>特权</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>不受限制</p>
            </td>
            <td>
            <p>无</p>
            </td>
            <td>
            <p>无</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>标准</p>
            </td>
            <td>
            <p>无</p>
            </td>
            <td>
            <p>需要运营商特权证书</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>受限</p>
            </td>
            <td>
            <p>需要 Mobile2Market 非特权证书</p>
            </td>
            <td>
            <p>需要运营商特权证书</p>
            </td>
        </tr>
    </tbody>
</table>
<table>
    <tbody>
    </tbody>
</table>
<p>基于 Windows Mobile 2003 的 Smartphone 还可以支持提示模式。运营商不是简单地否认用户安装或运行应用程序的能力，而是可以通过指定提示模式来推迟针对用户的决策。在这种情况中，系统会提示并询问用户是否允许运行或安装应用程序。执行策略如下：</p>
<table>
    <tbody>
        <tr>
            <th>
            <p>策略</p>
            </th>
            <th>
            <p>执行模式</p>
            </th>
            <th>
            <p>执行模式</p>
            </th>
        </tr>
        <tr>
            <td>&nbsp;
            <p>&#160;</p>
            </td>
            <td>
            <p>非特权</p>
            </td>
            <td>
            <p>特权</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>不受限制</p>
            </td>
            <td>
            <p>无</p>
            </td>
            <td>
            <p>无</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>标准</p>
            </td>
            <td>
            <p>需要 Mobile2Market 非特权证书（提示模式一样）</p>
            </td>
            <td>
            <p>需要 Mobile2Market 或运营商特权证书</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>受限</p>
            </td>
            <td>
            <p>需要 Mobile2Market 非特权证书</p>
            </td>
            <td>
            <p>需要 Mobile2Market 或运营商特权证书</p>
            </td>
        </tr>
    </tbody>
</table>
<table>
    <tbody>
    </tbody>
</table>
<p>如果您访问 Mobile2Market <a onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl05',this);" href="http://msdn.microsoft.com/mobility/windowsmobile/partners/mobile2market/smartphoneapps/default.aspx"><em><u><font color=#0000ff>Build Applications</font></u></em></a> 页，则可以找到主流移动运营商所采用的安全策略决策。 </p>
<div><a href="http://msdn2.microsoft.com/zh-cn/library/ms839377.aspx#mainSection"><img alt="" src="http://msdn2.microsoft.com/zh-cn/library/ms839377.arrow_px_up(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839377.aspx#mainSection"><u><font color=#800080>返回页首</font></u></a> <br></div>
<h3 id=EEAA>代码签名实践</h3>
<p>作为一名软件开发人员，在开发代码和部署应用程序的过程中，代码签名会对您产生影响。在开发过程中，您需要了解如何用证书配置仿真程序或设备来支持开发。当您想要部署应用程序时，您需要了解如何对应用程序进行数字签名、需要对哪些组件进行签名，以及如何对这些组件进行签名。</p>
<p>在开始开发 Smartphone 应用程序之前，您需要准备您的 Smartphone 设备和开发环境。对于 Smartphone 2002，您将了解如何配置 eMbedded Visual C++&#174; 3.0 以及如何选择是否使用特权或非特权证书进行签名。对于 Smartphone 2003，您将了解如何配置 eMbedded Visual C++ 4.0 和 Microsoft Visual Studio&#174; .NET 2003，以便使它们使用一套相同的证书，从而简化开发过程。</p>
<p><strong>Smartphone 2002 </strong><strong>和</strong> <strong>2003 </strong><strong>的共同配置步骤</strong> </p>
<p>对于 Smartphone 2002 和 Smartphone 2003，您需要使用 SDK 工具目录的命令提示来执行一些配置步骤。如果您已经在默认的位置安装了这些工具，则工具的目录为： </p>
<table>
    <tbody>
        <tr>
            <th>
            <p>平台</p>
            </th>
            <th>
            <p>工具目录</p>
            </th>
        </tr>
        <tr>
            <td>
            <p>Smartphone 2002</p>
            </td>
            <td>
            <p>C:\Windows CE Tools\wce300\Smartphone 2002\tools</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>Smartphone 2003</p>
            </td>
            <td>
            <p>C:\Program Files\Windows CE Tools\wce420\SMARTPHONE 2003\Tools</p>
            </td>
        </tr>
    </tbody>
</table>
<table>
    <tbody>
    </tbody>
</table>
<p>按照下面这些步骤打开命令提示，并将目录切换到工具目录： </p>
<ol>
    <li>
    <p>单击 <em>Start</em> 菜单，然后单击 <em>Run</em>（或者按下 Windows 徽标键和 R）。Run 对话框打开。 </p>
    <li>
    <p>在编辑字段中键入 <em>cmd</em>，然后按下 ENTER 键。命令窗口打开。 </p>
    </li>
</ol>
<p><img alt="" src="http://msdn2.microsoft.com/zh-cn/library/ms839377.smartphone_security01(zh-cn,MSDN.10).gif"> </p>
<div><strong>图</strong> <strong>1. </strong><strong>打开命令窗口</strong> </div>
<ol>
    <li>
    <p>将目录切换到上面特定于平台的工具目录。键入 cd &lt;tools path&gt;，然后按下 ENTER 键。 </p>
    </li>
</ol>
<p><img alt="" src="http://msdn2.microsoft.com/zh-cn/library/ms839377.smartphone_security02(zh-cn,MSDN.10).gif"> </p>
<div><strong>图</strong> <strong>2. </strong><strong>将目录切换到特定于平台的工具目录</strong> </div>
<p><strong>创建开发证书</strong> </p>
<p>Smartphone 2002 和 2003 SDK 附带有称为 <em>spdps</em> 的工具，该工具可用于创建特权开发人员证书，以便对设备端开发工具进行签名，并将该证书提供给 Smartphone 和 Smartphone 仿真程序。应当单独对 Smartphone 2002 和 Smartphone 2003 运行 <em>spdps</em> 命令，以确保仿真程序配置有适当的证书和对您的调试工具进行签名。</p>
<p><em>spdps </em>工具安装在 SDK 工具目录中。按照前面的步骤打开命令提示，并将目录切换到适当的工具目录：</p>
<table>
    <tbody>
        <tr>
            <th>
            <p>平台</p>
            </th>
            <th>
            <p>工具名称</p>
            </th>
            <th>
            <p>工具目录</p>
            </th>
        </tr>
        <tr>
            <td>
            <p><em>Smartphone 2002</em> </p>
            </td>
            <td>
            <p>sp2002dps</p>
            </td>
            <td>
            <p>C:\Windows CE Tools\wce300\Smartphone 2002\tools</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>Smartphone 2003</p>
            </td>
            <td>
            <p>spdps</p>
            </td>
            <td>
            <p>C:\Program Files\Windows CE Tools\wce420\SMARTPHONE 2003\Tools</p>
            </td>
        </tr>
    </tbody>
</table>
<table>
    <tbody>
    </tbody>
</table>
<p>现在用 /create 与 /device 参数运行前表中指定的工具；例如，键入&#8220;sp2002dps /create /device&#8221;，&lt;ENTER&gt; 将会运行 Smartphone 2002 的工具。在发出该命令之前，您必须将设备连接到 PC 和已建立的 ActiveSync 连接中。</p>
<p>图 3 显示的是您期望看到的情形。</p>
<p><img alt="" src="http://msdn2.microsoft.com/zh-cn/library/ms839377.smartphone_security03(zh-cn,MSDN.10).gif"> </p>
<div><strong>图</strong> <strong>3. </strong><strong>按下</strong> <strong>ENTER </strong><strong>返回特定于平台的工具的结果</strong> </div>
<p>我们在这里做的是对所有的设备端开发组件、远程工具和具有本地创建证书的调试器进行签名。这些工具需要对设备进行特权访问，因此我们将本地创建的证书&#8220;推&#8221;到了设备的特权执行信任存储区，这样设备将允许组件以特权进程运行。</p>
<p>有些移动运营商可能选择不支持即装即用开发的设备配置。在这种情况下，您将会看到下面的错误： </p>
<p><img alt=无标题 src="http://msdn2.microsoft.com/zh-cn/library/ms839377.smartphone_security04(zh-cn,MSDN.10).gif"> </p>
<div><strong>图</strong> <strong>4. </strong><strong>选择不支持即装即用开发的设备配置会返回一个错误</strong> </div>
<p>如果您的电话不支持即装即用开发，您需要联系移动运营商，看看他们是否提供配置电话的服务，这样您可以为其进行开发。例如，他们可能在 Web 上有一个开发人员计划，您可以加入并能够进行电话开发。</p>
<p>如果您在多个电话上进行开发，则您可以使用 spdps /device 命令将开发证书&#8220;推&#8221;到每个电话中。在这种情况下，您只需要使用 /device 参数。</p>
<p><img alt=无标题 src="http://msdn2.microsoft.com/zh-cn/library/ms839377.smartphone_security05(zh-cn,MSDN.10).gif"> </p>
<div><strong>图</strong> <strong>5. </strong><strong>使用一个参数</strong> </div>
<p>当您使用不带 /create 开关的 /device 时，实用工具会要求您选择一种证书。</p>
<p><img alt=无标题 src="http://msdn2.microsoft.com/zh-cn/library/ms839377.smartphone_security06(zh-cn,MSDN.10).gif"> </p>
<div><strong>图</strong> <strong>6. </strong><strong>选择一种证书</strong> </div>
<p><em>当</em> eVC 第一次以 Smartphone 设备为目标时，会自动创建&#8220;&lt;username&gt; Default Development Certificate&#8221;。可以通过 spdps /create 创建&#8220;Smartphone Privileged Development Certificate for &lt;username&gt;&#8221;。在这种情况下，我们希望选择&#8220;Smartphone Privileged Development Certificate for &lt;username&gt;&#8221;以&#8220;推&#8221;到设备中。该过程完成后，您将会看到一个同前面一样的成功屏幕。</p>
<p>切记，如果您硬重置电话或者电池完全没电，您需要通过重复这些步骤来重新配置电话。</p>
<p><strong>Smartphone 2002 </strong><strong>的特定配置步骤</strong> </p>
<p>对于 Smartphone 2002，您只能使用 eMbedded Visual C++ 3.0 来开发应用程序。采用上面提及的步骤，您可以在设备的特权和非特权证书存储区上创建一个已知的证书。这将会帮助您确定您的应用程序是否需要进行特权或非特权签名。这种方法重点在于通过仿真程序配置实际的 Smartphone 设备。仿真程序配备有开放式安全策略，这使得您能够开发任何类型的应用程序。由于运营商选择他们自己的安全策略，因此只有在您作为开发人员面对设备时才需要知道您使用哪一种证书进行签名。</p>
<p><strong>Smartphone 2003 </strong><strong>的特定配置步骤</strong> </p>
<p>您可以使用两种工具来为 Smartphone 2003 开发应用程序。前面的步骤已经配置好设备，这样 eMbedded Visual C++ 4.0 就可以将应用程序部署到设备和仿真程序并进行调试。Smartphone 2003 SDK 附带有特权和非特权开发证书。这些证书已经加载到了仿真程序特权和非特权证书存储区中。Visual Studio .NET 2003 使用非特权证书作为默认的证书。这部分重点在于配置您的设备，以便可以使用这些证书，这样您所有的工具和仿真程序就都有一套一致的证书。</p>
<p><strong>将测试证书添加到个人证书存储区</strong> </p>
<p>首先，您必须在您的开发 PC 上将 SDK 工具目录附带的证书添加到个人证书存储区中。这些证书文件称为 TestCert_Privileged.pfx and TestCert_UnPrivileged.pfx。为了将各个证书安装到个人证书存储区中，您需要： </p>
<ol>
    <li>
    <p>在 Explorer 中双击 .pfx 文件。 </p>
    <li>
    <p>单击&#8220;Next&#8221;。 </p>
    <li>
    <p>再次单击&#8220;Next&#8221;。 </p>
    <li>
    <p>再次单击&#8220;Next&#8221;— 证书没有密码。 </p>
    <li>
    <p>选择&#8220;Automatically select cert store&#8221;，然后单击&#8220;Next&#8221;。 </p>
    <li>
    <p>单击&#8220;Finish&#8221;。 </p>
    </li>
</ol>
<p><strong>将证书提供给设备</strong> </p>
<p>一旦您将证书添加到个人证书存储区，您就需要将它们添加到设备。这里您需要使用 rapiconfig 工具。Smartphone 2003 SDK 附带有将这些证书添加到适当设备证书存储区中的配置文件。使用前面给出的指导打开命令提示，并切换到 SDK 工具目录。类型：</p>
<pre>rapiconfig /p sdktestcerts.xml &lt;press enter&gt;
</pre>
<p>您应看到： </p>
<p><img alt="" src="http://msdn2.microsoft.com/zh-cn/library/ms839377.smartphone_security07(zh-cn,MSDN.10).gif"> </p>
<div><strong>图</strong> <strong>7. </strong><strong>使用</strong> <strong>rapiconfig </strong><strong>工具切换目录</strong> </div>
<p><strong>配置</strong> <strong>eMbedded Visual C++ 4.0 </strong><strong>项目</strong> <strong></strong></p>
<p>现在您的设备包含了 SDK 测试证书。最后一步是更新 eMbedded Visual C++ 4.0 项目，这样在部署它时它使用非特权测试证书来对应用程序进行签名。在 eMbedded Visual C++ 4.0 中： </p>
<ol>
    <li>
    <p>转到 Project，然后选择&#8220;Settings&#8221;。 </p>
    <li>
    <p>滚动到最右侧的选项卡&#8220;Security&#8221;（参见步骤 7 中的注释）。 </p>
    <li>
    <p>只选中顶部的复选框（对该应用程序进行签名）。 </p>
    <li>
    <p>按下上面的&#8220;Browse&#8221;按钮。 </p>
    <li>
    <p>选择称为&#8220;Smartphone 2003 Unprivileged Test Signing Authority&#8221;的证书，然后单击&#8220;OK&#8221;。 </p>
    <li>
    <p>取消选中&#8220;Configure device to trust signed applications&#8221;复选框。 </p>
    <p><strong>注</strong> 我们已经将证书提供到我们希望它们位于其中的存储区；因此我们不希望工具再次提供它们。通过取消选中该框，我们可以防止错误的证书进入到错误的存储区中。</p>
    <li>
    <p>单击&#8220;OK&#8221;。 </p>
    <p><strong>注</strong> Security 选项卡仅出现在 Smartphone 项目中。确保主 IDE 中的目标平台设置为 Smartphone 而不是 Pocket PC。即使您创建的是一个 Smartphone 项目，eMbedded Visual C++ 4.0 有时也会默认选择 Pocket PC，而不是 Smartphone。</p>
    </li>
</ol>
<p><strong>配置</strong> <strong>Visual Studio .NET 2003</strong> </p>
<p>Visual Studio 默认情况下，.NET 2003 使用 Smartphone 2003 SDK 所附带的证书。用适当的证书配置设备的步骤就是完成配置 Visual Studio .NET 2003 以自动用非特权证书对应用程序进行签名所需的步骤。</p>
<p>如果您确定您的 Visual Studio .NET 2003 应用程序需要进行特权签名，您就需要使用称为&#8220;Smartphone 2003 Privileged Test Signing Authority&#8221;的特权测试证书对应用程序组件（.exe 与 .dll）进行手动签名。您可以使用 signcode 工具来做到这一点。signcode 工具的使用在为部署进行应用程序签名 一节中进行介绍。</p>
<p><strong>注</strong> 这使得您能够通过从设备启动可执行文件来运行 一个需要特权信任的应用程序。然而，如果您从开发环境运行或调试应用程序，它将会使用非特权证书再次对应用程序进行签名。</p>
<p><strong>考虑特权访问的开发</strong> </p>
<p><strong>访问特权注册表项</strong> </p>
<p>您可以打开和浏览特权注册表项和值，但是您不能创建、修改，或者删除项或值。所有的注册表访问函数都返回一个 LONG 值。当您试图对一个要求特权访问的项执行创建、修改或删除时，返回值将为 ERROR_ACCESS_DENIED (0x05)。一定要检查这些注册表函数返回值并得体地失败！</p>
<p>在<a onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl06',this);" href="http://msdn.microsoft.com/mobility/understanding/gettingstarted/windowsmobile/default.aspx?pull=/library/en-us/dnsmtphn2k3/html/smartphone_security.asp"><em><u><font color=#0000ff>附录 A</font></u></em></a> 中有一个特权注册表项列表。</p>
<p><strong>调用特权</strong> <strong>API</strong> </p>
<p>如果您的应用程序中某个 API 失败，那可能是您调用了一个特权 API 而没有以特权信任模式运行。在这种情况下，函数调用会失败。每个函数指示它失败的方式是不同的，一般是通过一些返回值来指示。这本身不足以指示调用失败，因为您需要以特权信任模式运行。</p>
<p>如果由于您需要特权信任而怀疑某个函数调用失败，您可以调用 GetLastError 函数。如果返回值为 0x05 (ERROR_ACCESS_DENIED)，则表明为了使用该函数您可能需要以特权信任模式运行。</p>
<p>参阅说明由于需要特权签名而引发问题时如何进行经验测试的章节。</p>
<p>在<a onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl07',this);" href="http://msdn.microsoft.com/mobility/understanding/gettingstarted/windowsmobile/default.aspx?pull=/library/en-us/dnsmtphn2k3/html/smartphone_security.asp"><em><u><font color=#0000ff>附录 B</font></u></em></a> 中有一个特权 API 列表。</p>
<p><strong>编写</strong> <strong>DLL </strong><strong>与其他的组件</strong> </p>
<p>对于一个可执行文件来说，从其他的可执行组件（例如 DLL）加载功能是很常见的。通常，这是以运行时或者链接时加载函数的形式进行。有些标准的 Smartphone 应用程序允许通过编写实现特定功能的 DLL 来扩展其自身，例如 ActiveSync、Inbox 和 Home Screen。</p>
<p>当某个 Smartphone 可执行文件试图加载另一个组件时，系统要检查可执行文件的特权级别。如果它发现组件的信任级别低，它就不允许加载该组件。</p>
<p>几乎所有的系统可执行文件都是以特权信任模式运行的，记住这一点尤为重要。</p>
<p>对于 Smartphone 2002，试图将一个非特权组件加载到一个特权进程中将会失败而且系统不会给出任何提示。例如，您可能会试图创建一个 ActiveSync 服务提供程序。虽然您已经正确地在桌面和设备上安装了组件，而在桌面端，服务提供程序以 ActiveSync 选项的形式出现，当您试图进行同步时，没有传输数据，因为您的组件从来就没有加载到设备端。根据经验，任何插入到系统应用程序的组件都需要用特权证书进行签名。</p>
<p>对于 Smartphone 2003，试图将非特权组件加载到一个特权进程中的结果取决于安全策略。如有运营商允许提示模式，则系统会提示用户并请求决定是否加载组件。询问用户： </p>
<pre>This program needs a component from an unknown source that may not be trustworthy.
Do you want to load this component?
</pre>
<p>如果运营商不支持提示模式，则该行为与 Smartphone 2002 的一样。</p>
<p><strong>如果由于它需要特权签名而使我的应用程序或组件失败，我应如何进行经验测试？</strong> </p>
<p>如果您遵循了前面的配置指导，您的开发环境应当配置成自动用一个已知的非特权证书对应用程序进行签名。如果您遵循了这些配置指导并认为应用程序或组件可能需要特权签名，则您可以进行经验测试，方法是用您知道的设备特权存储区中的一个特权证书来进行签名。假定您已经利用前面的指导配置了环境，您可以通过以下步骤来帮助识别与安全有关的失败。</p>
<p><strong>eMbedded Visual C++ 3.0 </strong><strong>与</strong> <strong>4.0</strong> </p>
<p>对于 eMbedded Visual C++ 系列，您需要在项目设置中更改用来进行应用程序或组件签名的证书。取决于您使用的是 eMbedded Visual C++ 3.0 还是 4.0&#163;&#172;您需要进行稍有点不同的选择。</p>
<p><strong>注</strong> 由于 Smartphone 2002 仿真程序附带有开放式安全策略，所以您不能使用仿真程序来对 Smartphone 2002 执行这种测试。</p>
<table>
    <tbody>
        <tr>
            <th>
            <p>eVC 版本</p>
            </th>
            <th>
            <p>证书名称</p>
            </th>
        </tr>
        <tr>
            <td>
            <p><em>3.0</em> </p>
            </td>
            <td>
            <p>&lt;username&gt; 的 Smartphone 特权开发证书</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>4.0</p>
            </td>
            <td>
            <p>Smartphone 2003 特权测试签名颁发机构</p>
            </td>
        </tr>
    </tbody>
</table>
<table>
    <tbody>
    </tbody>
</table>
<ol>
    <li>
    <p>转到 Project 并选择 Settings。 </p>
    <li>
    <p>滚动到最右侧的选项卡 Security（参见步骤 7 中的注释）。 </p>
    <li>
    <p>只选中上面的复选框（对该应用程序进行签名） </p>
    <li>
    <p>按下上面的 Browse 按钮。 </p>
    <li>
    <p>从上表选择证书。 </p>
    <li>
    <p>取消选中&#8220;Configure device to trust signed applications&#8221;复选框。 </p>
    <p><strong>注</strong> 我们已经将证书提供到了我们希望它们位于其中的存储区；因此我们不希望工具再次提供它们。通过取消选中该框，我们可以防止错误的证书进入到错误的存储区中。</p>
    <li>
    <p>单击&#8220;OK&#8221;。 </p>
    <p><strong>注</strong>Security 选项卡仅出现在 Smartphone 项目中。确保主 IDE 中的目标平台设置为 Smartphone 而不是 Pocket PC。即使您创建的是一个 Smartphone 项目，eMbedded Visual C++ 4.0 有时会默认选择 Pocket PC，而不是Smartphone。</p>
    </li>
</ol>
<p>如果您现在重新构建所有的 应用程序或组件，则会使用一个特权证书进行签名。如果您的应用程序或组件现在像您所期望的那样开始正常工作，应用程序就需要进行特权签名。</p>
<p><strong>Visual Studio .NET 2003</strong> </p>
<p>用 Visual Studio .NET 2003测试稍有不同。在这种情况下，您需要使用 signcode 工具来对组件进行手动签名，然后尝试部署它们。关于使用 signcode 的指导在本文档的为部署进行应用程序签名 一节中。您需要选择 Smartphone 2003 特权测试签名颁发机构 证书来对应用程序或组件进行签名。切记，Visual Studio .NET 2003 只支持 Smartphone 2003。</p>
<p><strong>查询</strong> <strong>Smartphone </strong><strong>的证书存储区中有哪些证书</strong> </p>
<p>Smartphone 2003 和 Smartphone 2002 SDK 都附带有一个称为 rapiconfig 的工具。rapiconfig 允许您对电话上的证书存储区进行查询。2002 和 2003 SDK 都附带有一个名为 querystore.xml 的示例文件。您可以使用该文档来确切地查询电话在其特权、非特权以及安装存储区中有哪些证书。您将学会如何做到这些，包括： </p>
<ol>
    <li>
    <p>为特权、非特权以及安装存储区创建适当的 .xml 文件。 </p>
    <li>
    <p>使用 rapiconfig 获取电话信息。 </p>
    <li>
    <p>识别电话是否为开发而锁定。 </p>
    </li>
</ol>
<p><strong>创建查询文件</strong> </p>
<p>模板 querystore.xml 如下所示：</p>
<pre>&lt;!-- Sample XML to query a certificate store  --&gt;
&lt;wap-provisioningdoc&gt;
&lt;characteristic type="CertificateStore"&gt;
&lt;characteristic-query type="{Enter certificate store name over here}" /&gt;
&lt;/characteristic&gt;
&lt;/wap-provisioningdoc&gt;
</pre>
<p>您需要创建该文档的三个名为 querystore_priv.xml、querystore_unpriv.xml 和 querystore_spc.xml 的副本。名称并不重要；然而，在整个示例中我们将要使用这些名称。在 SDK 工具目录中制作 querystore.xml 的多个副本，这样它们就可以更容易地与命令行工具 rapiconfig 一起使用。</p>
<p>您可以使用记事本、喜爱的文本或 XML 编辑器来编辑这些文件。</p>
<table>
    <tbody>
        <tr>
            <th>
            <p>对于_</p>
            </th>
            <th>
            <p>替换_</p>
            </th>
            <th>
            <p>使用_</p>
            </th>
        </tr>
        <tr>
            <td>
            <p><em>Querystore_unpriv.xml</em> </p>
            </td>
            <td>
            <p>{在此输入证书存储区的名称}</p>
            </td>
            <td>
            <p>非特权执行信任 Authorities</p>
            </td>
        </tr>
        <tr>
            <td>
            <p><em>Querystore_priv.xml</em> </p>
            </td>
            <td>
            <p>{在此输入证书存储区的名称}</p>
            </td>
            <td>
            <p>特权执行信任 Authorities</p>
            </td>
        </tr>
        <tr>
            <td>
            <p><em>Querystore_spc.xml</em> </p>
            </td>
            <td>
            <p>{在此输入证书存储区的名称}</p>
            </td>
            <td>
            <p>SPC</p>
            </td>
        </tr>
    </tbody>
</table>
<table>
    <tbody>
    </tbody>
</table>
<p><strong>Using RAPIConfig</strong> </p>
<p>请参阅&#8220;配置开发环境&#8221;一节，打开 SDK 工具目录中的命令提示。rapiconfig 工具的工作方式对于 2002 和 2003 有点不同。2002 版输出在屏幕上；而 2003 版输出到一个文件。下面的指令将产生三个 .xml 文件。每个 .xml 文件都包含有某个特定存储区中的证书列表。 </p>
<p>Smartphone 2002 </p>
<pre>rapiconfig /p querystore_unpriv.xml &gt; unpriv_certs.xml &lt;press enter&gt;
rapiconfig /p querystore_priv.xml  &gt; priv_certs.xml &lt;press enter&gt;
rapiconfig /p querystore_spc.xml  &gt; spc_certs.xml &lt;press enter&gt;
</pre>
<p>Smartphone 2003</p>
<pre>rapiconfig /p querystore_unpriv.xml &lt;press enter&gt;
copy rapiconfigout.xml priv_certs.xml
rapiconfig /p querystore_priv.xml &lt;press enter&gt;
copy rapiconfigout.xml priv_certs.xml
rapiconfig /p querystore_spc.xml &lt;press enter&gt;
copy rapiconfigout.xml spc_certs.xml
</pre>
<p>您现在有三个文件，每个都包含有某个证书存储区中的证书列表：</p>
<table>
    <tbody>
        <tr>
            <th>
            <p>文件</p>
            </th>
            <th>
            <p>证书列表_</p>
            </th>
        </tr>
        <tr>
            <td>
            <p><em>priv_certs.xml</em> </p>
            </td>
            <td>
            <p>特权存储区</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>priv_certs.xml</p>
            </td>
            <td>
            <p>非特权存储区</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>spc_certs.xml</p>
            </td>
            <td>
            <p>安装存储区</p>
            </td>
        </tr>
    </tbody>
</table>
<table>
    <tbody>
    </tbody>
</table>
<p>如果您从 rapiconfig 获得一条错误消息，您应当检查下一部分。</p>
<p><strong>如果由于开发您的</strong> <strong>Smartphone </strong><strong>被锁定，将会发生什么情况？</strong> </p>
<p>运营商可以控制的电话安全的一个方面就是开发人员是否能够从他们的开发机器连接到电话。如果运营商选择了受限的策略，您将会接收到一条错误消息： </p>
<pre> Config failed (0x80070005): Access is denied
</pre>
<p>如果是这种情况，您就需要联系运营商，弄清楚他们是否为开发人员制定了一个允许您根据他们的特定电话硬件进行开发的计划。</p>
<p><strong>注</strong> 如果 .xml 文件中有错误，您也会接收到一条拒绝访问错误消息；但是错误号将为 0x80042004。</p>
<p><strong>为部署进行应用程序签名</strong> </p>
<p>要对应用程序进行签名，您需要获得受一个或多个目标电话信任的数字证书。该数字证书的信任级别必须达到运行所需的执行特权；也就是说，如果需要特权信任执行，则需用特权证书进行签名。如果只需要非特权信任执行，则需用非特权证书进行签名。对于大多数应用程序来说，非特权信任执行足够了。</p>
<p><strong>获得证书</strong> </p>
<p>Mobile2Market 在所有附带基于 Windows Mobile 的 Smartphones 的非特权存储区中都有证书。为了对应用程序进行签名，以便使其在各种手机中工作，我们建议您从 Mobile2Market <a onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl08',this);" href="http://msdn.microsoft.com/mobility/windowsmobile/partners/mobile2market/participatevendors.aspx"><em><u><font color=#0000ff>Participate Now</font></u></em></a> 一节中的一个参与证书供应商处购买证书。</p>
<p>从这些供应商处获得的证书通常是不受电话信任的。您必须使用此证书来对应用程序进行签名，然后将经过签名的应用程序提交给（通常通过 Web 接口）您的证书供应商。然后，该证书供应商会让一个自动进程用 Smartphone 信任的证书对应用程序进行签名，并为您提供一个下载该应用程序的链接。完成这些后，该供应商就可以验证您的身份，从而帮助维护电话信任证书的完整性。</p>
<p>该证书通常附带有包含所需 PIN 代码的物理 USB 设备。供应商会给您发送如何装配的指导。</p>
<p><strong>对应用程序和安装程序进行签名</strong> </p>
<p>一旦您已经完成开发并获得证书，就可以通过 5 个简单的步骤来创建经过签名的应用程序： </p>
<ol>
    <li>
    <p>可以用从一个 Mobile2Market 证书供应商处购买的证书来对应用程序的可执行组件（.exe 和 .dll）进行签名。下面是关于如何完成这些的指导。 </p>
    <li>
    <p>通过 Web 接口将经过签名的应用程序组件提交给证书供应商。联系您的证书供应商以获得具体指导。受电话信任的证书签名的一个或多个文件将返回给您。 </p>
    <li>
    <p>将这些组件构建到安装包 (.cab) 文件中。 </p>
    <li>
    <p>使用从某个 Mobile2Market 证书供应商处购买的证书对 .cab 文件进行签名。本文后面的部分有关于如何这样做的指导。 </p>
    <li>
    <p>通过 Web 接口将经过签名的 .cab 文件提交给您的证书供应商。联系您的证书供应商以获得具体指导。经过签名的 .cab 文件将返回给您。 </p>
    </li>
</ol>
<p>然后，可以将该 .cab 文件安装在所有基于 Windows Mobile 的 Smartphone 上。该应用程序无需提示即可自己运行。</p>
<p>为了对 .exe、.dll 或 .cab 文件进行签名，您需要使用 <em>signcode.exe</em> 工具，对于 Smartphone 2002 和 Smartphone 2003，该工具都安装在 Tools 目录中。这两种工具完全相同。运行该工具时，系统将呈现一个向导。</p>
<p><img alt="" src="http://msdn2.microsoft.com/zh-cn/library/ms839377.smartphone_security08(zh-cn,MSDN.10).gif"> </p>
<div><strong>图</strong> <strong>8. </strong><strong>打开数字签名向导</strong> </div>
<p>单击 Next，系统将询问您想要对哪个文件进行签名。您必须为每个要签名的组件（即为每个 .exe 和 .dll 以及您最终的 .cab 文件）运行一次该工具。可以看到我已经从我的项目的 ARMRel 目录中选择了 Signing Demo.exe。</p>
<p><img alt="" src="http://msdn2.microsoft.com/zh-cn/library/ms839377.smartphone_security09(zh-cn,MSDN.10).gif"> </p>
<div><strong>图</strong> <strong>9. </strong><strong>在数字签名向导中选择文件</strong> </div>
<p>单击 Next 后，系统将询问您是想要 Typical 设置还是 Advanced 设置；选择 Typical。下一屏让您选择签名所使用的证书。选择 Select From Store，然后，个人证书存储区中将为您呈现一个证书列表。您要使用的不是我们现在已经用完的本地创建的证书，而是从供应商处购买的证书。</p>
<p><strong>注</strong> 用 codesign 签名不会用完包含提供程序的签名事件。只有在通过供应商的 Web 站点将本地签名的应用程序提交给他们时，才会使用签名事件。</p>
<p><img alt="" src="http://msdn2.microsoft.com/zh-cn/library/ms839377.smartphone_security10(zh-cn,MSDN.10).gif"> </p>
<div><strong>图</strong> <strong>10. </strong><strong>选择签名证书</strong> </div>
<p>您应该很容易就能够识别您的 Mobile2Market 证书，因为 Issued By 字段和您从中购买证书的公司名相同。例如，我选择了 Geotrust 证书。一旦单击了 OK，就可以单击 Next。</p>
<p>下一屏将询问可选的描述数据；您可以单击 Next。您也不需要添加时间戳，所以可单击时间戳屏幕上的 Next。</p>
<p>现在，您已经成功地导航了该向导。单击 Finish，系统会对您的 .exe、.dll 或 .cab 进行签名。现在，您已准备好将组件提交给您的签名供应商。请参考供应商的指导来完成这些，但一般情况下一定要登录他们的 Web 站点，通常要使用他们发送的 USB 证书来验证身份。一旦登录，您就可以上载组件，并将这些组件用受 Smartphone 信任的证书进行签名。</p>
<p><strong>对需要特权访问的应用程序进行签名</strong> </p>
<p>对于某些安全策略，运营商拥有特权证书存储区中的证书。如果确定需要特权执行信任，那么您就需与您的运营商联系，通常通过他们的开发人员计划来确定如何用该证书对您的应用程序进行签名。</p>
<p><strong>注</strong> 运营商可以自行决定是否为您提供该项服务。</p>
<div><a href="http://msdn2.microsoft.com/zh-cn/library/ms839377.aspx#mainSection"><img alt="" src="http://msdn2.microsoft.com/zh-cn/library/ms839377.arrow_px_up(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839377.aspx#mainSection"><u><font color=#800080>返回页首</font></u></a> <br></div>
<h3 id=EDAA>小结</h3>
<p>Smartphone 应用程序安全策略和代码签名开始时可能会让人畏缩，似乎很复杂。而实际上它非常简单，通过本文，您现在可以了解 Smartphone 的不同证书存储区、如何将证书放置在这些存储区中，以及在开始部署时如何确保用正确的证书来对应用程序进行签名。使用这些简单的方法，可以确保您用正确的信任级别来对应用程序进行签名。</p>
<p>如果您有关于本文内容的任何反馈，请发送邮件到 <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#119;&#109;&#115;&#101;&#99;&#102;&#98;&#107;&#64;&#109;&#105;&#99;&#114;&#111;&#115;&#111;&#102;&#116;&#46;&#99;&#111;&#109;"><em><u><font color=#0000ff>wmsecfbk@microsoft.com</font></u></em></a>。</p>
<div><a href="http://msdn2.microsoft.com/zh-cn/library/ms839377.aspx#mainSection"><img alt="" src="http://msdn2.microsoft.com/zh-cn/library/ms839377.arrow_px_up(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839377.aspx#mainSection"><u><font color=#800080>返回页首</font></u></a> <br></div>
<h3 id=ECAA>附录 A：受保护的注册表项</h3>
<table>
    <tbody>
        <tr>
            <th>
            <p>注册表项</p>
            </th>
        </tr>
        <tr>
            <td>
            <p>HKEY_LOCAL_MACHINE\Comm</p>
            <p>HKEY_LOCAL_MACHINE\Drivers</p>
            <p>HKEY_LOCAL_MACHINE\HARDWARE</p>
            <p>HKEY_LOCAL_MACHINE\SYSTEM</p>
            <p>HKEY_LOCAL_MACHINE\Init</p>
            <p>HKEY_LOCAL_MACHINE\Security</p>
            <p>HKEY_LOCAL_MACHINE\WDMDrivers</p>
            <p>HKEY_LOCAL_MACHINE\Services</p>
            <p>HKEY CLASSES_ROOT (device specific)</p>
            </td>
        </tr>
    </tbody>
</table>
<table>
    <tbody>
    </tbody>
</table>
<div><a href="http://msdn2.microsoft.com/zh-cn/library/ms839377.aspx#mainSection"><img alt="" src="http://msdn2.microsoft.com/zh-cn/library/ms839377.arrow_px_up(zh-cn,MSDN.10).gif" border=0><u><font color=#800080> </font></u></a><a href="http://msdn2.microsoft.com/zh-cn/library/ms839377.aspx#mainSection"><u><font color=#800080>返回页首</font></u></a> <br></div>
<h3 id=EBAA>附录 B：特权 API 列表</h3>
<table>
    <tbody>
        <tr>
            <th>
            <p>组件</p>
            </th>
            <th>
            <p>API</p>
            </th>
        </tr>
        <tr>
            <td>
            <p>Public</p>
            </td>
            <td>
            <p>SetInterruptEvent</p>
            <p>SetSystemMemoryDivision</p>
            <p>CESetThreadPriority</p>
            <p>CeSetThreadQuantum</p>
            <p>ForcePageout</p>
            <p>VirtualCopy</p>
            <p>LockPages</p>
            <p>UnlockPages</p>
            <p>SetProcPermissions</p>
            <p>SetKMode</p>
            <p>ReadProcessMemory</p>
            <p>WriteProcessMemory</p>
            <p>SetCleanRebootFlag</p>
            <p>PowerOffSystem</p>
            <p>DebugActiveProcess</p>
            <p>CreateProcess（仅 DEBUG_ONLY_THIS_PROCESS 和 DEBUG_PROCESS 调试标志）</p>
            <p>KernelIOControl</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>扩展的电话应用程序接口 (ExTAPI)</p>
            </td>
            <td>
            <p>lineRegister </p>
            <p>lineSetCallBarringPassword</p>
            <p>lineSetCallBarringState </p>
            <p>lineUnregister </p>
            <p>lineSetPreferredOperator</p>
            <p>lineSetEquipmentState</p>
            <p>lineGetGeneralInfo</p>
            <p>lineManageCalls</p>
            <p>lineSetGprsClass</p>
            <p>lineGetNumberCalls</p>
            <p>lineSetHSCSDState</p>
            <p>lineGetUSSD</p>
            <p>lineSendUSSD</p>
            <p>lineSetSendCallerIDState</p>
            <p>lineSetCallWaitingState</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>SIM 管理器</p>
            </td>
            <td>
            <p>simUnlockPhone </p>
            <p>simSetLockingStatus</p>
            <p>simGetSmsStorageStatus</p>
            <p>simChangeLockingPassword </p>
            <p>simReadMessage</p>
            <p>simWriteMessage</p>
            <p>simDeleteMessage</p>
            <p>simReadRecord</p>
            <p>simWriteRecord</p>
            <p>simGetRecordInfo</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>短消息服务</p>
            </td>
            <td>
            <p>SmsSetMessageNotification</p>
            <p>SmsClearMessageNotification</p>
            <p>SmsReceiveAllMessagesFromSIM</p>
            <p>SmsSetSMSC</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>连接管理器</p>
            </td>
            <td>
            <p>ConnMgrProviderMessage</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>Critical Process Monitor (CPM)</p>
            </td>
            <td>
            <p>CPMRegister (Reboot)</p>
            <p>CPMShutdown</p>
            <p>CPMStatus</p>
            <p>CPMRegisterTest</p>
            </td>
        </tr>
        <tr>
            <td>
            <p>无线电接口层</p>
            </td>
            <td>
            <p>全部 RIL API</p>
            <p><strong>注</strong> <strong></strong>RIL API 所需的信任级别可通过将下列注册表项的值从 2 更改为 1 而得以修改：<br>[HKEY_LOCAL_MACHINE\Security\Policy\APIs\RILGSM] @="2"</p>
            </td>
        </tr>
    </tbody>
</table>
</div>
</div>
</div>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/38707.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-17 11:14 <a href="http://www.cppblog.com/gtwdaizi/articles/38707.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VC\S60 Static Library中获取毫秒级时间</title><link>http://www.cppblog.com/gtwdaizi/articles/33245.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Sun, 07 Oct 2007 02:28:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/33245.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/33245.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/33245.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/33245.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/33245.html</trackback:ping><description><![CDATA[<p>在vc下获取毫秒级时间有很多种方法, 但是在windows mobile下找了半天找到了下面的方法:<br><br>&nbsp;DWORD temp = GetTickCount();<br>&nbsp;readLen = fread(fileBuffer, 1, readLen, fp);<br>&nbsp;// 打印读取文件所需时间<br>&nbsp;printf("read file time: %d\n",GetTickCount()-temp);</p>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/33245.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 10:28 <a href="http://www.cppblog.com/gtwdaizi/articles/33245.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows Mobile下的SpbPocketPlus3安装</title><link>http://www.cppblog.com/gtwdaizi/articles/33180.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Sun, 07 Oct 2007 02:17:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/33180.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/33180.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/33180.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/33180.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/33180.html</trackback:ping><description><![CDATA[<p>靠,关于这个主题写了半天提交的时候没有成功, 报废了, 白写了, 也不想再写了, 反正总而言之, 我是直接在pc上面安装这个软件然后同步到PDA就好了, 而不是使用在PDA上面直接安装的方式..<br>有问题大家可以留言!</p>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/33180.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 10:17 <a href="http://www.cppblog.com/gtwdaizi/articles/33180.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><item><title>Windows Mobile5.0 开发平台的搭建</title><link>http://www.cppblog.com/gtwdaizi/articles/32838.html</link><dc:creator>郭天文</dc:creator><author>郭天文</author><pubDate>Tue, 25 Sep 2007 15:44:00 GMT</pubDate><guid>http://www.cppblog.com/gtwdaizi/articles/32838.html</guid><wfw:comment>http://www.cppblog.com/gtwdaizi/comments/32838.html</wfw:comment><comments>http://www.cppblog.com/gtwdaizi/articles/32838.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/gtwdaizi/comments/commentRss/32838.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/gtwdaizi/services/trackbacks/32838.html</trackback:ping><description><![CDATA[<p>今天折腾了一上午,终于把Windows Mobile5.0 开发平台的搭建的有点样子了, 趁中午休息时间,赶紧跟大家来分享一下:<br>搭建步骤如下:<br>1. 准备软件.<br>&nbsp;&nbsp;&nbsp;&nbsp;(1).Visual Studia 2005<br>&nbsp;&nbsp;&nbsp; (2).MicrosoftActiveSync4.1<br>&nbsp;&nbsp;&nbsp;&nbsp;(3).Windows Mobile 5.0 Pocket PC SDK.msi/Windows Mobile 5.0 Smartphone SDK.msi, PPC的SDK, 和 SmartPhone 的SDK, 看你的需要了, 不需要两个都安装.<br><br>2.软件安装.<br>&nbsp;&nbsp;&nbsp;&nbsp;(1).安装Visual Studia 2005, 只需要安装VC++ 和 VC#即可.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img alt="" src="http://www.cppblog.com/images/cppblog_com/gtwdaizi/Snap132.JPG" border=0><br>&nbsp;&nbsp;&nbsp; (2).安装MicrosoftActiveSync4.1.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;安装完毕，重启计算机<br>&nbsp;&nbsp;&nbsp;&nbsp;(3).安装Windows Mobile 5.0 Pocket PC SDK.msi/Windows Mobile 5.0 Smartphone SDK.msi.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><br>3.配置说明.<br>&nbsp;&nbsp;&nbsp; (1). 启动Visual Studia, 选择一般的环境变量配置,以用来开发多种语言程序.从下图中可以看到多了很多Smart Device的工程.<br>&nbsp;&nbsp;&nbsp;<img height=466 alt="" src="http://www.cppblog.com/images/cppblog_com/gtwdaizi/Snap2.JPG" width=680 border=0><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(2).很多帖子提到需要安装Device Emulator Manager的工具,其实没有这个必要.从Visual Studio的[tool]-&gt;[Device Emulator Manager]菜单,可以打开该工具.</p>
<p><img alt="" src="http://www.cppblog.com/images/cppblog_com/gtwdaizi/Snap3.jpg" border=0><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(3).选择Windows Mobile 5.0 Pocket PC Emulator ,右键单击[connect], 即可弹出模拟器<br><img height=551 alt="" src="http://www.cppblog.com/images/cppblog_com/gtwdaizi/Snap4.jpg" width=350 border=0><br>单击[Start],选择[Setting]<br><img height=222 alt="" src="http://www.cppblog.com/images/cppblog_com/gtwdaizi/Snap5.jpg" width=145 border=0><br>选择下方的[Connections]标签,选择其中的[Network Cards]<br><img height=326 alt="" src="http://www.cppblog.com/images/cppblog_com/gtwdaizi/Snap6.jpg" width=245 border=0><br>如下图选择<br><img height=320 alt="" src="http://www.cppblog.com/images/cppblog_com/gtwdaizi/Snap7.jpg" width=243 border=0><br>如下图设置:<br><img height=324 alt="" src="http://www.cppblog.com/images/cppblog_com/gtwdaizi/Snap9.jpg" width=245 border=0><br>这些信息可从网络连接获取.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(4)配置ActiveSync，打开[文件]-&gt;连接设置， 如下图设置：<br><img height=282 alt="" src="http://www.cppblog.com/images/cppblog_com/gtwdaizi/Snap10.jpg" width=342 border=0><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(5). 完成以上配置后.<br><br><img alt="" src="http://www.cppblog.com/images/cppblog_com/gtwdaizi/Snap3.jpg" border=0><br>选择Windows Mobile 5.0 Pocket PC Emulator ,右键单击[connect], 即可弹出模拟器. <br>如下图, 该选择上面图标发生了变化:<br><img height=349 alt="" src="http://www.cppblog.com/images/cppblog_com/gtwdaizi/Snap11.jpg" width=475 border=0><br>然后在右键单击 [Cardle],开始同步,弹出如下对话框:<br><img height=369 alt="" src="http://www.cppblog.com/images/cppblog_com/gtwdaizi/Snap13.jpg" width=503 border=0><br>点击下一步选择你要同步的内容即可.<br><img height=369 alt="" src="http://www.cppblog.com/images/cppblog_com/gtwdaizi/Snap17.jpg" width=503 border=0><br><img height=337 alt="" src="http://www.cppblog.com/images/cppblog_com/gtwdaizi/Snap16.jpg" width=366 border=0><br>至此,开发环境配置基本完成.<br>若还有疑问,可以留言,我将尽我所能帮助大家.谢谢!<br><br><br><br><br><br></p>
<img src ="http://www.cppblog.com/gtwdaizi/aggbug/32838.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-25 23:44 <a href="http://www.cppblog.com/gtwdaizi/articles/32838.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>