weitom1982

向各位技术前辈学习,学习再学习.
posts - 299, comments - 79, trackbacks - 0, articles - 0
  IT博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

有空再读
废话太多,有价值的东西少
官样文章,用来zb,或者骗gf.

作者:陶显芳 康佳集团

一、蹉跎岁月

2006年8月30日,国家标准化管理委员会在其官方网站上刊登了“2006年第8号(总第95号)中国国家标准批准发布公告”,标准号为GB20600-2006的《数字电视地面广播传输系统帧结构、信道编码和调制》就藏身于这批标准之中。公告显示,标准的批准时间为8月18日。作为国家强制性标准,国家给了一年的产业准备期,2007年8月1日将正式实施。

现在,一年的产业准备期已经过去了,我们还没有看到国内哪个电视台的电视节目表中有“高清”的字样,也没看到有哪个电视台给高清数字电视节目频道分配了频率使用表。在商场中也没有看到符合这个高清标准的电视机卖;由此,人们不得不怀疑,这套3合1的中国高清数字电视地面传输标准是否实施艰难。

自从1999年,中国政府有关部门宣布我国的高清数字电视节目试播成功以来,数字电视就开始成为中国人们生活中的一件大事,在各种新闻媒体上,有关数字电视的消息不断流传。从2000年起,每次在深圳高交会上都是一个最大的亮点。

2001年10月,在深圳高新技术交易会上,国内几大电视机生产厂商都展出了自己的高清数字电视产品,这不但给深圳高新技术交易会增添了光彩,也给政府有关部门以及各大电视机厂出尽了风头。

2002年国家广电总局向世人宣布:2003年广电将开播10套以上数字电视影视频道;2004年为中国广播电视的数字化年和产业化年;然而这些美好的愿望一直没有实现。

2003年10月,上海交大的ADTB-T方案和清华DMB-T方案,同时在深圳高新技术交易会上亮相,并突然传出我国优选的两套高清数字电视技术标准方案测试都未能成功。人们才开始知道,以前宣布我国的高清数字电视节目试播成功是“大红灯笼高高挂”中的四姨太怀孕——假的。

从此,关于上海交大的ADTB-T方案和清华的DMB-T方案的好消息不断传出。美国在成立华盛顿新政府的时候,曾召开过一次新宪法修改讨论会,各个州的代表为了表达自己的利益,互相讨价还价,使讨论会连续开了200多天,最终才制订出一部以今天的人看来也是一部非常成功的宪法;而我们为了制定一个“数字电视地面广播传输标准”双方也争斗了7年多的时间,这说明,我们的这个标准比美国的宪法还要伟大。只不过是,美国的新宪法当时是代表46个州的利益;而我们现在的新标准只是代表两方的利益。

实际上在2001年10月至2002年4月期间,国家标准化管理委员会还另外收到过成都电子科技大学和广电总局下属的广科院等4家单位提出的3套方案,他们也要求加入地面传输标准的竞标行列。这样,我国的高清数字电视地面传输标准方案就不只是上海交大和清华两家,而是6家。可能是因为其它4家单位实力还不够雄厚,或者脸皮薄,才不敢与上海交大和清华争斗,要么,5套方案一起包装成一个5合1的中国高清数字电视地面传输标准,哪就更起劲了。

二、是标准催生数字电视,还是数字电视催生标准

什么叫做标准?标准就是产品生产厂家对自己生产的产品质量的承诺和保证,也是国家技术、质量督察和检测部门对产品质量进行检查的法律依据。因此,标准一般都是首先在企业中使用,这称之为企业标准;尔后,等使用企业标准的企业逐步多起来以后,经过同一修改,企业标准才慢慢升为行业标准或国家标准,最后升为国际标准。企业标准一般要求优于行业标准;而行业标准又优于国家标准或国际标准。

当然任何标准都需要技术来支持,采用什么样的技术就有什么样的标准,但对于一个标准却可以采用多种不同的技术来实现。例如:采用16-QAM数字调制,其码率是4bit/秒;而采用8-VSB数字调制,也可以达到同样效果,或者选用3780-COFDM数字调制,也同样实现这个功能。但各种不同技术的应用,虽然功能一样,在性能上多少还是有些差别的。正是因为有这么一点点的差别,就使得ADTB-T和DMB-T两个方案的组织互相争斗的时间达6、7年之久。

制定一个技术标准一直以来都是一件很简单的事,国家标准化管理部门只需在现有各类产品的企业标准基础上,对所有厂家的各种型号产品的主要技术性能和质量指标,进行统一测试、对比、分类,然后制定一个既能体现各种产品的主要技术性能和质量指标,同时也符合用户质量要求的标准,一个新产品的技术标准(国家标准)就这样地诞生了。

因此,一项新的技术发明首先必须有人使用,并且要把它转化成产品后,才有可能成为标准。这种技术转化的过程应该是企业,即生产产品的单位,而不是学校或技术研究所。企业生产产品首先要经过设计定型、生产定型这两个基本过程,然后才能向技术质量检测和标准部门申请产品技术标准,即企业标准。

标准的制定过程应该是企业与国家标准化管理部门份内的事,而这次HDTV地面传输标准的制定却要劳动这么多单位,这么多部门,这可不是一件简单的事情。但我们不得不怀疑,没有企业的参与,制定这样的一个标准能够成功吗?可曾想过不久前出台的EVD、AVS等标准,这些标准还没等到产品生产出来,就将要过期了,它们很可能就是HDTV地面传输标准的前车之鉴。

国家标准出台太早,对技术产品性能的提高一点没有好处。比如我国发展最快的产品VCD、CVCD、SVCD以及逐行扫描电视;一开始的时候,这些产品都没有国家标准,所以它才能这么快的发展起来;但另一方面,如果没有国家标准,各个企业的产品质量也会鱼龙混杂,一些企业就会粗制滥造。因此,国家标准就是用来规范这些企业的行为,对他们产品质量进行监督和处罚,防止一些企业粗制滥造浪费社会资源。

数字电视也一样,不是有了一个国家标准就能发展起来的,相反,如果要想让数字电视产业能发展起来,国家就不应该马上制定国家标准,而是要等数字电视产品的技术性能和质量基本稳定以后再制定国家标准。在国家标准还没出台之前,一种产品有几个企业标准都是正常的,到最后,国家应该把几个企业标准统一到一个标准之中。

三、什么是单载波调制和多载波调制

大家都知道,上海交大的ADTB-T方案和清华的DMB-T方案,双方争论的焦点就是,单载波调制性能优越还是多载波调制性能优越。因此,在这里还是有必要简单介绍一下,什么是单载波调制和多载波调制。

所谓单载波调制,就是将需要传输的数据流调制到单个载波上进行传送,如:4-QAM(QPSK)、8-QAM、16-QAM、32-QAM、64-QAM、128-QAM、256-QAM或8-VSB、16-VSB等都是单载波调制。

上海交大的ADTB-T方案选用的是单载波调制,在1999年50周年大庆试播的时候,上海交大的ADTB-T方案采用的是8-VSB数字调制,到后来才改为16-QAM数字调制。

QAM调制也叫正交幅度调制,简称正交调幅;因为正交调幅有很多种调制模式,如上面列出的就有7种,一般记为n-QAM,n表示各种调制映射到星座图上的模数。模数越低,调制和解调电路就越简单,但传输的码率也相应降低,例如:4-QAM的码率为2bit/S,而16-QAM的码率为4bit/S。一般,信号传输条件越差,选择的模式就越低,例如:卫星通信只能选择QPSK,而有线电视可选64-QAM和128-QAM,甚至256-QAM;对于地面电视广播,信号发送一般选8-QAM、16-QAM、32-QAM,最高只能选到64-QAM。

正交调幅就是把一序列需要传送的数字信号(2进制码)分成两组,并分别对两组数字信号进行幅度编码,使之变成幅度不同的调制信号,即I信号和Q信号,然后用I信号和Q信号分别对两个频率相同,但相位正好相差 的两个载波进行调幅,最后再把两路调制过的信号合成在一起进行传送。由于在调制之前已经对输入信号进行过幅度编码,因此,这种调制也称为正交数字幅度调制。

我国的HDTV如选用MPGE-2编码,最高传送码率大约为20M bit/S,如果选用16-QAM调制模式,其频谱利用率是每赫芝传送4位数据,即码率为4bit/S。由此可知其载波最高频率约为6MHz,经高频调制后采用残留边带发送,其载频带宽大约为7点多MHz。

所谓多载波调制,就是将信道分成若干正交子信道,将高速数据信号转换成并行的低速子数据流,然后调制到在每个子信道上进行传输。如:n-COFDM,其中n为子载波数目。清华的DMB-T方案选用的是多载波调制,在DMB-T方案中采用3780-COFDM调制方式。多载波调制也叫编码正交频分复用调制。

就多载波调制中的各个载波而言,其调制的工作原理与n-QAM单载波调制的工作原理基本相同,只是把需要传送的数据分成很多组(这里为3780组),然后每组再分成两组,通过幅度编码以后便可生成两组I信号和Q信号,而后用3780组I信号和Q信号分别对3780个频率各不相同的载波进行正交调制,最后把所有的调制信号合在一起进行传送。

四、ADTB-T和DMB-T谁能当驸马

上面我们简单介绍了单载波调制和多载波调制的工作原理,下面我们进一步来分析单载波调制和多载波调制的优、缺点,最后由大家来猜一猜,ADTB-T和DMB-T,谁能当驸马?

根据上面分析,采用16-QAM单载波调制,其最高码率为24Mbit/S,载波频率为6MHz;如果选用多载波调制,在码率同样为24Mbit/S的情况下,采用3780-OFDM多载波调制,对于3780个载波平均下来,每个载波平均传送的码率大约只有6.3Kbit/S,这样,哪怕每个载波都选用QPSK调制,其载波的最高频率还是可以选得很低;如果选用16-QAM或64-QAM调制,其载波的最高频率还可以进一步降低。但这是在没有考虑解码以及图像信号处理需要时间的理想情况,实际并不是这样。

一方面,在数字电视机中,选用的载波频率也不能太低,因为,数字信号传送的速度一定要大于图像信号处理的速度,这样,最后输出信号才不会产生间断。例如,我国HDTV的行扫描频率大约为32KHz,如果不考虑MPEG解码电路以及图像信号处理电路对输入信号处理所需要的时间,那么,多载波的最低频率就不能低于32KHz,否则,行扫描电路就会出现没有信号可扫描的情况,图像显示就会出现间断。因此,MPEG解码电路以及图像信号处理电路对数字信号传送速度也有同样的要求。

另一方面,多载波解调制对数字信号进行分批处理时候,每次都需要等3780个载波传送的数据全部到齐以后,才能一次性地对数据进行处理,即需要对信号进行并转串处理;因此,其解调制过程消耗的时间相对来说比较长,其最低频率也就不能取得很低。另外,多载波调制一般都不采用残留边带发送,因此,调制后的频带宽度相对于残留边带发送来说大约要宽一倍。

综合以上因素,就平均而言,多载波的平均频率相对来说可以低一些,但载波的最高频率与单载波的频率相对来说,并不会相差很大。

载波频率低的最大好处就是,可以降低信号传送过程中的多经反射干扰(即图像重影效应)。下面我们分三种情况来分析:

比如单载波频率为6MHz,其周期为0.17uS,两个正交载波相差1/4个周期(90°),为0.0425uS;由于电磁波的速度约等于光速,即每微妙为300米,那么,频率为6MHz的载波对应于一个周期所传播的距离就是51米,即波长为51米;半个周期为25.5米(半波长),1/4个周期为12.75米(1/4波长)。

如果反射体的路经距离正好与电视接收点相差12.75米(或1/4波长的奇数倍),即电视接收机相当于同时收到两个信号,一个是主信号,另一个是反射信号,两个调制载波信号的相位正好相差90°(1/4波长);这样,两个调制载波信号互相叠加以后,不但会改变原来信号的相位,同时也会改变信号的幅度,结果相当于I和Q两路信号互相串扰,并且,当两个信号叠加之后的相位差越接近时,即反射信号越强,干扰就越严重;在这种情况下,数字电视接收机的调制解调电路可能无法正常解码。

如果反射体的路经距离正好与电视接收点相差半个波长(25.5米,或半个波长的奇数倍),则两个调制载波信号的相位正好相差180°(半波长),由于正交调制的两路信号(I和Q)都是对载波的半波进行幅度调制的,因此,两路调制过的信号合成之后就相当于是对载波的1/4波进行调制;当原信号正、负半周是对称时,则两个信号互相叠加的结果会使接收信号减弱,相当于电视接收机接收灵敏度降低;当原信号正、负半周不是对称时,则两个信号互相叠加的结果会使接收信号失真,相当于两路信号(I和Q)互相串扰,与两个调制载波信号的相位相差90°时没有多大区别。

如果反射体的路经距离正好与电视接收点相差1个波长(51米,或1个波长的整数倍),两个信号的相位正好相差360°(1个波长);当原信号正、负半周为对称时,则两个信号互相叠加的结果会使接收信号加强,相当于电视接收机接收灵敏度提高;当原信号正、负半周不是对称时,则两个信号互相叠加的结果会使接收信号失真,相当于两路信号(I和Q)互相串扰,与两个调制载波信号的相位相差90°时没有多大区别。

由此可见,只要接收到两个信号(主信号和反射信号)的相位角相差正好是90°(1/4波长)的整数倍,对单载波正交调制信号造成的干扰最严重;对于其它相位差同样也会产生干扰,只是干扰程度相对来说没有90°时那么严重。

假设多载波的最高频率只有3MHz,即为单载波频率的二分之一,相对来说多载波的波长比较长;根据两点之间的电磁场强度与距离的平方成反比的定理,可以求得,在1/4波长处是干扰最严重的地方,两者的电磁场强度相差4倍。而对所有载波平均而言,甚至可以相差几百倍,即多载波调制的多经干扰相对来说比单载波轻。

但多载波调制和解调的过程都非常麻烦,多个载波经过调制后合在一起传输,解调时对其再进行分离就非常困难;因为,在高码率传送之下,它无法用滤波电路把各个调制载波信号选出来,只能采用同步分离的方法,因此,它对同步信号的相位要求非常严格,所以多个载波对相位噪音的要求比单载波高很多。

如果多载波调制信号解调时各个载波信号分离不干净,就相当于多个载波之间会互相产生干扰,信噪比(S/N)就会降低。一般多载波解调电路要求信噪比(S/N)的门限值要比单载波解调电路高好几个db(根据报道为3-4dB)。

目前已经有很多方法可以降低单载波多经反射干扰,例如,采用数字延时均衡技术,即从信号中取出一部分信号经延时一个相位后再与原信号叠加,现在这种技术可以通过软件控制来实现,将来所有的数字信号接收机都可以采用这种技术。

很多人都认为,只有多载波调制才能用于移动电视接收机,而单载波调制无法实现移动接收的功能。我认为,这种想法毫无道理。

比如,一辆汽车的速度是每小时100公里(28米/秒),那么,它跑1/4周期(6MHz)的时间(0.0425uS)所对应的距离就是1.19×10-6米,这相当于2.3×10-8个波长;或它跑1/4波长的距离(12.75米)所对应的时间为0.46秒,相当于2710000个周期。这两个结果无论是在时间上或在距离上都没有可比性。因此,汽车速度对单载波的相位影响几乎等于零。而受影响最大的反而应该是,在0.46秒时间内,数字延时均衡电路是否能正常工作。

而对于高频载波在移动接收过程中产生的多普勒效应,它只影响接收频率的偏移,这种影响对单载波调制和多载波调制都是一样的。

特别值得注意的是,由于ADTB-T是单载波技术,因此,它对广电原有的发射系统能够很方便的接洽。根据资料分析,在前端数字化改造方面,交大方案的成本要比清华方案的成本节省约80~90%,仅需要一个MPEG和ADTB-T调制器即可利用原有模拟发射机发射数字信号,而清华方案必需要整套更换成全新的数字发射机,这笔代价在边远地区还是需要斟酌的很大的一笔开销。

同时,在衡量一个数字信号接收的时候,还需考虑信号的接收稳定率;由于是数字信号的属性是0和1,就是要么收到,要么收不到,这就凸现门限的意义;根据测试结果,DMB-T的接收门限比DVB-T低,可ADTB-T的接收门限比DMB-T还要低,这就是为什么采用ADTB-T的发射系统其覆盖范围比DMB-T的发射系统的覆盖范围更广阔的原因,因为其门限低,采用ADTB-T接收机的灵敏度要比DMB-T接收机的灵敏度高3-4dB,因此,其能够在更远的距离上接收弱信号。

另外,上交大单载波系统在组建单频网(SFN)时,对发射机时钟频率的精度和稳定度的要求仅为E-9。这同任何多载波系统相比,要低三个数量级,因此,其工程造价较低。

在发射功率方面相比,上交大单载波系统的发射机平均功率是多载波系统的二分之一,其标定功率则是后者的五分之一。即:在同样的覆盖范围之内,为了实现高数据率的固定接收,上交大方案需要1kW的平均发射功率,则其发射机的标定功率需要4kW,因为其峰均比(PAR)接近6dB。

而对于多载波系统(以欧洲标准为代表)而言,如果要覆盖相同的地区,则其平均发射功率需要2.0-2.5kW。这是因为:多载波系统与单载波系统相比,载噪比(C/N)门限值要增加3-4 dB。其次,其发射机的标定功率需要20-25kW,因为其峰均比(PAR)接近10dB。

选用单载波系统将来还可以把地面接收和有线接收同用一个高频头和解码器,因为,目前有线电视采用的调制方式基本上都是采用64-QAM,而地面传输一般都采用16-QAM,将来也可以选用64-QAM。

上面这些分析,对老百姓来说,不一定会感兴趣;但老百姓感兴趣的是,怎么样能买到既便宜又好用的电视机。相比之下,交大方案数字电视接收机的生产成本大约要比清华方案的生产成本低20~30%。这很清楚,如果由老百姓自己来选择的话,他们一定会知道自己应该选择什么样的数字电视接收机。但什么时候老百姓有过自己的选择权,皇帝家的驸马是由老百姓来选择的吗?

五、ADTB-T和DMB-T是双胞胎,还是畸

谁都清楚,是双胞胎就应该分开来抚养,是畸形儿就应该赶快动手术。上海交大的ADTB-T方案和清华的DMB-T方案,是两套功能完全相同的系统方案,它们在功能上没有互补性,在性能上也没有多大区别,它们在使用中完全可以互相取代,即他们是一对双胞胎。

既然是双胞胎,为什么在标准号为GB20600-2006的《数字电视地面广播传输系统帧结构、信道编码和调制》标准中还要把他们捆绑在一起,这不是把双胞胎又改变成畸形儿了吗?这个道理,在一般人看来是很难想象的,在医学上更无法进行解释。

实践已经证明,把上海交大的ADTB-T方案和清华的DMB-T方案,两个捆绑在一起,既增加成本(估计增加30%),还会降低机器的技术性能。国内所有电视机生产企业都强烈反对,殊不知中国的老百姓是否反而会喜欢这种奇特电视机?如果不是这样的话,那么只能认为,把两个方案捆绑在一起,唯一的好处就是能够增加“鸡的P”。

六、一个美丽的谎言

那些制定标准方案的人一次又一次告诉人们,如果采用了他们的标准,将来中国每年就可以少给外国人交几百亿的专利费。是这样的吗?

由于中国人自古以来就很少听说过“专利”这个词,现在如要他们交专利费,他们一定会觉得冤枉。因此在这里还需得向国民多解释一下,什么是专利,好让他们交专利费的时候,不会觉得冤枉。

1980年之前,在中国人的日常用语中是没有“专利”这个词的,如果某人说错了,“这是我的专利”;还很可能会给自己打上资本主义的标签而遭受批判。直到1985年,中国的专利法才开始诞生,但自从中国专利法诞生的二十多年来,基本上就没有人认真执行过,连中国人自己都很少知道,什么是专利法,外国人更不知道什么是中国专利。因此,到中国来申请发明专利的外国人更是少之又少。

另外,在中国还没有改革开放以前,西方8国是禁止向中国输出技术的,他们对中国一直都实行技术封锁,并且每年都要审查对中国出口商品的清单,是否有外国企业违反他们制定的法律,私自出口技术到中国;因此,那时候外国企业不可能会到中国来申请专利,他们的政府也不允许他们到中国来申请专利。

直到2003年,中国准备要加入WTO的时候,国外企业才开始到中国来申请专利,并且申请专利的这些企业,大部分都是工厂设在中国境内的外资企业。

我们知道,专利法有一个区域性和时间性,如果别人没有到我们国家来申请专利,那怕我们的产品使用了他人的专利技术,这也不算侵权;如果他们申请的专利超过了有效期,这也不算侵权。

另外,专利还有新颖性,如果他们的技术已经是公开了的,他们也不能到中国来申请专利,因此,他们如果不是第一时间在中国申请专利,而是把他们原来在异地申请过的专利,再次拿到中国来申请,这个也无效,因为他的技术已经被公开了;还有,如果他们申请的专利内容已经在中国的书刊上,或者其它地方的书刊上出现过,这个专利也无效。

很多中国人一听到别人有专利,好像就被镇住了。这里我诚恳地告诉你们,在中国的地盘里,不用怕外国人的专利。

1、2003年以前,外国人很少到中国来申请专利,特别是高新技术专利他们都不会到中国来申请。如果他们到中国来申请了专利,这些专利大部分都是无效的。一方面,他们不会把自己最新的技术不首先在本国申请,而第一时间跑到中国来申请;如果他在本国已经申请了专利,而过了半年再到中国申请专利(即专利已经公开),或者在半年时间之内他在中国申请专利时,没有提出优先权,他在中国申请的专利就无效。

对于数字电视的技术专利,大部分也是无效的,或者技术含量非常低。因为,1996年的时候,美国的数字电视节目就已经开始广播,与数字电视技术相关的专利大部分都是92、93年的,或92年以前的;在这个时间,中国基本上还处于技术被封锁时期,国外的企业不可能第一时间到中国来申请专利。到了2003年,国外开始对中国的技术封锁松绑的时候,此时的数字电视技术已基本成熟,即以后很少再出现关键技术,就算是有关键技术,他们也不会在第一时间拿到中国来申请专利。

2、中国人虽然对专利概念知之甚少,但吹牛的本事在全世界是知名的,这对外国人申请专利很不利。只要中国人吹过牛的事情,外国人就不能再申请专利。因为他申请的专利已经没有新颖性。你看,在中国真正的数字电视节目还没有正式广播之前,在商场里早已摆满了各种品牌的“数字电视”,你想他们还能申请专利吗?还有,如“永动机”,“水变油”等高新技术,也都是中国人发明的,并且还有中科院的某些院士表态支持,这些高新技术就算中国人没有申请过专利,将来,外国人也不能再申请专利。

3、中国是世界上生产科技论文最多的国家,因为,很多事业单位以及国营企业,还有大学、科研部门,每年都要评职称或提干,这些论文都是他们往上爬的垫脚石。很多论文虽然都是互相抄袭得来的,有些甚至还是胡编乱造;但,你别看不起它们,它们是对付外国人在中国申请专利的最好武器。因为,抄袭的东西,一般都是好东西,这些抄袭的内容大部分都是别人在国内、外发明的;只要有中国人抄袭过的东西,外国人在中国申请的专利就可以告它无效。哪怕是胡编乱造,但文字堆多了,也可能会出现奇迹,况且还有很多发明的灵感是来自科幻小说;因此,只要在文字堆中能找到的东西,外国人也不能再申请专利。

4、近年来,中国每年都有几万名专业技术人员报考专利工程师或专利律师,未来这些人将会成为与外国人打专利战的得力枪手。你看着吧,目前在中国申请的专利,包括外国人在中国申请的专利,很可能80%以上都要变成垃圾专利。因为,打专利战的输赢,主要是靠枪手的数量和提供子弹的多少。中国每年新增的几千名专利工程师和专利律师,还有每年生产的上千万份论文,这些就是将来打专利战最好的枪手和子弹。由此看来,中国政府每年给大学和科研机构提供上百亿元的科研经费,产生出来的论文,到最后还是大有用处的。

在美国联邦大法院打一次专利官司,时间需要整整3年;而大约97%的专利官司最终都是没有结果的,基本上都是通过庭外和解。同样在国际贸易委员会里面打专利官司,也是大约94%的专利官司最终是没有结果的,大部分都是通过庭外和解。实际上打专利官司就是给法院送钱,因此,一般外国人不会轻易到中国来打专利官司。

那么,如果不使用他们的标准,将来中国每年要给外国人交几百亿专利费,这么大的事情,为什么以前从来没有听说过一个类似的案例?没有案例就不能随便估价。因为,在美国打官司基本上也都是要讲案例的,这样才比较公平。因此,在中国最好也先搞几个案例出来,作为大家参考的样本;让将来准备打专利官司的双方都要掂量一下,值不值得打官司。

实际上,直到目前为止,中国的电视机企业在国内几乎没有向外国人交过一分钱专利费,我估计,广电部使用DVB-C有线数字电视广播系统这么久,可能也没有向别人交过专利费吧;因为,外国人在2003年以前基本上没有到过中国来申请专利,那为什么我们要向他们交专利费。至于外国人是否向中国政府部门或科研部门收过费,我们不得而知;但我们从没听说过哪企业还能从政府的手中收钱的。

另外,中国的企业每年都要向国外企业交好几百亿元的专利费,这也是真的,但只限于出口产品。因为,美国和一些欧洲国家都已经成为了技术强国,他们的经济收入早已不再是传统的有形产品,而是技术。例如,美国的微软公司主要收入,90%以上就是靠技术开发,靠卖软件来赚钱;美国的高通公司,80%以上的收入也是来自专利转让;还有很多从事集成电路技术开发的公司,大部分收入也是靠专利转让;世界上最著名的IBM公司每年的专利转让收入也超过25%。

还有,现在的数字电视技术大部分是美国人和欧洲人发明的,而他们基本上都不生产电视机了,那么中国人利用他们的技术,生产出来的电视机,再卖给他们,他们向我们收专利费,对我们有什么关系?最后还不是转嫁到他们用户的身上。实际上中国的大部分电视机生产企业出口电视机产品的时候,基本上都只是向代理商收取了那么一点点加工费,对于出口利润是多少?交了多少专利费?等等,一无所知。因为,这些都是代理商包办的,中国的企业根本就不敢自己拿产品在国外摆摊卖,因为老板生怕收不回钱。

美国可以利用他们的数字电视标准向中国的电视机生产企业收钱,是因为中国的电视机生产企业向美国出口电视机;而美国从来不出口电视机到中国,那我们可以通过什么手段来向美国人收钱?是通过中国的数字电视标准吗?我看不行吧?除非倒过来,我们只做技术,让美国人用我们的技术生产电视机,然后再卖给我们,那我们就可以理直气壮的向美国人收专利费了。但是,这个愿望什么时候才能实现?

那么,如果采用了他们的标准,将来每年就可以少给外国人交几百亿的专利费的理由又是什么呢?现在大家都应该明白了吧,这是他们利用错误的命题,来证明他们将来收钱的合理性。这是一种此地无银三百两的说法。

由此可以推断,估计到不了2015年,当中国开始大打专利战的时候,可能首先开战的就是中国人自己打自己人,而不是中国人打外国人。

很多人都以为,自己有了专利技术中国的数字电视就一定能发展起来,这种想法未免有点太天真。在中国现有的体制之下,专利只是给领导面子贴贴金而已,大部分专利基本上都没有使用价值的;而私人申请的专利,国家基本不支持,他们自己又没有能力实施,也难以转化成商品。因此,我们不能指望由一两个大学制定了一个标准方案,中国的数字电视就能发展起来。我们可以回过头看看我们的IC技术吧,没有自己价廉物美的IC产品,中国的数字电视真的能发展起来吗?

我们知道,电子技术的发展主要是靠IC技术的发展带动起来的,而在中国,尽管IC技术一直得到政府的大力支持和保护,但就是一直发展不起来。直到2003年国家开始全面对外开放IC市场的时候,中国才以20倍的速度向前发展,而这些在中国新投资的IC企业,几乎都是台商和外资企业,中国原来的IC企业几乎已经没有一席之地。

中国的IC明星,龙芯和汉芯,每年国家在它们身上花去的钱少说也有好几亿元,但他们的技术除了用来填充报纸版面之外,至今还没有一个能转化成商品。

实际上,自从改革开放以来,对中国电子工业贡献最大的根本就不是那些得到国家保护和支持的国有IC企业,对中国电子工业贡献最大的应该是深圳赛格电子配套市场。目前,在深圳赛格电子配套市场那里,什么IC产品基本上都可以买得到,并且价格比国外还要低廉。就是二十多年前,一些国有IC生产企业还需从深圳赛格电子配套市场那里购买IC产品,给内地电子产品生产企业配套。现在,深圳赛格电子配套市场每年的销售额已经超过1200亿元人民币,光从税务开出的发票就超过320多亿元,估计有80%以上的顾客都是只选择只开收款单据,而不开税务发票的。由此可以推算出,每年深圳赛格电子配套市场可带动中国电子工业的产值高达8000多亿元,相对于2006年全国电子工业总产值4.7万亿元的17 % 。

目前,全世界上数字电视的技术还在不断发展,相比之下,中国的数字电视标准与国外的数字电视标准相比,在技术上基本没有优势,当我们自己的数字电视产品生产出来的时候,可能别人更新的产品标准又要出来了,我们的EVD标准不就是这样吗?

因此,别人不可能会采用中国的数字电视标准,中国的数字电视标准将来也不可能升为国际标准;而中国的电视制式与国际不兼容,不但不利于中国电视机生产企业的技术配套(即IC器件和软件的配套),也不利于中国电视机生产企业的产品出口,同时,也失去了一次中国家电企业与国外家电企业互相交流技术的机会。

七、数字电视离我们还有多远

数字电视要取代模拟电视,这是必然趋势。因为,传统的模拟电视清晰度很低,基本上只能满足21寸图像显示器清晰度的要求,如果把图像显示放大到29寸以上,则图像清晰度就显得有点力不从心。不过现在也有人,在模拟电视的基础上,通过数字处理技术,采用加行插点的方法来提高大屏幕图像显示的清晰度,例如逐行扫描电视机就是这样得来的。这种方法可以延续模拟电视继续使用一段时间,但从长远来说还是无法满足人们对大屏幕和高清晰度电视的追求。

标准的数字电视机应该是在图像清晰度方面以及其它技术性能指标方面,都应该要比目前的模拟电视高出一筹。例如,在我国新的高清数字电视标准中,要求CRT高清数字电视机的水平清晰高于620线,要求平板高清数字电视机的水平清晰高于720线。

这个高清标准对现有的CRT电视机来说难度很大,因为目前国内生产的CRT显像管的规格基本上都是4:3的标准清晰度显像管;若要其达到高清标准的要求,必须要把尺寸加大到32寸以上,以及显示比例为16:9的高清晰度CRT显像管;实行这个目标,最关键还是需要一大笔资金投入,特别是目前在CRT电视机价格已经非常低廉的情况下,很难有人愿意再投资。因此,很难再指望CRT显像管能够满足我国高清数字电视1920X1080i图像显示格式的要求。

对于PDP平板高清数字电视则需要50多寸以上的大屏幕电视机才能达到1920X1080i显示格式的要求;对于LCD平板高清数字电视也需要40寸以上的大屏幕电视机才能达到1920X1280i显示格式的要求。然而这些高清平板显示屏的关键技术,基本上还是掌握在外国人手中,要想在几年内全部用高清平板显示屏来替代国内产生技术已经非常成熟的CRT显像管,难度会非常大。如果放弃CRT显像管,不但对中国经济是一个非常大的损失,因为,以前几千亿元的投资可能在几年内就化为乌有,而且也不符合中国的国情。

自从1996年,美国正式播放高清数字电视节目以来,“高清数字电视”这个词就一直牵动着中国人民的心。很多人都认为,今天中国的高清数字电视节目之所以没有广播,主是因为中国的数字电视标准迟迟没有出台。实际上这种认为是片面的。高清数字电视节目什么时候广播,主要取决于有没有高清数字电视节目源和与之对应的高清数字电视接收机;当高清数字电视节目源还很少,并且老百姓还买不起高清数字电视接收机的时候,高清数字电视节目开始过早广播,反而会浪费社会资源。

根据国外数字电视发展的经验,他们都是在高清数字电视节目广播之后,再引导普通电视用户慢慢地过渡到高清数字电视用户方面来,那些还没安装高清数字电视机的用户则可以通过安装数字电视机顶盒来收看高清数字电视节目。

但我们国家在高清电视节目还没有广播的情况下,广电部就开始引导中国的电视用户用数字电视机顶盒来收看模拟-数字电视节目。这是中国的特色,是中国赶超美国的唯一捷径,也是广电部每年要实现6390亿元收入目标,采取的最有效措施。

根据国家广电总局每年的《广电蓝皮书》报告,2003年广播电视总收入为470亿元,2006年首次突破千亿元大关,达到1099.12亿元。早在2003年,广电部就提出了要赶超中国电信的目标。2006年中国电信的营业收入为6390亿元,所以,还差5000多亿元。

为了达到这个目标,广电部从2003年就开始,由点到面进行我国有线电视模拟转数字的推广,到目前为止,全国已经有青岛、杭州、深圳、佛山、绵阳、南阳等10多个城市完成了全市整体平移,包括广西、海南、陕西、重庆等省市的有线电视模拟转数字工作都正在进入蓬勃平移的阶段。根据《2007年广电蓝皮书》透露,全国有线数字电视用户数已经突破1200万户大关,达1266.25万户,比2005年增长218.88%。全国已有25个大中城市实现有线电视数字化整体转换。

然而,也有人怀疑,用数字电视机顶盒来收看数字-模拟电视节目,不可能代表数字电视技术发展的方向,有线电视台给电视用户免费安装数字电视机顶盒,不但不能接收高清数字电视信号,连接收标清数字电视信号的效果都比原来普通电视接收模拟电视节目的效果差,这完全是给国家数字电视的发展引偏了方向,使中国的数字电视更难发展。

所谓的免费安装数字电视机顶盒,只不过是骗小孩上床,最后的成本费用还是要摊到电视用户身上。既然有线数字电视机顶盒是个好东西,为什么还要整体平移。下面我们不妨以广西有线数字电视整体平移为例,分析一下整体平移的好处。

根据报道,2006年广电部在中国西部最贫穷的省份广西投资22.9亿元,率先完成全省数字电视整体转换,其中由国家开发银行提供的10亿元中长期贷款,中国银行、交通银行、建设银行、农业银行则提供5亿元的短期流动贷贷款,负债200%。

由于是免费给电视用户安装数字电视机顶盒,广电部不可能免费提供高清数字电视机顶盒,最多只提供一个标清数字电视机顶盒。一个标清数字电视机顶盒的价格大约为500~600元,如果把前端设备的投资以及安装费用也算到电视机顶盒的身上,每个机顶盒的成本大约为800多元。这样,22.9亿元的投资可以安装286万个标清数字电视机顶盒。一般电子产品的折旧寿命为3~5年,这里对电视机顶盒的折旧率就按4年来计算,则每台每年的折旧费为200元。另外还需把银行的利息加上,假设银行的年利率为6%,每年的平均利息为52.5元。由此,可求得每台数字电视机顶盒每年的使用成本约为252.5元。

目前,广西有线数字电视用户每月收费为22元,原来每月收费为12元,相对于平移后每月增加收费10元,全年增加收费120元;相对于每台数字电视机顶盒每年亏损132.5元,这还没有包括税收部分,如果把税收也考虑进去,则每年亏损大约为140元。当然,在边收费的同时也可以边还利息,最后估计每台数字电视机顶盒每年要亏损130元。

这还是比较理想的情况,如果有些有线数字电视用户经济比较困难,或者对数字电视收看效果不满意,他看了几个月或一年之后,就不愿意再往他自己的银行户头里面存钱了,有线数字电视台对他也没办法,最多只能对他停机。这种情况估计有10~20%。由此可知,广电部在广西投资的22.9亿元,再过100年也收不回本钱。

如果全国的1亿多有线电视用户都按这种方法进行有线数字电视整体平移,估计需要投资800多亿元,并且每年最少要亏损130亿元。这笔费用一般广电部是不会从自己的口袋里掏的,他也亏不起,最后亏损的是银行,但银行亏损的钱,实际上就是全国股民的钱,因为,银行亏损后他们可以不断地印钞票往里填充,并且这也是得到政府默认的,没有政府的支持,广电部门不可能获得银行贷款。

另外,由于目前高清数字电视节目源还很少,有线电视台只能把模拟电视信号转换成数字信号来传送,相当于最初的电视图像信号是用大卡车整体包装运送的,而现在是先把货物打碎,然后改用客车或出租车来运送,最后再打包变回原样,这样的图像质量不可能比原来更好。并且,有些有线电视台以及节目运营商为了降低运营成本,很多免费送的数字电视信号接收机顶盒,都是伪劣产品。根据国际标准,数字电视信号对模拟电视信号的采样比为4:2:2,即亮度信号每取样4个点,两个色差信号应该各取2个点。但很多机顶盒生产商为了节省成本,省内存,只按4:1:1的比率对模拟电视信号进行采样。因此,用这样的数字电视机顶盒来收看数字电视信号,图像质量会变得更差。

虽然有线数字电视整体平移后可以多收几个台,但这并不是因为把模拟电视信号转换成数字电视信号后的功劳,因为原来模拟电视信号传输系统本身就可以传送最少70多个模拟电视节目信号,频率资源从来就没有用到极限。老百姓对整体平移意见也很大,他们认为这种整体平移的做法,与把你家的玻璃窗先打碎,然后再给你换个新的,最后还要向你多收钱没有什么两样。

由此看来,广电部门对有线数字电视进行整体平移,不管他的投资有没有回报,实际上对中国的高清数字电视产业发展一点都没有好处,因为数字电视机顶盒不可能代表高清数字电视发展的方向,这只能是一种技术倒退,和社会资源的浪费。

多年来,由于数字电视概念的过度炒作,很多电视机生产商满以为中国的高清数字电视时代很快就要到来了,因此,早早地就把CRT电视机的生产平台切换到LCD或PDP数字平板电视机的平台,由此引发了数字平板电视机与CRT电视机的激烈竞争,由于数字平板电视机增长速度过快,供过于求,使数字平板电视机的价格急速下滑,最后结果是,几乎所有的平板电视机生产企业均出现亏损。

根据国内主要彩电生产企业2006年年报显示,厦华2006年亏损6.5亿元,四川长虹净利润只有4000多万元,海信电器的净利润也只有1.52亿元,康佳净利润1.2亿元,而这3家企业的CRT业务的净利润都超过3亿元。为什么会出现这种矛盾的现象,原因就是:被宣称即将死亡的CRT电视,却养活了所谓的自己掘墓者平板电视。

当某类产品的市场基本饱和以后,产品的平均价格基本上就体现出顾客对商品的购买能力和购买商品的欲望。2005年彩色电视机的平均价格为1580元,2006年由于部分消费者对平板电视购买欲望的冲动,使彩电的平均价格有所上升,估计彩电的平均价格上升到了1800元左右,但并不是证明消费者的购买能力上升了;因此,后面几年,平板电视机价格下滑的现象还会继续。

我在2006年写的“中国平板电视的市场到底有多大”文章中指出:如果5年后,平板电视机真的能取代CRT电视机,则其平均价格应该下降到3300元以下,相当于每年要跌价15%。除非所有生产LCD平板电视机的厂商都是为了满足做数字游戏的乐趣,要么没有一个电视机厂商能在LCD平板电视机中赚到钱。

最近报道,深圳赛格-日立显像管厂因出现严重亏损,已经停产关闭。这好像是宣布,平板电视机又取得了一次伟大的胜利,CRT的末日就要来临了。但实际上并不是这样,深圳赛格-日立显像管厂的关闭,只是这个CRT显像管厂的战略转移,它的设备由深圳搬迁到内地,使生产成本进一步降低;因此,后面它对平板电视机的威胁力更大。

实际上中国电视机市场的划分已经越来越明显。14寸以下全部是黑白CRT电视机的市场;14寸至29寸全部是CRT电视机的市场;29寸以上全部是平板电视机的市场。三个市场井水不犯河水。2006年,中国电视机的产量分别为:黑白CRT电视机1000多万台,彩色CRT电视机接近7900万台,平板电视机510万台。2007年,估计平板电视机可能会超1000万台,但大部分都是出口;而7900万台的彩色CRT电视机产量基本保持不变。

目前中国大约有3亿多电视用户,电视机拥有量大约有3.5亿多台,其中有线电视用户为1亿多户。如果在5年内,有三分之一的普通电视用户要转为高清数字电视用户,那么需要更新1亿台电视机;假设每台40寸以上的大屏幕高清数字电视机单价为1万元,则总投资为1万亿元;电视台平均每个星期播放一次以上高清电视剧节目,平均每个高清电视剧投资1亿元,5年一共投资260亿元。把两项投资合在一起总投资为10260亿元,平均每年为2052亿元。这些费用将要全部摊到1亿个数字电视用户的身上,平均每户每年2052元;这个还没有包括电视运营商的管理费和利润。

如果把广电部每年5000多亿元收入的三分之一也摊到1亿个数字电视用户身上,那么,每个数字电视用户需要摊1700元。这样实现数字电视广播后,每个数字电视用户每年的支出大约为3750元。这笔费用,对于美国人来说是难以承受之轻,而对中国老百姓来说就是难以承受之重。

中国的高清数字电视什么时候才能真正发展起来,主要取决于两个方面:一个是电视台有没有高清数字电视节目源;另一个是中国的老百姓能不能买得起高清数字电视机,以及能不能交得起广电部每年5000多亿元的费用。

现在中国还是一个发展中国家。2005年10月,中国还在接受联合国最后一批物资援助;这说明,中国才刚刚摘掉贫困国家的帽子,中国的人均产值在全世界排名还在很后头,还没达到2000美元,离跨入发达国家的行列还很远。很多人不了解这种情况,以为我们国家的神舟5号都能上天了,难道我们连数字电视都搞不出来吗?

如果拿神舟5号作为历史标签跟发达国家相比,那么,我们在技术上比其它先进国家落后还要更远。我们曾记得,1961年4月12日莫斯科时间上午9时零7分,加加林乘坐“东方”1号宇宙飞船从拜克努尔发射场起航,在最大高度为301公里的轨道上绕地球一周,历时1小时48分钟,完成了世界上首次载人宇宙飞行,实现了人类进入太空的愿望。我们国家的神舟5号不是相隔了整整42年才实现这个愿望的吗?

posted @ 2007-09-27 15:53 高山流水 阅读(335) | 评论 (0)编辑 收藏

WinCVS操作手册
 
撰稿:paladin.lin     2003年11月5日
 
 
第一章: 概述
CVS是目前比较流行与优秀的版本管理与控制工具,是用来管理其它日常文档(如word工作文档之类)的一个强有力的工具。
WinCVS是CVS的一个客户端软件,它运行在Windows上,采用图形化方式登陆CVS服务器和CVS相关的操作与管理,不要学习复杂的cvs命令。企业内部都采用Linux/Unix做服务器,用Windows做客户端,所以WinCVS与CVS服务器是目前应用最广泛的版本控制与管理的组合。
本文主要介绍WinCVS的日常操作, CVS服务器的配置将在另外的文章中介绍,本文所有操作是基于CVS服务配置正确、数据仓库已初始化的基础上,
第二章: 术语
1、           Repository-------仓库: CVS服务器的根目录。模块(Module)的集合
2、           Module------------模块:,CVS服务器根目录下的第一级子目录。通常用于存放一个项目的所有文件
3、           Checkout----------检出: 通常指将仓库中的一整个模块首次导出到本地。
4、           Import------------导入:通常指通过提交整个目录结构并创建一个新的模块。
5、           Release-------发行版本:整个产品的版本
6、           Revision--------修订版:单个文件的版本
7、           Tag---------------标签:在一个开发的特定期对一个文件集给定的符号名
8、           Update------------更新:从模块中下载其他人的修改过的文件。更新本地的拷贝。
9、           Commit------------提交:将自己修改过的文件提交到模块中。
 
第三章: WinCVS初始化配置
第一步:             安装Wincvs
执行setup.exe安装,然后在一步步的确认就ok了.安装完毕后运行wincvs:
 
第二步:             配置WinCVS参数
Ø      Preferences -> General :普通参数设置
1.       Authentication :    验证方式,CVS默认采用pserver
2.       Path:                     CVS服务器的路径,就是Repository(仓库)
3.       Host address:       CVS服务器的IP地址或者域名。
4.       User name:           用户名。
5.       CVSROOT:           CVSROOT,由上面4项生成的字符串,用于连接服务器
6.        
Ø      Preferences -> Globals :全局参数设置
 
      
1.       checkout read-only:                     检出只读,wincvs默认导出文件为只读状态。去掉该选项。
2.       Prune(remove)empty directories 剪除(删除)空目录,去掉该选项。
 
Ø      Preferences -> WinCVS : WinCVS参数设置
 
第三步:             登陆
 
 
 
 
 
第四步:             导入模块
 
 
 
Ø      选择需要导入的目录
 
Ø      整理导入的文件类型(Entry State是OK标记就无需修改)
 
Ø      修改选中的文件类型
 
 
Ø      导入设置
 
 
 
 
 
第五步:             导出模块
cmd:
1 cvs checkout -P Documents/sipsir
该命令会在本地创建Documents
cvs client tool:
Ø      导出设置
 
 
Ø      模块成功导出
 
 
第四章: WinCVS日常操作
 
一、             修改文件,并上传到服务器
²     准备修改文件
 
²     修改文件
 
 
 
²     上传的修改文件
 
 
 
 
 
二、             下载服务器的文件,替换本地文件
假设服务器上“测试wincvs.doc”的word文件已经是1.2本,下载到本地来
 
 
 
 
 
三、             修改了一个文件,结果发现修改错了,需要重新下载服务器的文件。
 
 
 
 
 
四、             添加一个文件或一个目录。
cmd:
添加一个文件或目录
1 添加:cvs add test.txt
2 提交:cvs commit -m "no message" test.txt
添加目录及目录下所有文件,D:/cvs/sipsir
1 cd D:/cvs
2 cvs add sipsir
3 cd sipsir
4 cvs add *   (会把目录下所有文件和目录都添加了)
5 cvs commit –m “”
cvs client tool
²               打开需要放置文件的目录
 
²     新建立一个文件或目录
 
 
 
²     上传目录(如果文件中有子目录或文件,没有递归上传,需要在操作一遍)
²     上传文件
 
²     文件只是标记添加成功,还需要执行上传操作(具体操作查看“上传的修改文件”
 
 
 
五、             如何取回以前的某个版本
 
 
 
 
 
 
六、             删除分支/标签,取得最新的版本
 
 
 
七、             固定版本:经过一段时间修改,各个文件的版本不一致,而且文档管理到了一个阶段,需要固定版本。
 
 
 
 
八、             删除cvs服务器上的一个文件。
cmd
1  cvs remove -f test.txt
2  cvs commit -m "no message"
cvs client tool:
1 选中test.txt文件
 
2 删除文件
3 提交
九、             删除cvs服务器上的一个目录。
假设要删除 %cvs_home%\sipsir目录, 需要先删除目录中的所以文件,使该目录成为一个空目录,然后运行cvs update -P让CVS从仓库中清除空目录。
cmd
1 cd %cvs_home%
2 cvs update –P
3 cvs update

posted @ 2007-09-27 14:11 高山流水 阅读(5242) | 评论 (0)编辑 收藏

1、前言:

CVS是版本控制的利器,目前在Linux和Windows下都有不同版本;但是国内大多数应用介绍都是基于Linux等开放源代码的开放性软件组织,而且讲解的也不系统,让人摸不着头脑;Windows下的CVS使用介绍更是了了无几。
本文是针对Windows的LAN环境下使用CVS的经验介绍,一步一步的向您介绍如何配置和使用CVS的服务器端和客户端。同时,本文只使用到了CVS当中最基本的东西,还有很多更为高级的东西,本文暂不涉及。下面是本文的另一个连接映射,欢迎大家讨论使用,共同进步。
文章连接http://www.kuihua.net/book/list.asp?id=66
论坛连接http://www.kuihua.net/bbs/dispbbs.asp?boardID=1&;RootID=670&ID=670

2、安装版本:

2.1、服务器端(CVSNT)

1. 本文使用的是CVSNT-2.0.4,这是一个比较稳定的版本,不要使用最新的CVSNT-2.1.1,本人在使用中发现有比较严重的Bug。
2. 下载连接http://www.cvsnt.org 目前,它提供2.0.6和2.1.1版本的下载。
3. 上面连接还提供源代码,有兴趣的朋友还可以下载下来仔细研究:)。
4. 有心的朋友,仔细观察就会发现http://www.cvsnt.org 并没有提供任何客户端的下载,那是因为CVS.exe既可以用于服务器端又可以用于客户端,WinCVS是为了客户端使用的方便而定制的外壳。(关于这一点,本人未得到任何证实,只是本人在使用过程中的一种体会,欢迎大家讨论。)

2.2、客户端(WinCVS)

1. 本文使用的是WinCVS-1.3b13,这应该是一个最新版本:),本人在使用过程中并没有发现有任何严重的Bug。
2. 下载连接http://sourceforge.net/projects/cvsgui/
3. 此网站还提供丰富的CVS文档和相关源代码,以及多个OS下面的相关文档和代码;有收藏癖的朋友有福了:)。
4. WinCVS-1.3b13 使用的CVSNT的版本是CVSNT-2.0.2,在与服务器端的CVSNT-2.0.4 版本配合使用时,未发现任何不兼容或冲突现象。
5. 在本人的系统中用cvs version命令显示的结果如下:
Client: Concurrent Versions System (CVSNT) 2.0.2 (client/server)
Server: Concurrent Versions System (CVSNT) 2.0.4 (client/server)

3、服务器端(CVSNT)的安装与配置:

3.1、服务器端机器和环境配置:

1. 操作系统:Windows 2000 Professional SP2中文版
2. 机器名称:Server
3. 机器地址:192.168.0.6 (内部IP)
4. 网络环境:100兆交换局域网
5. 硬盘分区格式:FAT32与NTFS都可以。
6. 准备2个CVSNT的工作目录:
F:\KHRoot (存放自己源代码的根目录)
F:\KHTemp (存放CVS出错信息的目录)
7. 本机上存在有的用户列表:(由NT或本机的使用者创建)
Administrator (系统管理员)
Jackey (普通用户)
Goury (普通用户)
Riolee (普通用户)

3.2、安装CVSNT:

1. 下载CVSNT-2.0.4;使用administrator登陆到Server机器上。
2. 双击自解压的exe文件,选择Full Install,其它按照默认方式安装;安装完毕后可以在服务控制器中发现多了2个服务:cvsnt与cvslocking
3. 发送Service Control Panel到桌面,形成快捷方式。
4. 安装程序会自动将CVS安装路径,设置到系统的Path环境变量当中,因此使用者可以在控制台(cmd)中任意位置执行cvs.exe,这一点对下面的配置很重要!!

3.3、配置CVSNT服务器:

1. 双击Service Control Panel快捷方式,在Service Status页面,确认2个服务正常和稳定运行。
2. 选择Repository页面,点按Add按钮,选择已经准备好的F:\KHRoot这个目录,确认,OK,Yes,这时会在F:\KHRoot下面建立CVSRoot目录,这是CVS默认的管理目录(默认模块)。如果报错,那是系统Path路径未设置正确。
3. 选择Advanced页面,勾上Use local users for pserver ...,(Why? I don’t know!J),在Temporary栏选择已经准备好的F:\KHTemp,确认,OK。
4. 点按【应用】按钮,确认,退出,OK,搞定!!

3.4、小结:

1. 至此,CVSNT服务器端基本配置完毕,下面进行WinCVS的使用和管理。
2. 由于CVS支持远程管理,也就是客户端与服务器集成的特性,因此,我们将添加用户、权限控制、模块维护等所有的管理工作都放到远端(WinCVS)进行管理,服务器端这时可以Ctrl+Atl+Del进入锁定状态了,下面的所有工作都交给远端的WinCVS来进行管理。

4 客户端(WinCVS)的安装与配置:

4.1 客户端机器和环境配置:

1. 操作系统:Windows 2000 Professional SP2中文版
2. 机器名称:YCW2000
3. 机器地址:192.168.0.2 (内部IP)
4. 网络环境:100兆交换局域网,可以直接访问到Server
5. 硬盘分区格式:FAT32与NTFS都可以。

4.2 安装WinCVS:

1. 下载WinCVS 1.3b13,全部按照默认安装就可以了。
2. 启动WinCVS,开始使用。特别注意:以下的所有操作都是在YCW2000(192.168.0.2)这台机器上远程完成的,此时的Server(192.168.0.6)主机已经进入了锁定状态。

5 管理员使用WinCVS进行远程管理:

5.1 配置WinCVS成管理员状态:

1. 准备管理员工作目录:(在YCW2000机器上)
E:\CVSClient\Admin (管理员工作目录)
E:\CVSTemp (WinCVS临时目录)
2. 第一次启动WinCVS时会自动弹出Preferences配置页面,也可以通过Admin=>Preference菜单进入;第一次使用时需要配置如下的3个页面:
General页面设置:
注:按照图示方式输入即可,需要注意的是Path部分的格式是Unix路径格式,它指的是CVSNT端设置的工作根目录。
CVS页面设置: 注:Home路径是设置密码等文件的存放位置,必须指定,否则在登陆时,WinCVS也要弹出设置框。这个Home路径需要Python.exe这个外挂程序才有效。这里选择已经准备好的路径:E\CVSTemp
WinCVS页面设置:
注:此页面设置WinCVS的外挂编辑程序,通常使用UltraEdit比较方便。
3. 设置管理员的工作路径:可以点按图标 ,或View=>Browse Location=>Change…菜单进行设置,选择已经准备好的路径:E:\CVSClient\Admin,确认,OK,这时此目录将出现在WinCVS的左边导航栏【Workspace】内。
4. 至此,WinCVS就被配置成了远程的管理员使用状态,下面进行一般管理员需要的基本操作演练。演练的内容为:Administrator需要管理Jackey,Goury,Riolee三个用户,分别为这3个用户建立工作目录,每个人只能访问自己的工作目录。同时,只有Administrator能够进行权限分配,其它人没有任何管理权限。

5.2 管理员进行管理演练:

1. 登陆远程CVSNT:
  ◇ 选择Admin=>Login菜单,默认设置,OK。
  ◇ 弹出密码输入框,确认,OK。注意观察输出框【OutPut】的返回结果。
2. Checkout默认模块:(CVSRoot管理模块)
  ◇ 在左边导航栏【Workspace】内,选择【Admin】点按右键,选择【Checkout
  modules…】,在【Checkout settings】中输入CVSRoot,确定,OK。如下图:
  ◇ 如果成功的话,会在【Admin】栏下增加一个【CVSRoot】目录。表示您已经将【
  CVSRoot】这个管理模块下载到本地了。

3. CVS中目录权限介绍:

◇ 系统支持的目录权限列表:
r (读取权限)
w (写入权限)
c (创建和删除权限)
n (没有任何权限)
◇ 默认情况下,任何用户都拥有任何目录的所有权限。
◇ 任何情况下只有目录的拥有者和Administrator才有权力更改目录的使用权限。下面将会介绍如何修改目录权限和目录的拥有者。

4. 修改CVSRoot的权限:只让Administrator拥有rcw三种全部权限。

◇ 选中刚刚下载的【CVSRoot】模块,【Ctrl+L】或Admin=>Command Line…,弹出Command Line Settings对话框,直接执行CVS命令。
◇ 取消所有用户的默认权限:cvs chacl default:n 回车,OK,完成。
◇ 设置Administrator拥有所有权限:cvs chacl administrator:rcw 回车,OK,完成。
◇ 更改【CVSRoot】的拥有者:cvs chown administrator 回车,OK,完成。
◇ 查看【CVSRoot】的权限状态:cvs lsacl 回车,OK,在【Output】中显示:
Owner: administrator
default:n
administrator:rwc
◇【CVSRoot】的权限配置完毕。

5. 编写代码库中的模块文件,便于多用户下载方便。

l 需要自己编写的模块文件格式如下:(实现基本功能)
【模块一的描述】【n个空格或参数】【相对目录路径一(DirA)】
【模块二的描述】【n个空格或参数】【相对目录路径二(DirB)】
……
【模块X的描述】【n个空格或参数】【相对目录路径X(DirX)】
◇【描述信息】与【相对路径】在字面上不一致时,需要使用-a参数。
◇ 【相对路径】指的是CVS会自动带上根路径,这里是F:\KHRoot,所以上面例子的完整路径为:F:\KHRoot\DirA
◇ 了解了模块文件结构,现在来实际操作一把:双击【CVSRoot】模块下的modules文件,用UltraEdit打开进行编辑。
◇ 为Jackey,Goury,Riolee三个用户分配工作目录和完成其它模块描述。
CVSRoot CVSRoot
Jackey工作目录 -a Jackey
Goury工作目录 -a Goury
Riolee工作目录 -a Riolee
◇ 编辑完毕,存盘。回到WinCVS,选中modules这个文件【Ctlr+M】或右键选择【Commit selection…】,默认设置,【确认】,OK,完成上传。

6 . 为三个用户分别上传工作目录:

◇ 在YCW2000机器上的E:\CVSClient\Admin分别建立三个目录分别名为:Jackey,Goury,Riolee,作为临时交换目录。
◇ 在新创建的每个目录中用UltraEdit或拷贝一个Readme.txt作为引子文件!!:)
◇ 然后,回到WinCVS,在【Workspace】栏的【Admin】目录下形成如下的目录结构:
◇ 分别选中Goury,Jackey,Riolee,右键,点按【Import Module】,选择【Continue】,其它全部使用默认值,【确定】,OK,完成上传工作。
◇ 仔细观察【Output】窗口,确认都成功上传了。
◇ 转移到系统的Explore程序中,删除E:\CVSClient\Admin目录下的Jackey,Goury,Riolee三个目录。然后回到WinCVS当中。(一定要删除!!!:)
◇ 至此,就完成了工作目录的上传工作。

7. 【Checkout】下载3个用户的工作目录到【Admin】目录下:

◇ 在【Workspace】栏选择【Admin】目录,右键,点按【Checkout Module…】,如下图:
◇ 选择【…】,得到CVSNT上最新的模块配置情况,弹出如下的信息框:
◇ 这个结构图就是刚才在modules当中编写的模块文件格式信息。选择【Jackey工作目录】,下载到YCW2000机器的E:\CVSClient\Admin目录下。
◇ 按照以上操作,依次分别下载【Goury工作目录】和【Riolee工作目录】。形成如下状态:


8. 为三个用户分别设置各自目录的访问权限。(只有自己才能访问自己的工作目录)

◇ 选中【Goury】目录,【Ctrl+L】或Admin=>Command Line…,弹出Command Line Settings对话框,直接执行CVS命令。
◇ 取消所有用户的默认权限:cvs chacl default:n 回车,OK,完成。
◇ 设置Goury拥有所有权限:cvs chacl goury:rcw 回车,OK,完成。
◇ 查看【CVSRoot】的权限状态:cvs lsacl 回车,OK,在【Output】中显示:
Owner: administrator
default:n
goury:rwc
◇ 按照以上的方法依次分别设置【Jackey】与【Riolee】的工作目录访问权限。
◇ 至此,完成了3个用户的目录权限分配。注意,虽然Administrator也没有权力再次【Checkout】那3个用户的工作目录,但是它是这些目录的拥有者又是Administrator,因此,只有它才有权力更改这些目录的访问权限。

9. CVSNT系统中的用户管理原则:

◇ CVSNT的用户与本机(这里是Server机器)上的NT用户是相关联的,即CVSNT用的全是本机上存在的已有用户,因此在默认情况下可以不用设置任何用户名,只要使用本机上已经存在的用户名就可以用WinCVS进行登陆。
◇ 只有用Administrator身份登陆到CVSNT系统中,才有权力进行新用户的创建和删除。
◇ 使用CVS创建的新用户,必须与服务器端机器上的NT用户相绑定,才能生效;因此,这个新用户实际上是绑定它的NT用户的一个替身,在CVS系统中称为“别名”。
◇ 一个NT用户可以有多个‘替身’或‘别名’,充当多个CVS用户。

10. 用WinCVS进行新用户的添加和删除。(确保使用Administrator登陆)

◇ 【Ctrl+L】或Admin=>Command Line…,弹出Command Line Settings对话框,直接执行CVS命令。
◇ 添加新用户【Killer】:cvs passwd -a Killer 回车,设置密码,OK,完成。
◇ 绑定【Killer】到【Jackey】:cvs passwd -r Jackey Killer 回车,设置密码,OK,完成。
◇ 两次输入的密码可以不同,但以第二次输入的密码为最终密码。
◇ 删除用户【Killer】:cvs passwd -X Killer 回车,OK,完成。
◇ 其它特殊的功能查看passwd命令的帮助。

11.使用完毕后,一定要【Logout】,因为WinCVS退出时并不会自动注销自己在远端的会话;这样做是为了防止其它人接着打开WinCVS,不用登陆就可以完成你能进行的所有操作了。

6 WinCVS中常见的特殊操作:

6.1 如何删除下载的文件或目录:

1. 选中下载的某个或多个文件,执行【Remove】命令。
2. 再次选中这些文件,执行【Commit】命令就完成了删除文件的操作。
3. 本质上CVS是不会删除任何文件和目录的,即使是执行了以上操作,删除了某些文件,远端CVS实际执行的是将提交删除的文件放到了一个叫【Attic】的目录下,因此,这些被删除的文件是可以通过一定的方法恢复的。

6.2 如何恢复已经删除的文件或目录:

1. 在执行了【Remove】命令之后恢复文件。
◇ 【Ctrl+L】直接输入命令cvs add xxxxx,或执行【Add Selection】界面操作。
◇ 这样就可以直接恢复还未提交的删除文件。
2. 在执行了【Commit】命令之后恢复文件。
◇ 只能用【Ctrl+L】直接输入命令cvs add xxxxx,这时会得到一个空的文件。
◇ 选中这个空文件,执行【Update】操作,得到这个文件的实体。
◇ 再次选中这个文件,执行【Commit】操作,得到这个文件最新版本。
3. 由于CVS系统中本质上不会删除任何目录,因此,谈不上对目录的恢复,但是CVS系统默认情况下是要在用户本机上(如:YCW2000)要删除空目录,因此,可以用如下方法得到已被删除的空目录:cvs checkout -p xxx,也可以在Admin=>Preference的【Globals】页面进行设置。
4. 可见,CVS系统能够保证:只要上传到服务器的文件,无论你怎么在远程进行如何的操作,正常的或非正常的操作,都可以用Administrator登陆上去,通过以上的方法找到丢失的文件。除非用户进入到远端服务器,将文件手动删除,那就没办法了:)

6.3 如何得到以前版本的文件:

1. 有时我们需要得到以前版本的文件,而WinCVS默认方式只传递最新的版本。
2. 选中某个文件,【Ctrl+G】或右键,点按【Graph selection…】,使用默认设置,就可以得到该文件所以版本的图形结构描述。
3. 选中一个版本,右键,点按【Retrieve revision】,就可以得到相应的老版本文件。当然也可以得到最新版本的文件:)

6.4 有时WinCVS会变得异常缓慢,怎么办?

1. 确认安装了WinCVS的机器上没有安装CVSNT服务器端,因为它们使用的版本有可能不一致。
2. 只安装了WinCVS,但以前安装过其它版本的WinCVS,怎么办?
3. 先卸载所有的WinCVS系统,删除安装目录下的残留文件。
4. 打开注册表编辑器,全程查找cvs关键字,找到一个删除一个,一直到找不到为止!!:)
5. 重新安装WinCVS,这个问题基本上就可以解决了,我就是这样解决,不晓得你那里如何?:)

7 其它说明:

1. 本文的重点在介绍如何让使用者搭建CVSNT+WinCVS这个系统,因此重点介绍了管理员的常用操作,至于一般用户使用到的操作,相对比较简单和单一,使用WinCVS的次数多了,很快就会熟悉它了。
2. 这篇文档只是窥探了CVS的一点皮毛而已,CVS当中还有很多高级的用法,以及上百个命令,还有很多新鲜的管理源代码的方法,比如:tag,branch等模式;因此,热烈欢迎大家积极探索,不断共享,不断进步。。。。。。。。
3. 另外,cvs.html这个帮助,里面的信息也很丰富,但是,很多地方写得不够清楚,需要不断猜测和实践才能知道怎么回事,本文的很多经验都是看这个帮助,如此这般,采用这个笨办法得到的。。。。。。
4. 最后,祝愿看到此文的人,得到的帮助、提高等好处大于或等于浪费的时间、反而退步等坏处!!

posted @ 2007-09-27 13:50 高山流水 阅读(618) | 评论 (0)编辑 收藏

[原创]英文电影台词欣赏

翻译:shaobo(如转载请注明出自www.arsenalcn.com以及翻译者)

勇敢的心brave heart

part 1.

foreword:

Historians from England will say I am a liar.

But history is written by those

who have hanged heroes.

英国的历史学家们会说我在说谎

但历史是由处死英雄的人写的

part 2.

dialogue:

Of course, running a farm is a lot of work.

But that will all change when my sons arrive.

So, you\'ve got children.

Well, not yet. But I was hoping

that you could help me with that.

So you want me to marry you, then?

Well, it\'s a bit sudden, but all right.

Is that what you call a proposal?

I love you. Always have.

I want to marry you.

Is that a yes?

- Aye, that\'s a yes.

当然,

要经营农场要干很多活

但假如我能有个儿子,

一切都会轻松很多。

你都有孩子了?

还没哪.

不过我希望你能帮帮忙。

你希望我嫁给你,是吗?

是有点突然,不过没关系

这就是你所谓的求婚?

我爱你.

直到永远

我要娶你

你同意了?

对,我同意

friday night lights胜利之光

part 1.

monologue:

Boy, you remember everyminute of this. i\'m telling you right now.

You\'re young,but it goes fast.

Don\'t sleep,don\'t waste a second of it.

Because before you know it, it\'s done.

Nothing but babies and memories.

小伙子,我给你说,你要牢记现在的每一分钟。

你很年轻,但是时光荏苒。

不要过悠闲的日子,不要浪费每一秒时间。

因为当你意识到的时候,青春已经不再。

除了孩子和记忆不会留下任何东西。

part 2

pray:

Our father who art in heaven,hallowed be thy name.

Thy kingdom come,thy will be done on earth as it is in heaven.

Give us this day our daily bread and forgive us our trespasses.

As we forgive those who trespass against us.

Lead us not into temptation but deliver us from evil.

For thine is the kingdom,the power and the glory, forever.

Amen!

我们在天上的父,愿人都尊你的名为圣。

愿你的国降临,愿你的旨意行在地上,如同行在天上。

我们日用的饮食,求你今日赐给我们;

宽免我们的罪债,犹如我们宽免了人的债。

不要让我们陷入诱惑,救我们脱离凶恶。

因为国度,权柄,荣耀,全是你的,直到永远。

阿们!

A White Noise白色噪音

the movie\'s opening words:

"nobody knows whether our personalities pass on to another existence or sphere,

but if we can evolve an instrument so delicate as to be manipulated by our personality as it survives in the next life

such an instrument ought to record something"--Thomas Edison 1928

“没有人知道人死后是否能在另一个世界延续生命,但是如果我们能发明一种仪器,这种仪器精巧到能被存活于另一个世界的我们利用,那么这种仪器应该能记录下一些东西...”--托马斯·爱迪生 1928年

 

 

 

 

Team America --World Police  

Part one:

lyrics of song

I miss you more than MichaeI Bay

Missed the mark

When he made Pearl Harbor

I miss you more than that movie

Missed the point

And that\'s an awfuI Iot, girI

And now

Now you\'ve gone away

And aII I\'m trying to say

Is Pearl Harbor sucked

And I miss you

I need you Iike Ben AffIeck

Needs acting schooI

He was terribIe in that fiIm

I need you Iike Cuba Gooding

Needed a bigger part

He\'s way better than Ben AffIeck

And now

AII I can think about is your smiIe

And that shitty movie too

Pearl Harbor sucked

And I miss you

Pearl Harbor sucked

Just a IittIe bit more

Than I miss you

 

# 我想念妳比迈克尔·贝不着四六(偏离了正轨)更多~ #

# 当他拍珍珠港时~ #

# 我想念妳比那部电影跑了题更多~ #

# 而且是跑了很远。 女孩,现在~ #

# 现在妳离开了~ #

# 我只想对妳说~ #

# 就是,珍珠港够烂~ #

# 还有我很想妳~ #

# 我需要妳就像本·阿佛莱克需要上表演学习班~ #

# 他在戏里演的真烂~ #

# 我需要妳就像小库巴·古丁需要更多戏份~ #

# 他比本·阿佛莱克好太多了~ #

# 现在,我只想着妳的笑容~ #

# 还有那烂电影~ #

# 珍珠港烂~ #

# 还有我很想妳~ #

# 珍珠港烂得~ #

# 比我想妳只多那么一点点~ #

 

 

 

 

Part two :

monologue:

See, there are three kinds of people:

Dicks, pussies and assholes.

Pussies think everyone can get along

and dicks just wanna fuck all the time

without thinking it through.

But then you got your assholes,

Chuck.

And all the assholes want

is to shit all over everything.

So pussies may get mad at dicks

once in a while

because pussies

get fucked by dicks.

But dicks also fuck assholes, Chuck.

And if they didn\'t fuck the assholes,

you know what you\'d get?

You\'d get your dick and your pussy

all covered in shit.

(此独白只可意会)嘿嘿

Moonstruck 月色撩人

dialogue:

You were a tiger last night.

And you were a lamb,

as soft as milk.

Shh! Lower your voice.

They\'ll hear you in the back.

So what? The pleasure of marriage

is you sleep with the woman...

you don\'t worry about nothing.

Be quiet, Raymond!

(此台词同样只可意会)

National Treasure 国家宝藏

part 1:

dialogue:

Anyone that can do anything is gonna think we\'re crazy.Anyone crazy enough to believe us isn\'t gonna want to help.

We don\'t need someone crazy.But one step short of crazy,what do you get?

Obsessed.

Passionate.

 

能帮上忙的人认为我们是疯子。疯到能相信我们的人,又不想帮忙。

我们不需要疯子。只需要能接近疯狂的状态的人,你知道是什么状态吗?

五迷三道?

热情执着。

part 2

monologue:

You know,Thomas Edison tried and failed nearly 2000 times to develop the carbonized cotton-thread filament for the incandescent light bulb.

When asked about it, he said:"I didn\'t fail,I found out 2000 ways how not to make a light bulb."

But he only needed to find one way to make it work.

你知道,托马斯·爱迪生经过近2千次失败才发明了炭化棉线灯丝的白炽灯泡。

人们问他的时候,他说:“我并没有失败,我是发现了两千种做不成灯泡的方法。”

但成功的方法,他只需要找到一个便已足够。

加菲猫的经典台词摘录如下:(转载)
 

 

 

  Money is not everything. There"s Mastercard & Visa.

 

  钞票不是万能的,有时还需要信用卡.

 

  One should love animals. They are so tasty.

 

  每个人都应该热爱动物,因为它们很好吃.

 

  Save water. Shower with your girlfriend.

 

  要节约用水,尽量和女友一起洗澡.

 

  Love the neighbor. But don"t get caught.

 

  要用心去爱你的邻居,不过不要让她的老公知道.

 

  Behind every successful man, there is a man. And behind every

 

  unsuccessful man, there are two.

 

  每个成功男人的背后,都有一个女人. 每个不成功男人的背后, 都有两个.

 

  Every man should marry. After all, happiness is not the only thing

 

  in life.

 

  再快乐的单身汉迟早也会结婚,幸福不是永久的嘛.

 

  The wise never marry, And when they marry they become otherwise.

 

  聪明人都是未婚的,结婚的人很难再聪明起来.

 

  Success is a relative term. It brings so many relatives.

 

  成功是一个相关名词,他会给你带来很多不相关的亲戚(联系).

 

  Never put off the work till tomorrow what you can put off today.

 

  不要等明天交不上差再找借口, 今天就要找好.

 

  Love is photogenic. It needs darkness to develop.

 

  爱情就象照片,需要大量的暗房时间来培养.

 

  Children in backseats cause accidents. Accidents in backseats cause

 

  children.

 

  后排座位上的小孩会生出意外, 后排座位上的意外会生出小孩.

 

  "Your future depends on your dreams." So go to sleep.

 

  "现在的梦想决定着你的将来",所以还是再睡一会吧.

 

  There should be a better way to start a day than waking up every

 

  morning.

 

  应该有更好的方式开始新一天,而不是千篇一律的在每个上午都醒来.

 

  "Hard work never killed anybody." But why take the risk?

 

  努力工作不会导致死亡!不过我不会用自己去证明.

 

  "Work fascinates me." I can look at it for hours!

 

  工作好有意思耶!尤其是看着别人工作.

 

  God made relatives; Thank God we can choose our friends.

 

  神决定了谁是你的亲戚,幸运的是在选择朋友方面他给了你留了余地.

 

  When two"s company, three"s the result!

 

  两个人的状态是不稳定的,三个人才是!

 

  A dress is like a barbed fence. It protects the premises without

 

  restricting the view.

 

  服饰就象铁丝网,它阻止你冒然行动但并不妨碍你尽情的观看.

 

  The more you learn, the more you know, The more you know, the more

 

  you forget.

 

  The more you forget, the less you know. So why bother to learn.

 

  学的越多,知道的越多, 知道的越多,忘记的越多, 忘记的越多,知道的越少,

 

  为什么学来着

english patient 英国病人

part 1.

dialogue:

Why-- Why are you so determined

to keep me alive ?

Because I\'m a nurse.

 

你为何如此坚决要把我救活?

因为我是个护士

(中国的某些护士真是给南丁格尔丢脸!)

part2

dialogue:

You\'re in love with him,

aren\'t you ?

Your poor patient.

You think he\'s a saint

because of the way he looks.

I don\'t think he is.

 

I\'m not so

in love with him.

I\'m in love with ghosts

 

 

你爱上了……

你那个可怜的病人吗?

你以为他是个圣人……

因为他被烧成这样子

我倒认为他绝对不是

 

我并不是爱上他......

我爱上的是往事

(注:It is with true love as it is with ghosts: everyone talks of it, but few have seen it. ---La Rochefoucauld.往事如梦,真爱如鬼,每个人都在谈论,却鲜有人真正经历过刻骨铭心。)

part3

the letter:

My darling, I’m waiting for you. How long is a day in the dark? Or a week? The fire is gone now and I’m horrible cold. I really ought to drag myself outside, but then there’d be the sun. I’m afraid I waste the light on the paintings and on writing these words. We die. We die rich with lovers and tribes, tastes we have swallowed, bodies we have entered and swum up like rivers, fears we’ve hidden in like this wretched cave. I want all this marked on my body. We’ve the real countries. Not the boundaries draw on maps, the names of powerful men. I know you’ll come and carry me out into the palace of winds. That’s all I’ve wanted, to walk in such a place with you, with friends. An Earth without maps. The lamp’s gone out and I’m writing in the darkness.

这段相当难翻,头大了两圈,(我日英国病人!),在网上找了些资料和网友的译文,又理解了原著,觉得如下两篇更接近原义。

摘录译文1:

我的爱,我在等你。在黑暗里的一天,会有多长?一周吗?现在火灭了,我好冷。我得挣脱,我得出去,可是外面也得有阳光才好!我真怕,我也许会把光明都浪费到这样涂写上。我们都将死去,我们将与爱的人和不同种族的人一起充实而热烈的死去。我们咽下彼此的味道;交换彼此的身躯,浮游于爱河之上;恐惧时我们躲藏起来,正如这凄凉的洞穴。我要所有这些都镌刻在我的身体上。我们才是真实的国家,并非画在地图上的边界所示的,以掌权者命名的国家。我知道你定会回来抱着我,屹立风中。那就是我所要的--与你漫步在如此的土地上,与朋友们,在一个没有地图的地球上。灯枯油尽了,我在黑暗中写着.........

摘录译文2:

我的爱,我在等你。在黑暗里的一天,会有多长?一周吗?现在火灭了,我好冷。我得挣脱,我得出去,可是外面也得有阳光才好!我真怕,我也许会把光明都浪费到这样涂写上。我们会死。我们会死得富饶,饱含爱人、同胞,人生辛辣,世态炎凉;饱含我们浮沉过的苍茫人海;饱含那些想找一个这样小洞躲起来的恐慌。我想要这刻骨铭心的一切。我们是真正具体的无垠的国度,不是那画在地图上的,用强人的名字框定的边界。我知道你会来的,你会载我去清风的殿堂,我就要这些——和你,和朋友,在一个没有地图的地球上,在这样的一个地方,悠然漫步。灯灭了,我在黑暗中,写着........

搞笑译文:

我的小心肝,等你等的我肠子都青了。这黑灯瞎火的,我都不知道是过了一天哈,还是过了一个礼拜。火也灭掉啦,搞得我冷得要命。我恨不得把自己拎出去晒晒太阳,可惜现在是梅雨季节。我只能游手好闲地在画图和写情书上挥霍时光。啊我要死啦。不过我也总算有老婆有兄弟还有很多饭局,写生过不少美女的身体,也算是够本没白活。有时我也曾怕得恨不得藏在洞里。我把这些都用刺青文在身体上酷吧。别看人家又圈地来又有上层关系的,我们也总算能买楼啦。我知道你会回来的,把俺也带到啥米风的皇宫中逍遥逍遥。那我就都满足啦,吃饱了撑着就大家一起散散步消化消化。废除房地产改革!喔哟又停电了伊讲,我只好瞎写八写了。。。)

再贴一点相关资料:

    

      加拿大“环球邮报”曾刊登了一系列对此片道德议题的讨论。主要是将之与另一部战争爱情经典《卡萨布兰卡》作比较。两位男主人公都被迫在爱人与道德政治立场两者间作出选择。《卡》片中的里克选择了后者,而Almasy-英国病人,则选择了爱,选择了对得起自己的感情,这似乎是不负责的,但把人与战争所宣扬的政治意识立场相比,哪一个更实在呢。Almasy的“出卖”行为被看做对人类追求真善美的背叛,可战争本身不是违背人类对真善美的追求吗?他的行为是不是对战争的一种反叛呢,对于交出地图所产生的后果,其实他自己在片中也有所回答。当被割去双手拇指的Cravaggio 质问Almasy说:“千万人因你而丧生。”他回答:“千万人已经死去(因战争也会照样死去),只是不同的人罢了。”爱是有毁灭性的,但却无法与战争所带来的毁灭性相比。我感到Almasy死时是无悔的,正象他的情人临死在日记中写到:“我们虽死,但却饱含著爱与经历...国家的定义应当是我们(即人类),而不是地图上的国界。

    

      《英国病人》被称为一部宏伟的史诗(an epic),但片中的动人之处却是对人类心灵和细微感情的描述:从Almasy和Katherine对爱的热情追求,到Hanna和Kip因怕受到伤害而对爱的回避,其间充满了人性美的瞬间。辟如Hanna被Kip升到教堂顶部观赏壁画的一幕就是令人惊羡的美。这些正说明了人在残酷的战争背景下也并不放弃对真善美的追求。而只有回归爱才能永恒,就象只有沙漠的壮丽和艺术的精美才是永恒的,而不是战争,权利或者政治立场。

    

      影片结尾Almasy抱著情人的尸体痛哭的场面令人震憾,它似乎表达了一个人对整个世界的抗衡。正如《英国病人》原著中一段描写Hanna唱“国际歌”的情形,作家(Michael Ondatje)写到:

    

      There was no certainty to the song anymore, the singer could only be one voice against all the mountain of power. That was only surness.The one voice was the single unspoiled thing.

    

      那一个声音是呼唤人性的声音。

这里是小说的原文, 更容易理解些:

      

      "We die containing a richness of lovers and tribes, tastes we have swallowed, bodies we have plunged into and swum up as if rivers of wisdom, characters we have climbed into as if trees, fears we have hidden in as if caves. I wish for all this to be marked on my body when I am dead. I believe in such cartography--to be marked by nature, not just to label ourselves on a map like the names of rich men and women on buildings.We are communal histories, communal books . . . All I desired was to walk upon such an earth that had no maps."

Constantine 地狱神探

offscreen voice at end of movie:

I guess there\'s a plan for all of us.

I had to die...

...twice...

...just to figure that out.

Like the book says, he works his work

in mysterious ways.

Some people like it...

...some people don\'t.

 

我想,上帝为每个人都安排了一个计划

我死了两次...

才明白了自己的

就如书上所写:

"他做事的方式很神奇"

有些人喜欢...

有些人不喜欢

spellbound 爱德华医生[英格丽.褒曼,格利高里.派克]1945年

Women make the best psychoanalysts till they fall in love.

After that,they make the best patients.

女人在恋爱前是最优秀的精神病医生;恋爱之后,她们就成了最神经的精神病人。

英格丽·褒曼Ingrid Bergman    

 

the man who knew too little 特工插班生

When I was back in that room,I thought I was going to die.
My life passed before my eyes and I realized I cared about the wrong things.
I\'ve cared about money and success and getting to the top.Prestige and at the end of the day......

刚才在那个房间,我以为我死定了。当我的一生在我眼前一扫而过时,我才发现这辈子自己在意的东西是毫无意义的。以往我只关心钱、名望、地位和如何往上爬。结果到了最后.......

posted @ 2007-08-20 17:15 高山流水 阅读(1125) | 评论 (0)编辑 收藏

应用MFC开发高级应用程序

苟建兵 清华大学热能系(北京,100084)


目次:一、使用C/C++及VC与VB之比较   二、MFC编程综述  三、使用单文档-多视结构

       四、使用DDE服务  五、使用3D控制  六、使用自定义消息  

       七、使用不带文挡-视结构的MFC应用  八、MFC应用的人工优化


[摘要]:目前在Windows下开发应用程序的工具虽然很多,但是C/C++作为一种非常成
熟和高效的开发语言在大型复杂项目的开发中仍然得到了广泛应用。为了减轻程序
开发负担,提高开发效率,各种流行的C++都提供了类库,本文就是针对如何在
Visual C++环境中使用MFC类库来开发高级程序所需要解决的一些问题进行了的探
讨,重点讨论了利用MFC开发单文档多视应用程序和DDE应用程序的方法。


一、使用C/C++
随着Windows系列操作系统的日益普遍,传统的基于DOS编程逐渐转向Windows下编程
已经成为必然趋势。目前在Windows下开发应用程序的工具很多,典型的如Borland
C++、Visual C++、Visual Baisic以及Delphi等等。每种开发工具都各有其特点,
一般来讲用户可以根据自己的使用习惯和开发项目的性质来选择具体的开发语言。

Visual Basic是一个被软件界称之为划时代的革新产品,该软件改变了人们开发
Windows程序的方式,它采用交互式的可视化操作,使得人们开发Windows程序的每
一过程都有直观形象的反馈,从而加速整个开发进程。Visual Basic使得Windows程
序设计人员不再只依赖于复杂的SDK编程,使得开发Windows程序非常容易,可以
说,用户学习并使用VB来开发Windows应用的时间是最短的。Visual Basic版本几经
演变,目前已经发展到5.0。在4.0版本中,由于完全使用了面向对象的编程概念,
同时具有Windows 3.1和Windows 95下的版本,因而使得其开发复杂程序的功能逐渐
增强。VB5.0则抛弃了Windows 3.x的用户,只能在32位Windows中使用,据悉,该版
本吸收了Delphi的成功策略,引入了本地代码(Native Code)编译器,从而使得程序
执行速度大大加快,克服了以往版本由于执行文件采用P-Code代码而导致运行速度
慢的特点,根据微软的声明,该版本的采用本地代码编译后得到的应用程序在某些
情况下执行速度较以往提高了10~20倍,执行速度可以直逼与采用Visual C++编写的
应用,而应用开发速度则是VB的强项,因此Visual Basic 5.0非常具有竞争性。目
前Visual Basic非常广泛地用于开发各种Windows程序,如数据库前端应用程序和多
媒体应用等。但是,在作者看来,采用VB也有一定的缺点,原因有以下几点:
1. Visual Basic来源于Basic语言,虽然经过微软的不断增强,但是仍然缺乏非常
灵活的数据类型和编程策略,因而在开发一些项目必须的复杂数据结构遇到麻烦,
如链表、图和二叉树等等。由于在中大型项目开发后期,开发工作不再以界面为
主,而是在算法设计和底层软硬件工作,这就使VB开发项目的后期工作量大幅度增
加,为了达到项目要求,经常需要再转向C/C++开发一些专用的动态连接库来解决问
题。
2. Visual Basic运行速度慢,前文讲过,采用P-Code代码虽然执行文件很小,但是
在运行时需要解释执行,并且,它的运行必须有对应的VBRUN.DLL和所使用的VBX或
者OCX支持。对于浮点操作密集或者循环嵌套很多的应用来说,VB没有采取特别的优
化,因而执行速度远不如用C/C++和Fortran开发的应用速度快。VB 5.0虽然通过引
入本地代码编译器大大弥补了这个缺陷,但是由于其只能运行于32位Windows环境因
而在16位Windows上速度问题仍然得不到解决。虽然目前转向32位Windows的趋势非
常强劲,但是不容忽视由于硬件的限制或者使用习惯等诸多原因,还有许多用户仍
然在16位Windows上工作。在计算机十分普及的美国,96年使用16位Windows的用户
仍然超过了使用32位Windows的用户,任何进行系统软件设计的人员都应该照顾到这
些仍然使用16位Windows的用户。
3. VB不能灵活地使用系统资源。熟悉Windows编程的人都知道,如果要直接访问硬
件或者要编写对系统进行有效访问的应用程序,没有Windows API函数的帮助则非常
困难,但是令VB程序员失望的是,API函数是用C语言和汇编语言实现的,是为C编程
准备的,如果要在VB里面使用这些上千个API函数则比较麻烦,特别是,如果设计人
员不懂C语言则尤其困难。由于API函数的复杂性,而其本身不是为了方便VB编程而
提供的,因此在VB里面调用API函数需要一定的技巧,这些技巧足够用一本很厚的书
来表述。VB程序员可以从书店里找到好多本类似的书籍。可以说,任何一个VB程序
员发展到一定阶段都需要与众多的API函数打交道。另外,由于VB不支持端口操作,
因此,如果要编写类似数据采集等需要与硬件交互的程序则需要求救于C/C++语言。

4. Visual Basic项目分发和管理困难,其原因同上讲的,VB应用的运行不能脱离VB
的运行库和所使用的控件,因此,如果开发人员要将VB应用分发给用户那么一定要
带上VB的运行库和所使用的控件,并且要保证正确安装,这就导致即使一个非常简
单的应用也需要附带大量其它相关支撑库程序,对于VB 4.0及更高版本,由于大量
的使用了OLE控件(在VB中称为OCX),其安装更为复杂。
Delphi软件是国际宝兰公司(Borland)的得意之作,也是备受软件界推崇,与VB一
样,它完全是一个交互式的可视化开发平台,支持Client/Server应用程序的开发,
其最新版本2.0可以开发Windows 3.x、Windows 95和Windows NT的应用程
序。Delphi开发速度也非常快,与VB相比,由于具有本地代码编译器因此它产生的
可执行文件执行速度大大加快。Delphi软件是一个非常有竞争力的软件,采用的是
面向对象的Object pascal语言,支持硬件操作和API调用。但是由于采用的编程语
言为Pascal,这种语言并不非常流行,许多程序设计人员完全不熟悉这种语言,因
此极大地限制了该软件的使用,如果宝兰公司能够将Delphi软件提供的RAD开发机制
引入到其Borland C++中,则可能会形成一个非常成功的产品(目前该版本已经推
出,即C++ Builder,笔者注)。
VB和Delphi引入的可视化开发方法还有一个共同的缺点就是各个版本之间的兼容问
题。一般来讲,采用这些可视化开发工具开发的应用程序在移植到高版本时不会遇
到太大困难,但是一旦往相反方向移植则困难重重,有时甚至不可能。C/C++语言则
不具有这种局限性,各个版本之间的相互移植并不困难,高版本往低版本移植一般
只需重建工程文件即可大功告成。
综上所述,根据作者的观点,如果要开发一个大型复杂的应用程序首选的还是
C/C++,特别是在16位Windows下。虽然这会使前期工作增加,但是在项目的中后期
将逐渐会领略到其优越性和开发效率,其灵活高效的执行代码适合于对速度和应用
程序之间的协同性要求很高的场合。纯粹基于Windows SDK来开发Windows程序是一
项艰巨的工程,值得庆幸的是目前各种流行的C/C++开发工具都提供了类库开发框架
来简化整个开发过程而又不失其固有的灵活高效性,不同的开发语言所提供的类库
开发框架不同,如Borland C++提供的OWL(Object Windows Library)和 Visual C++
提供的MFC(Microsoft Fundmental Class),这两种类库都封装了大量的Windows
API和Windows的开发元素而使得开发任务简化,两种类库各有其优点,据作者掌握
的资料,采用MFC编写的应用程序执行代码更小,执行速度也更快,这大概是因为该
软件的开发者是开发Windows操作系统的Microsoft公司的缘故吧,现在MFC正逐渐成
为Windows下的类库开发标准,正被越来越多的其它C/C++编译工具所支持,如
Watcom C++。使用MC类库同时配合Visual C++提供的AppWizard、ClassWizard和
AppStudio可以大幅度提高开发效率。笔者在工作中积累了一些MFC的使用经验现在
提出来供大家参考,希望对广大同行有所帮助,尤其是那些仍然致力于16位Windows
编程的程序员。本文使用的Visual C++ 1.51编译器,但是其方法同样适用于其它
VC++版本,包括Visual C++ 4.x。
二、MFC编程综述
采用MFC开发Windows程序之所以能够大幅度提高开发速度和效率主要是因为MFC在类
层次封装了大量Windows SDK函数和典型Windows应用的缺省处理,这样,用户只需
要较少的编程就可以实现自己的开发任务。如果在MFC基础上再配合Visual C++提供
的AppWizard、ClassWizard和AppStudio工具那么更可以大幅度加快开发进程。MFC
提供大量的基类供程序员使用,常见的如CWinApp类、CFrameWnd类、CMDIFrameWnd
类、CMDIChildWnd类、CView类、CDC类和CDocument类等等。通过从这些基类中派生
出用户自己的类,然后重载特殊的几个函数就可以生成一个独立的应用程序。可以
说,采用MFC编写Windows应用程序是非常方便的,虽然其学习过程并不简单,但是
其提供的灵活高效性足以使任何Windows程序开发人员为之付出努力。如果用户不曾
使用过MFC,那么用户可以通过附录中所列的参考书去学习MFC的强大功能。
采用MFC应用框架产生的应用程序使用了标准化的结构,因而使得采用MFC编写的程
序的在不同平台上的移植变得非常容易,事实上,MFC的16位和32位版本之间差别很
小。MFC提供的标准化结构是经过众多专家分析调研后总结编写出来的,一般情况下
可以满足绝大多数用户的要求,但有时用户也可以通过重载一些函数来修改其缺省
的风格从而实现自己特有的风格,如自定义应用图表和灰色背景等。在MFC提供的文
档视结构中,文档、视和资源之间的联系是通过定义文档模板来实现的,如:
m_pSimuTemplate = new CMultiDocTemplate(
IDR_SIMUTYPE,
RUNTIME_CLASS(CSimuDoc),
RUNTIME_CLASS(CMyChild), // Derived MDI child frame
RUNTIME_CLASS(CSimuView));
上中第一项IDR_SIMUTYPE就包括了视口的菜单,加速键和图表等资源,如果用户使
用AppWizard来产生的应用基本框架,那么其也同时产生了缺省的图标,如果用户不
满意缺省图标(实际上用户很少满足于缺省图标),只需要将缺省图标删除,然后
编辑或者直接引入一个新的图标,在存储这一图标时只需要使用与被删除图标同样
的ID即可实现替代。
熟悉Windows程序开发的人都知道,在Windows上通过使用灰色背景可以增强应用程
序的视觉效果,曾有人戏称,灰色是图形界面永恒的颜色。使用MFC产生的应用程序
的背景缺省为白色,如果用户希望改变成灰色或者其它颜色,那就需要使用单独处
理,解决的办法很多,如在每次视口的OnPaint()事件中采用灰色刷子人为填充背
景,但是这不是最好的办法。笔者发现最好的办法就是采用AfxRegisterWndClass()
函数注册一个使用灰色背景刷的新的窗口类,这需要重载PreCreateWindow()函数来
实现这一点,如下程序代码片段所示:
BOOL CSimuView::PreCreateWindow(CREATESTRUCT& cs)
{
HBRUSH hbkbrush=CreateSolidBrush(RGB(192,192,192));//创建灰色背景刷
LPCSTR lpMyOwnClass=AfxRegisterWndClass(CS_HREDRAW
|CS_VREDRAW|CS_OWNDC,0,hbkbrush);//注册新类
cs.lpszClass=lpMyOwnClass;//修改缺省的类风格
return TRUE;
}
采用这种方法速度最快,也最省力。同时,还可以在PreCreateWindow()函数定义所
希望的任何窗口风格,如窗口大小,光标式样等。
三、使用单文档-多视结构
如果用户使用过MFC进行编程,那么就会发现借助于AppWizard基于MFC无论编写SDI
(单文档界面)还是编写MDI(多文档界面)都是十分方便的。MDI应用程序目前使用越
来越普遍,人们熟悉的Microsoft公司的Office系列产品以及Visual系列产品都是典
型的多文档应用程序。这种多文档界面具有多窗口的特点,因而人们可以在一个程
序中使用多个子窗口来实现不同数据的浏览查看。如果用户要实现在MDI各个窗口之
间针对同一数据进行不同的可视化就是一件比较麻烦的事情。值得庆幸的是,MFC提
供的文档-视结构大大简化了这一工作。文档-视结构通过将数据从用户对数据的观
察中分离出来,从而方便实现多视,亦即多个视口针对同一数据,如果一个视口中
数据发生改变,那么其它相关视口中的内容也会随之发生改变以反映数据的变化。
SDI和MDI这两种Windows标准应用程序框架并不是总能满足用户的需要,就作者的工
作而言,就特别需要一种被称为单文档多视的应用程序,英文可以缩写为SDMV。通
过SDMV应用我们可以利用文档类来统一管理应用程序的所有数据,同时需要采用多
窗口以多种方式来可视化这些的数据,如棒图,趋势图和参数列表,从而方便用户
从不同角度来观察数据。MDI虽然具有多窗口的特点,但是其为多文档,即通常情况
下,一个视口对应一个文档,视口+文档便构成一个子窗口。在各个子窗口之间数据
相互独立,如果要保持数据同步更新就需要采用特殊的技术了,采用这种方式既费
时又费力。通过笔者的实践发现,利用MFC本身提供的多视概念通过适当改造MDI窗
口应用程序就可以实现上述SDMV结构。
所谓SDMV应用程序本质上仍然是一个MDI应用程序,只是在程序中我们人为控制使其
只能生成一个文档类,这个文档在第一个视口创建时创建,注意,这里并不需要限
制各个视口的创建先后顺序。此后与MDI窗口固有特性不同的是,所有新创建的子窗
口都不再创建独立文档,而是把该新视口直接连接到已有的文档对象上,这样就使
其成为单文档多视的结构,所有相关数据都存储在文档对象中,一旦文挡中数据发
生改变,通过UpdateAllViews()函数通知所有相关视口,各个视口就可以在
OnUpdate()中相应数据的变化。这种响应机制如下图所示:

图 1 文档-视结构数据更新机制
由于MDI本质上并不是为这种单文档多视机制服务的,因而在实际应用时需要解决一
些问题。
1、窗口标题问题
窗口标题本来不应该成为问题,缺省情况下MDI窗口通过在文档模板中提供的资源ID
所提供的对应字符串来确定窗口标题。但是对于SDMV应用,由于各个视口实质上是
对应于同一个文挡,因此每个视口都具有相同标题,只不过增加了一个数据用于指
示这是第几个视口。如果在各个视口中指明具体的窗口名字,那么由不同的视口启
动创建文档产生的窗口标题就不同,这个名字会影响到后继视口。为了作到不同类
型的视口如棒图视口和曲线视口具有不同的标题,这就需要一定的技术处理。根据
笔者的摸索发现可以采用如下步骤实现:
首先在从标准的MDI子窗口基类CMDIChildWnd派生一个自己的子窗口类,姑且命名为
CMyChild,然后在其成员变量中增加一个CString型变量用以存储当前窗口标题:
CString winTitle;
然后在不同的视口创建过程中通过获取父窗口指针按自己的意愿对上述变量进行赋
值,程序片段如下:
pChild=(CMyChild*)GetParent();
pChild->winTitle="棒图显示窗口";
最后在CMyChild派生类中重载CMDIChildWnd基类中的OnUpdateFrameTitle()函数来
强制实现窗口标题的个性化,这一函数在各种类库手册上和联机帮助中都没有,但
的确有这样一个具有保护属性的函数用来实现窗口标题的更新操作,这可以从MFC类
库的源代码中找到该函数的实现。重载后的源代码如下:
void CMyChild::OnUpdateFrameTitle(BOOL bAddToTitle)
{
// update our parent window first
GetMDIFrame()->OnUpdateFrameTitle(bAddToTitle);

if ((GetStyle() & FWS_ADDTOTITLE) == 0)
return; // leave child window alone!

CDocument* pDocument = GetActiveDocument();
if (bAddToTitle && pDocument != NULL)
{
char szOld[256];
GetWindowText(szOld, sizeof(szOld));
char szText[256];

lstrcpy(szText,winTitle); //Modified by author!
if (m_nWindow > 0)
wsprintf(szText + lstrlen(szText), ":%d", m_nWindow);

// set title if changed, but don't remove completely
if (lstrcmp(szText, szOld) != 0)
SetWindowText(szText);
}
}
2、如何创建SDMV应用
如何创建SDMV应用比较麻烦,下面通过举例来具体说明。该例子假设用户需要建棒
图类型和曲线形式的两种视口,假设用户已经利用CView基类派生并且实现了这两个
类,分别对应于CMyChart和CMyTraceView两个类。
1) 在应用类(从CWinApp派生出来的类)的头文件中加入下列变量和函数原型说
明:
CMultiDocTemplate* m_pMyTraceTemplate;
CMultiDocTemplate* m_pMyChartTemplate;
int ExitInstance();
2) 在应用类的InitInstance成员函数中删除对AddDocTemplate函数的调用和
OpenFileNew()语句,并且加入如下代码:
m_pMyTraceTemplate = new CMultiDocTemplate(
IDR_MYTRACEVIEW,
RUNTIME_CLASS(CSimuDoc),
RUNTIME_CLASS(CMyChild), // Derived MDI child frame
RUNTIME_CLASS(CMyTraceView));

m_pMyChartTemplate = new CMultiDocTemplate(
IDR_MYCHART,
RUNTIME_CLASS(CSimuDoc),
RUNTIME_CLASS(CMyChild), // Derived MDI child frame
RUNTIME_CLASS(CMyChart));
3) 实现ExitInstance()函数,在其中删除所用的两个辅助模板:
int CTestApp::ExitInstance()
{
if(m_pMyChartTemplate) delete m_pMyChartTemplate;
if(m_pMyTraceTemplate) delete m_pMyTraceTemplate;
return TRUE;
}
4) 在菜单资源中去掉File菜单中的New和Open项,加入New Chart View和New
Trace View两项,在对应的菜单命令中实现如下:
void CMainFrame::OnNewMychart()
{
// TODO: Add your command handler code here
OnNewView(((CSimuApp*)AfxGetApp())->m_pMyChartTemplate);
}
void CMainFrame::OnNewMyTrace()
{
// TODO: Add your command handler code here
OnNewView(((CSimuApp*)AfxGetApp())->m_pMyTraceTemplate);
}
上中OnNewView的实现如下:
BOOL CMainFrame::OnNewView(CMultiDocTemplate* pDocTemplate)
{
CMDIChildWnd* pActiveChild = MDIGetActive();
CDocument* pDocument;
if (pActiveChild == NULL ||
(pDocument = pActiveChild->GetActiveDocument()) == NULL)
{
TRACE0("Now New the specify view\n");
ASSERT(pDocTemplate != NULL);
ASSERT(pDocTemplate->IsKindOf(RUNTIME_CLASS(CDocTemplate)));
pDocTemplate->OpenDocumentFile(NULL);
return TRUE;
}

// otherwise we have a new frame to the same document!
CMultiDocTemplate* pTemplate = pDocTemplate;
ASSERT_VALID(pTemplate);
CFrameWnd* pFrame = pTemplate->CreateNewFrame(pDocument, pActiveChild);
if (pFrame == NULL)
{
TRACE0("Warning: failed to create new frame\n");
return FALSE; // command failed
}
pTemplate->InitialUpdateFrame(pFrame, pDocument);
return TRUE;
}
OnNewView是整个SDMV应用的核心组成,它的任务是创建一个新的指定类型的视口,
它首先判断是否有活动视口存在,文档是否已经创建,正常情况下活动视口存在则
表明文档存在,如果不存在则利用所指定的文档模板创建一个新的活动视口,否则
则只创建视口,同时将其连接到已存在的文档对象上。
通过以上步骤就可以实现SDMV应用,在其后的具体应用中利用文档对象的
UpdateAllViews()函数和视口的OnUpdate()函数就可以很好的工作了。
四、使用DDE服务
Windows 3.x是一个分时多任务操作环境,在此环境下,多个应用程序可以并发地执
行。为了在并发执行的多个任务之间共享数据和资源,Windows 提供了几种机制,
主要是通过剪贴板(Clipboard)和动态数据交换(Dynamic Data Exchange)。前者对
于用户需要直接参与的数据交换来说,是一个非常方便的工具,但是如果希望数据
交换自动进行时就必须依靠DDE技术了。编写DDE应用的技术也发展了好几代,从最
初的基于消息的DDE到基于DDEML(动态数据交换管理库),再到现在流行的OLE技
术。DDE技术的发展使得程序开发人员编写DDE应用更为简洁。从发展趋势来看,基
于OLE的数据交换是最好的,它特别符合当今软件领域的客户-服务器机制
(Client-Server)。为适应多平台和Internet的需要,在OLE基础上微软又开发了
ActiveX技术。但是不容忽视的是,基于传统的DDE数据交换也自有它的应用空间,
使用仍然广泛。目前在Windows 3.x下,基于OLE的远程数据交换还很不成熟,但是
在WFW(Windows for Workgroup)下基于网络动态数据交换的技术却很成熟,目前也
应用非常普遍。关于DDE应用的开发和NetDDE的应用可以参看附录7。
1、回调函数的处理
由于DDEML机制需要使用回调函数,因此使用DDEML的关键是解决在MFC编程体系中回
调函数的使用。回调函数(Callback function)大量用于Windows的系统服务,通过
它,程序员可以安装设备驱动程序和消息过滤系统,以控制Windows的有效使用。
许多程序员都发现,利用MFC或者其它的C++应用编写回调函数是非常麻烦的,其根
本原因是回调函数是基于C编程的Windows SDK的技术,不是针对C++的,程序员可以
将一个C函数直接作为回调函数,但是如果试图直接使用C++的成员函数作为回调函
数将发生错误,甚至编译就不能通过。通过查询资料发现,其错误是普通的C++成员
函数都隐含了一个传递函数作为参数,亦即“this”指针,C++通过传递一个指向自
身的指针给其成员函数从而实现程序函数可以访问C++的数据成员。这也可以理解为
什么C++类的多个实例可以共享成员函数但是确有不同的数据成员。由于this指针的
作用,使得将一个CALLBACK型的成员函数作为回调函数安装时就会因为隐含的this
指针使得函数参数个数不匹配,从而导致回调函数安装失败。要解决这一问题的关
键就是不让this指针起作用,通过采用以下两种典型技术可以解决在C++中使用回调
函数所遇到的问题。这种方法具有通用性,适合于任何C++。
1. 不使用成员函数,直接使用普通C函数,为了实现在C函数中可以访问类的成员变
量,可以使用友元操作符(friend),在C++中将该C函数说明为类的友元即可。这种
处理机制与普通的C编程中使用回调函数一样。
2. 使用静态成员函数,静态成员函数不使用this指针作为隐含参数,这样就可以作
为回调函数了。静态成员函数具有两大特点:其一,可以在没有类实例的情况下使
用;其二,只能访问静态成员变量和静态成员函数,不能访问非静态成员变量和非
静态成员函数。由于在C++中使用类成员函数作为回调函数的目的就是为了访问所有
的成员变量和成员函数,如果作不到这一点将不具有实际意义。解决的办法也很简
单,就是使用一个静态类指针作为类成员,通过在类创建时初始化该静态指针,如
pThis=this,然后在回调函数中通过该静态指针就可以访问所有成员变量和成员函
数了。这种处理办法适用于只有一个类实例的情况,因为多个类实例将共享静态类
成员和静态成员函数,这就导致静态指针指向最后创建的类实例。为了避免这种情
况,可以使用回调函数的一个参数来传递this指针,从而实现数据成员共享。这种
方法稍稍麻烦,这里就不再赘述。
2、在MFC中使用DDEML
对于典型的MFC应用程序,主框架窗口类(CMainFrame)只有一个实例,因此可以使用
静态成员函数作为回调函数,从而实现DDE机制。具体的代码片段如下:
(1) 在CMainFrame类中声明如下静态成员:
static CMainFrame* pThis;
static DWORD idInst;
static HDDEDATA CALLBACK EXPORT DdeCallback(UINT,UINT,HCONV,HSZ,HSZ, HDDEDATA,DWORD,DWORD);
(2) 在类的创建代码(OnCreate())中作如下说明:
pThis=this;
lpDdeCallback=MakeProcInstance((FARPROC)DdeCallback,hInstance);
if(DdeInitialize(&idInst,(PFNCALLBACK)lpDdeCallback,CBF_FAIL_EXECUTES
|CBF_SKIP_REGISTRATIONS|CBF_SKIP_UNREGISTRATIONS,0L))
{
AfxMessageBox("不能初始化DDE服务","错误");
DestroyWindow();
}
(3) 回调函数实现如下:
HDDEDATA FAR PASCAL _export CMainFrame::DdeCallback(UINT iType,UINT iFmt, HCONV hConv,HSZ hsz1,HSZ hsz2,HDDEDATA hData,DWORD dwData1,DWORD dwData2)
{
char szBuffer[16];
int i;

switch(iType)
{
case XTYP_CONNECT: //hsz1=topiv, hsz2=service
return (HDDEDATA)TRUE;//TRUE;
case XTYP_ADVSTART: //hsz1=topic, hsz2=item
case XTYP_REQUEST:
case XTYP_ADVREQ:
case XTYP_POKE: //hsz1=Topic, hsz2=item, hData=data
case XTYP_ADVSTOP:
return NULL;
}
}
3、避免变量类型冲突
如果在MFC应用直接使用DDEML服务,那么该MFC应用在编译时将会遇到变量类型HSZ
重复定义错误。经过追踪发现,错误在于在DDEML.H对HSZ作了如下定义:
DECLARE_HANDLE32(HSZ);
而在AFXEXT.H(通过stdafx.h引入)中对HSZ又作了如下说明:
typedef BPSTR FAR* HSZ; // Long handle to a string
两个定义一个为32位整数,一个为BASIC字符串指针,当然会发生编译器不能作变量
类型转换的错误。实际上,将HSZ声明为BASIC字符串指针主要用于在MFC应用中使用
VBX控制。要改正这一错误,就必须保证不要在同一个代码模块中使用DDEML和VBX支
持,通过将使用DDEML和VBX的代码分开,并在使用DDEML代码的模块中最开头定义如
下编译器宏就可以解决上述问题:
#define NO_VBX_SUPPORT
五、使用3D控制
毫无疑问,3D控制的使用可以显著提高Windows应用程序的界面友好性,目前,许多
流行的Windows应用程序都使用了3D控制,典型的如Microsoft公司的Office系列软
件,而且,在Windows 95和Windows NT 4.0中,3D控制更是作为操作系统的一部分
直接提供,这意味着在其上运行的软件不需要作任何特殊处理,就具有3D界面效
果,但是,很遗憾的是,在Windows 3.x中,除了命令按钮控制使用3D控制以外,其
余所有的控制,如编辑框,列表框,检查框等都只使用2D控制,要想使用3D控制,
程序设计人员就必须在自己的程序中作一定的修改,考虑到目前3D效果的流行,这
点努力是值得的。
为了支持3D效果,Microsoft公司提供了一个专门用于3D控制的动态连接库,即
CTL3D.DLL,但是在其Visual C++中却没有如何使用3D控制的讨论,并且,Visual
C++也不直接支持3D编码,因为它不包括使用3D控制所必须的头文件。但是,这并不
意味着在Visual C++中不能使用3D控制,只不过用户需要从其它地方获取技术支持
罢了。由于使用的是动态连接库机制,因此,任何其它语言提供的3D头文件和
CTL3D.DLL的输入库都是可用的。作者使用的就是Borland公司的Borland C++中提供
的CTL3D.H和CTL3D.LIB。在C/C++中使用3D控制的方法也有很多种,在这里,为节约
篇幅,只讨论与本文相关的主题,即使用MFC编程时如何使用3D控制。
在MFC的所有对话框中使用3D控制可以遵循如下步骤:
1. 在CWinApp::InitInstance函数中调用Ctl3dRegister和Ctl3dAutosubclass函
数:
Ctl3dRegister(AfxGetInstanceHandle());
Ctl3dAutoSubclass(AfxGetInstanceHandle());
值得一提的是,在AppWizard产生的应用框架的CWinApp::InitInstance中有一个函
数调用为SetDialogBkColor,此函数的作用是将所有对话框的背景颜色设置为灰
色,这个功能与3D界面实现相同的功能,可以移去此语句。
由于CTL3D在初始化时读入所有的系统颜色并自己维持,为了使应用程序能够正确反
映系统颜色的变化,MFC应用程序可以在WM_SYSCOLORCHANGE消息中调用
Ctl3dColorChange函数。
2. 在MFC应用程序的CWinApp类中的ExitInstance函数中调用Ctl3dUnregister函
数,以方便Windows对CTL3D库的正确管理。
3. 在MFC应用程序的项目文件中加入CTL3D.LIB(可以用IMPORT.EXE产生)。
使用上述CTL3D的自动子类化的机制可以大大简化使用3D控制,如果这不满足你的要
求,那么你就必须单独在需要使用3D控制的对话框的OnInitDialog()中自行子类化
相关的控制类了,典型的如下代码片断所示:
BOOL CMyDialog::OnInitDialog()
{
Ctl3dSubclassDlgEx(m_hWnd,CTL3D_ALL);
return TRUE;
}
上面讲了在对话框中使用3D效果的办法,如果用户想在非对话框中使用3D控制,典
型的在FormView导出类中使用,可以在导出类的OnInitialUpdate函数中进行适当修
改,修改的大小取决于你是否使用了3D控制的自动子类化机制。如果使用前面提到
的自动子类化方法,那么仅需要在相应的OnInitialUpdate函数中调用
Ctl3dSubclassDlg函数了,如下代码片断所示:
void CMyView::OnInitialUpdate()
{
Ctl3dSubclassDlg(m_hWnd,CTL3D_ALL);
}
否则,则需要修改如下:
void CMyView::OnInitialUpdate()
{
Ctl3dSubclassDlgEx(m_hWnd,CTL3D_ALL);
}
六、使用自定义消息
1、MFC的消息映射机制
Windows是一个典型的消息驱动的操作系统,程序的运行是靠对各种消息的响应来实
现的,这些消息的来源非常广泛,既包括Windows系统本身,如WM_CLOSE、
WM_PAINT、WM_CREATE和WM_TIMER等常用消息,又包括用户菜单选择、键盘加速
键以及工具条和对话框按钮等等,如果应用程序要与其它程序协同工作,那么消息的来
源还包括其它应用程序发送的消息,串行口和并行口等硬件发送的消息等等。总
之,Windows程序的开发是围绕着对众多消息的合理响应和实现来实现程序的各种功
能的。使用过C语言来开发Windows程序的人都知道,在Windows程序的窗口回调函数
中需要安排Switch语句来响应大量的消息,同时由于消息的间断性使得不同的消息
响应之间信息的传递是通过大量的全局变量或者静态数据来实现的。
人们常用的两种类库OWL和MFC都提供了消息映射机制用以加速开发速度,使用者只
需要按规定定义好对应消息的处理函数自身即可,至于实际调用由类库本身所提供
的机制进行,或采用虚函数,或采用消息映射宏。为了有效节约内存,MFC并不大量
采用虚函数机制,而是采用宏来将特定的消息映射到派生类中的响应成员函数。这
种机制不但适用于Windows自身的140条消息,而且适用于菜单命令消息和按钮控制
消息。MFC提供的消息映浠剖欠浅G看蟮模市碓诶嗟母鞲霾愦紊隙韵⒔?br> 控制,而不简单的局限于消息产生者本身。在应用程序接收到窗口命令时,MFC将按
如下次序寻找相应的消息控制函数:
SDI应用
MDI应用
视口
视口
文档
文档
SDI主框架
MDI子框架
应用
MDI主框架

应用
大多数应用对每一个命令通常都只有一个特定的命令控制函数,而这个命令控制函
数也只属于某一特定的类,但是如果在应用中对同一消息有多个命令控制函数,那
么只有优先级较高的命令控制函数才会被调用。为了简化对常用命令的处理,MFC在
基类中提供并实现了许多消息映射的入口,如打印命令,打印预览命令,退出命令
以及联机帮助命令等,这样在派生类中就继承了所有的基类中的消息映射函数,从
而可以大大简化编程。如果我们要在自己派生类中实现对消息的控制,那么必须在
派生类中加上相应的控制函数和映射入口。
2、使用自己的消息
在程序设计的更深层次,人们常常会发现只依赖于菜单和命令按钮产生的消息是不
够的,常常因为程序运行的逻辑结构和不同视口之间数据的同步而需要使用一些自
定义的消息,这样通过在相应层次上安排消息响应函数就可以实现自己的特殊需
要。比如如果我们要在特定的时间间隔内通知所有数据输出视口重新取得新数据,
要依靠菜单命令和按钮命令实现不够理想,比较理想的解决办法是采用定时器事件
进行特定的计算操作,操作完成后再采用SendMessage发送自己的特定消息,只有当
这一消息得到处理后才会返回主控程序进行下一时间计算。通过在文档层次上安排
对消息的响应取得最新计算数据,而后通过UpdateAllViews()成员函数来通知所有
相关视口更新数据的显示。视口通过重载OnUpdate()成员函数就可以实现特定数据
的更新显示。
如果用户能够熟练使用SendMessage()函数和PostMessage()函数,那么要发送自定
义消息并不难,通常有两种选择,其一是发送WM_COMMAND消息,通过消息的WORD
wParam参数传递用户的命令ID,举例如下:
SendMessage(WM_COMMAND,IDC_GETDATA,0); //MFC主框架发送
然后在文档层次上安排消息映射入口:
ON_COMMAND(IDC_GETDATA, OnGetData)
同时在文档类中实现OnGetData()函数:
void CSimuDoc::OnGetData()
{
TRACE("Now in SimuDoc,From OnGetData\n");
UpdateAllViews(NULL);
}
注意在上中的消息映射入口需要用户手工加入,Visual C++提供的ClassWizard并不
能替用户完成这一工作。上中例子没有使用PostMessage函数而使用SendMessage函
数的原因是利用了SendMessage函数的特点,即它只有发送消息得到适当处理后方才
返回,这样有助于程序控制。
另一种发送自定义消息的办法是直接发送命令ID,在控制层次上采用ON_MESSAGE来
实现消息映射入口,注意这时的命令控制函数的原型根据Windows本身消息处理的规
定必须如下:
afx_msg LONG OnCaculationOnce(WPARAM wParam,LPARAM lParam);
相对来讲,这种机制不如上述机制简单,也就不再赘述。
七、使用不带文挡-视结构的MFC应用
文档-视结构的功能是非常强大的,可以适合于大多数应用程序,但是有时我们只需
要非常简单的程序,为了减少最终可执行文件尺寸和提高运行速度,我们没有必要
使用文挡-视结构,典型的有简单SDI应用和基于对话框的应用。
1、简单SDI应用
此时只需要使用CWinApp和CFrameWnd两个类就完全可以了。由于CWinApp类封装了
WinMain函数和消息处理循环,因此任何使用MFC进行编程的程序都不能脱离开该
类。实际上使用CWinApp类非常简单,主要是派生一个用户自己的应用类,如
CMyApp,然后只需重载CWinApp类的InitInstance()函数:

BOOL CMyApp::InitInstance()
{
m_pMainWnd=new CMainFrame();
ASSERT(m_pMainWnd!=NULL); //error checking only
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
至于所需要的主框架类,则可以直接使用ClassWizard实用程序生成,该类的头文件
与实现代码可以与CMyApp类的头文件和实现代码放在一起。注意,这里由一个技
巧,由于ClassWizard的使用需要有相应的CLW文件存在,而收工建代码时没有对应
的CLW文件,因此不能直接使用,解决办法是进入App Studio实用工具后使用
ClassWizard,此时系统会发觉不存在相应的CLW文件,系统将提示你重建CLW文件并
弹出相应对话框,这时候你不需要选择任何文件就直接选择OK按钮,这样系统将为
你产生一个空的CLW文件,这样就可以使用ClassWizard实用工具了。为了将CWinApp
和CFrameWnd的派生类有机地结合在一起,只需在CFrameWnd派生类的构造函数中进
行窗口创建即可。典型代码如下:
CMainFrame::CMainFrame()
{
Create(NULL,"DDE Client Application",WS_OVERLAPPEDWINDOW,rectDefault,
NULL,MAKEINTRESOURCE(IDR_MAINFRAME));
}
采用ClassWizard实用程序生成相关类代码后,所有的类的其它实现和维护就同普通
由AppWizard实用程序产生的代码一样了。
2、基于对话框的程序
有些主要用于数据的输入和输出等的应用在使用时没有必要改变窗口大小,典型的
如各种联机注册程序,这些使用对话框作为应用的主界面就足够了,而且开发此类
应用具有方便快捷的特点,代码也比较短小,如果直接采用各种控制类生成所需要
的控制就特别麻烦。在Visual C++ 4.x版本中使用AppWizard就可以直接生成基于对
话框的应用。在Visual 1.x中没有此功能,因此这类应用需要程序员自己实现。
实际上使用MFC实现基于对话框的应用非常简单,同样只使用两个MFC类作为基类,
这两个类为CWinApp类和CDialog类。所使用的对话框主界面同样可以先用App
Studio编辑对话框界面,再使用ClassWizard产生相应代码框架,然后修改CMyApp类
的声明,增加一个该对话框类的成员变量m_Mydlg,最后修改CMyApp类的
InitInstance()函数如下:
BOOL CMyApp::InitInstance()
{
m_Mydlg.DoModal();
return TRUE;
}
八、MFC应用的人工优化
使用C/C++编写Windows程序的优点就是灵活高效,运行速度快,Visual C++编译器
本身的优化工作相当出色,但这并不等于不需要进行适当的人工优化,为了提高程
序的运行速度,程序员可以从以下几方面努力:
1) 减少不必要的重复显示
相对来讲,Windows的GDI操作是比较慢的,因此在程序中我们应该尽可能地控制整
个视口的显示和更新,如果前后两此数据不发生变化,那么就不要重新进行视口的
GDI图形操作,尤其对于背景图显示时非万不得已时不要重绘,同时不要经常五必要
的刷新整个窗口。
2) 在视口极小化时不要进行更新屏幕操作
在窗口处于极小化时没有必要继续进行视口更新工作,这样可以显著提高速度。为
此需要在子窗口一级捕获上述信息(视口不能捕获该类信息),再在视口中进行相
应操作。如下代码片段所示:
首先在子窗口类中添加如下程序段:
void CMyChild::OnSysCommand(UINT nID,LPARAM lparam)
{
CMDIChildWnd::OnSysCommand(nID,lparam);
if(nID==SC_MINIMIZE){
RedrawFlag=0;
}
else
RedrawFlag=1;
}
再在视口更新时中修改如下:
void CMyChart::OnUpdate( CView* pSender, LPARAM lHint, CObject* pHint )
{
if(pChild->RedrawFlag)
{
InvalidateRect(&r,FALSE);
TRACE("Now In CMyChart::OnUpdate\n");
}
}
至于上中pChild指针可以在视口创建的例程中获取:
pChild=(CMyChild*)GetParent();
3) 使用永久性的资源
在频繁进行GDI输出的视口中,如在监控软件中常常使用的趋势图显示和棒图显示等
等,应该考虑在类层次上建立频繁使用的每种画笔和刷子,这可以避免频繁的在堆
中创建和删除GDI对象,从而提高速度。
4) 使用自有设备描述句柄
亦即在创建视口时通过指定WM_OWNDC风格来拥有自己的显示设备句柄,这虽然会多
消耗一些内存,一个DC大约占800字节的内存,但是这避免了每次进行GDI操作前创
建并合理初始化显示设备句柄这些重复操作。特别是要自定义坐标系统和使用特殊
字体的视口这一点尤其重要。在16M机器日益普遍的今天为了节约一点点内存而降低
速度的做法并不可取。
5) 优化编译时指定/G3选项和/FPix87选项
/G3选项将强迫编译器使用386处理器的处理代码,使用嵌入式协处理器指令对那些
频繁进行浮点运算的程序很有帮助。采用这两种编译开关虽然提高了对用户机型的
要求,但在386逐渐被淘汰,486市场大幅度萎缩,586市场日益普及的今天上述问题
已经不再成为问题了。
九、结束语
总体上讲,使用Visual C++和MFC类库进行Windows编程是非常方便的,本文中所提
到的一些看法只代表本人的观点,经验也只是笔者根据近年使用MFC进行Windows编
程的总结,在此写出来是希望对那些使用VC和MFC进行Windows编程的同行有所帮
助,如有不同看法欢迎与笔者联系讨论。
十、参考文献:
[1]. David J.Kruglinski ,Visual C++技术内幕,清华大学出版社,1995
[2]. 郑雪明,Visual C++基础类库参考大全,学苑出版社,1994
[3]. B.R. Overland,Visual C++程序设计精髓,科学出版社,1995
[4]. Mike Klein,Windows程序员使用指南--DLL和内存管理,清华大学出版社,
1995
[5]. Richard Wilton,Microsoft Windows软件开发环境与技术, 清华大学出版
社,1993
[6]. 芶建兵,倪维斗,Windows下网络DDE的使用,电子与电脑,1997.2

 

        回到页顶 

posted @ 2007-07-05 16:54 高山流水 阅读(1372) | 评论 (0)编辑 收藏

基本要求

1.1 程序结构清析,简单易懂,单个函数的程序行数不得超过100行。
1.2 打算干什么,要简单,直接了当,代码精简,避免垃圾程序。
1.3 尽量使用标准库函数和公共函数。
1.4 不要随意定义全局变量,尽量使用局部变量。
1.5 使用括号以避免二义性。

2.可读性要求
2.1 可读性第一,效率第二。
2.2 保持注释与代码完全一致。
2.3 每个源程序文件,都有文件头说明,说明规格见规范。
2.4 每个函数,都有函数头说明,说明规格见规范。
2.5 主要变量(结构、联合、类或对象)定义或引用时,注释能反映其含义。
2.7 常量定义(DEFINE)有相应说明。
2.8 处理过程的每个阶段都有相关注释说明。
2.9 在典型算法前都有注释。
2.10 利用缩进来显示程序的逻辑结构,缩进量一致并以Tab键为单位,定义Tab为 6个
字节。
2.11 循环、分支层次不要超过五层。
2.12 注释可以与语句在同一行,也可以在上行。
2.13 空行和空白字符也是一种特殊注释。
2.14 一目了然的语句不加注释。
2.15 注释的作用范围可以为:定义、引用、条件分支以及一段代码。
2.16 注释行数(不包括程序头和函数头说明部份)应占总行数的 1/5 到 1/3 。


3. 结构化要求

3.1 禁止出现两条等价的支路。
3.2 禁止GOTO语句。
3.3 用 IF 语句来强调只执行两组语句中的一组。禁止 ELSE GOTO 和 ELSE RETURN。
3.4 用 CASE 实现多路分支。
3.5 避免从循环引出多个出口。
3.6 函数只有一个出口。
3.7 不使用条件赋值语句。
3.8 避免不必要的分支。
3.9 不要轻易用条件分支去替换逻辑表达式。

4. 正确性与容错性要求

4.1 程序首先是正确,其次是优美
4.2 无法证明你的程序没有错误,因此在编写完一段程序后,应先回头检查。
4.3 改一个错误时可能产生新的错误,因此在修改前首先考虑对其它程序的影响。
4.4 所有变量在调用前必须被初始化。
4.5 对所有的用户输入,必须进行合法性检查。
4.6 不要比较浮点数的相等,
如: 10.0 * 0.1 == 1.0 , 不可靠
4.7 程序与环境或状态发生关系时,必须主动去处理发生的意外事件,如文件能否
逻辑锁定、打印机是否联机等。
4.8 单元测试也是编程的一部份,提交联调测试的程序必须通过单元测试。

5. 可重用性要求

5.1 重复使用的完成相对独立功能的算法或代码应抽象为公共控件或类。
5.2 公共控件或类应考虑OO思想,减少外界联系,考虑独立性或封装性。
5.3 公共控件或类应建立使用模板。

附:C++ 编程规范,delphi作相应的参考


.1适用范围

本标准适用于利用Visul C++ ,Borland C++进行软件程序开发的人员.。



.2变量命名

命名必须具有一定的实际意义,形式为xAbcFgh,x由变量类型确定,Abc、Fgh表示连续意
义字符串,如果连续意义字符串仅两个,可都大写.如OK.

具体例程:

BOOL类型 bEnable;



ch * char chText
c * 类对象 cMain(对象实例)
h * Handle(句柄) hWnd
i * int
n * 无符号整型
p * 指针
sz,str * 字符串
w WORD
x,y 坐标

Char或者TCHAR类型 与Windows API有直接联系的用szAppName[10]形式否则用
FileName[10]形式,单个字符也可用小写字母表示;

Int类型 nCmdShow;

LONG类型 lParam;

UINT类型 uNotify; 



DWORD类型 dwStart;

PSTR类型 pszTip;

LPSTR类型 lpCmdLine

LPTSTR类型 lpszClassName;

LPVOID类型 lpReserved

WPARAM类型 wParam,

LPARAM类型 lParam

HWND类型 hDlg;

HDC类型 hDC;

HINSTANCE类型 hInstance

HANDLE类型 hInstance,

HICON类型 hIcon;

int iTmp

float fTmp

DWORD dw*

String , AnsiString str *

m_ 类成员变量 m_nVal, m_bFlag
g_ 全局变量 g_nMsg, g_bFlag

局部变量中可采用如下几个通用变量:nTemp,nResult,I,J(一般用于循环变量)。

其他资源句柄同上

.3常量命名和宏定义

常量和宏定义必须具有一定的实际意义;

常量和宏定义在#include和函数定义之间;

常量和宏定义必须全部以大写字母来撰写,中间可根据意义的连续性用下划线连接,每一
条定义的右侧必须有一简单的注释,说明其作用;

资源名字定义格式:

菜单:IDM_XX或者CM_XX

位图:IDB_XX

对话框:IDD_XX

字符串:IDS_XX

DLGINIT:DIALOG_XX

ICON:IDR_XX

.4函数命名

函数原型说明包括引用外来函数及内部函数,外部引用必须在右侧注明函数来源: 模
块名及文件名, 如是内部函数,只要注释其定义文件名;

第一个字母必须使用大写字母,要求用大小写字母组合规范函数命名,必要时可用下划线
间隔,示例如下:

void UpdateDB_Tfgd (TRACK_NAME); //Module Name :r01/sdw.c

void PrintTrackData (TRACK_NAME); //Module Name :r04/tern.c

void ImportantPoint (void); //Module Name :r01/sdw.c

void ShowChar (int , int , chtype); //Local Module

void ScrollUp_V (int , int); //Local Module

.5结构体命名

结构体类型命名必须全部用大写字母,原则上前面以下划线开始;结构体变量命名必须用
大小写字母组合,第一个字母必须使用大写字母,必要时可用下划线间隔。对于私有数
据区,必须注明其所属的进程。全局数据定义只需注意其用途。

示例如下:

typedef struct

{

char szProductName[20];

char szAuthor[20];


char szReleaseDate[16];

char szVersion[10]; 


unsigned long MaxTables;

unsigned long UsedTables;

}DBS_DATABASE;

DBS_DATABASE GdataBase;



6 控件的命名:
用小写前缀表示类别

用小写前缀表示类别:
fm 窗口
cmd 按钮
cob combo,下拉式列表框
txt 文本输入框
lab labal,标签
img image,图象
pic picture
grd Grid,网格
scr 滚动条
lst 列表框
frm fram



7注释

原则上注释要求使用中文;

文件开始注释内容包括:公司名称、版权、作者名称、时间、模块用途、背景介绍等,复
杂的算法需要加上流程说明;

函数注释包括:输入、输出、函数描述、流程处理、全局变量、调用样例等,复杂的函数
需要加上变量用途说明;

程序中注释包括:修改时间和作者、方便理解的注释等;





引用一: 文件开头的注释模板

/******************************************************************

** 文件名:

** Copyright (c) 1998-1999 *********公司技术开发部

** 创建人:

** 日 期:

** 修改人:

** 日 期:

** 描 述:

**

** 版 本:

**--------------------------------------------------------------------------
---





******************************************************************/



引用二: 函数开头的注释模板

/*****************************************************************

** 函数名:

** 输 入: a,b,c

** a---

** b---

** c---

** 输 出: x---

** x 为 1, 表示...

** x 为 0, 表示...

** 功能描述:

** 全局变量:

** 调用模块:

** 作 者:

** 日 期:

** 修 改:

** 日 期:

** 版本

****************************************************************/

引用三: 程序中的注释模板

/*----------------------------------------------------------*/

/* 注释内容 */

/*----------------------------------------------------------*/

8 程序

a. 程序编码力求简洁,结构清晰,避免太多的分支结构及太过于技巧性的程序,
尽量不采用递归模式。

b. 编写程序时,亦必须想好测试的方法,换句话说,”单元测试” 的测试方案应
在程序编写时一并拟好。

c. 注释一定要与程序一致。

d. 版本封存以后的修改一定要将老语句用/* */ 封闭,不能自行删除或修改,并要
在文件及函数的修改记录中加以记录。

e. 程序中每个block 的开头 ”{" 及 "}” 必须对齐,嵌套的block 每进一套,
缩进一个tab,TAB 为4个空格,block类型包括if、for、while、do等关键字引出的。

f. 对于比较大的函数,每个block 和特殊的函数调用,都必须注明其功能,举例如下



count.divisor = 1193280 / freq; // compute the proper count

OutByte((unsigned short)67, (unsigned char)182); // tell 8253 that a
count is coming

OutByte((unsigned short)66, count. c[0]); // send low-order byte

OutByte((unsigned short)66, count. c[1]); // send high-order byte



×××××××××××××××××××××××××××××××××××××××

bcb,delphi中的变量命名:

遵循匈牙利命名法,命
名必须有意义,制定如下规定

窗体: 以大写的W开始,如About版权窗体, 命名为WAbout

文件:以大写的F开始,如About版权窗体,文件命名为FAbout.cpp

按钮(Button):如退出按钮,命名为btnExit

……

基类: 加base标记,如报表基类,窗体命名为:WBaseRep, 文件命名为FBaseRep.cpp 

posted @ 2007-07-05 16:53 高山流水 阅读(455) | 评论 (0)编辑 收藏

有多种病毒会把一些重要文件隐藏起来,下面看看如何解决中病毒后不能/无法显示隐藏文件的问题,象落雪病毒就会引起这种现象,不能/无法显示隐藏文件是因为病毒修改了注册表的某些键值,这时我们可以采取下面的方法来显示隐藏文件

第一种解决不能/无法显示隐藏文件的方法: 把下面内容复制到记事本,保存为 1.reg文件于任何地方,然后双击就搞定了。
 
REGEDIT4

[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\explorer\Advanced\Folder\Hidden]
"Text"="隐藏文件"
"Type"="group"
"Bitmap"="C:\\WINDOWS\\SYSTEM\\SHDOC401.DLL,4"
"HelpID"="update.hlp#51131"

[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\explorer\Advanced\Folder\Hidden\SHOWALL]
"RegPath"="Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced"
"Text"="显示所有文件"
"Type"="radio"
"CheckedValue"=dword:00000000
"ValueName"="Hidden"
"DefaultValue"=dword:00000000
"HKeyRoot"=dword:80000001
"HelpID"="update.hlp#51105"

[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\explorer\Advanced\Folder\Hidden\NOHIDDEN]
"RegPath"="Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced"
"Text"="不显示隐藏文件"
"Type"="radio"
"CheckedValue"=dword:00000000
"ValueName"="Hidden"
"DefaultValue"=dword:00000000
"HKeyRoot"=dword:80000001
"HelpID"="update.hlp#51104"

[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\explorer\Advanced\Folder\Hidden\NOHIDORSYS]
"RegPath"="Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced"
"Text"="不显示隐藏文件或系统文件"
"Type"="radio"
"CheckedValue"=dword:00000000
"ValueName"="Hidden"
"DefaultValue"=dword:00000000
"HKeyRoot"=dword:80000001
"HelpID"="update.hlp#51103"
[/code]
显示隐藏文件:
[code]
REGEDIT4

[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\explorer\Advanced\Folder\Hidden]
"Text"="隐藏文件"
"Type"="group"
"Bitmap"="C:\\WINDOWS\\SYSTEM\\SHDOC401.DLL,4"
"HelpID"="update.hlp#51131"

[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\explorer\Advanced\Folder\Hidden\SHOWALL]
"RegPath"="Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced"
"Text"="显示所有文件"
"Type"="radio"
"CheckedValue"=dword:00000001
"ValueName"="Hidden"
"DefaultValue"=dword:00000000
"HKeyRoot"=dword:80000001
"HelpID"="update.hlp#51105"

[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\explorer\Advanced\Folder\Hidden\NOHIDDEN]
"RegPath"="Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced"
"Text"="不显示隐藏文件"
"Type"="radio"
"CheckedValue"=dword:00000002
"ValueName"="Hidden"
"DefaultValue"=dword:00000000
"HKeyRoot"=dword:80000001
"HelpID"="update.hlp#51104"

[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\explorer\Advanced\Folder\Hidden\NOHIDORSYS]
"RegPath"="Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced"
"Text"="不显示隐藏文件或系统文件"
"Type"="radio"
"CheckedValue"=dword:00000000
"ValueName"="Hidden"
"DefaultValue"=dword:00000000
"HKeyRoot"=dword:80000001
"HelpID"="update.hlp#51103"



我们还可以用下面的方法解决不能/无法显示隐藏文件的问题,具体如下:
第二种方法:
 有时候系统中病毒以后(例如sxs.exe和lsass(落雪病毒)),杀毒软件无法杀毒,或

者没有杀毒软件.这时就需要手动杀毒.这时往往需要删除病毒文件,病毒文件为了

保护自己,总是把自己隐藏起来.把文件属性设置成隐藏,一般的病毒我们通过修改

菜单:工具--文件夹选项--查看--显示隐藏文件 即可.但是很多病毒通过修改注册

表使我们这步操作失效,还是无法看到隐藏文件,下面的操作就是教我们如何通过

修改注册表让隐藏的文件原形毕露。

首先要显示出被隐藏的系统文件

运行——regedit

HKEY_LOCAL_MACHINE\Software\Microsoft\windows\CurrentVersion\explorer\A

dvanced\Folder\Hidden\SHOWALL,将CheckedValue键值修改为1

但可能依然没有用,隐藏文件还是没有显示,这是因为病毒在修改注册表达到隐

藏文件目的之后,把本来有效的DWORD值CheckedValue删除掉,新建了一个无效的

字符串值CheckedValue,并且把键值改为0!

方法:删除此CheckedValue键值,单击右键 新建——Dword值——命名为

CheckedValue,然后修改它的键值为1,这样就可以选择“显示所有隐藏文件”和

“显示系统文件”。 

posted @ 2007-06-18 14:58 高山流水 阅读(6045) | 评论 (16)编辑 收藏

     摘要: 什么是系统进程?它能做什么?   进程是程序在计算机上的一次执行活动。当你运行一个程序,你就启动了一个进程。显然,程序是死的(静态的),进程是活的(动态的)。进程可以分为系统进程和用户进程。凡是用于完成操作系统的各种功能的进程就是系统进程,它们就是处于运行状态下的操作系统本身;用户进程就是所有由你启动的进程。进程是操作系统进行资源分配的单位。 ...  阅读全文

posted @ 2007-06-18 14:17 高山流水 阅读(759) | 评论 (0)编辑 收藏

前一段用了mscomm控件编写程序,但是部署到新的设备上时需要手工注册控件,很是麻烦,能不能编写一个Winapi的程序自动注册呢?所以就自己写了一个程序。

原理:如何手工来注册安装MSComm控件。

 

  第一步:将Mscomm.srg, Mscomm32.ocx,Mscomm32.dep三个文件复制到系统文件夹中。要注意的是,MSComm控件是要授权的,所以必须将其使用“执照”Licence 在注册表中登记注册,下一步就是注册方法。至于为什么要这样做,可以看看下面的网页:http://support.microsoft.com/support/kb/articles/q151/7/71.asp

  

  第二步:用Windows下的注册工具regsvr32注册该OCX控件,点击“开始”->"运行",再在中填入(假设操作安装在C盘,WIN2000):

      Regsvr32  C:\winnt\system32\Mscomm32.ocx

 

    第三步:在注册表中手工新建一个主键项:先在点击“开始”->"运行",再在中填入regedit命令打开注册表,找到HKEY_CLASSES_ROOT\Licenses,在其中添加主键
4250E830-6AC2-11cf-8ADB-00AA00C00905 并将内容设置为:

       kjljvjjjoquqmjjjvpqqkqmqykypoqjquoun

   (注:这项内容也可以用记事本程序打开Mscomm.srg文件看到)

这是手工注册的过程,非常繁琐。我得程序也是按照这个顺序执行的。

源代码:

//
#include <windows.h>
#include <stdio.h>
#include <string.h>

void CPFile(char file);
void regsted();
void regOCX();

void CPFile(char file[],char tarpath[]) //将三个文件拷贝到系统目录
{
 char tempsys[100];
    char *r;
 char *t;

 r=tarpath;
 t=tempsys;
 strcpy(t,r);

 char path[256];
 char *p;
 char *q;
    GetModuleFileName(GetModuleHandle(NULL),path,sizeof(path));
 
    p = path;
 while(strchr(p,'\\'))
 {
  p = strchr(p,'\\');   
        p++; 
 }
    *p = '\0';


 p=strchr(path,'\0');
    q=file;
 strcpy(p,q);
   
    p=strchr(tempsys,'\0');
 *p = '\\';
  p++;


    q=file;
 strcpy(p,q);
   
 CopyFile(path,tempsys,FALSE);

}

void regsted()   //将相关信息写入注册表
{
 HKEY hKey;
    DWORD dwDip;
 LPBYTE owner_Get=new BYTE[80];
 DWORD type_1=REG_SZ;
 DWORD cbData_1=80;
 long exist=RegQueryValueEx(HKEY_CLASSES_ROOT, "Licenses\\4250E830-6AC2-11cf-8ADB-00AA00C00905", NULL, &type_1, owner_Get, &cbData_1);

    if(exist!=ERROR_SUCCESS)
 {
   long ret =  RegCreateKeyEx(HKEY_CLASSES_ROOT,"Licenses\\4250E830-6AC2-11cf-8ADB-00AA00C00905",0l,NULL,REG_OPTION_VOLATILE,KEY_ALL_ACCESS,NULL,&hKey,&dwDip);
         DWORD leng=37;

   char key[37]="kjljvjjjoquqmjjjvpqqkqmqykypoqjquoun";
         LPBYTE lpb=new BYTE(37);
         for(int i=0;i<37;i++)
      lpb[i]=key[i];
         long ret2 = RegSetValueEx(hKey,NULL,NULL,REG_SZ,lpb,leng);

 }
}


void regOCX()//调用新进程注册组件
{

    char commandline[256];
 char windowsdir[256];
    char lastcommandline[257];

    PROCESS_INFORMATION pi;
    STARTUPINFO si = {sizeof(si)};
   
 char OCXfile[50]="\\MSCOMM32.OCX";
 char REGfile[50]="\\regsvr32.exe";
    char *p,*q;
    GetSystemDirectory(windowsdir, 256);
 p=commandline;
 q=windowsdir;
 strcpy(p,q);


 p=strchr(commandline,'\0');
    q=OCXfile;
 strcpy(p,q);

 p=strchr(windowsdir,'\0');
    q=REGfile;
 strcpy(p,q);


 p=commandline;
 q=&lastcommandline[1];
    strcpy(q,p);
    lastcommandline[0]=' ';
 

   

    // 启动regsvr32.exe作为子进程
    BOOL ret = CreateProcess(windowsdir, lastcommandline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
    if(ret)
 {
     CloseHandle(pi.hThread);
   
     CloseHandle(pi.hProcess);

 }

}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow )
{

    char sys[100];

    char file1[20]="Mscomm32.ocx";
 char file2[20]="Mscomm32.dep";
 char file3[20]="Mscomm.srg";

 GetSystemDirectory(sys,100);

    CPFile(file1,sys);
 CPFile(file2,sys);
 CPFile(file3,sys);

    regOCX();
 
 regsted();

 return 0;
}

》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
后记:

代码加入: include “stdafx.h”
         作者没有加入可能因为变成环境的问题。
          mscomm的文件一共有4个,注册使用的应该只有ocx这一个,但为什么都要copy出来不太明白。另一个问题是active控件的源文件和使用上不太了解。
          ms的文章没有时间读,我的理解可能.red文件是用来对照注册表的。


        当使用IS等安装程序时,可以实现对控件的自动注册,并对注册表进行操作,所以这种解决方法也没有必要了。
         这种方法的主要问题仍然是在注册上,导致了程序无法实现绿色安装。
         注册程序写入到主程序时需要每次做一个注册与否的判断,分开的话在操作上会给用户造成麻烦。

判断软件注册的方法一个是对照注册表。另一个是做一个global的标志来帮助判断(别的有待学习:P)前者更合理,但有点麻烦:(

         这段程序实现了对操作系统工具的直接调用,以及对系统文件的操作。  
         结合操作系统,网络的知识编写出具备全面而有效功能的软件。

posted @ 2007-06-14 16:55 高山流水 阅读(966) | 评论 (0)编辑 收藏



http://61.135.153.43/music_1024/mgsend_1019.mp3

曲名: BEST IS YET TO COME (和平将至)
作词,作曲: RIKA MURANAKA
编曲: DAVID DOWNES
录制地点: BEECH PARK STUDIO,IRELAND (爱尔兰)
演唱: AOIFE NI FHEARRAIGH
使用乐器: 低音风管, 超重音提琴, 小提琴, 打击乐曲组, 电子琴


An cuimhin leat an gra
Cra crol an ghra
Nil anois ach ceol na h-aiche
Talm siorai i ngra
Leannain le smal
Lig leis agus beidh leat
Lig leis agus beidh gra
Cuimhne leat an t-am
Nuair a bhi tu sasta
An culmhne leat an t-am
Nuair a bhi tu ag gaire
Ta an saol iontach
ma chreideann tu ann
Tug aghaidh ar an saoi is sonas siorai inar measc
Ceard a tharla do na laethanta sin
Ceard a tharla do na h-oicheanta sin
An cuimhin leat an t-am
Nuair a bhi tu faoi bhron
An cuimhin leat an t-am
Go siorai sileadh na ndeaor
An ormsa no orainne a bhi an locht
Ag mothu cailite s'ar fan
Cen fath an t-achrann is sileadh na ndeor
Ta ailieacht sa saol
Ma chuardaionn tu e
Ta gliondar sa saol
Cuardaimis e
la la la la la la la la la la la la


Do you remember the time when little things made you happy
你还记得吗?你为小事而快乐的时光?
Do you remember the time when simple things made you smile
你还记得吗?你为平凡之事而微笑的时光?
Life can be wonderful if you let it be
如果你顺其自然,生活其实很精彩
Life can be simple if you try
如果你努力而为,生活其实很简单
What happened to those days?
What happened to those nights?
日复一日,到底发生了什么事?
Do you remember the time when little things made you so sad
你还记得吗?你为小事而悲伤的时光?
Do you remember the time when simple things made you cry
你还记得吗?你为平凡之事而哭泣的时光?
Is it just me, or is it just us
只是我吗?或者是我们一起?
Feeling lost in this world?
在这个世界迷失?
Why do we have to hurt each other?
为什么我们不由的伤害对方?
Why do we have to shed tears?
为什么我们不由的流泪?
Life can be beautiful if you try
如果你努力,生活是很美好的
Life can be joyful if we try
如果我们努力,生活是很幸福的
Tell me I am not along
告诉我我并不孤单
Tell me we are not alone in this world fighting against the wind
在我们与风搏斗时,告诉我我们在这世界上并不孤单
Do you remember the time when simple things made you happy
你还记得吗?你为平凡之事而开心的时光?
Do you remember the time when simple things made you laugh
你还记得吗?你为平凡之事而开怀大笑的时光?
You know life can be simple
你知道,生活可以是平凡的
You know life is simple
你知道生活确实很平凡
Because the best thing in life is yet to come
因为生命中最美好的事情即将到来
Because the best is yet to come
因为
最美好的即将到来
the best is yet to come

posted @ 2007-04-27 12:57 高山流水 阅读(1939) | 评论 (1)编辑 收藏

仅列出标题
共30页: 1 2 3 4 5 6 7 8 9 Last