2008年5月28日星期三

Windows Mobile 开发常见问题集(三)

Windows Mobile 开发常见问题集(三)
http://www.csai.cn 作者:不详 来源:aspxboy 2006年6月8日 发表评论 进入社区
1、Q:SQL Mobile的SQL语法和SQL Server的语法有差异么?

  A:SQL Mobile的语法和SQL Server的语法略有差异,可以从SQL Mobile的文档中查找SQL Mobile具体支持哪些SQL语句。总的来说,对绝大部分的开发来说,这些差异不会造成影响。

2、Q:SQL Mobile支持B/S模式吗?

  A:不支持。

3、Q:可以在.NET Compact Framework 1.0上访问由.NET Compact Framework 2.0产生的数据库吗?

  A:SQL Mobile数据库的格式和SQL Server CE 2.0是相同的,因此可以直接在.NET Compact Framework 1.0中进行访问。

4、Q:SQL Mobile数据库文件支持XCOPY吗?可以简单地复制到其他Windows Mobile设备上吗?

  A:是的。SQL Mobile数据库本身是一个文件数据库,直接复制到其他安装了SQL Mobile支持组件的Windows Mobile设备或模拟器上就可以使用了。

5、Q:Visual Studio .NET 2003是否支持Windows Mobile 5.0的开发?

  A:不可以,如果开发基于Windows Mobile 5.0的应用程序请使用Visual Studio 2005。

6、Q:要想从传统的PC程序员转向到移动设备的开发上来,需要在技术上作哪些准备?

  A:移动设备的开发对于基础开发语言和开发技术的要求与PC上是相同的,只需要了解移动设备在哪些方面与PC平台有所不同即可。

7、Q:C#可以开发Windows Moblie应用程序吗?

  A:可以。

8、Q:如果获取.NET Compact Framework 2.0的安装程序并将其安装到Windows Mobile 5.0设备中?

  A:Visual Studio 2005提供了.NET Compact Framework 2.0安装程序,在开发部署时会自动部署到移动设备上。

9、Q:Windows Mobile 5.0中没有集成.NET Compact Framework 2.0,是不是生成的应用程序安装包就应该带上.NET Compact Framework 2.0?

  A:技术上来说是的。但能否在应用程序中提供.NET Compact Framework 2.0取决于微软对此的授权情况。

10、Q:如何把.NET Compact Framework 2.0与应用程序一同打包发布?

  A:.NET Compact Framework 2.0有一个单独的CAB安装包,可以把此文件与应用程序打成一个安装包。

11、Q:用Visual Studio 2003开发可以获得很好的兼容性吗?

  A:用Visual Studio 2003开发的基于.NET Compact Framework 2.0的程序可以在Windows Mobile 5.0的设备上运行。

12、Q:在Windows Mobile上面是否开发COM+或者DLL?

  A:可以开发DLL动态共享库。

13、Q:C#是否支持Windows Mobile 5.0的DirectX开发?

  A:支持。

14、Q:现有的使用Visual Studio开发的Smartphone 2003应用程序,可以移植到Windows CE 5.0平台上吗?

  A:可以。

15、Q:Windows Mobile 5.0内置红外线接口API吗?

  A:Windows Mobile 5.0对红外接口的支持并没有更新,需要采用之前的方法进行红外接口的开发,例如与串口通信等。

16、Q:如何开发手机游戏,特别是能够交互的网络游戏?

  A:Windows Mobile对游戏开发的支持是比较充分的,可以采用DirectX技术进行3D或2D界面的开发;对于网络部分,Windows Mobile可以支持socket通信方式。所以,从技术上来讲,开发网络游戏是完全没有问题的。

17、Q:我们公司目前更多关注的是嵌入式领域,也就是Windows CE,而非Windows Mobile。我们主要是在关注IPTV领域,在这方面有哪些的资源

  A:Windows CE是一种可自定义的嵌入式操作系统, 适用于各种内存很少的设备。OEM可以使用Windows CE设计平台和自定义应用程序,使用户可以获得各种设备的最佳体验,例如手持设备、瘦客户机、逻辑控制器以及各种高级消费类电子产品。 Windows Mobile是基于Windows CE构建的一种完善的软件平台。与Windows CE不同,Windows Mobile Smartphone和Pocket PC操作系统专为要求特殊硬件配置的设备而设计。该软件包括标准化 的接口和应用程序,可确保在各种硬件设计中的兼容性。 所以Windows Mobile和Windows CE的资源是通用的,您可以在http://www.microsoft.com/china/mobile、http: //www.microsoft.com/windowsmobile/,以及微软社区http://www.microsoft.com/china/windowsmobile/communities/default.mspx获得相应的资源和帮助。

18、Q:我们在Windows Mobile上进行应用开发遇到一些底层的接口问题,如何取得微软的技术支持?

  A:微软将一如既往地对基于Windows Mobile操作系统开发的独立软件开发商和开发人员进行支持,可以直接向800-820-3800全球技术支持中心寻求支持,或者提供具体问题细节,我们将给出相应的解决方案。

19、Q:如何才能将我们的软件放到微软的Mobile2Market项目中去?对MVP有没有什么优惠?

 A:Mobile2Markert项目在中国是非常优惠的,目前对MVP 没有特别优惠。另外,如何将软件放到微软的Mobile2Market中请参考http: //www.microsoft.com/china/mobile/developer/developerprograms/mobile2market/default.asp

20、Q:哪些工具可用于Pocket PC 2003开发?

  A:要构建Pocket PC 2003本机C++应用程序,您需要Microsoft eMbedded Visual C++ 4.0、Microsoft eMbedded Visual C++ 4.0 Service Pack 3,以及Pocket PC 2003 SDK。

21、Q:为了支持 Windows Mobile 2003 Second Edition 的增强功能(例如高分辨率或横向屏幕),应该在应用程序中做些什么?

  A:Windows Mobile 2003 Second Edition 提供了全新的屏幕方向和分辨率,包括针对Pocket PC的横向、方形和VGA支持以及针对Smartphone的QVGA支持。这种版本不需要新的SDK。

22、Q:Pocket PC 2002应用程序可以在Pocket PC 2003 设备上工作吗?

  A:使用文档化API且功能良好的Pocket PC 2002 应用程序无需重新编译即可在 Pocket PC 2003 设备上运行。

23、Q:如何从eVB迁移到Visual Basic .NET?

 A: 从eVB迁移到Visual Basic .NET并不容易,但迁移的好处远远超过了成本: • 数据类型更丰富:eVB只有16 字节的VARIANT;Visual Basic .NET使用.NET Framework通用类型系统。 • 执行更快:eVB需要解释;Visual Basic .NET在执行前由JIT(实时)编译器编译为本机代码。 • 错误处理更完善:eVB仅支持"On Error";Visual Basic .NET支持结构化异常处理。 • 支持结构:eVB不支持;Visual Basic .NET支持命名空间、类和结构。 • 面向对象:eVB是面向过程的;Visual Basic .NET支持完全的OOP(面向对象编程)。 • "一等公民":eVB总是希望迎头赶上MFC;Visual Basic .NET则是.NET的核心。 • 本机XML支持:eVB不支持;Visual Basic .NET支持本机XML和XML Web服务。 • 数据模型更完善:ADO.NET远远超过了ADOCE;它是最好的数据模型。 • 执行更安全、更可靠:eVB是一种脚本语言;Visual Basic .NET为托管代码。 • 还有许许多多! 同时,还有各种各样的资源(从移植实验到技术文章)可以帮助开发人员进行这种过渡。

24、Q:应该使用什么开发工具来编写基于.NET Compact Framework的Pocket PC应用程序?

   A:Microsoft Visual Studio .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支持它。

25、Q:有什么资源可以用于进行Windows Mobile 2003 Second Edition的开发?

  A:下载新 的Windows Mobile Developer资源包,其中包括白皮书以及新的和更新的代码示例。该版本不需要全新的SDK。可以用新的模拟器软件包对应用程序进行测试。 eMbedded Visual C++ 4.0开发人员应当下载eMbedded Visual C++ 4.0 Service Pack 3。

26、Q:什么工具可用于Smartphone 2002开发?

  A:要开始开发Microsoft Smartphone 2002应用程序,您需要eMbedded Visual C++ 3.0和Smartphone 2002 SDK。两者都可以在Windows Mobile Developer获得。

27、Q:MFC或ATL可用于Smartphone 2002开发吗?

  A:不可以,Smartphone 2002不支持MFC与ATL开发。

28、Q:可以使用eMbedded Visual Basic 3.0来构建Smartphone 2002应用程序吗?

  A:不可以,不支持以Smartphone 2002为目标的eVB 开发。

29、Q:哪些工具可用于进行Microsoft Smartphone 2003开发?

   A:对于Smartphone 2003,有两种开发选择,或者通过带有Service Pack 3的eMbedded Visual C++ 4.0开发本机代码,或者通过Visual Studio .NET 2003开发托管代码。这两种情况都需要下载Smartphone 2003 SDK。Windows Mobile 2003 Second Edition模拟器软件包使您可以在Second Edition设备上测试应用程序。eMbedded Visual C++ 4.0和Smartphone 2003 SDK都可以在Windows Mobile Developer获得。



Windows Mobile 开发常见问题集(二)

Windows Mobile 开发常见问题集(二)
http://www.csai.cn 作者:不详 来源:aspxboy 2006年6月8日 发表评论 进入社区
1、Q:请问如何才能保证应用程序能够及时地释放系统资源
  
  A:由于.NET Compact Framework所运行的移动设备,受限于CPU、内存、电源,因此其中的Garbage Collection时经过调整的,垃圾回收的速度比.NET Framework更快。通过调用Dispose()方法,可以立即释放掉对象所占用的非托管资源。

2、Q:在Visual Studio中可以定义一个所有文件都可以使用的宏吗?比如:#define AA,要求在所有的.cs文件中都可以使用#if AA public class A() #else public class B();

 A:可以。在VS 2005的解决方案资源管理器中,用鼠标右键单击项目,选择其属性。在属性对话框的Build页中,可以找到conditional compilation symbol,在其中输入AA,即可在该项目的所有C#源代码文件中使用这个符号。

3、Q:可以将Smartphone应用程序转换为Pocket PC应用程序吗?

  A:可以。在.NET Compact Framework 2.0中,只要您没有用到某些特殊的API,Pocket PC应用程序与Smartphone程序是可以互相转换的,只需要在控件上做些调整即可。

4、Q:.Net Framework 2.0有没有对Media coder/decoder的支持?开发第三方的媒体播放程序可以不依赖.Net CF2.0吗?

  A:.NET Compact Framework 2.0本身可以开发Direct3D Mobile的应用程序。也可以在VS 2005中以C++开发Native Code的媒体播放程序,而无须依赖.NET Compact Framework 2.0。

5、Q:使用.Net开发的智能设备程序是否比用C语言开发的程序效率低很多?

   A:使用.NET开发的程序会比使用C语言开发的本地程序要慢一些,不过对于一般的应用软件来说,下率不会差太多,除非是需要实时处理硬件或I/O的程 序,必须要使用C语言进行开发之外,一般的应用程序用.NET Compact Framework开发即可,因为这样可以获得最好的灵活性和可移植性。

6、Q:用托管C++开发的应用程序执行效率会不会比用C#开发的应用程序高?

  A:不会。由於托管C++与C#源代码在经过编译之后,都将成为IL代码,由.NET Compact Framework来执行,因此在效率上不会有差别。

7、Q:请问.NET Compact Framework 2.0对于使用不同CPU的移动设备支持好吗?.NET Compact Framework 2.0在GSM应用方面有没有增强?
  A:.NET Compact Framework具有Windows Mobile跨平台的特性,因此开发时不需要考虑底层的OS、CPU和其它硬件因素。目前.NET Compact Framework对常见的CPU都能够支持,例如ARM、MIPS、SH、x86等。另外在GSM应用方面,主要针对Smartphone的应用作了加强。
8、Q:请问MFC在Windows Mobile Development中处于什么地位?Douglas Boling写的Programming Microsoft Windows CE .NET一书中好像并不推崇使用MFC开发Windows Mobile应用程序。

   A:MFC还是以本地C++的方式进行开发,其特点是执行效率高,但必须花费更多的心思在�源分配、回收等编程技巧上。如果使用.NET Compact Framework进行开发,虽然执行效率比本地程序略差,但整体而言,可移植性与灵活性都较好,而且不必为回收资源担心,开发者能够专注于真正重要的业 务逻辑流程。

9、Q:.NET Compact Framework 2.0与1.0有什么区别?

  A:. NET Compact Framework 2.0主要针对1.0原有的控件及类库进行了改善,提供了更多的支持,并新增了许多类型和控件,.NET Compact Framework 2.0更加接近.NET Framework,同时在效率上也相对1.0有所提升。

10、Q:在制作安装程序的时候,如何在start->program菜单中生成程序的快捷方式?

   A:在VS 2005中建立Smart Device Cab Project,在File System页面中,可以看到Application Folder,这就是Start->Program的位置,可以先建立Primary Output的快捷方式,然后将此快捷方式移到Programs Folder,并构建Cab文件即可。

11、Q:移动设备与WEB网页设计有什么主要区别?

  A:Visual Studio开发环境中移动设备与Web设计是非常类似的 ,可以使用同样的语言进行设计, 不同的只是能够使用的类以及控件有所区别。

12、Q:.NET Compact Framework中可以实现鼠标的双击、右击、中间键单击等用户事件吗?

  A:运行Windows Mobile的设备没有鼠标,所以这些事件也不存在。对于常用的右键弹出上下文相关菜单,在触摸屏上一般用单击并且按住一段时间来实现。

13、Q:Mobile应用程序的界面处理可以使用CSS样式表吗?

  A:不可以。

14、Q:Smartphone上面能够支持横屏幕吗?

  A:不支持。

15、Q:如何在Pocket PC中调整控件的位置使得应用程序可以支持横向屏幕?

  A:可通过设置控件的Anchor和Dock属性来自适应屏幕。

16、Q:界面开发完成后,在移植方面需要注意些什么?

   A:一般来说,要移植到不同平台上必需要重新设计用户界面;可以重用的只是业务逻辑,不是用户界面。
17、Q:我在移动开发过程中用到了很多控件,难以在一页之内显示,如何为它们添加一个滚动条?

  A:可以将这些控件放到一个Panel中,并设置其AutoScroll属性为true即可;如果使用VS2005,拖拽数据源到窗体上时,会自动将所有控件包括在一个Panel里。

18、Q:TableAdapter在.NET Compact Framework 1.0中从未出现过,是新特性吗?

  A:是的,TableAdapter是.NET Compact Framework 2.0中新增加的。

19、Q:SQL Mobile带有像SQL Server那样企业管理器吗?Visual Studio 2005支持在桌面上直接查看SQL Mobile的数据库吗?

  A:您可以通过SQL Server 2005的企业管理器连接到SQL Mobile数据库进行编辑。Visual Studio 2005也支持在桌面上创建或修改SQL Mobile数据库文件。

20、Q:提交成功后如何取消保存?

  A:目前BindingSource尚不支持事务,因此提交成功后是没有办法再undo的。

21、Q:移动设备内存较小,填充DataSet是否有大小限制?

  A:DataSet在逻辑上并没有对大小的限制。但是DataSet的大小必须小于当前前的可用内存,否则会有内存分配不成功的异常出现。

22、Q:如果数据源中的数据在显示前需要处理(例如格式转换),可以使用DataBinging吗?

  A:BindingSource是直接将DataSet与控件进行关联,所以如果需要进行其他操作的话,就不能使用BindingSource。或者,可以在访问数据库后,先在DataSet里对需要转换的数据进行必要的处理之后,再进行显示。

23、Q:DataSet实际上在内存中产生了一套数据副本,如何解决版本控制的问题?

  A:DataSet本身不存在版本控制的问题。在把数据提交回SQL Mobile的时候,的确需要有一些机制来保证修改完成的数据应该是最新的,但是DataSet本身的数据结构是不会发生变化的。

24、Q:能否通过Pocket PC上的程序更新服务器上的数据库信息?

  A:可以。可以使用SQL Mobile中的RDA或者是合并复制的方法和远程SQL Server数据库进行数据同步或更新。具体的实现可以参考SQL Server相关部分的文档。

25、Q:SQL Mobile一定要要安装在移动设备上吗?

  A:是的。SQL Mobile需要安装在Windows Mobile或者Windows CE设备上。

26、Q:SQL Moble支持存储过程吗?

  A:目前还不支持。

27、Q:SQL Mobile必须和应用程序部署在同一台设备上吗?可否远程连接?它是否是一个文本数据库?
 
  A:是的。SQL Mobile必须和应用程序部署在同一个设备上,现在还不支持远程连接。SQL Mobile是一个文件数据库,但不是一个文本数据库。

28、Q:能不能在一些应用中以XML替代SQL的作用?

  A:可以的。XML的查询效率比SQL Mobile要低,但是在数据比较少的情况下不需要安装更多的组件,这是XML的一个优势。

29、Q: Tableadapter与DataAdapter之间有何区别?DataAdapter是多个TableAdapter的组合吗?

   A:不是的,TableAdapter是对DataAdapter的一个扩展,TableAdapter本身包括了对应数据表的信息。 TableAdapter完成从数据库连接、执行SQL语句到将结果填充到DataSet中的一个完整操作,而DataAdapter只支持数据填充的操 作。

30、Q:做了SQL Moblie的sdf文件后,Publications后的数据库表中会出现msrepl_tran_version或rowguid字段,这是为什么?

  A:这两个字段是为了保证数据同步,由系统自动添加的,请不要进行修改。

31、Q:网上出了个Reflector反编译工具,可以99%反编译用C#开发的EXE和DLL,怎么才能更好地保护应用程序?

  A:目前大部分应用程序采用混淆和对关键字符串加密的方式,更好的方式可能还要继续探讨。

Windows Mobile 开发常见问题集(一)

Windows Mobile 开发常见问题集(一)
http://www.csai.cn 作者:不详 来源:aspxboy 2006年6月8日 发表评论 进入社区

1、Q:新建项目的时候选择哪个项目类型才能创建智能设备的应用程序?

  A:在Visual Studio的新建项目对话框中选择Visual C#或者Visual Basic项目类型,选择智能设备模板,然后再选择相应的设备SDK,最后选择"Device Application",就可以创建一个移动设备的应用程序了。

2、Q:托管代码与本地代码有哪些区别?

  A:托管代码是指使用.NET Compact Framework开发的程序代码,可执行文件被编译成IL,执行时需要有.NET的运行时环境。而本地代码指用C++等语言开发的程序代码,可执行文件被编译成与CPU指令集有关的机器码,可以直接运行。 

3、Q:能不能简要介绍一下Magneto里面对OTA和MMS的支持?

  A:Magneto对OTA有很好的支持,SDK文档的通讯部分中,有针对OTA的专门介绍。MMS的应用程序基本都是由第三方开发的,因为MMS是基于WAP协议的,而Magneto本身对WAP的支持也很好,具体的协议也可以在SDK文档里找到。

4、Q:请问用Visual Basic .NET开发PDA数据库程序能不能使用ADO.NET

  A:Visual Basic .NET开发PDA数据库不需要引用System.data.oledb,只需要引用System.Data.SqlServerCe命名空间就可以了。 该命名空间中的数据库操作类和ADO.NET是基本一致的。可以用它们来开发针对SQL Server CE的应用程序。

5、Q:在Visual C++2005中,可以使用.Net Compact Framework吗?

  A:不能,现在.NET Compact Framework只支持C#和VB.NET,而不支持C++/CLI。但是在VS.NET 2005中可以用C++来开发Native代码来支持移动设备。 

6、Q:从什么地方可以得到Smartphone开发环境?

  A:Smartphone的SDK可以在微软网站上找到,而Visual Studio 2005 Beta 2可以通过参加微软活动的方式获得。MEDC 2005的参加者都获得了VS.NET 2005和Windows Mobile 5 SDK的开发光盘。 

7、Q:托管性的代码执行效率怎么样?和使用Visual C++编写的代码相比较。

  A:托管代码的执行效率肯定不如本地代码高,但是托管代码也有一些好处是无法取代的。

8、Q:是否可以使用Visual Studio .NET 2003来开发能够运行在Windows Mobile 2005上的应用程序?

  A:首先更正一下,Windows Mobile最新一代的操作系统叫 做Windows Mobile 5,而不是Windows Mobile 2005。是的,使用VS.NET 2003开发的应用程序是可以在Windows Mobile 5上正常运行的,因为Windows Mobile 5 ROM中内置了.NET Compact Framewrok 1.0 SP3。 

9、Q:PDA上不能用Pocket Access么?SQL CE太大了。

  A:可以使用Pocket Access来开发Windows Mobile上的应用程序。可以采用C++调用OLEDB或者ADOCE的方式来访问Pocket Access数据库。

10、Q:Visual Studio 2005的新功能是否只在Windows Mobile 5里受到支持,2003是否支持?

  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开发文档的"What's New"部分,分别描述了这两方面的新特性。

11、Q:请问如何在模拟器里面配置连接到移动网络?

  A:模拟器如果需要连接移动网络的话,必须有专门的硬件提供支持。可以在开发PC的串口上连一个GPRS的模拟器,SDK文档中对此有专门的说明。

12、Q:SQL CE可以像Pocket Access那样仅使用一个文件就能运行么?是否需要像PC上那样安个服务器才能使用?

  A:不会的,只需要在Windows Mobile上安装SQL Server CE的支持库,也就是就是一些DLL文件。而SQL Server CE的库文件是一个单独的文件,不需要安装一个服务器。

13、Q:开发好的程序通过什么方式部署到手机上?对手机有什么要求?

  A:开发的程序需要打包成cab文件部署到手机上。除了通过ActiveSync安装外,还可以通过网络下载存储卡运行等方式来安装应用程序。对手机的要求是,必须和开发程序的目标平台相兼容。比如为Windows Mobile 5开发的应用程序,可能就没办法很好地运行在Windows Mobile2003平台上。

14、Q:在模拟器上面开发程序,和真实环境有区别么?需要注意一些什么?

  A:模拟器的仿真度十分高,Windows Mobile 5的模拟器甚至可以支持ARM指令,所以基本不会遇到兼容性的问题。但是对于一些需要连接外部设备的应用场景,比如前边说的无线网络,还有GPS设备等,就需要用到实际设备了。

15、Q:当开发国际化应用程序时,应该特别注意哪些方面?

  A:对于国际化的应用程序,.NET本身就已经提供了非常好的支持。可以把用户界面的文字保存在相应的资源文件中,然后由应用程序判断操作系统的语言版本来调用相应的文字。

16、Q:用.NET开发Pocket PC程序需要考虑设备具体使用的是哪种CPU吗?

  A:不必。无论是在虚拟机上的x86指令集,还是实际设备上的ARM指令集,对.NET Compact Framework程序的运行来说都一样。 

17、Q:Windows Mobile 5 是否支持通过语音控制新的开发程序?

  A:现在还不支持。 

18、Q:可以在vwd2005 bata2中开发Pocket PC程序吗?Pocket PC是否具有浏览器?

  A:可以,Pocket PC平台是内置浏览器的。 

19、Q:Visual Studio 2005的Mobile开发,支持Mobile 2003的设备吗?

  A:支持,VS 2005本身就自带Windows Mobile 2003的SDK。

20、Q:Windows Mobile 5.0 for Smartphone较之前的版本有何明显的区别?对于测试这一领域,我们需要注意些什么?

  A:Windows Mobile 5的Smartphone平台更多的变化是在API层面,比如对数据库的支持、对GPS API的支持等, Windows Mobile 5 SDK文档中对此有详细地说明。

21、Q:对开发来说CDMA和GPRS的数据传输是透明的吗?

  A:对于软件开发来说数据传输是透明的,CDMA和GPRS对于上层应用程序来说,只要支持HTTP协议或者TCP/IP协议就可以进行数据传输的操作。 

22、Q:Visual Studio .NET能否支持Nokia的S60系列系统开发?

  A:可以,Visual C++能支持Nokia S60的开发。 

23、Q:Pocket PC与Mobile开发的主要区别在哪里?

  A:Window Mobile是微软公司基于Windows CE.NET的一个平台。它包含Pocket PC和Smartphone两个版本。 

24、Q:SDE从哪里可以下载?Pocket PC 2005的模拟器可以从哪里下载?

 A:SDE是早期用来开发移动设备程序的VS扩展,目前网 上似乎很难找到。其实不用安装它,安装所需版本的Pocket PC或者Smartphone的SDK即可。各个版本的Windows Mobile开发的SDK和模拟器的地址可以从这篇Blog上下载(http: //twodays.cnblogs.com/archive/2005/06/30/184107.htm)。 

25、Q:.NET Compact Framework 2.0能装在Windows Mobile 2003上吗?

  A:可以。.NET Compact Framework 2.0必须手动安�到Windows Mobile 2003的机器上。

26、Q:请问有没有好的Windows Mobile编程的网站或者论坛?

  A:OpenNETCF.org、www.devbuzz.comwww.codeproject.comwww.msdn.com/mobility/www.pocketpcdn.com

27、Q:Windows Mobile 2003上的.NET Compact Framework能升级到.NET Compact Framework 2.0吗?

  A:可以。.NET Compact Framework 2.0必须手动安�到Windows Mobile 2003的机器上。

28、Q:请问编写WML文件与使用.NET Compact Framework进行开发有什么联系和区别?

  A:WML是能够利用WAP浏览器进行浏览的文件,是一种基于Web的开发方式。.NET Compact Framework是在设备上运行的程序,是基于应用的开发方式。

29、Q:在使用.NET Compact Framework 1.0进行开发时,用EVC直接调用Native代码与使用C#通过P/Invoke在性能上有什么差别?在.NET Compact Framework 2.0上,用C++直接调用和用C#通过P/Invoke又如何呢?

 A:用EVC�用Native API的效率,会比使用.NET Compact Framework通过P/Invoke调用Native API要高,这是.NET Compact Framework本身的特性。在从托管代码中调用Native API时,其内部会进行一些额外的类型转换动作,这会导致效率的降低。

30、Q:有没有支持显示HTML文本的控件?

  A:WebBrowser控件可以用于HTML文本。

31、Q:CAB安装后会在Pocket PC上自动生成"卸载程序",如何制作安装包,才能不自动产生"卸载程序"?

  A:利用VS 2005建立Smart Device Cab Project,在Solution Explorer的Cab Project上点击鼠标右键选择Property,即可看到有一个选项为NoUninstall,默认为False,改为True就可以了。

32、Q:OpenNETCF能运行在.NET Framework 1.1环境下吗?其中的控件可以与.NET Framework 1.1控件混合使用吗?怎样在Visual Studio .NET 2003中加入OpenNETCF控件?

  A:当初在设计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程序开发所 用,除了少部份针对PC与Pocket PC的同步功能所编写的类之外,大部分都是在.NET Compact Framework上执行的,一般不支持.NET Framework。OpenNETCF的Smart Device Framework安装完毕之后,可以在VS 2003左侧的工具箱中看到OpenNETCF的控件,可以直接拖放来使用。


2008年5月15日星期四

c++中string的用法

之所以抛弃char*的字符串而选用C++标准程序库中的string类,是因为他和前者比较起来,不必担心内存是否足够、字符串长度等等,而且作为一个类出现,他集成的操作函数足以完成我们大多数情况下(甚至是100%)的需要。我们可以用 = 进行赋值操作,== 进行比较,+ 做串联(是不是很简单?)。我们尽可以把它看成是C++的基本数据类型。

首先,为了在我们的程序中使用string类型,我们必须包含头文件 <string>。如下:
#include <string> //注意这里不是string.h string.h是C字符串头文件

1.声明一个C++字符串
声明一个字符串变量很简单:
string Str;
这样我们就声明了一个字符串变量,但既然是一个类,就有构造函数和析构函数。上面的声明没有传入参数,所以就直接使用了string的默认的构造函数,这个函数所作的就是把Str初始化为一个空字符串。String类的构造函数和析构函数如下:
a) string s; //生成一个空字符串s
b) string s(str) //拷贝构造函数 生成str的复制品
c) string s(str,stridx) //将字符串str内"始于位置stridx"的部分当作字符串的初值
d) string s(str,stridx,strlen) //将字符串str内"始于stridx且长度顶多strlen"的部分作为字符串的初值
e) string s(cstr) //将C字符串作为s的初值
f) string s(chars,chars_len) //将C字符串前chars_len个字符作为字符串s的初值。
g) string s(num,c) //生成一个字符串,包含num个c字符
h) string s(beg,end) //以区间beg;end(不包含end)内的字符作为字符串s的初值
i) s.~string() //销毁所有字符,释放内存
都很简单,我就不解释了。

2.字符串操作函数
这里是C++字符串的重点,我先把各种操作函数罗列出来,不喜欢把所有函数都看完的人可以在这里找自己喜欢的函数,再到后面看他的详细解释。
a) =,assign() //赋以新值
b) swap() //交换两个字符串的内容
c) +=,append(),push_back() //在尾部添加字符
d) insert() //插入字符
e) erase() //删除字符
f) clear() //删除全部字符
g) replace() //替换字符
h) + //串联字符串
i) ==,!=,<,<=,>,>=,compare() //比较字符串
j) size(),length() //返回字符数量
k) max_size() //返回字符的可能最大个数
l) empty() //判断字符串是否为空
m) capacity() //返回重新分配之前的字符容量
n) reserve() //保留一定量内存以容纳一定数量的字符
o) [ ], at() //存取单一字符
p) >>,getline() //从stream读取某值
q) << //将谋值写入stream
r) copy() //将某值赋值为一个C_string
s) c_str() //将内容以C_string返回
t) data() //将内容以字符数组形式返回
u) substr() //返回某个子字符串
v)查找函数
w)begin() end() //提供类似STL的迭代器支持
x) rbegin() rend() //逆向迭代器
y) get_allocator() //返回配置器
下面详细介绍:

2.1 C++字符串和C字符串的转换
C ++提供的由C++字符串得到对应的C_string的方法是使用data()、c_str()和copy(),其中,data()以字符数组的形式返回字符串内容,但并不添加'\0'。c_str()返回一个以'\0'结尾的字符数组,而copy()则把字符串的内容复制或写入既有的c_string或字符数组内。C++字符串并不以'\0'结尾。我的建议是在程序中能使用C++字符串就使用,除非万不得已不选用c_string。由于只是简单介绍,详细介绍掠过,谁想进一步了解使用中的注意事项可以给我留言(到我的收件箱)。我详细解释。

2.2 大小和容量函数
一个C++字符串存在三种大小:a)现有的字符数,函数是size()和length(),他们等效。Empty()用来检查字符串是否为空。b)max_size() 这个大小是指当前C++字符串最多能包含的字符数,很可能和机器本身的限制或者字符串所在位置连续内存的大小有关系。我们一般情况下不用关心他,应该大小足够我们用的。但是不够用的话,会抛出length_error异常c)capacity()重新分配内存之前 string所能包含的最大字符数。这里另一个需要指出的是reserve()函数,这个函数为string重新分配内存。重新分配的大小由其参数决定,默认参数为0,这时候会对string进行非强制性缩减。

还有必要再重复一下C++字符串和C字符串转换的问题,许多人会遇到这样的问题,自己做的程序要调用别人的函数、类什么的(比如数据库连接函数Connect(char*,char*)),但别人的函数参数用的是char*形式的,而我们知道,c_str()、data()返回的字符数组由该字符串拥有,所以是一种const char*,要想作为上面提及的函数的参数,还必须拷贝到一个char*,而我们的原则是能不使用C字符串就不使用。那么,这时候我们的处理方式是:如果此函数对参数(也就是char*)的内容不修改的话,我们可以这样Connect((char*)UserID.c_str(), (char*)PassWD.c_str()),但是这时候是存在危险的,因为这样转换后的字符串其实是可以修改的(有兴趣地可以自己试一试),所以我强调除非函数调用的时候不对参数进行修改,否则必须拷贝到一个char*上去。当然,更稳妥的办法是无论什么情况都拷贝到一个char*上去。同时我们也祈祷现在仍然使用C字符串进行编程的高手们(说他们是高手一点儿也不为过,也许在我们还穿开裆裤的时候他们就开始编程了,哈哈…)写的函数都比较规范,那样我们就不必进行强制转换了。
2.3元素存取

我们可以使用下标操作符[]和函数at()对元素包含的字符进行访问。但是应该注意的是操作符[]并不检查索引是否有效(有效索引 0~str.length()),如果索引失效,会引起未定义的行为。而at()会检查,如果使用 at()的时候索引无效,会抛出out_of_range异常。
有一个例外不得不说,const string a;的操作符[]对索引值是a.length()仍然有效,其返回值是'\0'。其他的各种情况,a.length()索引都是无效的。举例如下:
const string Cstr("const string");
string Str("string");

Str[3]; //ok
Str.at(3); //ok

Str[100]; //未定义的行为
Str.at(100); //throw out_of_range

Str[Str.length()] //未定义行为
Cstr[Cstr.length()] //返回 '\0'
Str.at(Str.length());//throw out_of_range
Cstr.at(Cstr.length()) ////throw out_of_range

我不赞成类似于下面的引用或指针赋值:
char& r=s[2];
char* p= &s[3];
因为一旦发生重新分配,r,p立即失效。避免的方法就是不使用。

2.4比较函数
C ++字符串支持常见的比较操作符(>,>=,<,<=,==,!=),甚至支持string与C-string的比较(如 str<"hello")。在使用>,>=,<,<=这些操作符的时候是根据"当前字符特性"将字符按字典顺序进行逐一得比较。字典排序靠前的字符小,比较的顺序是从前向后比较,遇到不相等的字符就按这个位置上的两个字符的比较结果确定两个字符串的大小。同时,string ("aaaa") <string(aaaaa)。
另一个功能强大的比较函数是成员函数compare()。他支持多参数处理,支持用索引值和长度定位子串来进行比较。他返回一个整数来表示比较结果,返回值意义如下:0-相等 〉0-大于 <0-小于。举例如下:
string s("abcd");

s.compare("abcd"); //返回0
s.compare("dcba"); //返回一个小于0的值
s.compare("ab"); //返回大于0的值

s.compare(s); //相等
s.compare(0,2,s,2,2); //用"ab"和"cd"进行比较 小于零
s.compare(1,2,"bcx",2); //用"bc"和"bc"比较。
怎么样?功能够全的吧!什么?还不能满足你的胃口?好吧,那等着,后面有更个性化的比较算法。先给个提示,使用的是STL的比较算法。什么?对STL一窍不通?靠,你重修吧!

2.5 更改内容
这在字符串的操作中占了很大一部分。

首先讲赋值,第一个赋值方法当然是使用操作符=,新值可以是string(如:s=ns) 、c_string(如:s="gaint")甚至单一字符(如:s='j')。还可以使用成员函数assign(),这个成员函数可以使你更灵活的对字符串赋值。还是举例说明吧:
s.assign(str); //不说
s.assign(str,1,3);//如果str是"iamangel" 就是把"ama"赋给字符串
s.assign(str,2,string::npos);//把字符串str从索引值2开始到结尾赋给s
s.assign("gaint"); //不说
s.assign("nico",5);//把'n' 'I' 'c' 'o' '\0'赋给字符串
s.assign(5,'x');//把五个x赋给字符串
把字符串清空的方法有三个:s="";s.clear();s.erase();(我越来越觉得举例比说话让别人容易懂!)。
string提供了很多函数用于插入(insert)、删除(erase)、替换(replace)、增加字符。
先说增加字符(这里说的增加是在尾巴上),函数有 +=、append()、push_back()。举例如下:
s+=str;//加个字符串
s+="my name is jiayp";//加个C字符串
s+='a';//加个字符

s.append(str);
s.append(str,1,3);//不解释了 同前面的函数参数assign的解释
s.append(str,2,string::npos)//不解释了

s.append("my name is jiayp");
s.append("nico",5);
s.append(5,'x');

s.push_back('a');//这个函数只能增加单个字符 对STL熟悉的理解起来很简单

也许你需要在string中间的某个位置插入字符串,这时候你可以用insert()函数,这个函数需要你指定一个安插位置的索引,被插入的字符串将放在这个索引的后面。
s.insert(0,"my name");
s.insert(1,str);
这种形式的insert()函数不支持传入单个字符,这时的单个字符必须写成字符串形式(让人恶心)。既然你觉得恶心,那就不得不继续读下面一段话:为了插入单个字符,insert()函数提供了两个对插入单个字符操作的重载函数:insert(size_type index,size_type num,chart c)和insert(iterator pos,size_type num,chart c)。其中size_type是无符号整数,iterator是char*,所以,你这么调用insert函数是不行的:insert(0,1, 'j');这时候第一个参数将转换成哪一个呢?所以你必须这么写:insert((string::size_type)0,1,'j')!第二种形式指出了使用迭代器安插字符的形式,在后面会提及。顺便提一下,string有很多操作是使用STL的迭代器的,他也尽量做得和STL靠近。
删除函数erase()的形式也有好几种(真烦!),替换函数replace()也有好几个。举例吧:
string s="il8n";
s.replace(1,2,"nternationalizatio");//从索引1开始的2个替换成后面的C_string
s.erase(13);//从索引13开始往后全删除
s.erase(7,5);//从索引7开始往后删5个

2.6提取子串和字符串连接
题取子串的函数是:substr(),形式如下:
s.substr();//返回s的全部内容
s.substr(11);//从索引11往后的子串
s.substr(5,6);//从索引5开始6个字符
把两个字符串结合起来的函数是+。(谁不明白请致电120)

2.7输入输出操作
1.>> 从输入流读取一个string。
2.<< 把一个string写入输出流。
另一个函数就是getline(),他从输入流读取一行内容,直到遇到分行符或到了文件尾。

2.8搜索与查找
查找函数很多,功能也很强大,包括了:
find()
rfind()
find_first_of()
find_last_of()
find_first_not_of()
find_last_not_of()
这些函数返回符合搜索条件的字符区间内的第一个字符的索引,没找到目标就返回npos。所有的函数的参数说明如下:
第一个参数是被搜寻的对象。第二个参数(可有可无)指出string内的搜寻起点索引,第三个参数(可有可无)指出搜寻的字符个数。比较简单,不多说不理解的可以向我提出,我再仔细的解答。当然,更加强大的STL搜寻在后面会有提及。
最后再说说npos的含义,string::npos的类型是string::size_type,所以,一旦需要把一个索引与npos相比,这个索引值必须是string::size)type类型的,更多的情况下,我们可以直接把函数和npos进行比较(如:if(s.find("jia")== string::npos))。

2008年5月14日星期三

FW: CString,string,char*的综合比较



 
CString,string,char*的综合比较

(一) 概述

string和CString均是字符串模板类,string为标准模板类(STL)定义的字符串类,已经纳入C++标准之中;

CString (typedef CStringT > CString)为Visual C++中最常用的字符串类,继承自CSimpleStringT类,主要应用在MFC和ATL编程中,主要数据类型有char(应用于ANSI), wchar_t(unicode),TCHAR(ANSI与unicode均可);

char*为C编程中最常用的字符串指针,一般以'\0'为结束标志;

(二) 构造

string是方便的,可以从几乎所有的字符串构造而来,包括CString和char*;

CString次之,可以从基本的一些字符串变量构造而来,包括char*等;

char*没有构造函数,仅可以赋值;

举例:

char* psz = "joise";

CString cstr( psz );

string str( cstr );

(三) 运算符重载

a) operator=

string是最方便的,几乎可以直接用所有的字符串赋值,包括CString和char*;

CString次之,可以直接用些基本的字符串赋值,包括char*等;

char*只能由指针赋值,并且是极危险的操作,建议使用strcpy或者memcpy,而且char*在声明的时候如未赋初值建议先设为NULL,以避免野指针,令你抓狂;

举例:

char *psz = NULL;

psz = new char[10]; //当然,以上的直接写成char *psz = new char[10];也是一样

memset( psz, 0, 10 );

strcpy( psz, "joise" );

CString cstr;

cstr = psz;

string str;

str = psz;

str = cstr;

delete []psz;

b) operator+

string与CString差不多,可以直接与char*进行加法,但不可以相互使用+运算符,即string str = str + cstr是非法的,须转换成char*;

char*没有+运算,只能使用strcat把两个指针连在一起;

举例:

char* psz = "joise";

CString cstr = psz;

cstr = cstr + psz;

string str = psz;

str = str + str + psz;

strcat( psz, psz );

strcat( psz, cstr );//合法

strcat( psz, str );//非法,由此可见,CString可自动转换为const char*,而string不行

c) operator +=

string是最强大的,几乎可以与所有的字符串变量+=,包括CString和char*;

CString次之,可以与基本的一些字符串变量进行+=而来,包括char*等;

char*没有+=运算符,只能使用strcat把两个指针连在一起;

d) operator[]

CString最好,当越界时会抛出断言异常;

string与char*下标越界结果未定义;

举例:

char* psz = "joise";

CString cstr = psz;

cout << cstr[8];

string str = psz;

cout << str[8];

cout << psz[8];

e) operator== 、operator!=、operator> 、operator< 、operator>= 、perator<=

CString与string之间不可以进行比较,但均可以与char*进行比较,并且比较的是值,而不是地址;

cout << ( psz == cstr );

cout << ( psz == str );

cout << ( str == psz );

cout << ( cstr == psz );//以上代码返回均为1

(四) 常用算法

a) 查找
作用 char* string CString
查找指定值 strchr
strstr
strrstr
strspn find Find
第一个匹配的值 fild_first_of FindOneOf 从后面开始查找 ReserveFind 指定匹配方式 find_if

注:find_if中是把范围内的值挨个代入匹配函数直至返回true

b) 比较
作用 char* string CString 查找指定值(区分大小写) strcmp
strncmp
strcoll
_strncoll operator<
operator>
operator<=
operator>=
operator==
operator!= Collate

Compare 查找指定值(不区分大小写) _stricmp
_strnicmp
_stricoll
_strnicoll CollateNoCase

CompareNoCas

注:返回值如果<0则前面的值小于后面的值,反之亦然

c) 替换
作用 char* string CString 查找指定值 _strset
_strnset
replace
replace_copy
replace_copy_if
replace_if Replace

d) 插入
作用 char* string CString 查找指定值 insert Insert
e) 增加 作用 char* string CString 动态增加值 strcat push

append Append

AppendChar

AppendFormat


f) 截取
作用 char* string CString 得到部分值 用下标操作 substr Left

Mid

Right

Truncate


g) 移除
作用 char* string CString 移除部份值 remove Remove 移除空白值 RemoveBlanks

注:此为ATL提供,非C函数 remove_if Trim

TrimLeft

TrimRig


h) 转换大小写
作用 char* string CString 转换大小写 _strlwr

_strupr MakeLower

MakeUpper


i) 与其他类型转换
作用 char* string CString 转化为数字 atoi

atod

atof Format 转化为char* c_str
GetBuffer

GetBufferSetLen

j) 格式化
作用 char* string CString 格式化 sprintf Format


k) 得到长度
作用 char* string CString
得到长度 strlen length GetLength 得到大小 size GetAllocLength

l) 判断为空
作用 char* string CString 判断是否为空 判断是否==NULL或者第一个字符是否是'\0' empty IsEmpty

m) 重定义大小
作用 char* string CString 重定义大小 realloc
new resize GetBufferSetLength

n) 释放资源
作用 char* string CString 释放 free

delete (delete[]) ReleaseBuffer

ReleaseBufferSetLength

(五) 安全性>

CString > string > char*;

(六) 灵活性

CString > string >char*;

(七) 可移植性

char* = string > CString

转:如何:在各种字符串类型之间进行转换

如何:在各种字符串类型之间进行转换

本主题演示如何将各种 Visual C++ 字符串类型转换为其他字符串。可以转换的字符串类型包括 char *、wchar_t*、_bstr_t、CComBSTR、CString、basic_string 和 System.String。在所有情况下,在将字符串转换为新类型时,都会创建字符串的副本。对新字符串进行的任何更改都不会影响原始字符串,反之亦然。
从 char * 转换
示例

此示例演示如何从 char * 转换为上面列出的其他字符串类型。
复制代码

// convert_from_char.cpp
// compile with: /clr /link comsuppw.lib

#include <iostream>
#include <stdlib.h>
#include <string>

#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"

using namespace std;
using namespace System;

int main()
{
char *orig = "Hello, World!";
cout << orig << " (char *)" << endl;

// Convert to a wchar_t*
size_t origsize = strlen(orig) + 1;
const size_t newsize = 100;
size_t convertedChars = 0;
wchar_t wcstring[newsize];
mbstowcs_s(&convertedChars, wcstring, origsize, orig, _TRUNCATE);
wcscat_s(wcstring, L" (wchar_t *)");
wcout << wcstring << endl;

// Convert to a _bstr_t
_bstr_t bstrt(orig);
bstrt += " (_bstr_t)";
cout << bstrt << endl;

// Convert to a CComBSTR
CComBSTR ccombstr(orig);
if (ccombstr.Append(L" (CComBSTR)") == S_OK)
{
CW2A printstr(ccombstr);
cout << printstr << endl;
}

// Convert to a CString
CString cstring(orig);
cstring += " (CString)";
cout << cstring << endl;

// Convert to a basic_string
string basicstring(orig);
basicstring += " (basic_string)";
cout << basicstring << endl;

// Convert to a System::String
String ^systemstring = gcnew String(orig);
systemstring += " (System::String)";
Console::WriteLine("{0}", systemstring);
delete systemstring;
}

输出

Hello, World! (char *)
Hello, World! (wchar_t *)
Hello, World! (_bstr_t)
Hello, World! (CComBSTR)
Hello, World! (CString)
Hello, World! (basic_string)
Hello, World! (System::String)

从 wchar_t * 转换
示例

此示例演示如何从 wchar_t * 转换为上面列出的其他字符串类型。
复制代码

// convert_from_wchar_t.cpp
// compile with: /clr /link comsuppw.lib

#include <iostream>
#include <stdlib.h>
#include <string>

#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"

using namespace std;
using namespace System;

int main()
{
wchar_t *orig = L"Hello, World!";
wcout << orig << L" (wchar_t *)" << endl;

// Convert to a char*
size_t origsize = wcslen(orig) + 1;
const size_t newsize = 100;
size_t convertedChars = 0;
char nstring[newsize];
wcstombs_s(&convertedChars, nstring, origsize, orig, _TRUNCATE);
strcat_s(nstring, " (char *)");
cout << nstring << endl;

// Convert to a _bstr_t
_bstr_t bstrt(orig);
bstrt += " (_bstr_t)";
cout << bstrt << endl;

// Convert to a CComBSTR
CComBSTR ccombstr(orig);
if (ccombstr.Append(L" (CComBSTR)") == S_OK)
{
CW2A printstr(ccombstr);
cout << printstr << endl;
}

// Convert to a CString
CString cstring(orig);
cstring += " (CString)";
cout << cstring << endl;

// Convert to a basic_string
wstring basicstring(orig);
basicstring += L" (basic_string)";
wcout << basicstring << endl;

// Convert to a System::String
String ^systemstring = gcnew String(orig);
systemstring += " (System::String)";
Console::WriteLine("{0}", systemstring);
delete systemstring;
}

输出

Hello, World! (wchar_t *)
Hello, World! (char *)
Hello, World! (_bstr_t)
Hello, World! (CComBSTR)
Hello, World! (CString)
Hello, World! (basic_string)
Hello, World! (System::String)

从 _bstr_t 转换
示例

此示例演示如何从 _bstr_t 转换为上面列出的其他字符串类型。
复制代码

// convert_from_bstr_t.cpp
// compile with: /clr /link comsuppw.lib

#include <iostream>
#include <stdlib.h>
#include <string>

#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"

using namespace std;
using namespace System;

int main()
{
_bstr_t orig("Hello, World!");
wcout << orig << " (_bstr_t)" << endl;

// Convert to a char*
const size_t newsize = 100;
char nstring[newsize];
strcpy_s(nstring, (char *)orig);
strcat_s(nstring, " (char *)");
cout << nstring << endl;

// Convert to a wchar_t*
wchar_t wcstring[newsize];
wcscpy_s(wcstring, (wchar_t *)orig);
wcscat_s(wcstring, L" (wchar_t *)");
wcout << wcstring << endl;

// Convert to a CComBSTR
CComBSTR ccombstr((char *)orig);
if (ccombstr.Append(L" (CComBSTR)") == S_OK)
{
CW2A printstr(ccombstr);
cout << printstr << endl;
}

// Convert to a CString
CString cstring((char *)orig);
cstring += " (CString)";
cout << cstring << endl;

// Convert to a basic_string
string basicstring((char *)orig);
basicstring += " (basic_string)";
cout << basicstring << endl;

// Convert to a System::String
String ^systemstring = gcnew String((char *)orig);
systemstring += " (System::String)";
Console::WriteLine("{0}", systemstring);
delete systemstring;
}

输出

Hello, World! (_bstr_t)
Hello, World! (char *)
Hello, World! (wchar_t *)
Hello, World! (CComBSTR)
Hello, World! (CString)
Hello, World! (basic_string)
Hello, World! (System::String)

从 CComBSTR 转换
示例

此示例演示如何从 CComBSTR 转换为上面列出的其他字符串类型。
复制代码

// convert_from_ccombstr.cpp
// compile with: /clr /link comsuppw.lib

#include <iostream>
#include <stdlib.h>
#include <string>

#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"
#include "vcclr.h"

using namespace std;
using namespace System;
using namespace System::Runtime::InteropServices;

int main()
{
CComBSTR orig("Hello, World!");
CW2A printstr(orig);
cout << printstr << " (CComBSTR)" << endl;

// Convert to a char*
const size_t newsize = 100;
char nstring[newsize];
CW2A tmpstr1(orig);
strcpy_s(nstring, tmpstr1);
strcat_s(nstring, " (char *)");
cout << nstring << endl;

// Convert to a wchar_t*
wchar_t wcstring[newsize];
wcscpy_s(wcstring, orig);
wcscat_s(wcstring, L" (wchar_t *)");
wcout << wcstring << endl;

// Convert to a _bstr_t
_bstr_t bstrt(orig);
bstrt += " (_bstr_t)";
cout << bstrt << endl;

// Convert to a CString
CString cstring(orig);
cstring += " (CString)";
cout << cstring << endl;

// Convert to a basic_string
wstring basicstring(orig);
basicstring += L" (basic_string)";
wcout << basicstring << endl;

// Convert to a System::String
String ^systemstring = gcnew String(orig);
systemstring += " (System::String)";
Console::WriteLine("{0}", systemstring);
delete systemstring;
}

输出

Hello, World! (CComBSTR)
Hello, World! (char *)
Hello, World! (wchar_t *)
Hello, World! (_bstr_t)
Hello, World! (CString)
Hello, World! (basic_string)
Hello, World! (System::String)

从 CString 转换
示例

此示例演示如何从 CString 转换为上面列出的其他字符串类型。
复制代码

// convert_from_cstring.cpp
// compile with: /clr /link comsuppw.lib

#include <iostream>
#include <stdlib.h>
#include <string>

#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"

using namespace std;
using namespace System;

int main()
{
CString orig("Hello, World!");
wcout << orig << " (CString)" << endl;

// Convert to a char*
const size_t newsize = 100;
char nstring[newsize];
strcpy_s(nstring, orig);
strcat_s(nstring, " (char *)");
cout << nstring << endl;

// Convert to a wchar_t*
// You must first convert to a char * for this to work.
size_t origsize = strlen(orig) + 1;
size_t convertedChars = 0;
wchar_t wcstring[newsize];
mbstowcs_s(&convertedChars, wcstring, origsize, orig, _TRUNCATE);
wcscat_s(wcstring, L" (wchar_t *)");
wcout << wcstring << endl;

// Convert to a _bstr_t
_bstr_t bstrt(orig);
bstrt += " (_bstr_t)";
cout << bstrt << endl;

// Convert to a CComBSTR
CComBSTR ccombstr(orig);
if (ccombstr.Append(L" (CComBSTR)") == S_OK)
{
CW2A printstr(ccombstr);
cout << printstr << endl;
}

// Convert to a basic_string
string basicstring(orig);
basicstring += " (basic_string)";
cout << basicstring << endl;

// Convert to a System::String
String ^systemstring = gcnew String(orig);
systemstring += " (System::String)";
Console::WriteLine("{0}", systemstring);
delete systemstring;
}

输出

Hello, World! (CString)
Hello, World! (char *)
Hello, World! (wchar_t *)
Hello, World! (_bstr_t)
Hello, World! (CComBSTR)
Hello, World! (basic_string)
Hello, World! (System::String)

从 basic_string 转换
示例

此示例演示如何从 basic_string 转换为上面列出的其他字符串类型。
复制代码

// convert_from_basic_string.cpp
// compile with: /clr /link comsuppw.lib

#include <iostream>
#include <stdlib.h>
#include <string>

#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"

using namespace std;
using namespace System;

int main()
{
string orig("Hello, World!");
cout << orig << " (basic_string)" << endl;

// Convert to a char*
const size_t newsize = 100;
char nstring[newsize];
strcpy_s(nstring, orig.c_str());
strcat_s(nstring, " (char *)");
cout << nstring << endl;

// Convert to a wchar_t*
// You must first convert to a char * for this to work.
size_t origsize = strlen(orig.c_str()) + 1;
size_t convertedChars = 0;
wchar_t wcstring[newsize];
mbstowcs_s(&convertedChars, wcstring, origsize, orig.c_str(), _TRUNCATE);
wcscat_s(wcstring, L" (wchar_t *)");
wcout << wcstring << endl;

// Convert to a _bstr_t
_bstr_t bstrt(orig.c_str());
bstrt += " (_bstr_t)";
cout << bstrt << endl;

// Convert to a CComBSTR
CComBSTR ccombstr(orig.c_str());
if (ccombstr.Append(L" (CComBSTR)") == S_OK)
{
CW2A printstr(ccombstr);
cout << printstr << endl;
}

// Convert to a CString
CString cstring(orig.c_str());
cstring += " (CString)";
cout << cstring << endl;

// Convert to a System::String
String ^systemstring = gcnew String(orig.c_str());
systemstring += " (System::String)";
Console::WriteLine("{0}", systemstring);
delete systemstring;
}

输出

Hello, World! (basic_string)
Hello, World! (char *)
Hello, World! (wchar_t *)
Hello, World! (_bstr_t)
Hello, World! (CComBSTR)
Hello, World! (CString)
Hello, World! (System::String)

从 System::String 转换
示例

此示例演示如何从 System.String 转换为上面列出的其他字符串类型。
复制代码

// convert_from_system_string.cpp
// compile with: /clr /link comsuppw.lib

#include <iostream>
#include <stdlib.h>
#include <string>

#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"
#include "vcclr.h"

using namespace std;
using namespace System;
using namespace System::Runtime::InteropServices;

int main()
{
String ^orig = gcnew String("Hello, World!");
Console::WriteLine("{0} (System::String)", orig);

pin_ptr<const wchar_t> wch = PtrToStringChars(orig);

// Convert to a char*
size_t origsize = wcslen(wch) + 1;
const size_t newsize = 100;
size_t convertedChars = 0;
char nstring[newsize];
wcstombs_s(&convertedChars, nstring, origsize, wch, _TRUNCATE);
strcat_s(nstring, " (char *)");
cout << nstring << endl;

// Convert to a wchar_t*
wchar_t wcstring[newsize];
wcscpy_s(wcstring, wch);
wcscat_s(wcstring, L" (wchar_t *)");
wcout << wcstring << endl;

// Convert to a _bstr_t
_bstr_t bstrt(wch);
bstrt += " (_bstr_t)";
cout << bstrt << endl;

// Convert to a CComBSTR
CComBSTR ccombstr(wch);
if (ccombstr.Append(L" (CComBSTR)") == S_OK)
{
CW2A printstr(ccombstr);
cout << printstr << endl;
}

// Convert to a CString
CString cstring(wch);
cstring += " (CString)";
cout << cstring << endl;

// Convert to a basic_string
wstring basicstring(wch);
basicstring += L" (basic_string)";
wcout << basicstring << endl;

delete orig;
}

输出

Hello, World! (System::String)
Hello, World! (char *)
Hello, World! (wchar_t *)
Hello, World! (_bstr_t)
Hello, World! (CComBSTR)
Hello, World! (CString)
Hello, World! (basic_string)

如何使用 类进行文件的 I/O 处理

摘要:传统的文件 I/O 库如 Unix 的 <io.h> 和 <stdio.h> ,由于其程序接口的原因,在很大程度上强制程序员进行某些处理,缺乏类型安全和国际化支持。C++ 的 <fstream> 库则在文件的 I/O 方面提供了一个增强的、面向对象的、具有国际化意识的库。本文将介绍如何使用这个库进行文件的 I/O 处理并利用它来编写易于跨平台的代码。

  大多数 C++ 程序员都熟悉不止一个文件 I/O 库。首先是传统的 Unix 风格的库,它由一些低级函数如 read() 和 open()组成。其次是 ANSI C 的 <stdio.h> 库,它包含 fopen() 和 fread()等函数。其它的还有一些具备所有权的库或框架,比如 MFC,它有很多自己的文件处理类。

  这些库一般都很难跨平台使用。更糟的是,上述提到的 C 库由于其程序接口的原因,在很大程度上强制程序员进行某些处理,而且缺乏类型安全支持。

  标准 C++ 提供提供了一个增强的、面向对象的、具有国际化意识的 <fstream> 库。这个库包含一系列派生于标准 ios_base 和 ios 类的类模板。因此, <fstream> 提供了高级的自动控制机制和健壮性。本文下面将示范如何使用 <fstream> 类实现文件的输入/输出处理:

  第一步:创建文件流

  输入文件流(ifstream)支持重载的 >> 操作符,同样,输出文件流(ofstream)支持重载的 << 操作符。结合了输入和输出的文件流被称为 fstream。下面的程序创建了一个 ifstream 对象:dict,并将该对象中的每一个单字显示到屏幕上:
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
using namespace std;
int main()
{
  string s;
  cout<<"enter dictionary file: ";
  cin>>s;
  ifstream dict (s.c_str());
  if (!dictionary) // were there any errors on opening?
    exit(-1);
  while (dictionary >> s) cout << s <<''\n'';
}   

  我们必须调用 string::c_str() 成员函数,因为 fstream 对象只接受常量字符串作为文件名。当你将文件名作为参数传递时,构造函数试图打开指定的文件。接着,我们用重载的!操作符来检查文件的状态。如果出错,该操作符估值为 true。最后一行是个循环,每次反复都从文件读取一个单字,将它拷贝到 s,然后显示出来。注意我们不必显式地检查 EOF,因为重载操作符 >> 会自动处理。此外,我们不用显式地关闭此文件,因为析构函数会为我们做这件事情。
过时和荒废的 <fstream.h> 库支持 ios::nocreate 和 ios::noreplace 标志。但新的 <fstream> 库已经取代了 <fstream.h> 并不再支持这两个标志。

  文件的打开模式

  如果你不显式指定打开模式,fstream 类将使用默认值。例如,ifstream 默认以读方式打开某个文件并将文件指针置为文件的开始处。为了向某个文件写入数据,你需要创建一个 ofstream 对象。<fstream> 定义了下列打开模式和文件属性:
ios::app // 从后面添加
ios::ate // 打开并找到文件尾
ios::binary // 二进制模式 I/O (与文本模式相对)
ios::in // 只读打开
ios::out // 写打开
ios::trunc // 将文件截为 0 长度

  你可以用位域操作符 OR 组合这些标志:
ofstream logfile("login.dat", ios::binary | ios::app);

  fstream 类型对象同时支持读和写操作:
fstream logfile("database.dat", ios::in | ios::out);

  第二步:设置文件的位置

  文件具备一个逻辑指针,它指向该文件中的某个偏移位置。你可以通过调用seekp()成员函数,以字节为单位将这个指针定位到文件的任意位置。为了获取从文件开始处到当前偏移的字节数,调用seekp()即可。在下面的例子中,程序将文件位置前移10个字节,然后调用 tellp()报告新位置:
ofstream fout("parts.txt");
fout.seekp(10); // 从0偏移开始前进 10 个字节
cout<<"new position: "<<fout.tellp(); // 显示 10

  你可以用下面的常量重新定位文ian指针:
ios::beg // 文件开始位置
ios::cur // 当前位置,例如: ios::cur+5
ios::end // 文件尾

  第三步:读写数据

  fstream 类为所有内建数据类型以及 std::string 和 std::complex 类型重载 << 和 >> 操作符。下面的例子示范了这些操作符的使用方法:
fstream logfile("log.dat");
logfile<<time(0)<<"danny"<<''\n''; // 写一条新记录
logfile.seekp(ios::beg); // 位置重置
logfile>>login>>user; // 读取以前写入的值

2008年4月20日星期日

Windows Embedded Blog from China
Windows Mobile开发资源介绍

目前Windows Mobile的开发资源已经非常多了,我们在这里试着对这些资源进行一个归纳,使第一次进入Windows Mobile领域的开发者能够更容易得找到有用的开发资源。
Windows Mobile是什么

Windows Mobile是微软为智能手机和PDA提供的操作系统,在Windows Mobile 5.0之前分为Pocket PC和Smartphone两种版本,Pocket PC中包括PDA版本和带电话功能的Phone Edition。在Windows Mobile 6.0中分为三类:Professional,即Pocket PC Phone Edition; Standard, 即Smartphone;Classic,即无电话功能的Pocket PC。

Windows Mobile是基于Windows CE操作系统开发的针对智能手机和PDA的操作系统平台。所以Windows Mobile的硬件与应用程序都是由相关的标准要求,符合标准才能够运行Windows Mobile操作系统。
获取开发工具

目前Windows Mobile的主流开发平台/语言分为两种:.NET(包括C#和VB.NET)和C++。微软已经将这两种开发语言的支持加入到Visual Studio中。Visual Studio 2005和2008均内置了Windows Mobile的SDK,可以直接开发Windows Mobile应用程序。Visual Studio也支持安装最新版本的Windows Mobile SDK。

如果想用Visual Studio开发Windows Mobile应用程序的话,必须已经获取了Visual Studio Professional或以上版本。

除了Visual Studio外,我们还可以使用免费的eMbedded Visual C++ 4.0来开发C++应用程序。在安装SP4版本后,可以支持基于Windows CE 5.0设备的应用开发(目前Windows Mobile 5.0和6.0均基于Windows CE 5.0)。下载地址如下:

http://www.microsoft.com/downloads/details.aspx?FamilyId=1DACDB3D-50D1-41B2-A107-FA75AE960856&displaylang=en

eMbedded Visual C++ 4.0 SP4下载地址:

http://www.microsoft.com/downloads/details.aspx?familyid=4A4ED1F4-91D3-4DBE-986E-A812984318E5&displaylang=en

在安装完成开发工具后,还需要根据不同的目标设备安装不同版本的Windows Mobile SDK。我们可以在MSDN网站的下载中查询"Windows Mobile x.0 SDK",或者直接去下面链接中查找:

http://msdn2.microsoft.com/en-us/windowsmobile/bb264327.aspx

比如,Windows Mobile 6.0 SDK的下载地址:

http://www.microsoft.com/downloads/details.aspx?FamilyID=06111a3a-a651-4745-88ef-3d48091a390b&DisplayLang=en

如果要开发中文版的应用程序,还需要安装单独的本地化模拟器映像文件。Windows Mobile 6.0的语言映像文件下载链接如下:

http://www.microsoft.com/downloads/details.aspx?familyid=38C46AA8-1DD7-426F-A913-4F370A65A582&displaylang=en

除此之外,我们还需要安装ActiveSync 4.5,来使开发环境与Windows Mobile设备相连接。在Vista中Windows Mobile Device Center与ActiveSync的功能相同。

如果使用.NET Compact Framework来开发应用程序,还需要保证目标设备上安装了.NET CF的CLR,如果没有目标设备安装.NET CF,可以下载单独的.NET CF再发布包:

http://www.microsoft.com/downloads/details.aspx?FamilyID=9655156b-356b-4a2c-857c-e62f50ae9a55
网络资源

Windows Mobile开发中心

http://msdn2.microsoft.com/en-us/windowsmobile/default.aspx

Windows Mobile产品主页

http://www.microsoft.com/windowsmobile/

http://www.microsoft.com/china/windowsmobile

Windows Mobile移动解决方案联盟

http://www.wmisv.com.cn/

Pocket PC Developer Network

老牌Pocket PC开发者网站,在EVC和EVB时代曾经是开发者唯一的选择,不过后来风头逐渐被OpenNETCF盖过,但目前依旧是最完整的开发文章目录

http://www.pocketpcdn.com/

Smartphone Developer Network

Pocket PC Developer Network的姊妹网站

http://www.smartphonedn.com/

Code Project

综合性开发者网站,其中CE开发和.NET CF开发部分由许多值得借鉴的示例代码

http://www.codeproject.com/KB/mobile/

DEVBUZZ.COM

老牌Embedded Visual Basic开发网站,转型.NET CF后,仍然有一些开发资源值的一看

http://www.devbuzz.com/
开发资源

OpenNETCF

著名的开源类库,早先由多位MVP发起,进行公司化运作,后被Novell收购,先为咨询公司。OpenNETCF的最新版本仍可以免费使用,但不提供源代码。

http://www.opennetcf.com/

InTheHand

著名的开源类库,32feet.NET是以Bluetooth和IrDA开发为主的Shared Source类库。

http://inthehand.net/

Mobile Line of Business Solution Accelerator

由微软开发的一套移动商业软件开发指导包

http://www.microsoft.com/downloads/details.aspx?FamilyId=80A5C2C5-4F9B-4C1A-BFF6-2A3C6B68D15B&displaylang=en

Mobile Client Software Factory

微软开发的一套软件工厂框架,将设计模式应用于Mobile软件开发

http://msdn2.microsoft.com/en-us/library/aa480471.aspx

下载地址:

http://www.microsoft.com/downloads/details.aspx?FamilyID=F9176708-9F57-4C0F-97FB-F9C65A9BBF22&displaylang=en


开发社区

中文的开发论坛:

l 微软移动开发者论坛

微软的官方开发者论坛,目前的版主是微软最有价值专家(MVP)。

http://forums.microsoft.com/china/default.aspx?ForumGroupID=459&SiteID=15

l CSDN嵌入式开发论坛

最大的开发者社区,硬件/嵌入式开发板块中包括"嵌入开发(WinCE)"板块和移动平台板块中包括"Windows Mobile"板块

http://community.csdn.net/

l Windows Mobile开发者社区

CSIP创建的开发者讨论社区

http://www.winbile.net/BBS/

l 马宁的Windows Mobile开发研究

http://groups.csdn.net/aawolf_Mobile

l 博客园的Windows Mobile应用开发团队博客

shttp://mobiledev.cnblogs.com/

英文论坛:

l MSDN开发者社区:Smart Device Development

http://forums.microsoft.com/MSDN/default.aspx?ForumGroupID=11&SiteID=1

Webcast

l 中文MSDN与TechNet Webcast

Windows移动开发系列课程

http://www.microsoft.com/china/msdn/events/webcasts/shared/webcast/Series/WindowsMobile.aspx

Windows Mobile 技术开发黄金周

http://www.microsoft.com/china/msdn/events/webcasts/shared/webcast/Series/Mobilegoldenweek.aspx

Windows Mobile 2nd 开发黄金周

http://www.microsoft.com/china/msdn/events/webcasts/shared/webcast/Series/Mobilegoldenweek2nd.aspx

Windows Mobile 3rd 技术开发黄金周

http://www.microsoft.com/china/msdn/events/webcasts/shared/webcast/Series/mobile3rd.aspx

TechNet Windows 移动系列课程

http://www.microsoft.com/china/technet/webcasts/class/mobile.mspx

l 英文Webcast和Virtual Labs

Windows Mobility Marvels

主要针对的是Windows Mobile开发者,包括Webcast和Virtual Labs

http://www.microsoft.com/events/series/msdnmobility.aspx

Windows Mobility Marvels部分课程下载

http://www.microsoft.com/downloads/details.aspx?FamilyID=08e4391d-e07d-41fe-b2b8-aa4225281347&DisplayLang=en

Windows Mobile Solutions

针对IT Pro和Windows Mobile用户的Webcast系列

http://www.microsoft.com/events/series/msecmobility.aspx
BLOG

l Windows Mobile产品组英文BLOG

Windows Mobile Team Blog

http://blogs.msdn.com/windowsmobile/

.NET Compact Framework Team Blog

http://blogs.msdn.com/netcfteam/

Visual Studio For Device

http://blogs.msdn.com/vsdteam/

SQL Server Compact

http://blogs.msdn.com/SQLServerCompact/

l 产品组成员BLOG

Mike Hall的BLOG

http://blogs.msdn.com/mikehall/

Rob Tiffany's Windows Mobile Accelerator

主要研究领域为SQL CE和BOL Accelerator

http://blogs.msdn.com/robtiffany/

David Kline

.NET Compact Framework应用领域

http://blogs.msdn.com/davidklinems/

Steve Lasker's Web Log

SQL CE和Sync Service for ADO.NET

http://blogs.msdn.com/stevelasker/

Steven Pratschner's .Net CF WebLog

.NET Compact Framework CLR运行机制

http://blogs.msdn.com/stevenpr/

l 英文开发者BLOG

OpenNETCF Blogs

以开发OpenNETCF开源类库闻名的公司,拥有多位重量级MVP的BLOG

http://blog.opennetcf.org/

In the hand Blogs

另一个以开发InTheHand开源类库闻名的开发者BLOG

http://inthehand.net/blogs/

l 中文开发者BLOG

马宁的移动开发BLOG

http://blog.csdn.net/aawolf

张欣的BLOG

http://twodays.cnblogs.com/

黎波的BLOG

http://www.cnblogs.com/upto/

2008年2月13日星期三

Total Commander 7.02a CCF中英绿色美化版本
推荐的原因:最经典的软件之一,如果你不会使用,请到xbeta兄的新浪博客 善用佳软栏目学习:

http://blog.sina.com.cn/s/alist_1188742767_2_1.html

下载在下面附件!

预览 (7.0):

s1.jpg (375.44 KB)
2007-10-25 18:59

======================================================

1. 常见问题
配置以英文/XP-2K3/XGA/Windows Classic Theme为标准. 最佳搭配WinRAR/DAEMON/集成解码包. 其余搜索论坛.

a. Vista用户
1. Office插件
此插件貌似只能使用绝对路径.由于Vista没有自带转换器,若TC的安装目录不是C:\Program Files\Total Commander,则必须手动修改Office.ini中MSWRD832.CNV的所在目录.
2. 部分WFX不支持Vista.
b. 创建自解压档:[url=]?[/url][url=]压缩时将*.RAR/ZIP/7Z改为*.EXE. ZIP格式可以在TC中将*.ZIP 直接改名为*.EXE?[/url]
c. 别名:[url=]?[/url][url=]按左/右方向键定位到命令行后,输入别名即可打开相应程序. 如→CDO打开光驱,CDC关闭.?[/url]
d. 整合WinRAR[url=]?[/url][url=]在TOOLS下建立WinRAR目录,拷入WinRAR.exe/Default.SFX/Rarreg.key三个文件, 打开USER.ini文件,将%PROGRAMFILES%\WINRAR\WINRAR.EXE替换为%COMMANDER_PATH%\TOOLS\WINRAR\WINRAR.EXE.?[/url]
e. (批量)转换图像格式[url=]?[/url][url=]选中一/多张图片,按Alt+F5, 右侧下拉框中选择imagine, 将文件后缀由imagine改为想要的格式, 如JPG, GIF, PIC等, 确定.不建议转换多帧GIF. ?[/url]
f. CHM[url=]?[/url][url=]CHMDir是WCX&WDX, WCX时用于制作CHM或提取CHM资源, WDX时用于自定义列/鼠标悬停/批量改名/搜索等, 此插件配合TC的按目录压缩功能, 适合打包Firefox插件Scrapbook储存的网页并利用其WDX功能进行批量改名.
WCX用法:

提取资源: 选中某CHM后按Ctrl+PgDn.
制作CHM: 选中文件夹或文件后,按Alt+F5,下拉选中CHM,确定.

IEView是WLX, 使用IE核心查看CHM, 按F3. 第一次打开时可能会跳出下载的提示,选择打开, 方框打勾, 确定. 按4则用Archview查看CHM压缩情况.?[/url]
g. 报毒
使用自解压文件时会自动删除目标目录中的所有文件.手动解压亦可.

2. 插件/工具
此版本包括WCX, WDX, WFX, WLX 共47个, ADDON/工具若干. 全部汉化.

WCX - 12个:
7zip (7z), CheckSum (sha), CHMDir (chm/its), DirCopy (dircopy), ICLRead (icl), Imagine (imagine), ISO (iso&etc), MHTUnpack (mht/msg), Mover (mover), TreeCopyPlus (treecopy), Wipe (wipe), InstallExplorer (exe/msi)
---Alt+F5打包,Ctrl+PgDn提取资源. 部分如 MHTUnp & ISO & InstallExplorer 只可Ctrl+PgDn, 不适用Alt+F5

Dircopy:复制本目录结构, 不复制文件
Imagine.wcx: Ctrl+PgDn提取图片资源, Alt+F5转换图片格式.
InstallExplorer: 支持Wise/Vise Installer, Inno Setup, Gentee Installer, InstallShield, NullSoft Installer, SetupFactory, Eschalon Installer, 和 Windows Installer (MSI).
Mover: 移动归类. 以文件后缀/日期等整理本目录下选定的 (打包)文件, 子目录不受影响.
TreeCopyPlus: 复制归类. 用于整理搜索结果, 保留各文件原来的目录结构.
Wipe: 安全删除文件.

WDX - 15个:
AnyTag, CDocProp, CRCTag32, DirSizeCalc, ExeFormat, EXIF, FileX, ImgSize, Permissions, RarInfo, Shareinfo, TextLine, Torrent, UnicodeTest, WDX4I
---Shift+F1选择.

Font (WLX)/CHMDir (WCX) 同时作为WDX使用.
自定义列预设12项:
Audio, Checksum, CHM, Compiled, Directory, FileInfo, Font, Photo, Picture, Office, RAR, Torrent.
自定义提示信息:
覆盖操作提示 - 6类, 鼠标悬停提示 - 9类.

WFX - 7个:
ProcFS (查看/关闭进程), MSIE Cache (查看IE缓存), TC Services (查看/启/禁用系统服务), Uninstalle (删除程序), TConsole (命令行窗口), DevMan (设备管理器), EventNT (事件查看)
---Alt+R进入网上邻居后使用.

WLX -13个:
Archview, Excellence, FileInfo, Font, ICLView, HTMLView, IEView, Imagine, Mmedia, nfoviewer, Office, VisualDirSize.
---F3/Ctrl+Q 调用.

支持查看字体 (Font), 影音 (Mmedia), HTM?/MHT (HTMLView), CHM/PDF... (IEview), 压缩档/CHM/MHT/ISO... (ArchView), Exe/Dll... (FileInfo), Excel (Excellence), Word (Office), 图片 (Imagine), Nfo/Diz (nfoviewer), 图标 (ICLView), 屏幕保护 (SCRList), 文件/目录大小 (VisualDirSize, 只支持Ctrl+Q).
部分文件可同时被多个插件支持,如本版的WinRAR自解压程序被Archview/FileInfo/ICLView同时支持,F3查看时可按4切换插件.

---工具
Akelpad: 文本编辑器, 含以下16个插件

AutoComplete: 编辑CPP/HTML时自动完成, Ctrl+F1
AutoSave: 自动保存. F8
FullScreen: 全屏. F11
HexSel: 查看HEX值
Highlight: 语法高亮
LineBoard: 行号, F6开关, Shift+F6设置颜色.
Lines: 行处理
LinkExtract: 提取HTML中的超链接
Macros: 宏
MinimizeToTray: 最小化至系统栏. F9
RecentFiles: 自动删除列表中不存在的文件
SaveAllAs: 批量转换代码页.
SelAutoCopy: 选择后自动复制.
SpecialChar: 显示换行符等特殊字符. F7开关, Shift+F7设置颜色.
Toolbar: 工具栏
ContextMenu: F12调用. 7.02+附带Akelpad的重要插件. Lines, Macros, HexSel, SelAutoCopy和LinkExtract等均通过此插件调用.不再设置单独的快捷键. 部分插件亦可通过此插件开关/设置.

NIRCMD: 多用途命令行工具,预设10个外部命令和9个别名.
---ADDON
TotalEditor:
预设TC外部命令em_batchopen/em_batchmedia. 同时打开选定的文本或影音档. 若选定 (多重)目录,则其下所有子目录的此类文件一并打开.
NewFile: 新建文件 (夹).
Restarter: 重启TC
TCQSP: 快速查找
TC Log Viewer: 查看操作记录

3. 配置
大致说明

a. 颜色:11种. MultiMedia, Picture, Archive, Disk Image, Document, Executable, Temporary, Hidden, Checksum, Download, Database
b. 工具栏: 2个, DEFAULT (用于TC内部命令)和TOOLS (用于管理系统/绿色工具).
c.Hotlist列表: 以WXP的系统变量为准 (英).
d. 图标/帮助: X-Qute, 其它为Vicons.中文帮助文件使用本坛slownet兄作品.
e. 菜单: 整合自EE+张学思版 (6.5x)+大量改动. 快捷键大部参照张版 (6.5x).
f. 开始菜单:

加/卸载镜像: 需DAEMON支持.
快速删除目录: 用于文件数量极大的目录 (不使用回收站),慎用!!!
批量打开文本: 选定目录/文件后使用该命令, 则Akelpad会打开选定 (文件夹 (含子文件夹下))的所有文本.
批量打开影音: 同上, 调用Windows Media Player播放, 最好配合集成Codec包,如Final Codecs.
新建文件/夹: 给不知道Shift+F4的人用.
新建会话: 强行新开TC窗口
重启TC.
快速查找加强版.
查看操作记录.
备份至桌面: 打包User目录和WCX_FTP.ini至桌面.

======================================================
更新细节:
* Update on 1/10/07
更新:
TC -> 7.02a
WDX 2个: AnyTag -> 0.98(支持Vista), WDX4I -> 0.1b
Akelpad -> 3.40及全部插件
ADDON 1个: TCQSP -> 2.2
UNRAR.DLL -> 3.71.1.246 (WinRAR)
中文帮助HLP -> 7.02a Final.

增加:
ADDON 1个: TC Log Viewer(查看操作记录)及相关外部命令.
Akelpad插件 1个: FullScreen
Office插件所需的转换器.(For Vista)

调整:
部分插件设置
更换MHTUnp.wcx为MHTUnPack.wcx

* Update on 7/9/07[url=]?[/url][url=]更新:
TC -> 7.02
WDX 2个: FileX -> 1.7; CRC32Tag -> 0.21Beta
WLX 2个: Imagine -> 1.0.0.0 Beta 5, HTMLView -> 1.2
AkelPad -> 3.38 及大部分插件.
NirCMD -> 2.00, 兼容Vista
UNRAR.DLL -> 3.70.100.211 (WinRAR)
中文帮助HLP -> 7.01 Final.

增加:
WDX 5个: WDX4i, Permissions, ExeFormat, UnicodeTest, TextLine
WFX 2个: MSIE Cache (查看IE缓存), EventNT (事件查看)
WLX 2个: HTMLView (这个和IEView都有Bug,只能再次补上), SCRList (查看SCR)
ADDON 1个: TCQSP (快速查找加强版)
颜色方案 2个: Download, Database
自定义列 1个: Compiled
鼠标悬停提示 2个: Compiled及Ini/Inf
TinnyTCRestarter及相关外部命令/开始菜单项
快捷键 2个: Shift+Ctrl+F9/0
别名7个 (NirCMD相关)
AkelPad插件 3个: Macros, LinkExtract, ContextMenu, AutoSave
FileInfo插件UnUpack.dll (PE Explorer)
常用设置备份功能.

调整:
菜单/中文语言包/开始菜单/INC/插件设置/自定义列...
WDX <- DirSizeCalc: 降回1.21, 2.0B2无法按目录大小排序, 除非设置两列大小.
拆分WINCMD.INI/USER.INI, 升级保留文件大都并入USER目录, 其中USER.INI定义常用选项, HISTORY.INI保存操作记录.
汉化FileInfo (2.09), EventNT (1.3), 进一步汉化ICLView和部分WDX显示信息.
大量微调.

删除:
WFX 1个: Versions
RAR的覆盖提示设置
AkelPad插件: URLMenu?[/url]
* Update on 22/6/07[url=]?[/url][url=]修正版本.
更新:
TC -> 7.01
AkelPad -> 3.32 及部分插件.
UnRAR.dll (WinRAR)
中文帮助HLP -> 7.0 Final.

增加:
快捷键: Shift+Ctrl+Home
AkelPad插件: RecentFiles

删除:
外部命令/别名三个,RS/IS/CS.

调整:
菜单/INC描述, Ctrl+Home/End
修正英文版使用汉化MMedia及菜单中的Unicode字符.?[/url]
* Update on 8/6/07[url=]?[/url][url=]更新:
TC -> 7.0 Final
AkelPad -> 3.31, 及全部插件.
WLX 1个: Imagine -> 1.0.0.0 Beta 4
WDX 2个: FileX ->1.6, DirSizeCalc -> 2.0 Beta 2

增加:
WDX 1个: AnyTag (尺寸较大,但AudioInfo有些问题)
Addon 1个: NewFile (用于新建文件 (夹))
AkelPad插件5个: HexSel, AutoComplete, Lines, SaveAllAs, SpecialChar.
NIRCMD及相关外部命令10个/别名2个
快捷键: Shift+Alt+123456789, Shift+Ctrl+C, Shift+Ctrl+I
TotalEditor外部命令1个: BatchMedia.

删除:
CDOC及相关外部命令em_CDOC/别名CDOC
WLX 1个: HTMLView
WDX 1个: AudioInfo (速度慢/MP3只读取ID3V1/停止开发)及相应配置

调整:
所有分辨率共用设置,存入User.ini
菜单, INC, 语言包
WCX后缀: gif -> imagine, tcpy -> treecopy, move -> mover
Devcon.exe并入TC目录,用于在\\设备管理器中删除设备.
[Rename]和[Splitperfile]段并入USER.ini.
快捷键: Shift+Ctrl+123456, Ctrl+123456
默认显示属性, 记录日志.
插件参数.?[/url]
* Update on 17/3/07[url=]?[/url][url=]更新:
TC -> 7.0 PB4
ADDON 1个: TotalEditor -> 0.20
WCX 2个: ISO -> 1.74b1, 7Zip -> 0.55
WDX 1个: CRC32Tag -> 0.19B
TOOLS 1个: Akelpad -> 3.25

增加:
WLX 1个: HTMLView, 主要针对IEView和MMedia的冲突.
Akelpad插件2个: LineBoard, HighLight
程序别名18个
覆盖操作及鼠标悬停自定义提示信息, 7类/5类
外部命令20个.
自定义列2个: CHM, FileInfo
新增内部命令的菜单项及相应快捷键

调整:
NoClose并入TC所在目录.
菜单, 语言包, INC, 工具栏, 其它参数修正
快捷键:Ctrl+012349, Shift+Ctrl+012349,Alt+X/Z,Ctrl+Home/End

取消:
TotalEditor对压缩包的设置?[/url]
* Update on 24/12/6 (2007大礼包专用版)[url=]?[/url][url=]更新:
WCX 1个: 7zip -> 0.54
WLX 2个: FileInfo -> 2.09, Imagine -> 1.0.0.0 b3
WDX 1个: CRC32Tag -> 0.18B
UnRAR.dll (From WinRAR) & UnUPX.dll (From PE Explorer).
图标库: ICL->DLL, 支持菜单图标.

增加:
WFX 4个: Uninstaller (卸载程序) / TConsole (命令行窗口) / DevMan (设备管理器) / Versions (在线更新)
WCX 2个: MHTUnp (提取MHT资源) / Imagine (制作/提取GIF资源)
ADDON 1个: TotalEditor/及自定义命令em_batchopen, 已设置批量打开文本文件/压缩档 (开始菜单中).
自定义列1个: Font
菜单图标
缩略图自定义项

调整:
默认编辑器: AkelPad (含插件MinimizeToTray/SelAutoCopy/Toolbar/URLMenu).
快捷键: 细分Shift+F6和F2, Alt+L&U / 左&两侧文件夹树.
MSI: Enter运行,Ctrl+PgDn提取资源.
WLX次序,Archview增加7Zip支持,Fileinfo支持查看UPX/Aspack压缩细节.
Hotlist.
允许预览WMF (=3).
缩略图缓存目录设为..\CACHE.
开始菜单.
汉化部分插件, 如ProcFS/Services/TConsole/ICLView...
大量微调.

*****以下段值从此版开始另存入%commander_path%\user.ini文件,今后升级本美/绿版本可备份此文件保留大部分个人设置*****
[Commandlinehistory]
[DirMenu]
[DriveHints]
[MkDirHistory]
[RenameTemplates]
[RenameSearchFind]
[RenameSearchReplace]
[SearchName]
[SearchIn]
[SearchText]
[Selection]
[left]
[right]
[lefttabs]
[righttabs]
[RightHistory]
[LeftHistory]
[user]
[800x600 (8x16)]
[1152x864 (8x16)]
[1280x1024 (8x16)]
[1400x1050 (8x16)]
[1440x900 (8x16)]
[1600x1200 (8x16)]
[1680x1050 (8x16)]?[/url]
* Update on 24/11/06[url=]?[/url][url=]升级:
TC ->7.0 PB2
SkimEdit ->3.07
WCX 2个: CHMDir -> 0.40c, ICLRead -> 1.3
WLX 4个: FileInfo ->2.08, Font -> 0.09, ICLView -> 3.10.2006, Imagine -> 0.97 Final

增加:
WCX 4个: DirCopy (复制目录结构), ICLRead (制作/提取ICL资源) & Mover (文件移动归类), InstallExplorer (提取MSI资源)
WDX 1个: ShareInfo, CRCTag32
WFX 2个: ProcFS (任务管理器), TC Services (系统服务)
颜色方案1个: Checksum
自定义列1个: Checksum

修正:
菜单: TC7新增命令,冗余项
WLX: Font (中文版), 描述错误,
SFXHEAD.SFX: 替换为WinRAR的Zip.SFX.
图标库兼容Vista.

快捷键:
Alt+U: 改为开/关一列文件夹树 (左侧窗口)
Shift+Ctrl+F8: 设为开/关文件夹树
Shift+Ctrl+Y: 设为查看TC内部命令

调整:
菜单, 颜色, INC, Button Bar, blahblahblah...?[/url]
* Update on 7/8/6[url=]?[/url][url=]升级:
部分插件

修正:
菜单, 工具栏, 描述错误, WDX配置, 其它微调.

替换:
中文版帮助文件换回HLP格式, CHM对压缩免疫,:- (.
NoClose.pif 换成 NoClose Replacer
WLX 1个 - IEView (不同作者)

增加:
WCX 2个 - Wipe (Secure Delete) & TreeCopyPlus
WDX 4个 - AudioInfo & CDocProp & RarInfo & Torrent
WLX 3个 - ArchView & nfoviewer & Mmedia (调用WMP, 配合集成codecs为佳, e.g. ffdshow, MyMPC)
颜色方案 4个 - Document, Executable, Temporary, Hidden
自定义列 4个 - Office, RAR, Torrent, Photo
插件中文 - Excluding ICLView.

删除:
绿色软件 2个 - Remove Hotfix Backups & RegCompact
WDX 1个 - AnyTag (过大, 替换为AudioInfo)
图标库 Buttonbar.icl 中未用图标?[/url]
* Update on 3/8/06[url=]?[/url][url=]修正:英文版中的几个绝对路径, 菜单冗余项
增加:中文版.?[/url]

串行通讯注意事项

作者:佚名 文章来源:本站原创 点击数:1234 更新时间:2005-6-6

1 选择通讯方式 -- 同步还是非同步
正如在《Serial communications in MicrosoftWin32》等文章中提到的,同步(NonOverLapped)方式是比较简单的一种方式,编写起来代码的长度要明显少于异步(OverLapped)方式,我开始用同步方式编写了整个子程序,在Windows98 下工作正常,但后来在Windows2000下测试,发现接收正常,但一发送数据,程序就会停在那里,原因应该在于同步方式下如果有一个通讯 Api在操作中,另一个会阻塞直到上一个操作完成,所以当读数据的线程停留在 WaitCommEvent 的时候,WriteFile就停在那里。我又测试了我手上所有有关串行通讯的例子程序,发现所有使用同步方式的程序在 Windows 2000下全部工作不正常,对这个问题我一直找不到解决的办法,后来在 Iczelion 站点上发现一篇文章提到 NT 下对串行通讯的处理和 9x有些不同,根本不要指望在 NT 或 Windows 2000 下用同步方式同时收发数据,我只好又用异步方式把整个通讯子程序重新写了一遍。所以对于这个问题的建议是:如果程序只打算工作在 Win9x 下,为了简单起见,可以用同步方式写程序,如果程序打算在 NT下也可以工作的话,就必须用异步方式写。

2 Win32 通讯 API Bug 之一 --- CommConfigDialog

CommConfigDialog 是弹出系统内置串口设置对话框的 API,我们在设备管理器中设置串口参数的对话框就是这个,使用这个API 时不用先打开端口,它并不针对一个已打开的端口,而是仅仅是把 DCB 的内容填写到对话框中,当按了 OK 后把输入的结果存回到
DCB 数据结构中,至于什么时候把结果设置到串口上,那就是你自己要做的事情了。
CommCinfigDialog 的定义如下:
BOOL CommConfigDialog(
LPTSTR lpszName, // pointer to device name string
HWND hWnd, // handle to window
LPCOMMCONFIG lpCC // pointer to comm. configuration structure
);

但在使用中发现,对话框有时能出来,有时出不来,最后总结的经验是问题出在 COMMCONFIG 结构的 dwSize字段上,COMMCONFIG 的定义如下:
typedef struct _COMM_CONFIG {
DWORD dwSize;
WORD wVersion;
WORD wReserved;
DCB dcb;
DWORD dwProviderSubType;
DWORD dwProviderOffset;
DWORD dwProviderSize;
WCHAR wcProviderData[1];
} COMMCONFIG, *LPCOMMCONFIG;

在参数中,wVersion 要填 100h,dwProviderSubType 要填 1,但 dwSize 就不能填 sizeof
COMMCONFIG 了,我发现好象一定要把 dwSize 设置为比 sizeof COMMCONFIG
对话框才能出来,所以我用的代码中定义了一个足够大的缓冲区作为结构的地址:
_CommConfigDialog proc
local @stCC[256]:BYTE
pushad
invoke RtlZeroMemory,addr @stCC,sizeof @stCC
mov (COMMCONFIG ptr @stCC).dwSize,256
mov (COMMCONFIG ptr @stCC).wVersion,100h
mov (COMMCONFIG ptr @stCC).dwProviderSubType,1
invoke CommConfigDialog,addr [esi].szPortName,[esi].hWnd,addr @stCC
popad
ret
_CommConfigDialog endp

3 Win32 通讯 API Bug 之二--- BuildCommDCB

BuildCommDCB 的功能是把一个字符串如 com1:9600,n,8,1 这样的转换到具体的数据填写到 DCB中,但使用中也存在问题,我发现我用它转换象 com1:9600,e,7,1 之类的带校验位的字符串,它总是无法把这个 e给我转换过去,设置好串口一看,成了 9600,n,7,1,而上面提到的 CommConfigDialog返回的结果用来设置串口却是正确的,经过比较,发现问题出在 DCB.fbits.fParity 这个 bit 上,只有把这个 bit 置1,校验位才是有效的,而 BuildCommDCB 恰恰是漏了这个 bit,所有如果你要使用 BuildCommDCB,别忘了补充把DCB.fbits.fParity 设置回去,我用的代码是:

_BuildCommDCB proc _lpszPara,_lpstDCB
pushad
mov esi,_lpstDCB
assume esi:ptr DCB
invoke RtlZeroMemory,esi,sizeof DCB
invoke BuildCommDCB,_lpszPara,esi
;********************************************************************

; 根据校验位补充设置 DCB 中的 DCB.fbits.fParity 字段
;********************************************************************
mov dword ptr [esi].fbits,0010b
cld
@@:
lodsb
or al,al
jz @F
cmp al,'='
jz _BCD_Check
cmp al,','
jnz @B
_BCD_Check:
lodsb
or al,al
jz @F
or al,20h
cmp al,'n'

jnz @B

;********************************************************************
; 扫描到 =n 或 ,n 则取消校验位
;********************************************************************

mov esi,_lpstDCB
and dword ptr [esi].fbits,not 0010b
@@:
popad
ret
_BuildCommDCB endp

4 Win32 通讯编程的一般流程

由于同步方式相对比较简单,在这里讲述的是异步方式的流程,在其他的很多文章里提到了 Windows 通讯 API 有二十多个,它们是:
BuildCommDCB
BuildCommDCBAndTimeouts
ClearCommBreak
ClearCommError
CommConfigDialog
EscapeCommFunction
GetCommConfig
GetCommMask
GetCommModemStatus
GetCommProperties
GetCommState
GetCommTimeouts
GetDefaultCommConfig
PurgeComm
SetCommBreak
SetCommConfig
SetCommMask
SetCommState
SetCommTimeouts
SetDefaultCommConfig
SetupComm
TransmitCommChar
WaitCommEvent
我刚看到这些 API 的时候,都不知道如何使用它们,但并不是所有这些 API 都是必须用的,比如说你要检测当前串口的设置可以只用
SetCommState 而不用 GetCommProperties 和
GetCommConfig,虽然它们返回的信息可能更多。同样,如果有些值你想用缺省的,比如缓冲区的大小和超时的时间等等,那么
SetupComm 和 BuildCommDCBAndTimeouts、SetCommTimeouts
也可以不用,TransmitCommChar 是马上在发送序列中优先插入发送一个字符用的,平时也很少用到,下面讲的是必须用到的 API和使用步骤
建立 Event -- 用 CreateEventinvoke CreateEvent,NULL,TRUE,FALSE,NULL
用异步方式操作串口必须要定义 OVERLAPPED 结构,其中的 hEvent 必须自己建立,你要定义两个 OVERLAPPED结构,一个用于读一个用于写,当然也必须建立两个 Event,把它们放入 OVERLAPPED.hEvent

打开串口 -- 用 CreateFile
invoke CreateFile,addr szPortName,GENERIC_READ or
GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL
注意用异步方式必须指定 FILE_FLAG_OVERLAPPED,而文件方式必须 OPEN_EXISTING,读写必须是
GENERIC_READ or GENERIC_WRITE

设置串口参数 -- 用 SetCommState
invoke SetCommState,hCom,addr dcbx
hCom 是前面打开成功后返回的句柄,dcbx 是数据结构
DCB,里面包括了通讯的具体参数,至于这个参数的建立,你可以自己填写,也可以用前面提到的 BuildCommDCB 或
CommConfigDialog 填写

建立读数据的线程
到这里,就可以开始读数据了,一般我们是在主线程中写数据,因为写是我们可以控制的,而读的时候我们不知道数据什么时候会到,所以要建立一个线程专门用来读数据,在这个线程中,我们循环地用
ReadFile 读串口,同时用 WaitCommEvent 检测线路状态。

如果要检测通讯状态,如 CTS 信号,RingIn 等等 -- 用
SetCommMask、WaitCommEvent、ClearCommError、GetCommModemStatus

invoke SetCommMask,hCom,EV_BREAK or EV_CTS or EV_DSR or EV_ERR or
EV_RING or EV_RLSD or EV_RXCHAR or EV_RXFLAG or EV_TXEMPTY
SetCommMask 指定 WaitCommEvent 要等待的事件名称,具体的参数请查手册


invoke WaitCommEvent,hCom,addr dwEvent,NULL
WaitCommEvent 等待一直到 SetCommMask 指定事件之一发生


invoke ClearCommError,hCom,addr dwError,addr stComStat
在 WaitCommEvent 以后,要用 ClearCommError 清除事件的 Flag,以便进行下一轮
WaitCommEvent,同时这个 API 可以获得更详细的事件信息


invoke GetCommModemStatus,hCom,addr dwModemStatus
同样,GetCommModemStatus 是用来获得串口线路状态的,如 CTS、RING 等等,当 WaitCommEvent
返回时,只是指出了如 CTS 等等状态有变化,但具体是变成 On 还是 Off 了还要靠这个 API 去取得更详细的信息

读数据 -- 用 ReadFile


invoke ReadFile,hCom,addr szBuffer,sizeof szBuffer,addr
dwBytesRead,addr stReadState
最后一个参数是开头定义的 OVERLAPPED 结构的地址,指定了它就表示是用异步方式的读方式,这个 API 会马上返回,接下去要用

invoke GetOverlappedResult,hCom,addr stReadState,addr
dwBytesRead,FALSE
将其余的数据读完

结束时关闭端口 -- 停止 WaitCommEvent 的等待以及关闭端口 CloseHandle

平时程序会停留在 WaitCommEvent 的等待中,当要终止线程的时候,必须是程序从 WaitCommEvent
中退出来,这时候要用

按照 Win32 手册上的说明,参数为 NULL 的 SetCommMask 会使另一个线程中的 WaitCommEvent
马上返回,然后就是用 CloseHandle 关闭端口
invoke CloseHandle,hCom
5 Win32 通讯 API Bug 之二--- SetCommMask 和 WaitCommEvent

严格的说这不应该是 Bug,而是偶然的情况,我发现有些时候我的读线程无法结束,跟踪发现是停在了 WaitCommEvent
上,这说明有时候 invoke SetCommMask,hCom,NULL 并不能使 WaitCommEvent
退出,我最后使用的办法是: 在 SetCommMask 以后再执行 invoke
SetEvent,stReadState.hEvent,把读的 OVERLAPPED 结构中的 Event 置位,让
WaitCommEvent 认为有 Event 发生,它就会马上返回,也许这并不是普遍的情况,但如果你的程序也是停在了
WaitCommEvent 的地方,不妨一试。

6 如何编写读线程中的循环

按照《Serial communications in Microsoft Win32》一文中的例程,读循环可以用:
#define READ_TIMEOUT 500 // milliseconds
DWORD dwRes;
DWORD dwRead;
BOOL fWaitingOnRead = FALSE;
OVERLAPPED osReader = {0};
// Create the overlapped event. Must be closed before exiting
// to avoid a handle leak.

osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osReader.hEvent == NULL)
// Error creating overlapped event; abort.
if (!fWaitingOnRead) {
// Issue read operation.
if (!ReadFile(hComm, lpBuf, READ_BUF_SIZE, &dwRead, &osReader)) {
if (GetLastError() != ERROR_IO_PENDING) // read not delayed?
// Error in communications; report it.
else
fWaitingOnRead = TRUE;
}

else {
// read completed immediately
HandleASuccessfulRead(lpBuf, dwRead);
}

}

if (fWaitingOnRead) {
dwRes = WaitForSingleObject(osReader.hEvent, READ_TIMEOUT);
switch(dwRes)
{

// Read completed.
case WAIT_OBJECT_0:
if (!GetOverlappedResult(hComm, &osReader, &dwRead, FALSE))
// Error in communications; report it.
else
// Read completed successfully.
HandleASuccessfulRead(lpBuf, dwRead);

// Reset flag so that another opertion can be issued.
fWaitingOnRead = FALSE;
break;
case WAIT_TIMEOUT:

// Operation isn't complete yet. fWaitingOnRead flag isn't
// changed since I'll loop back around, and I don't want
// to issue another read until the first one finishes.
//
// This is a good time to do some background work.

break;
default:

// Error in the WaitForSingleObject; abort.
// This indicates a problem with the OVERLAPPED structure's
// event handle.

break;


}

这一段程序在 98 下正常,但非常不幸的是在 Win2000 下,ReadFile 总是返回读正确,并不返回
ERROR_IO_PENDING,使下面的 WaitForSingleObject 的循环形同虚设,要命的是,ReadFile
返回读正确却每次只读一个字节,结果程序工作得很奇怪,即使缓冲区中有很多的字符,程序也每次只能读一个字符,要等到发送字符或做其他的操作使线路状态改变了,才能读下一个字符,我不知道这个奇怪的现象是如何发生的,反正我解决的办法是在
ReadFile 前加 WaitCommEvent,真正等到 EV_RXCHAR 以后才去
ReadFile,到最后,我用的循环是这样的,虽然没有一篇文章中的例子是这样的,但它却同时在 windows9x 和
windows2000 下工作得很好:

.while dwFlag & IF_CONNECT

;********************************************************************
; 检测其它的通信事件
; 如果检测到且定义了 lpProcessEvent 则调用 lpProcessEvent
;********************************************************************

invoke WaitCommEvent,hCom,addr @dwEvent,NULL ;addr stReadState
push eax
invoke ClearCommError,hCom,addr @dwError,addr @stComStat
pop eax
.if eax == 0
invoke GetLastError
.if eax == ERROR_IO_PENDING
or dwFlag,IF_WAITING
.endif
.else

;这里是线路状态的处理
.endif

;********************************************************************
; 如果没有在等待异步读的过程中,则读端口
;********************************************************************

.if ! (dwFlag & IF_WAITING)
mov @dwBytesRead,0
invoke ReadFile,hCom,addr @szBuffer,sizeof @szBuffer,\
addr @dwBytesRead,addr stReadState
.if eax == FALSE
or dwFlag,IF_WAITING
invoke GetLastError
.if eax != ERROR_IO_PENDING
;这里是错误处理
.endif
.else

and dwFlag,not IF_WAITING
mov eax,@dwBytesRead
.if eax != 0
;这里是接收到的数据处理
.endif
.endif
.endif

;********************************************************************
; 如果在异步读端口中,则等待一段
;********************************************************************
.if dwFlag & IF_WAITING
invoke WaitForSingleObject,stReadState.hEvent,200
.if eax == WAIT_OBJECT_0
and dwFlag,not IF_WAITING
invoke GetOverlappedResult,hCom,addr stReadState,\
addr @dwBytesRead,FALSE
.if eax != 0
mov eax,@dwBytesRead
.if eax != 0

;这里是接收到的数据处理
.endif
.else
;这里是错误处理
invoke ClearCommError,hCom,addr @dwError,addr @stComStat
.endif
.else
;这里是错误处理
.endif
.endif
.endw

7 流控制的问题
在流控制方式为"无"和"软件控制"的情况下,基本上没有什么问题,但在"硬件控制"下,win32 手册中说明
RTS_CONTROL_HANDSHAKE 控制方式的含义是:
Enables RTS handshaking. The driver raises the RTS line when the
"type-ahead" (input) buffer is less than one-half full and lowers
the RTS line when the buffer is more than three-quarters full. If
handshaking is enabled, it is an error for the application to adjust
the line by using the EscapeCommFunction function.
也就是说,当缓冲区快满的时候 RTS 会自动 OFF 通知对方暂停发送,当缓冲区重新空出来的时候, RTS 会自动 ON,但我发现当
RTS 变 OFF 以后即使你已经清空了缓冲区, RTS 也不会自动的
ON,造成对方停在那里不发送了,所以,如果要用硬件流控制的话,还要在接收后最好加上检测缓冲区大小的判断,具体是使用
ClearCommError 后返回的 COMSTAT.cbInQue,当缓冲区已经空出来的时候,要使用 invoke
EscapeCommFunction,hCom,SETRTS 重新将 RTS 设置为 ON。


来自http://www.gjwtech.com