weitom1982

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

什么是全球定位系统(GPS)

全球定位系统(Global Positioning System - GPS)是美国从本世纪70年代开始研制,历
时20年,耗资200亿美元,于1994年全面建成,具有在海、陆、空进行全方位实时三维导航
与定位能力的新一代卫星导航与定位系统。经近10年我国测绘等部门的使用表明,GPS以全
天候、高精度、 自动化、高效益等显著特点,赢得广大测绘工作者的信赖,并成功地应用
于大地测量、工程测量、航空摄影测量、运载工具导航和管制、地壳运动监测、工程变形监
测、资源勘察、地球动力学等多种学科,从而给测绘领域带来一场深刻的技术革命。



全球定位系统(Global Positioning System,缩写GPS)是美国第二代卫星导航系统。是在子
午仪卫星导航系统的基础上发展起来的,它采纳了子午仪系统的成功经验。和子午仪系统一
样,全球定位系统由空间部分、地面监控部分和用户接收机三大部分组成。



按目前的方案,全球定位系统的空间部分使用24颗高度约2.02万千米的卫星组成卫星星座。
21+3颗卫星均为近圆形轨道,运行周期约为11小时58分,分布在六个轨道面上(每轨道面四
颗),轨道倾角为55度。卫星的分布使得在全球的任何地方,任何时间都可观测到四颗以上
的卫星,并能保持良好定位解算精度的几何图形(DOP)。这就提供了在时间上连续的全球
导航能力。



地面监控部分包括四个监控间、一个上行注入站和一个主控站。监控站设有GPS用户接
收机、原子钟、收集当地气象数据的传感器和进行数据初步处理的计算机。监控站的主要任
务是取得卫星观测数据并将这些数据传送至主控站。主控站设在范登堡空军基地。它对地面
监控部实行全面控制。主控站主要任务是收集各监控站对GPS卫星的全部观测数据,利用这
些数据计算每颗GPS卫星的轨道和卫星钟改正值。上行注入站也设在范登堡空军基地。它的
任务主要是在每颗卫星运行至上空时把这类导航数据及主控站的指令注入到卫星。这种注入
对每颗GPS卫星每天进行一次,并在卫星离开注入站作用范围之前进行最后的注入。



全球定位系统具有性能好、精度高、应用广的特点,是迄今最好的导航定位系统。随着全球
定位系统的不断改进,硬、软件的不断完善,应用领域正在不断地开拓, 目前已遍及国民
经济各种部门,并开始逐步深入人们的日常生活。



2.GPS如何定位



  GPS接收机可接收到可用于授时的准确至纳秒级的时间信息;用于预报未来几个月内卫
星所处概略位置的预报星历;用于计算定位时所需卫星坐标的广播星历,精度为几米至几十
米(各个卫星不同,随时变化);以及GPS系统信息,如卫星状况等。



  GPS接收机对码的量测就可得到卫星到接收机的距离,由于含有接收机卫星钟的误差及
大气传播误差,故称为伪距。对0A码测得的伪距称为UA码伪距,精度约为20米左右,对P码
测得的伪距称为P码伪距,精度约为2米左右。



  GPS接收机对收到的卫星信号,进行解码或采用其它技术,将调制在载波上的信息去掉
后,就可以恢复载波。严格而言,载波相位应被称为载波拍频相位,它是收到的受多普勒
频 移影响的卫星信号载波相位与接收机本机振荡产生信号相位之差。一般在接收机钟确定
的历元时刻量测,保持对卫星信号的跟踪,就可记录下相位的变化值,但开始观测时的接收
机和卫星振荡器的相位初值是不知道的,起始历元的相位整数也是不知道的,即整周模糊
度,只能在数据处理中作为参数解算。相位观测值的精度高至毫米,但前提是解出整周模糊
度,因此只有在相对定位、并有一段连续观测值时才能使用相位观测值,而要达到优于米级
的定位 精度也只能采用相位观测值。



  按定位方式,GPS定位分为单点定位和相对定位(差分定位)。单点定位就是根据一台
接收机的观测数据来确定接收机位置的方式,它只能采用伪距观测量,可用于车船等的概略
导航定位。相对定位(差分定位)是根据两台以上接收机的观测数据来确定观测点之间的相
对位置的方法,它既可采用伪距观测量也可采用相位观测量,大地测量或工程测量均应采用
相位观测值进行相对定位。



  在GPS观测量中包含了卫星和接收机的钟差、大气传播延迟、多路径效应等误差,在定
位计算时还要受到卫星广播星历误差的影响,在进行相对定位时大部分公共误差被抵消或削
弱,因此定位精度将大大提高,双频接收机可以根据两个频率的观测量抵消大气中电离层误
差的主要部分,在精度要求高,接收机间距离较远时(大气有明显差别),应选用双频接收
机。



  在定位观测时,若接收机相对于地球表面运动,则称为动态定位,如用于车船等概略导
航定位的精度为30一100米的伪距单点定位,或用于城市车辆导航定位的米级精度的伪距差
分定位,或用于测量放样等的厘米级 的相位差分定位(RTK),实时差分定位需要数据链
将 两个或多个站的观测数据实时传输到一起计算。 在定位观测时,若接收机相对于地球表
面静止,则称为静态定位,在进行控制网观测时,一般均采用这种 方式由几台接收机同时
观测,它能最太限度地发挥GPS的定位精度,专用于 这种目的的接收机被称为大地型接 收
机,是接收机中性能最好的一类。目前,GPS已经能 够达到地壳形变观测的精度要求,IGS
的常年观测台站已 经能构成毫米级的全球坐标框架。



3.GPS系统如何组成



GPS系统包括三大部分:空间部分—GPS卫星星座;地面控制部分—地面监控系统;用户设备
部分—GPS信号接收机。



GPS卫星星座;



GPS工作卫星及其星座 由21颗工作卫星和3颗在轨备用卫星组成GPS卫星星座,记作(21+3)
GPS星座。 24颗卫星均匀分布在6个轨道平面内,轨道倾角为55度,各个轨道平面之间相距
60度, 即轨道的升交点赤经各相差60度。每个轨道平面内各颗卫星之间的升交角距相差90
度, 一轨道平面上的卫星比西边相邻轨道平面上的相应卫星超前30度。
在两万公里高空的GPS卫星,当地球对恒星来说自转一周时,它们绕地球运行二周, 即绕地
球一周的时间为12恒星时。这样,对于地面观测者来说,每天将提前4分钟见到同一颗GPS
卫星。位于地平线以上的卫星颗数随着时间和地点的不同而不同,最少可见到4颗, 最多可
见到11颗。在用GPS信号导航定位时,为了结算测站的三维坐标,必须观测4颗 GPS卫星,称
为定位星座。这4颗卫星在观测过程中的几何位置分布对定位精度有一定的影响。对于某地
某时,甚至不能测得精确的点位坐标,这种时间段叫做“间隙段”。但这种 时间间隙段是
很短暂的,并不影响全球绝大多数地方的全天候、高精度、连续实时牡己蕉ㄎ徊饬俊?GPS工
作卫星的编号和试验卫星基本相同。
地面监控系统
对于导航定位来说,GPS卫星是一动态已知点。星的位置是依据卫星发射的星历—描述卫星
运动及其轨道的 的参数算得的。每颗GPS卫星所播发的星历,是由地面监控系统提供的。卫
星上的各种设备是否正常 工作,以及卫星是否一直沿着预定轨道运行,都要由地面设备进
行监测和控制。地面监控系统 另一重要作用是保持各颗卫星处于同一时间标准—GPS时间系
统。这就需要地面站监测 各颗卫星的时间,求出钟差。然后由地面注入站发给卫星,卫星
再由导航电文发给用户设备。 GPS工作卫星的地面监控系统包括一个主控站、三个注入站和
五个监测站。
GPS信号接收机
GPS 信号接收机的任务是:能够捕获到按一定卫星高度截止角所选择的待测卫星的信号,
并跟踪这些卫星的运行,对所接收到的GPS信号进行变换、放大和处理,以便测量出GPS信号
从卫星 到接收机天线的传播时间,解译出GPS卫星所发送的导航电文,实时地计算出测站的
三维位置, 位置,甚至三维速度和时间。
静态定位中,GPS接收机在捕获和跟踪GPS卫星的过程中固定不变,接收机高精度 地测量GPS
信号的传播时间,利用GPS卫星在轨的已知位置,解算出接收机天线所在位置的 三维坐标。
而动态定位则是用GPS接收机测定一个运动物体的运行轨迹。GPS信号接收机 所位于的运动
物体叫做载体(如航行中的船舰,空中的飞机,行走的车辆等)。载体上 的GPS接收机天线
在跟踪GPS卫星的过程中相对地球而运动,接收机用GPS信号实时地 测得运动载体的状态参
数(瞬间三维位置和三维速度)。
接收机硬件和机内软件以及GPS数据的后处理软件包,构成完整的GPS用户设备。GPS接收机
的结构 分为天线单元和接收单元两大部分。对于测地型接收机来说,两个单元一般分成 两
个独立的部件,观测时将天线单元安置在测站上,接收单元置于测站附近的适当地方, 用
电缆线将两者连接成一个整机。也有的将天线单元和接收单元制作成一个整体,观测时将
其 安置在测站点上。
GPS接收机一般用蓄电池做电源。同时采用机内机外两种直流电源。设置机内电池的目的 在
于更换外电池时不中断连续观测。在用机外电池的过程中,机内电池自动充电。 关机后,
机内电池为RAM存储器供电,以防止丢失数据。
近几年,国内引进了许多种类型的GPS测地型接收机。各种类型的GPS测地型接收机用于 精
密相对定位时,其双频接收机精度可达5mm+1PPM.D,单频接收机在一定距离内精度可达
10mm+2PPM.D。用于差分定位其精度可达亚米级至厘米级。 目前,各种类型的GPS接收机体
积越来越小,重量越来越轻,便于野外观测。GPS和GLONASS 兼容的全球导航定位系统接收
机已经问世。



4.GPS接收机如何分类
GPS卫星发送的导航定位信号,是一种可供无数用户共享的信息资源。对于陆地、 海洋和空
间的广大用户,只要用户拥有能够接收、跟踪、变换和测量GPS信号的接收设备, 即GPS信
号接收机。可以在任何时候用GPS信号进行导航定位测量。根据使用目的的不同, 用户要求
的GPS信号接收机也各有差异。目前世界上已有几十家工厂生产GPS接收机, 产品也有几百
种。这些产品可以按照原理、用途、功能等来分类。



按接收机的用途分类
导航型接收机 此类型接收机主要用于运动载体的导航,它可以实时给出载体的位置和速
度。这类接收机 一般采用C/A码伪距测量,单点实时定位精度较低,一般为±25mm,有SA影
响时为±100mm。 这类接收机价格便宜,应用广泛。根据应用领域的不同,此类接收机还可
以进一步分为: 车载型——用于车辆导航定位; 航海型——用于船舶导航定位; 航空
型——用于飞机导航定位。由于飞机运行速度快,因此,在航空上用的接收机 要求能适应
高速运动。 星载型——用于卫星的导航定位。由于卫星的速度高达7km/s以上,因此对接收
机的要求更高。
测地型接收机
测地型接收机主要用于精密大地测量和精密工程测量。定位精度高。仪器结构复杂,价格较
贵。 授时型接收机 这类接收机主要利用GPS卫星提供的高精度时间标准进行授时,常用于
天文台及无线电通讯中时间同步。
按接收机的载波频率分类
单频接收机 单频接收机只能接收L1载波信号,测定载波相位观测值进行定位。由于不能有
效消除 电离层延迟影响,单频接收机只适用于短基线(<15km)的精密定位。



双频接收机 双频接收机可以同时接收L1,L2载波信号。利用双频对电离层延迟的不一样,
可以消除电离层 对电磁波信号的延迟的影响,因此双频接收机可用于长达几千公里的精密
定位。
按接收机通道数分类
GPS接收机能同时接收多颗GPS卫星的信号,为了分离接收到的不同卫星的信号,以实现对卫
星信号的跟踪、处理和量测,具有这样功能的器件称为天线信号通道。根据接收机所具有的
通道种类可分为: 多通道接收机 序贯通道接收机 多路多用通道接收机
按接收机工作原理分类
码相关型接收机 码相关型接收机是利用码相关技术得到伪距观测值。
平方型接收机 平方型接收机是利用载波信号的平方技术去掉调制信号,来恢复完整的载波信
号 通过相位计测定接收机内产生的载波信号与接收到的载波信号之间的相位差,测定伪距
观测值。
混合型接收机 这种仪器是综合上述两种接收机的优点,既可以得到码相位伪距,也可以得
到载波相位观测值。
干涉型接收机 这种接收机是将GPS卫星作为射电源,采用干涉测量方法,测定两个测站间距
离。



5.如何使用GPS接收机(一)



   GPS作为野外定位的最佳工具,在户外运动中有广泛的应用,在国内也可以越来越经常
地看见有人使用了。GPS不象电视或收音机,打开就能用,它更象一架相机,你需要有一定
的技巧。现在介绍一些GPS使用办法和经验。



  首先大家要弄清使用GPS时常碰到的一些术语:



  1.坐标(coordinate)   



有2维、3维两种坐标表示,当GPS能够收到4颗及以上卫星的信号时,它能计算出本地的3微
坐标:经度、纬度、高度,若只能收到3颗卫星的信号,它只能计算出2维坐标:精度和纬
度,这时它可能还会显示高度数据,但这数据是无效的。大部分GPS不仅能以经/纬度
(Lat/Long)的方式,显示坐标,而且还可以用UTM(Universal Transverse Mercator)等坐标
系统显示坐标但我们一般还是使用LAT/LONG系统,这主要是由你所使用的地图的坐标系统决
定的。坐标的精度在Selective Availability(美国防部为减小GPS精确度而实施的一种措
施)打开时,GPS的水平精度在100-50米之间,视接受到卫星信号的多少和强弱而定,若根据
GPS的指示,说你已经到达,那么四周看看,应该在大约一个足球场大小的面积内发现你的
目标的。



  在SA关闭时(目前是很少见的,但美政府计划将来取消SA),精度能达到15米左右(GPS性
能介绍上说的精度都给的是no SA值,唬人的)。高度的精确性由于系统结构的原因,更差
些。经纬度的显示方式一般都可以根据自己的爱好选择,一般
有"hddd.ddddd","hddd*mm.mmm"","hddd*mm"ss.s"""(其中的“*”代表“度”,以下同)地
球子午线长是39940.67公里,纬度改变一度合110.94公里,一分合1.849公里,一秒合30.8
米,赤道圈是40075.36公里,北京地区纬在北纬40度左右,纬度圈长为40075*sin(90-40),
此地经度一度合276公里,一分合1.42公里一秒合23.69米,你可以选定某个显示方式,并把
各位数字改变一对应地面移动多少米记住,这样能在经纬度和实际里程间建立个大概的对
应。大部分GPS都有计算两点距离的功能,可给出两个坐标间的精确距离。高度的显示会有
英制和公制两种方式,进GPS的SETUP页面,设置成公制,这样在其他象速度、距离等的显示
也都会成公制的了。



  2.路标(Landmark or Waypoint)



  GPS内存中保存的一个点的坐标值。在有GPS信号时,按一下"MARK"键,就会把当前点记
成一个路标,它有个默认的一般是象"LMK04"之类的名字,你可以修改成一个易认的名字(字
母用上下箭头输入),还可以给它选定一个图标。路标是GPS数据核心,它是构成“路线”
(见3)的基础。标记路标是GPS主要功能之一,但是你也可以从地图上读出一个地点的坐标,
手工或通过计算机接口输入GPS,成为一个路标。一个路标可以将来用于GOTO功能(见5)的目
标,也可以选进一条路线Route,见3.)作为一个支点。一般GPS能记录500个或以上的路
标。



  3.路线(ROUTE)



  路线是GPS内存中存储的一组数据,包括一个起点和一个终点的坐标,还可以包括若干
中间点的坐标,每两个坐标点之间的线段叫一条"腿"(leg)。常见GPS能存储20条线路,每条
线路30条"腿"。各坐标点可以从现有路标中选择,或是手工/计算机输入数值,输入的路点
同时做为一个路标(Waypoint/Landmark)保存。实际上一条路线的所有点都是对某个路标的
引用,比如你在路标菜单下改变一个路标的名字或坐标,如果某条路线使用了它,你会发现
这条线路也发生了同样的变化。可以有一条路线是"活跃"(Activity)的。“活跃”路线的路
点是导向(见5)功能的目标



。   4.前进方向(Heading)



  GPS没有指北针的功能,静止不动时它是不知道方向的。但是一旦动了起来,它就能知
道自己的运动方向。GPS每隔一秒更新一次当前地点信息,每一点的坐标和上一点的坐标一
比较,就可以知道前进的方向,请注意这并不是GPS头指的方向,它老人家是不知道自己的
脑袋和运动路线是成多少度角的。不同GPS关于前进方向的算法是不同的,基本上是最近若
干秒的前进方向,所以除非你已经走了一段并仍然在走直线,否则前进方向是不准确的,尤
其是在拐弯的时候你会看到数值在变个不停。方向的是以多少度显示的,这个度数是手表表
盘朝上,12点指向北方,顺时针转的角度。有很多GPS还可以用指向罗盘和标尺的方式来显
示这个角度。一般同时还显示前进平均速度,也是根据最近一段的位移和时间计算的。



  5.导向(Bearing)



  导向功能在以下条件下起作用:



  1.)以设定"走向"(GOTO)目标。"走向"目标的设定可以按"GOTO"键,然后从列表中选择
一个路标。以后"导向"功能将导向此路标



。   2.)目前有活跃路线(Activity route)。活跃路线一般在设置->路线菜单下设定。如
果目前有活动路线,那么"导向"的点是路线中第一个路点,每到达一个路点后,自动指到下
一个路点。



  在"导向"页面上部都会标有当前导向路点名称("ROUTE"里的点也是有名称的)。它是根
据当前位置,计算出导向目标对你的方向角,以与"前进方向"相同的角度值显示。同时显示
离目标的距离等信息。读出导向方向,按此方向前进即可走到目的地。有些GPS把前进方向
和导向功能结合起来,只要用GPS的头指向前进方向,就会有一个指针箭头指向前进方向和
目标方向的偏角,跟着这个箭头就能找到目标。



  6.日出日落时间(Sun set/raise time)



  大多数GPS能够显示当地的日出、日落时间,这在计划出发/宿营时间时是有用的。这个
时间是GPS根据当地经度和日期计算得到的,是指平原地区的日出、日落时间,在山区因为
有山脊遮挡,日照时间根据情况要早晚各少半个小时以上。GPS的时间是从卫星信号得到的
格林尼制时间,在设置(setup)菜单里可以设置本地的时间偏移,对中国来说,应设+8小
时,此值只与时间的显示有关。



  7.足迹线(Plot trail)



  GPS每秒更新一次坐标信息,所以可以记载自己的运动轨迹。一般GPS能记录1024个以上
足迹点,在一个专用页面上,以可调比例尺显示移动轨迹。足迹点的采样有自动和定时两种
方式自动采样由GPS自动决定足迹点的采样方式,一般是只记录方向转折点,长距离直线行
走时不记点;定时采样可以规定采样时间间隔,比如30秒、一分钟、5分钟或其他时间,每
隔这么长时间记一个足迹点。在足迹线页面上可以清楚地看到自己足迹的水平投影。你可以
开始记录、停止记录、设置方式或清空足迹线。“足迹”线上的点都没有名字,不能单独引
用,查看其坐标,主要用来画路线图(计算机下载路线?)和“回溯”功能。很多GPS有一种叫
做“回溯”(Trace back)的功能,使用此功能时,它会把足迹线转化为一条“路线”
(ROUTE),路点的选择是由GPS内部程序完成的一般是选用足迹线上大的转折点。   同
时,把此路线激活为活动路线,用户即可按导向功能原路返回。要注意的是回溯功能一般会
把回溯路线放进某一默认路线(比如route0)中,看你GPS的说明书,使用前要先检查此线路
是否已有数据,若有,要先用拷贝功能复制到另一条空线路中去,以免覆盖。回溯路线上的
各路点用系统默认的临时名字如"T001"之类,有的GPS定第二条回溯路线时会重用这些名
字,这时即使你已经把旧的路线做了拷贝,由于路点引用的名字被重用了,所以路线也会改
变,不是原来那条回溯路线了。请查看你GPS的使用说明书,并试用以明确你的情况。有必
要的话,对于需要长期保存的TraceBack路线,要拷贝到空闲路线,并重命名所有路点名
字。



6.如何使用GPS接收机(二)



  GPS比较费电池,多数GPS使用四节碱性电池一直开机可用20-30小时,说明书上的时间
并不是很准确的,长时间使用时要注意携带备用电池。大部分GPS有永久的备用电池,它可
以在没有电池时保证内存中的各种数据不会丢失。由于GPS在静止时没有方向指示功能,所
以同时带上一个小巧的指北针是有用的。标记路标时,GPS提供一个默认的路标名,比如
LMK001之类,难于记忆,虽可改成一个比较好记一些的名字,但一是输入不便,用上下箭头
选字母很费劲,二是一般只能起很短的英文名字,比如6或9个字母,仍然不好记,同时再带
上一个小的录音机/采访机随时记录,是个不错的主意。



  1.有地图使用



  GPS与详细地图配合使用时有最好的效果,但是国内大比例尺地图十分难得,GPS使用效
果受到一定限制。“万一”你有目的地附近的精确地图,则可以预先规划线路,先做地图上
规划,制定行程计划,可以按照线路的复杂情况和里程,建立一条或多条线路(ROUTE),读
出路线特征点的坐标,输入GPS建立线路的各条“腿”(legs),并把一些单独的标志点作为路
标(Landmark/Waypoint)输入GPS。GPS手工输入数据,是一项相当烦琐的事情,请想一下,
每个路标就要输入名字、坐标等20多个字母数字,每个字母数字要按最多到十几次箭头才能
出来,哈哈,这就是有人舍得花很多钱来买接线和软件,用计算机来上载/下载数据的原
因。带上地图!行进时用一是利用GPS确定自己在地图上的位置,二是按照导向功能指示的
目标方向,配合地图找路向目标前进。同时一定要记录各规划点的实际坐标,最好再针对每
条规划线路建立另一条实际线路,即可作为原路返回时使用,又可回来后作为实际路线资料
保存,供后人使用。



  2.无图使用这是更为常见的使用方式。



  1.)使用路点定点:常用于确定岩壁坐标、探洞时确定洞口坐标或其他象线路起点、转
折、宿营点的坐标。用法简单,MARK一个坐标就行了。找点:所要找的地点坐标必须已经以
路标(landmark/waypoint)的形式存在于GPS的内存中,可以是你以前MARK的点或者是从以前
去过的朋友那里得到的数据,手工/计算机上载成的路标数据。按GOTO键,从列表中选择你
的目的路标,然后转到“导向”页面,上面会显示你离目标的距离、速度、目标方向角等数
据,按方向角即可。



  2.)使用路线输入路线:若能找到以前去过的朋友记录的路线信息,把它们输入GPS形成
线路,或者(常见于原路返回)把以前记录的路标编辑成一条线路。路线导向:把某条路线激
活,按照和“找点”相同的方式,“导向”页会引导你走向路线的第一个点,一旦到达,目
标点会自动更换为下一路点,“导向”页引导你走向路线的第二个点...若你偏离了路线,
越过了某些中间点,一旦你再回到路线上来,“导向目标”会跳过你所绕过的那些点,定为
线路上你当前位置对应的下一个点。



  3.)回溯回溯功能实际是输入线路(route)的一种特殊方法,它在原路返回时十分好使。
但有些注意事项,



由于国内大比例尺不宜得到,所以朋友们每次出去玩希望都能带一组正确数据回来,有地图
时整理一套地图+实测路线坐标,没地图时整理一套线路描述+实测坐标,发到网上,逐渐积
攒起来,形成咱们自己的地理数据库,以后再有朋友走这条线路就可以免除雇向导和迷路之
苦了!



7.什么是RTK技术



常规的GPS测量方法,如静态、快速静态、动态测量都需要事后进行解算才能获得厘米级的
精度,而RTK是能够在野外实时得到厘米级定位精度的测量方法,它采用了载波相位动态实
时差分(Real - time kinematic)方法,是GPS应用的重大里程碑,它的出现为工程放样、
地形测图,各种控制测量带来了新曙光,极大地提高了外业作业效率。



高精度的GPS测量必须采用载波相位观测值,RTK定位技术就是基于载波相位观测值的实时动
态定位技术,它能够实时地提供测站点在指定坐标系中的三维定位结果,并达到厘米级精
度。在RTK作业模式下,基准站通过数据链将其观测值和测站坐标信息一起传送给流动站。
流动站不仅通过数据链接收来自基准站的数据,还要采集GPS观测数据,并在系统内组成差
分观测值进行实时处理,同时给出厘米级定位结果,历时不到一秒钟。流动站可处于静止状
态,也可处于运动状态;可在固定点上先进行初始化后再进入动态作业,也可在动态条件下
直接开机,并在动态环境下完成周模糊度的搜索求解。在整周末知数解固定后,即可进行每
个历元的实时处理,只要能保持四颗以上卫星相位观测值的跟踪和必要的几何图形,则流动
站可随时给出厘米级定位结果。



RTK技术的关键在于数据处理技术和数据传输技术,RTK定位时要求基准站接收机实时地把观
测数据(伪距观测值,相位观测值)及已知数据传输给流动站接收机,数据量比较大,一般
都要求9600的波特率,这在无线电上不难实现。



8.RTK技术如何应用



1. 各种控制测量 传统的大地测量、工程控制测量采用三角网、导线网方法来施测,不仅
费工费时,要求点间通视,而且精度分布不均匀,且在外业不知精度如何,采用常规的GPS
静态测量、快速静态、伪动态方法,在外业测设过程中不能实时知道定位精度,如果测设完
成后,回到内业处理后发现精度不合要求,还必须返测,而采用RTK来进行控制测量,能够
实时知道定位精度,如果点位精度要求满足了,用户就可以停止观测了,而且知道观测质量
如何,这样可以大大提高作业效率。如果把RTK用于公路控制测量、电子线路控制测量、水
利工程控制测量、大地测量、则不仅可以大大减少人力强度、节省费用,而且大大提高工作
效率,测一个控制点在几分钟甚至于几秒钟内就可完成。



2. 地形测图 过去测地形图时一般首先要在测区建立图根控制点,然后在图根控制点上架
上全站仪或经纬仪配合小平板测图,现在发展到外业用全站仪和电子手簿配合地物编码,利
用大比例尺测图软件来进行测图,甚至于发展到最近的外业电子平板测图等等,都要求在测
站上测四周的地形地貌等碎部点,这些碎部点都与测站通视,而且一般要求至少2-3人操
作,需要在拼图时一旦精度不合要求还得到外业去返测,现在采用RTK时,仅需一人背着仪
器在要测的地形地貌碎部点呆上一二秒种,并同时输入特征编码,通过手簿可以实时知道点
位精度,把一个区域测完后回到室内,由专业的软件接口就可以输出所要求的地形图,这样
用RTK仅需一人操作,不要求点间通视,大大提高了工作效率,采用RTK配合电子手簿可以测
设各种地形图,如普通测图、铁路线路带状地形图的测设,公路管线地形图的测设,配合测
深仪可以用于测水库地形图,航 海海洋测图等等。



3. 放样程放样是测量一个应用分支,它要求通过一定方法采用一定仪器把人为设计好的点
位在实地给标定出来,过去采用常规的放样方法很多,如经纬仪交会放样,全站仪的边角放
样等等,一般要放样出一个设计点位时,往往需要来回移动目标,而且要2-3人操作,同时
在放样过程中还要求点间通视情况良好,在生产应用上效率不是很高,有时放样中遇到困难
的情况会借助于很多方法才能放样,如果采用RTK技术放样时,仅需把设计好的点位坐标输
入到电子手簿中,背着GPS接收机,它会提醒你走到要放样点的位置,既迅速又方便,由于
GPS是通过坐标来直接放样的,而且精度很高也很均匀,因而在外业放样中效率会大大提
高,且只需一个人操作。



9.什么叫导航



导航是一个技术门类的总称,它是引导飞机、船舶、车辆以及个人(总称作运载体)安
全、准确地沿着选定的路线,准时到达目的地的一种手段。导航的基本功能是回答:我现在
在哪里?我要去哪里?如何去?
导航应由导航系统完成,包括装在运载体上的导航设备以及装在其他地方与导航设备配
合使用的导航台。从导航台的位置来看,主要有:



陆基导航系统: 即导航台位于陆地上,导航台与导航设备之间用无线电波联系。



星基导航系统:导航台设在人造卫星上,扩大覆盖范围。



导航是人类从事政治、经济和军事活动所必不可少的信息技术。今天,随着人类活动的
发展,对导航的要求越来越高。

posted @ 2006-04-19 11:01 高山流水 阅读(434) | 评论 (0)编辑 收藏

单位转换探讨

自由人笔记
1 基础知识
1.1 用于构成十进制倍数和分数单位的词头(词冠)
词头中文名    词头英文名    符号    所表示的因数    词头中文名    词头英文名    符号    所表示的因数
分    deci    d    10-1    皮    pico    p    10-12
厘    centi    c    10-2    千    kilo    K    103
毫    milli    m    10-3    兆    mega    M    106
微    micro    μ    10-6    吉    giga    G    109
纳    nano    n    10-9    太    tera    T    1012
  为不失一般性,下面的一些公式中将以希腊字母Θ代表无词头和十进制分数单位的词头(m、μ、n、p)。但一定要注意Θ本身并不是一种词头,仅是本文为避免列出大量雷同的公式而约定的一个符号而已。所以,当您看到Θ时,一定要想到它就是m、μ、n、p或者是没词头;在您需要含无词头单位参数的公式时,就请把Θ去掉;而在您需要含某种词头单位参数的公式时,就就请把Θ换成所需的词头。
1.2 分贝
在电子学中,分贝是表示传输增益或传输损耗以及相对功率比等的标准单位,其代号为dB(英文decibel的缩写)。其形式上表示倍数,实质上既能表示经作常用对数压缩处理后的倍数(以分贝表示的传输增益和传输损耗等,特点是本质无量纲),又能表示约定基准值的参数值(电压电平、功率电平,以分贝表示的电场强度、功率通量密度,杂散辐射功率和邻道功率相对于载波功率的电平等,特点是本质有量纲)。采用的根本原因在于对数运算能够压缩数据长度和简化运算(将乘、除、指数运算分别转化为加、减、乘运算),特别适合表达指数变化规律。我们这里约定,以符号lg表示以10为底的对数。经作对数变换后的本质有量纲单位常称作电平单位(与其基准值相等的参数值称零电平。电平的单位还有贝尔和奈培两种,但由于文献[1]规定“统一使用分贝为电信传输单位”,这里不采用。以下所称电平均以分贝为词头),而原来的单位可称作线性单位。
分贝与线性值的比较见下表:
分贝值(dB)    电压、电流比线性值    功率比线性值    分贝值(dB)    电压、电流比线性值    功率比线性值    分贝值(dB)    电压、电流比线性值    功率比线性值
0.0    1.000    1.000    1    1.122    1.259    11    3.548    12.59
0.1    1.012    1.023    2    1.259    1.585    12    3.981    15.85
0.2    1.023    1.047    3    1.413    1.995    13    4.467    19.95
0.3    1.035    1.072    4    1.585    2.512    14    5.012    25.12
0.4    1.047    1.096    5    1.778    3.162    15    5.623    31.62
0.5    1.059    1.122    6    1.995    3.981    16    6.310    39.81
0.6    1.072    1.148    7    2.239    5.012    17    7.079    50.12
0.7    1.084    1.175    8    5.012    6.310    18    7.943    63.10
0.8    1.096    1.202    9    2.818    7.943    19    8.913    79.43
0.9    1.109    1.230    10    3.162    10.00    20    10.00    100.0
  分贝的定义分以下三种情况:
1.2.1 对电压和与电压呈线性关系的参数的表达
  电压和与电压呈线性关系的参数,这里权且简称为电压型参数,以A表示,以x表示其
单位。以1x为基准值,则A的电平单位为称分贝x,代号为dBx,计算公式为
             A(x)
  A(dBx)=20lg ————                        (1) 
             1x  
          A(dBx)
          ——————
            20
  A(x)=10                               (2)
  A可以是电压(电动势、端电压)、电场强度和天线系数,x可以是V、mV、μV,V/m、mV/m、μV/m和m-1 等,对应的电平单位分别为dBV、dBmV、dBμV, dBV/m、dBmV/m、dBμV/m(常记为dBμ)和dBm-1等。
  同类电压型电平单位(天线系数除外)词头之间的转换公式为
  dBx=dBmx+60=dBμx+120                 (3)
  dBmx=dBμx+60                          (4)
1.2.2 对功率和与功率呈线性关系的参数的表达
  功率和与功率呈线性关系的参数,这里权且简称为功率型参数,以B表示,以x表示其单位。以1y为基准值,则B的电平单位称分贝y,代号为dBy,计算公式为
             B(y)
  B(dBy)=10lg ————                       (5)
             1y   
           B(dBy)
          ——————
            10
  B(y)=10                               (6)
  B可以是功率或功率密度,y 可以是 W、mW、μW,W/m2、mW/cm2、μW/cm2 、pW/m2等, 对应的电平单位分别为dBW、dBmW(常记为dBm)、dBμW, dBW/m2、dBmW/cm2、dBμW/cm2、dBpW/m2等。
  同类功率型电平单位词头之间的转换公式为
  dBy=dBmy+30=dBμy+60                  (7)
dBmy=dBμy+30                          (8)
1.2.3对功率倍数的表达
  以P1表示输入功率、辐射功率、载波功率(对应的电压有效值为U1,电流有效值为I1),P2表示输出功率、接收功率、杂散辐射/邻道功率(对应的电压有效值为U2,电流有效值为I2),仍以y表示P1、P2的单位,则传输增益G或传输损耗L的分贝表达式为:
               P2(y)      U2(I2)
  G(或L)(dB)=10lg ————  =20lg ————            (9)
               P1(y)      U1(I1)
  这里的y可以是W、mW、μW、KW、MW等,P1(U1、I1)与P2(U2、I2)的单位应一致,G和L的单位为dB  。
  杂散辐射相对于载波功率的电平P杂散辐射和邻道功率相对于载波功率的电平P邻道功率,其值为负数,单位一般记为dBC(英文carrier有“载波”之意),表达式为:
                        P2(y)
  P杂散辐射(或P邻道功率)(dBC)=10lg ————                 (10)
                         P1(y) 
  特别地,当U1表示接收机的可用灵敏度,U2分别表示接收机输入比可用灵敏度高3dB的有用信号而使输出信纳比降回到12dB的相邻波道上无用信号电压和落入有用信号工作频率的二信号三阶互调的组合频率的电压(两条频率的电压应相等)时,两电压倍数的分贝值分别表示接收机的邻道选择性P邻道选择和互调抗扰性P互调抗扰,其值为正数,单位一般记为dBr(英文relative有“相对的” 之意),表达式为:
                          U2(y)
  P邻道选择(或P互调抗扰)(dBr)=20lg ————                  (11)
                           U1(y) 
另外,天线增益和噪声系数也可归入此类,详见第6节。

2 射频电压
  射频电压一般指电台、仪器射频级和天线系统中所研究频率上信号的电压幅度,按检波方式,可分为平均值(AV)电压、均方根值(RMS)电压、峰值(PEAK)电压等,以下简称为电压。习惯上,信号发生器和接收天线输出端的开路电压称为电动势,以ein表示;而当其接上负载(如通信接收机、场强仪、测试接收机、频谱分析仪、综合测试仪的收信端等,下面统称为接收设备,以及假负载)后,其输出端和所接负载输入端的电压称为端电压,以Vin表示。电压的线性单位通常有V、mV、μV,对应的电平单位分别为dBV、dBmV、dBμV。不同词头的电压单位间的换算可利用(3)、(4)两式。为区别电动势与端电压,通常在电动势单位后加(e.m.f.)或(EMF),而在端电压单位后加(c.c.)或不加注明。
  当信号发生器或接收天线输出端的阻抗与负载阻抗匹配时,电动势为端电压的2倍,即
  ein(ΘV)=2Vin(ΘV)                     (12)
  ein(dBΘV)=Vin(dBΘV)+6.02               (13)
  其它参数到接收功率的转换公式有
   Pr (dBm)=Vin (dBμV)-F(dB)               (14)
上式中F为折算系数,F(dB)=90+10lgR,R为接收设备的输入阻抗。当阻抗为50Ω时,F=106.99dB,当阻抗为75Ω时,F=108.75dB 。
  E(dBμV/m)=Vin (dBμV)+K(dBm-1 )                (15)
  S(dBW/m2)=Vin(dBV)+K(dBm-1 )-25.76       (16)
式中K为天线系数,详见第7节。

3 射频功率
  射频功率一般指电台、仪器射频级和天线系统中所研究频率上信号在一个特定的射频周期内输出到负载上的的功率算术平均值, 以下简称为功率。分为峰包功率、平均功率、载波功率等。习惯上, 以P表示。功率的线性单位通常有W、mW、μW,对应的电平单位分别为dBW、dBmW(常记为dBm)、dBμW。不同词头的功率单位间的换算可利用(7)、(8)两式。发射功率一般用Pt(英文transmit有“发射”之意)表示,接收功率一般用Pr(英文receive有“接收”之意) 表示。
  接收功率与其它参数的转换公式为
   Vin (dBμV)=Pr (dBm)+F(dB)               (17)
  E(dBμV/m)=Pr (dBm)+F(dB)+K(dBm-1 )      (18)
S(dBW/m2)=Pr (dBm)+F(dB)+K(dBm-1 )-25.76(19)

4 电场强度
  电场强度是长度为1米(m)的天线所感应的电压,简称场强,习惯上以E表示。场强的线性单位通常有V/m、mV/m、μV/m,对应的电平单位分别为dBV/m、dBmV/m、dBμV/m(常记为dBμ)。不同词头的场强单位间的换算可利用(3)、(4)两式。
  场强与其它参数间的折算公式有
  Vin(dBΘV)=E(dBΘV/m)-K(dBm-1 )          (20)
  Pr (dBm)=E(dBμV/m)-F(dB)-K(dBm-1 )      (21)
  S(dBW/m2)=E(dBV/m)-25.76               (22)
  S(dBμW/cm2)=E(dBμV/m)-125.76            (23)

5 功率通量密度
  功率通量密度是电波入射到单位面积上的辐射功率,简称功率密度,通常以S表示。平均功率密度是电波入射到单位面积上的平均辐射功率。功率密度的线性单位通常有 W/m2、mW/cm2、μW/cm2 、pW/m2,对应的电平单位分别为dBW/m2、dBmW/cm2、dBμW/cm2、dBpW/m2等。功率密度单位间的换算,面积单位相同的可利用(7)、(8)两式。面积单位不同的换算公式为
  S(Θ W/m2)=100S(Θ W/cm2)                (24)
  S(dBΘW/m2)=S(dBΘ W/cm2)+40             (25)
  功率密度与场强间线性值的折算公式为
  S(W/m2)=E2(V/m)/120π                   (26)
  S(μW/cm2)=E2(μV/m)/(120π×1010)            (27)
  功率通量密度与其它参数的转换公式为
  E(dBV/m)=S(dBW/m2)+25.76                (28)
  E(dBμV/m)=S(dBμW/cm2)+125.76            (29)
  Vin(dBV)=S(dBW/m2)-K(dBm-1 )+25.76         (30)
Pr (dBm)=S(dBW/m2)-F(dB)-K(dBm-1 )+25.76(31)

6 天线功率增益
  天线在某方向上的辐射强度(每单位立体角内天线所辐射的功率)与天线从其信号源所得净功率的比值的4π倍称为天线在该方向上的功率增益,简称天线增益。天线增益的最大值称为天线峰值功率增益[2]。通常所说的天线增益便指的是天线峰值功率增益,而对非峰值功率增益常常指明是某方向上的增益。
  对通常所说的天线增益,有一个更常见的相对于标准天线的定义:被研究天线在最大辐射方向的辐射强度与和被研究天线具有同等输入功率的标准天线在同一点所产生的最大辐射强度之比[3]。准确地说,这种定义下的天线增益应称为天线的相对增益。当以理想的各向同性辐射器(或称点源辐射器、无方向性天线)为标准天线时,相对增益的定义与前述峰值功率增益的定义是等价的。
  发射天线增益一般用Gt 表示,接收天线增益一般用Gr 表示。天线增益的线性单位为倍,  以各向同性辐射器为标准天线的增益称绝对增益或无方向增益,其分贝单位为dB或dBi (英文 isotropic意思是“各向同性的”), 以半波振子天线为标准天线的分贝单位为dBd(英文 dipole 和doublet均有“对称振子”、“偶极”之意),两者的转换公式为
  G(相对于各向同性天线的倍数)=1.64G(相对于半波振子天线的倍数 )   (32)
G(dBi)=G(dBd)+2.15                    (33)

7 天线系数
  天线系数是天线所在点的场强与负载阻抗匹配情况下天线(或包括电缆的天线)输出端电压之比,常用K或Ke 表示(本文用K表示),单位为m-1 ,分贝表示为dBm-1(天线系数的单位中m为长度单位米的符号),即
        E(ΘV/m)
  K(m-1 )=——————                       (34)
        Vin(ΘV)
  K(dBm-1 )=E(dBΘV/m)-Vin(dBΘV)             (35)
  文献[3]规定,天线系数包括天线的有效高度、变换器的损耗、电缆的损耗以及电缆与接收机之间的失配损耗等,而文献[4]称天线系数通常不含电缆损耗。 本文以文献[3]为准。天线系数与天线增益的转换公式为
  K(dBm-1 )=20lgf(MHZ)-Gr(dB d)+br-31.92        (36)
式中br为电缆损耗,如果天线增益Gr中已包含电缆损耗,则应去掉此项。
另外,如果需要加长已知天线系数的天线的电缆,那么,实际的K值应加上加长电缆的损耗。
http://suncilang.bokee.com
8 噪声系数
噪声系数是接收机或有源器件输入信噪功率比与输出信噪功率比之比。线性值用Fn表示,无量纲;分贝值用NF表示,有的文献称分贝表示的噪声系数为噪声指数。
Fn = 1 + Te/T0
其中Te为输入等效噪声温度,T0为规定室温290K 。
NF(dB)=10lgFn

posted @ 2006-04-19 10:52 高山流水 阅读(2229) | 评论 (0)编辑 收藏

[编程宝典]C#开发短信的方法和简介
[ 2005-11-27 12:13:00 | By: 自由人 ]
 

C#开发短信的方法和简介

       没发过短信的年轻人肯定是属于那种受保护的稀有动物,通讯发达的今天短信已经成为人们交流的重要手段,其中也蕴含着巨大的市场和经济利益,掌握短信技术的人才也受到各大公司的追捧是目前职场上耀眼的明星。本文介绍了短信的原理和实现方法,重点说明了短信的编码方式、AT指令以及用 C#实现串口通讯的方法。
  
    前言
  
    目前,主有三种发送短信的方式:
  
    1、 网关方式:就是向当地的电信部门申请,不需要额外的设备,适用于大型的通信公司,像华为、傲天、中兴、亚信等。
  
    2、 终端方式:就是借助像GSM MODEM之类的设置(支持AT指令的手机也行),通过数据线连接电脑,来发送短信,用这种方法比较适用于小型及个人。要实现这种方式必须理解串口通信、AT指令、短信编码、解码,这也是本文讨论的重点。
  
    3、 利用一些网站来实现,方式简单,不过对网站依赖性太高,对网络的要求也比较高,非常不适于进行项目开发
  
    
  原理篇
  
    短信编码
  
    在收发短信方面,按时间产生先后,共产生了三种模式:Block Mode、基于AT指令的Text Mode、基于AT指令的PDU Modem, Text Mode比较简单,多款诺基亚手机均支持该模式。西门子的手机大多只支持PDU模式,PDU模式是发送或接收手机SMS信息的一种方法,短信息正文经过十六进制编码后被传送。目前,PDU已取代Block Mode,因我们主要探讨PDU模式的发送。以西门子3508手机为例。
  
    SMS是由Etsi所制定的一个规范(GSM 03.40 和 GSM 03.38)。当使用7-bits编码时,它可以发送最多160个字符;但用8 -bit编码,最多可以发送140个字符,通常无法直接通过手机显示;还有用16-bit编码时,最多70个字符,被用来显示Unicode(UCS2) 文本信息,可以被大多数的手机所显示。我们今天讨论的是UCS2编码,也就是说,最多只能发送70个字符,不管英文还是中文。
  
    现例如我们现在要发送如下信息,向我的手机13715342642发送"你好,Hello!"。在没有发送之前,你要清楚,手机SIM卡所在地的短信中心号,并不是你现在所在地方的短信中心号,像我在深圳,深圳的短信中心号是:8613800755000,即使我现在到外地,短信中心号仍是深圳。从上面我们得到了下面的信息:
  
    接收的手机号:13715342642
    短信中心号:8613800755000
    短信内容:你好,Hello!
  
    在实际使用中,上面这些信息并不为手机所执行,要进行编码手机才会执行,先不管,看看编码后的信息:
  
  0891683108705500F011000D91683117352446F2000800124F60597DFF0C00480065006C006C006F0021
  
    看不懂吧,我来解释一下:
  
    08 - 指的是短信中心号的长度,也就是指(91)+( 683108705500F0)的长度
  
    91 - 指的是短信息中心号码类型。91是TON/NPI遵守International/E.164标准,指在号码前需加'+'号;此外还有其它数值,但91最常用。
  
    683108705500F0 - 短信息中心号码。由于位置上略有处理,实际号码应为:8613800731500(字母F是指长度减1)。这需要根据不同的地域作相应的修改。前面的(08)+(91)+( 683108705500F0)实际上就构成了整个短信的一部份,通称短消息中心地址(Address of the SMSC)。
  
    11 - 文件头字节
  
    00 - 信息类型(TP-Message-Reference)
  
    0D - 被叫号码长度
  
    91 - 被叫号码类型
  
    其实在实际处理中,我们通常把11000D91写死在程序中,因为在国内,这些数据都是不会改变的。
  
    683117352446F2 -被叫号码,经过了位移处理,实际号码为"8613715342642"。上面的(00)+(0D)+(91)+ ( 683117352446F2),构成了整个短信的第二部份目的地址(TP-Destination-Address)。
  
    00 - 协议标识TP-PID,这里一般为00
  
    08 - 数据编码方案TP-DCS(TP-Data-Coding-Scheme),采用前面说的USC2(16bit)数据编码
  
    00 - 有效期TP-VP(TP-Valid-Period)
  
    12-长度TP-UDL(TP-User-Data-Length),也就是4F60597DFF0C00480065006C006C的长度 36 / 2 = 18 的十六进 12
  
    4F60597DFF0C00480065006C006C 006F0021- 这里就是短信内容了,实际内容为:"你好,Hello!"
  
  AT指令
  
    说到AT指令可多了,有厚厚的一本书,不属于我们今天讨论的范围,在这里我仅讨论在发送短信中必须要用的几个AT指令。
  
    与SMS有关的GSM AT指令(from GSM07.05)如表1所示:
  
  AT 指令 功 能
  AT+CMGC Send an SMS command(发出一条短消息命令)
  AT+CMGD Delete SMS message(删除SIM卡内存的短消息)
  AT+CMGF Select SMS message formate(选择短消息信息格式:0-PDU;1-文本)
  AT+CMGL List SMS message from preferred store(列出SIM卡中的短消息PDU/text: 0/"REC UNREAD"-未读,1/"REC READ"-已读,2/"STO UNSENT"-待发,3/"STO SENT"-已发,4/"ALL"-全部的)
  AT+CMGR Read SMS message(读短消息)
  AT+CMGS Send SMS message(发送短消息)
  AT+CMGW Write SMS message to memory(向SIM内存中写入待发的短消息)
  AT+CMSS Send SMS message from storage(从SIN|M内存中发送短消息)
  AT+CNMI New SMS message indications(显示新收到的短消息)
  AT+CPMS Preferred SMS message storage(选择短消息内存)
  AT+CSCA SMS service center address(短消息中心地址)
  AT+CSCB Select cell broadcast messages(选择蜂窝广播消息)
  AT+CSMP Set SMS text mode parameters(设置短消息文本模式参数)
  AT+CSMS Select Message Service(选择短消息服务)
  表一:相关的GSM AT指令
  
    我现在以实例来说明这些指令的使用方法:
  
    先用手机数据线将手机连接到电脑串口,并将串口的波特率设置为19200,可以开始了。
  
    1、首先测试你的连接及手机是否支持AT指令,请在你的串口调试程序中输入:
  
    AT<回车>
  
    屏幕上返回"OK"表明计算机与手机连接正常,那样我们就可以进行其它的AT指令测试了
  
    2、设置短信发送格式
  
    AT+CMGF=1<回车>
  
    屏幕上返回"OK"表明现在短信的发送方式为PDU方式,如果是设置为TEXT方式,则,AT+CMGF=0<回车>
  
    3、 发送短信
  
    发送内容及手要号仍旧同上面在编码中的一样,编码后,得到要发送的数据如下
  
  0891683108705505F011000D91683117352446F2000800124F60597D002C00480065006C006C006F0021
  
    我们用如下指令来发送
  
    AT+CMGS=33<回车>
  
    如果返回">",就把上面编码数据输入,并以CTRL+Z结尾,稍等一下,你就可以看到返回OK啦。
  
    说明一下,为什么AT+CMGS=33呢,是这样得来的:
  
  11000D91683117352446F2000800124F60597D002C00480065006C006C006F0021
  
    这一段字符串的长度除以2得到的结果,上面的字符串,短信中心号加上短信内容得到的,怎么得到的,请回顾一下解码部份
  
    在我们前面的讨论中,一条完整的短信发送,只要执行三条AT指令,AT、AT+CMGS=?、AT+CMGS=?就可以了。由于篇幅,我只能在这里提到这么多,大家要是想了解更多,可以向各手机厂商索取AT指令白皮书,里面很详细的。
  
    上面讲到的,只能为我们实际中作准备,我们还必须要一个发送途径,根据我们的需要,我们选择投资最少,实现比较方便的串口通信。注意,串口通过数据线跟手机相连,用AT指令来实现发送短信,在我们选择数据线时,建议购买原厂所配,非原厂所配,在使用过程中,经常出现一些莫明其妙的问题,比如,手机屏幕黑了,手机老是提示电池电量不足之类的。
    串口通信
  
    在C#中要实现串口通信,很多人都不知所措,在论坛上经常可以看到"怎么用MSCOMM实现串口通信"、"怎样能过串口与设备相连"诸如此类的问题。其实国外的网友早就把这些列入FAQ中了。
  
    通常,在C#中实现串口通信,我们有四种方法:
  
    第一:通过MSCOMM控件这是最简单的,最方便的方法。可功能上很难做到控制自如,同时这个控件并不是系统本身所带,所以还得注册,不在本文讨论范围。可以访问http://www.devhood.com/tutorials/tutorial_details.aspx?tutorial_id =320 ,一个国外网友的写的教程,作者很热心,我曾有发邮件给他,很快就回复了。
  
    第二:微软在.NET新推出了一个串口控件,基于.NET的P/Invoke调用方法实现,详细的大家可以访问微软网站http: //msdn.microsoft.com/msdnmag/issues/02/10/NETSerialComm/default.aspx,方便得到更多资料。
  
    第三:就是用第三方控件啦,可一般都要付费的,不太合实际,不作考虑
  
    第四:自己用API写串口通信,这样难度高点,但对于我们来说,可以方便实现自己想要的各种功能
  
    在本文,我们采用第四种方法来实现串口通信,不过不是自己写,用一个国外网友现成的已经封装好的类库,不过功能简单点,相对我们来说已经够用了。
  
    在整个终端短信的操作过程中,与串口的通信,只用到了四个功能,打开、写、读、关闭串口。下面是类库对这四个功能的定义:
  
    打开串口:
  
    函数原型:public void Open()
  
    说明:打开事先设置好的端口
  
    示例:
  
  using JustinIO;
  
  static JustinIO.CommPort ss_port = new JustinIO.CommPort();
  ss_port.PortNum = COM1; //端口号
  ss_port.BaudRate = 19200; //串口通信波特率
  ss_port.ByteSize = 8; //数据位
  ss_port.Parity = 0; //奇偶校验
  ss_port.StopBits = 1;//停止位
  ss_port.ReadTimeout = 1000; //读超时
  try
  {
   if (ss_port.Opened)
   {
    ss_port.Close();
    ss_port.Open(); //打开串口
   }
   else
   {
    ss_port.Open();//打开串口
   }
   return true;
  }
  catch(Exception e)
  {
   MessageBox.Show("错误:" + e.Message);
   return false;
  }
  
    写串口:
  
    函数原型:public void Write(byte[] WriteBytes)
  
    WriteBytes 就是你的写入的字节,注意,字符串要转换成字节数组才能进行通信
  
    示例:
  
  ss_port.Write(Encoding.ASCII.GetBytes("AT+CGMI\r")); //获取手机品牌
  
    读串口:
  
    函数原型:public byte[] Read(int NumBytes)
  
    NumBytes 读入缓存数,注意读取来的是字节数组,要实际应用中要进行字符转换
  
    示例:
  
  string response = Encoding.ASCII.GetString(ss_port.Read(128)); //读取128个字节缓存
  
    关闭串口:
  
    函数原型:ss_port.Close()
  
    示例:
  
  ss_port.Close();
  
    由于篇幅,以及串口通信涉及内容广泛,我在这里只讲这些。

posted @ 2006-04-19 10:49 高山流水 阅读(2900) | 评论 (7)编辑 收藏

实际上GPRS DTU上实现的是协议栈是TCP/IP Over PPP。我们在使用时必须要有一些相应的概念。因此在下面我们就与SARO-3130P使用相关的一些事项作一些简要的说明,如果您想详细了解这些协议,请参见相关书籍:

1. 每一次SARO-3130P拨ATD*99***1#(或ATD*99***1#)之后其实都在采用PPP协议和移动的接入设备(一般是移动公司的一台特殊的GGSN路由器)进行握手,当PPP协议握手成功后,SARO-3130P都会获得一个动态IP地址。一般来说,每一次SARO-3130P下线后(挂断连接或者直接断电后)在重新进行拨号和PPP握手后取得的动态IP地址都是不一样的。但是移动公司可以通过为客户开通特定的APN和发行特殊的SIM卡,使得用这张SIM卡获得的动态IP地址每一次都不变。也就是说可以做到SIM卡和IP地址绑定。

2.  我们在做测试时,应当注意到如下事实:在采用公网的Apn(“cmnet”)的条件下,如果我们用SARO-3130P主动向公网上的一个静态公网IP地址发起TCP连接,只要这个公网上的机器确实有侦听相应的端口,这样是可以连上的;但是相反地,如果是由公网上的静态IP向SARO-3130P动态获得的IP地址主动发起的TCP连接将不会成功。这个现象的原因是:实际上SARO-3130P获得的动态IP地址是移动的一个特殊的内部网段上的地址,这个特殊内部网段里的地址如果要和外部网(公网)的地址进行TCP通信,必须通过一个类似于TCP代理(或者NAT)的设备进行通信的转发。换句话说,这个动态地址对于网络上的其他机器来说是不可访问的。

3. 标准AT命令+CGDCONT的主要作用是指定Apn。Apn是Access Point Name(访问接入点)的缩写,移动通过开通特殊的Apn为行业客户提供Vpn(Virtual Private Net)服务。比如说,如果是要上公网(Internet),应当使用“cmnet”作为Apn。又如,某企业向移动公司申请了Vpn服务,移动公司为其开通了一个Apn为“hxsw.gd”,则我们就应当用这个Apn来设置Gprs模块,格式如下: AT+CGDCONT=1,“IP”,“hxsw.gd”

4.  确定一条TCP连接有4个要素,这4个要素是双方的IP地址和双方的TCP端口号,这也就是SARO-3130P为什么将本地端口、目的端口和目的IP地址结合起来作为连接的ID号(SARO-3130P在PPP握手成功后获得的动态地址只要不断线重连就不会改变)的原因。

5.  使用TCP协议进行数据通信时,必须要经过三个阶段,第一个阶段是连接建立阶段,第二个阶段是数据收发阶段,第三个阶段是连接释放阶段:

1).连接建立阶段:连接的建立又有主动连接和被动连接之分,一般来说客户机都是主动发起连接的,而服务器是被动接受连接的。

所谓的主动连接是指本方主动向远端发起连接请求, 而被动连接指的是本方侦听一个端口,等待远端及其主动向自己发起一个连接请求并且进行回应并且最终握手建链成功。

在连接成功,切换到数据态后,我们可以通过OPEN命令帧控制SARO-3130P 进行主动连接。当然,连接时要指定对方的IP地址和端口号。至于被动连接,SARO-3130P也可以支持,目前的程序只支持侦听一个端口。对方主动连接(SARO-3130P被动连接)成功后将建立一条新的通信连接,SARO-3130P将把这个被动连接成功的事件通知给上位机。

2).数据收发阶段:当一条连接建立之后,我们就可以在这条连接上进行数据收发了。

我们可以使用SEND命令帧控制SARO-3130P进行数据发送。当然,发送时要指定连接号(通过本地端口、目的地址和端口唯一确定)。

对于对方发送过来的数据,SARO-3130P首先将其存储在自身的数据缓冲区中,然后将数据已到达此事件通知给上位机,上位机读取到数据已到达事件后,应当及时使用RECV命令帧控制SARO-3130P将相应连接上的所有数据通过串口读出,当数据读出后,这些数据原先占用的数据缓冲区空间将会被释放。注意,由于SARO-3130P的数据缓冲区有限(总量仅有25K Bytes),所以,对于对方发来的数据,上位机一定要及时读出,否则数据越积越多,可能会导致数据缓冲区溢出,丢失数据。

3).挂断连接阶段:当一条连接上的所有数据都已经收发完成了,不再需要这条连接时,就可以把连接给挂断了。

和连接建立阶段相类似,挂断也分为主动挂断和被动挂断。

我们可以使用RSET命令帧控制SARO-3130P进行连接的主动挂断。

如果连接被对方主动挂断,SARO-3130P将会把这个事件通知给上位机进行处理。

posted @ 2006-04-19 09:55 高山流水 阅读(623) | 评论 (0)编辑 收藏

enzo的实车图片

我申请不到好用的网络硬盘,就发到自己的邮箱里了。
tamiya_modena@126.com
访问mail.126.com进入,密码:TAMIYA

刹车系统
            http://www.apracing.com/index.htm
            http://www.wilwood.com/products.asp
            http://www.brembo.com/
            http://www.alcon.co.uk/frameset.asp

Data Aquisition:
            http://www.piresearch.com/
            http://www.2d-datarecording.com/home.html

发动机管理及燃油系统
            http://www.fluidcontrol.net/
            http://www.hilborninjection.com/index.asp
            http://www.twminduction.com/
            http://www.haltech.com.au/Products/ECUs/ecus.html
            http://www.electromotive-inc.com/
            http://www.motec.com/
            http://www.msdignition.com/
            http://www.fuelairspark.com/catalog/sequential.asp
            http://www.redlineweber.com/
            http://www.racecar.co.uk/dellorto/
            http://www.atlinc.com/
            http://www.f1systems.com/home.html
            http://www.autronic.com

减震器
            http://www.ohlins.com/contact_home.shtml
            http://www.sachs-race-engineering.de/owx_medien/media40/4062.pdf
            http://www.dynamicsuspensions.com/
            http://www.koni.com/_racing/frame.html
            http://www.penskeshocks.com/

Extinguishers:
            http://www.lifeline-fire.co.uk/history/hist.htm
            http://www.spa-uk.co.uk/design/firesystems.htm


Hose and Fluid Connectors:
            http://www.amfmotorsports.com/goodridgeprod.htm
            http://www.aeroquip.com/pages/lit.html
            http://www.earls.co.uk/


Turbchargers:
           http://www.holset.co.uk/flash/index.html
           http://www.egarrett.com/index.jsp
           http://asp.turbo.com.sg/technical_turbo_fundamentals.asp
           http://www.3kwarner.de/english/03_press/meldungen/01031999.shtml

posted @ 2006-04-08 11:05 高山流水 阅读(176) | 评论 (0)编辑 收藏

http://www.futureme.org/
这个网站可以写一封邮件在指定的日子发给自己。
等到收到自己曾经写好的邮件时。看自己实现了多少梦想,改变了多少,学会了多少,成长了多少,失去了多少。
另外有的邮件是公开的,可以公布自己的想法,而自己可以通过别人的邮件了解别人的世界和思想,
相信会获益良多。
  另外你也可以通过它来试试李开复的报纸测试法,呵呵,把自己的“所作所为”写给自己(写给别人更有效,但可能有风险:P),这样来修正自己的错误,发现自己的优势。
  把它作为一个计划工具表也不错,当然最好不要影响网站的正常运行,毕竟是大家的嘛。
说了这么多,其实我只是写给自己一封邮件罢了。有空多常识,最近很郁闷。。。。

posted @ 2006-04-05 13:10 高山流水 阅读(419) | 评论 (1)编辑 收藏

>

                  有云的地方,就有天下。 
                  有人的地方,就有江湖。
    
    赵客漫胡缨,吴钩霜雪明,银鞍照白马,飒沓如流星。
    十步杀一人,千里不留行,事了拂衣去,深藏身与名…………
    
    江湖,有刀光剑影,有荆棘丛生,有人心险恶,也有豪气干云。
    江湖,有世事无常,有一诺千金,虽险境重重,却精彩纷呈。
    
    任何充满两面性的东西都散发着难以抗拒的奇异魅力,比如罂粟花,比如本*拉登,亦如———江湖。
    
    江湖,现代成人童话里永恒的天堂,无数人梦想置身其中,纵马驰四方,仗剑走天涯,凭一己之力独步武林,惩恶扬善,最终美人得抱,名利双收。无奈现实和梦想的巨大差距磨灭了许多人的壮志雄心。行走江湖,没有一身好功夫怎么行?而自己又确实不是一块练武的料,从小就没进过武校,没削发为僧也没出家为道,无名师指点,无师自通更是遑从谈起。童子功?倒是练过十多年,只是从来不见成效。
    
    好,就是你,今天我要点醒的就是你这种人。
    
    我最近连看了四十集《倚天屠龙记》,几集《射雕》,再加上以前看过的无数本李寻欢、楚留香、陆小凤等武林成功人士的生平传记,得出几点经验。只需详读本文,你的武林之梦即将成为现实。
    
    好,出发吧,临渊羡鱼,不如退而结网。
    
    
    
    
    一、 出身
    
    这里的出身与地主贫农无关,指的是你生下来时候的家庭状况。
    很多人肯定认为最好是生在武林世家,这是个流行的谬误。武林世家从来都出不了旷世大侠。
    比较出名的武林世家如山西彭家,五虎断门刀的绝技世代相传。写哪朝哪代的小说里都有他,但每次出场的第一个镜头不是被故事头号反面人物一掌震死就是被故事头号正面人物一脚踢飞,反正都是绿叶的角色,只起衬托和修饰的作用。
    再如福建林家,和五虎断门刀一样,有祖传的辟邪剑法,却练不出一个高手,才被余沧海灭了满门,终于有个林平之学到了真货,却搞得绝子绝孙,双目已盲。
    
    总之一句话,祖传的东西都是撇火药,害人害己,千万学不得。
    还有比较著名的是四川唐门,以暗器和毒著称。从军事学的角度来看,远程兵器的确比肉搏兵器先进了一大步,可是莫忘了这里是江湖,讲究的是单打独斗,讲究的是光明磊落,暗箭伤人难免被人不齿。所以说四川唐门只是在重蹈萨达姆的覆辙,发展大规模杀伤性武器(暗器)和生化武器(毒),必将遭到武林同道的制裁。
    还有其他一些世家,诸如游家庄(游驹)、牛家村(傻姑)、温家堡(这地名怎么这么耳熟?)、李家城(??)…………等地也千万去不得,投胎的时候,切记切记。
    那么,武林世家不能去,就找一个武林中的大门派,父母都在其中工作,双职工,有车有房。虎父无犬子,自己也可子承父业,成为一代大侠?
    又错!
    所谓虎父无犬子纯粹是一句屁话,谁要是还相信,宋远桥和宋青书就会马上跳出来给他一记响亮的耳光。再往上古走,刘备和刘阿斗?典型的虎父犬子。关羽、关平?一代不如一代。赵云和赵……,赵云的儿子是谁?不知道?那就是无名之辈嘛。
    
    所以,不要以为老爸的侠名远扬会给你带来点什么,那反而可能成为你一生挥之不去
  的阴影,就好比克鲁伊夫之于小克鲁伊夫,少年英才终成仲永。
    
    这也不成那也不成,那最好的出身是什么?下面我来公布正确答案。
    
    是孤儿!
    
    闭上你张大的嘴,把你鼓出来的眼珠子按回去,没错,就是孤儿。
    
    孤儿多好啊,无牵无挂,可以放手干一番大事。比较成功的例子是石破天,从小就不
  知道父母是谁,整天在江湖上漂着,终成一代大侠。
    
    可没有父母的照顾,一个孤儿怎么活啊?
    
    放心,你看江湖上那么多人,从来就没有固定工作,整天东晃西晃,唯一爱好的两件事就是打架和耍个性,可人家不是照样活得好好的,还经常一掷千金,钱根本就不是问题
  。
    
    所以,那么多孤儿成了大侠,不是孤儿的制造成孤儿也要成大侠。所以张翠山夫妇才会被逼死(张无忌的爹妈),所以郭啸天才会就义(郭靖他老爹),所以胡一刀才会被小人害死(胡斐他爸)。
    
    况且,孤儿还有另一个好处,等你学成武艺之后,可以借追查自身身世之名在江湖中上窜下跳东奔西走以求扬名立万。要不然,你整天无所事事的在江湖上晃着,岂不成了追名逐利之辈?老大,我可是想把你塑造成侠义的化身啊,你也给我留点发挥的空间行吗?
  
    
    所以啊,阿弥陀佛,你不当孤儿,谁当孤儿?
    
    但是也有例外。林平之不是也被灭了满门的孤儿吗?为什么他没有成为一代大侠呢?
  
    
    当然,要成为一代大侠,仅仅当个孤儿还是远远不够的,要不然孤儿院岂不成了武林中最强的门派?

  二、 选派
    
    好,现在你回绝了山西彭家、福建林家以及四川唐门等一系列武林世家的请求,同时,也婉拒了陆小凤、杨过以及令狐冲等一系列大侠的邀请,你独自一人来到世间,当你睁开双眼,你发现自己睡在一间破落的茅草屋中,身边没有一个亲人,恭喜!你已经是一个孤儿了。
    
    但是你要戒骄戒躁,要知道孤儿院并非武林中最强的门派,要成为一代大侠,身为孤儿只是万里长征的第一步,以后的路还长。
    
    行走江湖当然要有一身好功夫才行,江湖上门派众多,你准备选哪门哪派呢?
    
    少林,武林泰斗,七十二绝技闻名天下,只要学会其中一两样便可傲视群雄。虽说投身少林须得出家,不能吃肉不能喝酒不能找MM,可为了学武,你忍了。
    
    兄弟,我佩服你,可你还是赶紧从少林寺辞职不干了吧。翻翻整个武林的古代史和近代史,那儿除了达摩祖师以外还出过哪位牛逼人物?达摩祖师怕也是后来的少林和尚吹出来的吧,什么一苇渡江,我想古时候“苇”是一种货币的单位也说不一定。
    
    少林后山的无名老僧?对,他是很牛,慕容博和萧远山两个人加一块儿也干不过他,可他这辈子除了这一把还干过点别的什么事?只有一件事,扫地,隐姓埋名的扫了一辈子地。也许这是他的个人爱好,我们不应该戴着有色眼镜来看无名老僧,但他的行为,确实是与我们原定仗剑走天涯、名利双收的基本原则是背道而驰的啊。况且大材小用,未必就能把小事办好,试想用日月鞭法放羊(那明天可以改行卖羊肉串了),用降龙十八掌打蚊子(最好不要是脸上的蚊子),用龙爪手打牌(用钻石来做麻将先)…………
    
    那么武当呢?和少林一样,难以造就大才。况且张三丰成就太高,你不想一辈子笼罩在他的阴影之下吧?再说这些武林大派,虽然平时名声甚大,却都是浪得虚名之辈,每当武林浩劫来临,他们就变得弱不禁风,轻易被杀得七零八落,根本不抵事(废话,抵事了把我们得主角往哪儿搁?),所以这些门派都不宜选择。
    
    几千年过去了,什么明教、古墓派都早已消声匿迹,少林、武当也日见势危,只有昔日的武林第一大帮————丐帮,如今依然欣欣向荣。你不见,天桥下仍旧散布着他们的眼线,广场上到处奔走着他们的舵主…………
    
    打住,打住,你是想加入丐帮?兄弟,你肯吃苦我也不忍心啊。丐帮自洪七公以后就没出过能人,原因在于他们传销式的经营是行不通的。好比,今天,我把我们系的人全部拉去加入了丐帮,好,我就是丐帮磨子桥分舵的舵主,然后你把你们寝室的人全部叫来加
  入了我丐帮,我就封你为丐帮北园分堂的堂主,享受处级待遇,每天不用去要饭而别人要来的饭你先吃…………。这显然不行嘛,长此以往,一个帮被搞得严重冗员,职务臃肿不堪,急需分流下岗一批…………
    
    算了,还是不讨论丐帮的问题了,反正不能加入丐帮。如果你已经加入了,那请与《武林日报》联系,该报社急需聘请战地记者一名,丐帮人多,唯一的好处就是打探消息较快。
    
    那么,不选这些大派了,选一个普通点的门派可不可以呢?比如,巨鲸帮?
    
    这可万万使不得,巨鲸帮可算江湖上有名的烂派了,武功烂,人也烂。和前面提到的彭家五虎断门刀一样,巨鲸帮也是几乎每本小说必有,该帮帮众一般是从头到尾只会一招黑虎掏心,跑去抢劫又往往遭遇敌军主力,他们的台词通常只有两句,一句是,“此路是
  我开,此树是我栽…………”,另一句是,“英雄,饶命啊,我上有八十岁的老母,下有…………”两句台词一说完就彻底从镜头上消失,是个彻头彻尾的群众演员。
    
    加入巨鲸帮的想法从此休得再提。
    
    那么究竟选谁呢?记住,你要的不是加入哪一门哪一派,也不是要拜谁为师,而是学武功,学世界上最牛逼的武功,绝对不要拘泥于师承和门派。
  
    
    三、 寻师

    
    那到底要怎样才能学到最好的武功呢?把诸位武林成功人士的传记拿来看看吧。
    
    令狐冲,虽为华山弟子,却是在将被逐出师门,面壁于思过崖之时才遇风清扬学到独孤九剑,从此笑傲江湖。
    
    杨过,从全真教到古墓,都没学到什么真本事,直到后来掉入山谷碰见独孤求败那只大鸟(此处指独孤求败生前养的那只大鸟,勿生歧义),才学会玄铁剑法,功力大增。
    
    张无忌,更是在身中玄冥神掌,又坠入山崖,将死之时方学到九阳神功,此后罕逢敌手,独步武林。
    
    …………………………
    
    古语云“天将降大任于是人也,必先劳其心智,饿其体肤,空乏其身…………”他们都是遭遇了一番苦难才学会绝世武功的,所以…………,你明白了吗?有苦难你要去遭受,没有苦难制造苦难你也要去遭受啊。
    
    所谓水逢山则增灵,山逢水则添韵,山水之间乃灵韵之地,你的苦难最好在富含灵气的山水之间经历,成功的机会更大,而那些在城市的高楼上跳下来的人,从来都是死路一条,没看见谁学会了绝世武功。(张国荣)
    
    好了,现在你就可以出发,来到山水之间,看看有没有什么苦难会降临。没有?那么制造苦难吧,跳崖其实不失为一种好的方法。
    
    要成大事,天时地利人和缺一不可,天时需选黄道吉日,人和当有无畏之心,地利?则要好好斟酌斟酌。
    
    强烈推荐:
    
    
    1、 峨嵋山
    
    峨嵋天下秀,人所共知。峨嵋距成都不远,往返车费只需几十块钱。若报必胜之心,确信能有去无回,不成功便成仁,那么车费还可只算单边,花费的确比较合算。峨嵋山风景宜人,此行还可兼做旅游之用,实在是一举两得,何乐而不为呢?
    
    山腰以下都算凡俗之地,不提也罢。自清音阁起,脱俗之感便油然而生。“杰然高阁出清音,仿佛仙人下抚琴。”这种地方绝不缺少世外高人,李白有诗为证:蜀僧抱绿倚,西下峨嵋峰,为我一挥手,如听万棵松…………。李连杰(无名)说,武功琴韵虽不相同,但原理相通,都讲求大音希声之境界…………。峨嵋山能秀出如此琴韵圣手,那必然也孕育得出盖世得武学奇才,所以啊,峨嵋山你算是来对了。
    
    清音阁往上,经十二盘,上华严顶,再到莲花石、钻天坡、洗象池、雷洞坪…………,一路美景尽收眼底,不禁要感叹一下大自然的鬼斧神工。
    
    随行还有貌美声脆的导游小姐一路解说,无须付费,只要悄悄跟随其他旅行团即可。
  
    
    过九十九道拐,金顶就在眼前,再往前的曙光台,就是你寻师学武的最佳之地,还犹豫什么?跳吧。
    
    
    2、 青城山。
    
    青城天下幽,闻名遐迩。青城山条件和峨嵋山相似,也是风景宜人,可一举两得,只
  是青城山离成都更近,花费更低,还有上山缆车索道,可供反复跳崖之用。
    
    
    3、 长白山。
     长白山上终年积雪,跳崖安全系数更大,还有千年人参,可增进内功,更有排毒养颜
  之功效。
    
    千年人参岂是那么好找的?
    
    是啊,有的江湖中人,找了一辈子也找不到,可对于我们的主角,是摔一跟斗都可以
  捡一个起来,这一点在很多武林往事中得到了验证。所以啊,你根本不用担心,去那里你
  可以不带干粮不带钱不带信用卡,就拿千年人参当饭吃。(萝卜?)
    
    
    4、 神女峰
    
    曾闻神女之名,心生敬畏,寒假亲往一看,果然非同凡响。昔日襄王有意,而神女无
  心,此峰亦如之孤高清绝,傲气临云,巍然而立,俯视苍生。下临长江如缠腰玉带,光影
  波澜,过往千帆。此处动静皆宜,俯仰生姿,实乃旅游观光,自杀轻生之胜地。
    
    适合跳崖的名山还很多,以上的仅供参考,还有一些山是欲跳崖学武者的大忌,这里
  也列出来,谨记谨记。
    
    
    1、 塔子山。
    
    虽说车程更短,来往方便,但此山实在太矮,完全没有隐圣纳贤之兆,实在无任何跳
  的意义,仅能供练习之用,兼可做烧烤。
    
    
    2、 珠穆朗玛峰。
    
    此山下抵凡俗,上临九宵,高不见顶。终年冰积雪盖,云遮雾罩,不能说不是一块跳
  崖宝地。无奈海拔实在太高,且常有雪崩,想跳崖之人恐怕还没走到山顶,就被崖跳下来
  砸死。
    
    山上倒是确有圣贤,去年有五名来自北大的武林后起之秀上山求访,不见归来,相传
  已被他收为关门弟子,此番奇遇,羡煞旁人。但只恐我等千里迢迢的赶去,路途遥远,舟
  车劳顿,他却突然宣布非北京户口者不收,乘兴而去,败兴而回,岂不枉然?
    
    所以建议无北京户口者莫登此山,即使真到了此地,也只可做观光之想,勿生杂念。
  
    
    诸多选择,莫看花了眼。切记,登山不是目的,跳崖只是工具。好了,多说无益,快
  选一座山吧,你马上就可以学到绝世武功了
  

  四、 学武
    
    好了,现在你孤身一人来到峨眉山,站在曙光台上,面前云海汹涌,头上天光闪烁,
  如此美景,此生不必再作它想,你两眼一闭,纵身跳下。
    
    你在空中飞着,你自觉身轻如燕,你紧闭双眼,你在想什么?
    
    你现在肯定感觉到作为孤儿的好处了吧,试想如果你不是孤儿,你要到峨眉山跳崖,
  那你鼠目寸光的父母肯定会为你的行程制造最大的障碍。
    
    你的脸干嘛抽搐啊?别怕,别紧张,江湖的确险恶,没一件事情是安全的,吃饭会被
  人下毒,走路会被人暗算,睡觉会被人吹迷香…………,但据我的经验,跳崖却是绝对安
  全的,崖壁上总有一棵树会拦住你,山腰总有几根树藤会把你缠住…………,从来没见哪
  个跳崖的人会死,听说狼牙山五壮士现在都还健在…………
    
    现在你好点了吗?别紧张了,睁开眼,带点微笑,对,就是这个表情。来,跟我一起
  唱郑均的《第三只眼》,一、二、三、“…………我一直以为我自己,是在向上飞,耳边
  传来的声音,似乎非常美,我没想到,我是在,往下坠,往下坠………………”
    
    咦,怎么大半天了都还没被挂住,那些松树、山藤呢?怎么没了?靠!不是叫你们保
  护环境吗?
    
    “咔”,一棵万年老松旁逸斜出,将你拦住,你感激涕怜,差点跪下。松树爷爷啊,
  就算全世界都已把我放弃,至少还有你…………。
    
    “咔”,怎么又有“咔”的一声?什么,万年老松都被你两百斤的体重压断了?靠,
  不是早叫你去减肥了吗?身为一个武林人士怎么可以如此放任自己?
    
    你此时万念俱灰,自认必死无疑。不过你放心,个体的斗争始终无法摆脱宿命的缰绳
  ,你不会死。这不,几根树藤缠住了你,把你悬在半空,树藤从崖壁上一个洞中长出,你
  沿着树藤,爬进了那个山洞。
    
    现在你孤身一人被困于绝壁,上不能上,下不能下,喊天天不应,叫地地不灵,方圆
  一百里之内人迹罕至,你又没带手机,更没有互联网,总之一句话,你出不去了。
    
    
  
  【8】:好,恭喜,兄弟,你有福了。喂,别哭啊,你来看看,你马上会发现洞里流淌着一弯
  清泉,泉水甘甜可口,清冽宜人,可供饮食洗漱之用。这可是正宗的矿泉水啊,如假包换
  ,童叟无欺。你还会发现洞里长着很多蘑菇,将就点吧,山洞里实在也只能长这些东西了
  ,什么,你要吃荤?好吧,你马上又会发现泉水里游着许多小白鱼,而且天生愚钝,极易
  捕捉,这下你每日四菜一汤,都有保障了吧。而且,这些洞里的蘑菇和鱼都绝对无毒,可
  放心食用,且富含维生素C,经常服用可大大增进内功。
    
    好象一般这类山洞里的东西,统统都是大补之物,以后诸位进得其中,请快些动手,
  哪怕一根草也摘来吃了,须知机缘不等人,好东西数量有限,欲抢从速。
    
    你现在饮食无忧,还可增长功力,怎么样,这小日子过得还不错吧?什么,你不喜欢
  吃鱼? ……%¥#%$@……多隆,关门,放狗。
    
    好吧,现在你在洞中饮食数日,内力大增。某一日你无聊之极突然发现洞壁上仿佛有
  一道石门(你大脑缺氧,前几天干什么去了?),可惜开门需要口令。你将芝麻开门、大
  葱开门、天王盖地虎、show me the money、三个代表等历史上一系列著名的口令通通试了
  一遍,门就是不开,你气急败坏,骂道“我操,到底要怎样才行?”,这时,门应声而开
  ,原来口令就是这一句,事情就是这么巧。(这算什么,比这巧的还多着呢)
    
    你欣喜若狂,一跃而进,这是一间石室,你面前有一个或古朴或华丽的箱子,其中似
  乎藏有异宝(几乎是百分之百的有),可惜那是个密码箱,而输错密码会触动机关而死(
  幸好银行的ATM不是这样),没关系,你也不用怕,走过去,闭上眼睛,随便按几下,就是
  那个号码,机缘巧合啊,你又对了(一般都是这样。哥们儿,还练什么武啊,直接去银行
  取钱得了)。密码箱自动打开,里面有一本书,啊!!原来这就是五百年前威震武林,打
  遍天下无敌手的《九天十地菩萨摇头怕怕霹雳金光雷电掌》。
    
    暂停!说到这里插两句,什么武功啊兵器这些,好象都是越古老的越凶,动不动就是
  几百年前的,动不动就是上古秘籍,这已经成为了一个思维定式。兵器就更不说了,上古
  神兵方能所向披靡。照这个推理,历史上武功最高的人可不是什么写《九阴真经》的黄裳
  ,更不是挥刀自宫的东方不败,而是曾经隐居于北京龙骨山周口店的山顶洞人。可山顶洞
  人也不是最厉害的啊,根据达尔文的理论,猴子应该更厉害些啊?也对,要不然孙悟空怎
  么能够大闹天宫,打遍诸神无敌手呢?可孙悟空为什么又被如来佛压在了五行山下呢?因
  为如来佛用的是五行山啊!你还想不通?根据科学考证,早在地球上出现猴子的几亿年以
  前,地壳运动已经把岩石挤压成山体,五行山可比孙悟空老多了。
    
    现在你已经拿到了武林中独一无二的绝顶武功秘籍,高兴吧,那你还等什么,快练啊
  。
    
    什么,你是文盲,不识字?靠,你早说嘛。
    
    好吧,这时石室的角落处走出一个佝偻的身影,千万别怕,他不是鬼,他是这本秘籍
  的第N代传人,是在此地隐居了一百多年的武林老前辈,至于隐居的原因可以有多种,或者
  是被情人抛弃,或者是为了一句誓言,或者是因为看破红尘,反正多半是为了耍个性,这
  原因你可以不管,你只要清楚,他会收你为该门派的第N+1代弟子,并且将这本秘籍的精义
  详细的传授给你,怎么样,有此名师,练成绝世武功不应该再存在任何问题了吧。
    
    什么,老前辈说的是文言文,你听不懂?……好,算你狠(我要是老前辈就一掌劈了
  你),可老前辈他厚德载物,义品仁心,本着我佛慈悲的大无畏精神,只是长叹了一声“
  劫数,劫数啊”,然后一掌按在你的天灵盖,一掌抵在你的丹田,两股浑厚的内家真气输
  入你的身体,几个时辰下来,老前辈已经将毕生功力悉数传给了你,而自己则油竭灯枯而
  死,临死之前还轻轻唱了一句“……俺们那旮都系东北人……”。
    
    你假意悲伤一阵,觉得留在此处已再无意义(反正你是文盲,没有老前辈你无法再有
  进展),你想要出去闯荡一番。你已学会绝世武功,千仞绝壁再也拦不住你,你运起绝顶
  轻功,左脚点右脚背,右脚点左脚背,分分钟就飞到了山顶(完全不符合力学原理)。
    
    好,现在你已有一技傍身,胸中又有雄心壮志,少年英才,意气风发,只等在江湖上
  闯出一番名头。你弓身曲腿,举手遮眉,高瞻远眺,在夕阳下的山顶上摆下几个奇酷无比
  的造型之后,就要转身离去,从此踏上一生的侠义之途…………
    
    慢!专家指出,身负绝世武功和成为万人景仰的大侠之间绝

  五、 取名
    
    现在来回想一下,千百年来万人景仰的大侠都是哪些人?有楚留香、西门吹雪、独孤
  求败、令狐冲、叶孤城…………,现在我来问问,我们最记得的是他们的什么?武功?长
  相?性格?身材?血型?三围?…………
    
    全错!是名字。你没发现这些名字有什么特别之处吗?很好听,很顺口是吧。闯荡江
  湖没有一个响亮的名字怎么行呢?你叫什么?牛大春?靠!叫这种名字还敢来江湖上混!
  没关系,现在江湖上还没人认识你,赶紧改还来得及,反正你是孤儿,姓什么叫什么
  都没人敢管你,现在你又体会到孤儿的好处了吧。
    
    给你取个什么名字呢?要朗朗上口,要有深意,又要让人一听就忘不了…………,这
  不容易,取名可不是一门简单的艺术。
    
    历史上武功最高的人(也就是原始人,原始社会以前的虽然武功更高,但那不能叫人
  )应该没有名字,那时候是依据每个个体的特征来相互辨认的,直到现在还有些原始部落
  保留了这个传统,有电影《与狼共舞》为证,那里面的名字,什么挥拳向天、风中散发、
  踢鸟…………等都是个体特征的描述。可后来人多了,这样取名就行不通了,你挥拳向天
  ,可我也经常向着天挥拳啊,你叫风中散发,可我的头发比你还长…………,怎么办?所
  以需要名字来区分个体,名字就此诞生了。
    
    最早的名字,可能是尧、舜、禹,看看,那时候人的名字多古朴大方啊,可到了黄帝
  那儿,取名就开始兴起浮华之风了。黄帝叫什么名字?靠!你TMD是不是炎黄子孙啊………
  
    
    好了好了,我不骂你了,我忘了你是文盲,有时候我也确实有些冲动。黄帝叫公孙轩
  辕,怎么样,这个名字象个武林高手吧。
    
    闲话就不多说了,下面谈谈怎样给你取名,先谈姓。对普通人来讲,姓是爹妈给的,
  没得选择,可你就不同了,你是孤儿嘛(孤儿好象很拽)。
    
    姓的选择首推复姓。“西门吹雪吹的不是雪,是血…………”这句经典名句你该耳熟
  能详吧。象西门、欧阳、司马、慕容、令狐、独孤…………等都是上上之选。如果实在不
  喜欢复姓,单姓也并非不可,象楚、古、秦、白、江…………等也都是不错的选择。
    
    凡事有两面,有的姓则是行走江湖的大忌。比如金,铜臭味太重,多半是个为富不仁
  的商贾,准备作我们主角的杀富济贫对象吧。牛,乡土气太浓,只适合在你们村员外家当
  个打手。毛,恭喜,赶快去作山贼这份很有前途的职业去吧…………
     总之,姓要儒,要雅,要姓得有内涵,千万不可草率,要慎之又慎,须知姓对名字整
  体感觉的影响是非常大的,比如楚留香,如果姓王,那他可能只是个下岗女工。令狐冲如
  果姓赵,好,电脑城四楼卖盗版光盘的第二个摊位上坐的就是他了。
    
    我个人认为历史上最酷的一个名字是西门吹雪,可为什么大家都姓西门,西门豹就只
  能是个小官吏,而西门庆则注定是个淫贼呢?
    
    姓毕竟不是一切,名也同样重要。和姓一样,名也不能浅薄,要深沉,要朦胧,要有
  诗情,要有画意。同样推荐复名。象公孙轩辕,轩辕二字于朦胧中带着古意,是上佳之选
  。关羽,羽字虽平常,但云长二字尽显悠然之意,一种高手寂寞的感觉马上扑面而来。张
  飞,飞字虽俗,但翼德二字,威猛之势尽出。慕容复姓得那么好,可为什么落得凄惨下场
  ?错就错在名字,如果改叫慕容龙城,那就定是威震天下,势不可挡的武林霸主,如果叫
  慕容秋水,那必然是天资国色,绝代佳人,沉鱼落雁,闭月羞花了。
    
    取名还有个讲究,就是根据你的五行。所谓五行聚则万事兴,所以五行缺一不可,那
  么缺水的就在名字里面加个淼,缺木的加个森,缺金的加个鑫…………
    
    什么,你五行都缺?那你就叫金木水火土吧,怪是怪了点,好记。
    
    有了名字,那还不够,还得有号。苏轼号什么?东坡居士嘛,从此苏东坡之名流传千
  古。不过这里所说的不是这种号,而是江湖上的名号。比较偷懒的方法是用地名加数字再
  加一个鬼、怪、仙、虎…………之类的名词,比较著名的如黄河四鬼、江南七怪、桃谷六
  仙…………等。这种方法看似聪明,实则行走江湖的大忌。你看那些七鬼八怪们每次不是
  被当作黑道扛坝子为祸武林的证据就是被当作白道大侠们除暴安良的舞台,反正几乎都没
  什么好结局。
    
    仔细想想,其实好多著名的武林人士,都没有号,比如张无忌、令狐冲、郭靖………
  …。那些什么长白五虎、塞外三熊之类的,多半是为了烘托气势,营造气氛之用。
    
    不过世事无绝对,楚留香号盗帅,杨过号神雕大侠,独孤求败号剑魔,所以说这个号
  嘛,可有可无。有就必须精,没有也无所谓。(这么半天说的都是废话)
    
    好好想想吧,千百年后当人们传颂你的事迹,首先想起的就是你的名字。牛大春这个
  名字你也想让它流传千古?我看你还是赶紧改行当个兽医比较合适。
    
    再补一句多余的,兽医其实也是一个很有前途的职业,《周渔的火车》相信大家都看
  过了吧。
  

  六、 择兵
    
    现在你肯定想了一个好名字吧,叫司马云长还是令狐春水?好吧,我不管你,反正你
  自己负责。
    
    喂,站住,别忙走啊,你就准备这样赤手空拳的去闯荡江湖?行走江湖,没有一件称
  手的兵器怎么行?
    
    你练的是掌法,不用兵器?俗!简直俗不可奈。你以为兵器只有打架的时候才用?大
  错特错,兵器不仅是杀人的工具,更是个性的象征,气质的表率,内涵的体现。一件好的
  兵器能和你的名字交相辉映,给后人留下更深刻的印象。小李飞刀就是其中一个成功的典
  范。
    
    那么,刀枪剑棍,十八般兵器,该选哪样呢?
    
    首推是剑。剑乃兵中君子,剑是尊贵的象征,古代的帝王将相,不会武功,但都以佩
  剑为荣,王孙公子也多佩剑为装饰,剑的意义,可以说已经远远超过了一件普通的兵器。
  剑,早已洗尽血腥之相,尽剩儒雅之气,一旦拥有,别无所求,实乃行走江湖,杀人灭口
  ,必备工具。
    
    再看江湖历史,历来大侠多用剑,令狐冲、杨过、独孤求败、风清扬、西门吹雪……
  ……一想就是一大堆。用剑,能体现你清雅脱俗的气质,如果有名剑,那更能锦上添花。
  
    
    江湖自古多名剑,数不胜数。
    
    轩辕:昔日黄帝持之于指南车上,驱迷雾,扫阴霾,率应龙旱魃,御百兽而战蚩尤!
  
    
    干将、莫邪:此两剑为名师所铸,威力无比,气宇非凡,持之能开元创世,斩妖除魔
  。
    
    太阿:乃帝王之兵,持之号令天下,莫敢不从。
    
    纯钩:乃将帅之兵,持之能挥兵百万,克敌制胜。
    
    三清:天地生太极,太极生两仪,两仪化三清,而三清生万物。
    
    湛卢:威力毁天灭地,锋利亦冠绝当世,乃千古神兵。
    
    乾坤:此剑左右两边分别以黑白两种奇铁熔铸而成,一黑一白,切合乾坤之道,包含
  阴阳之气。
    
    …………………………
    
    此外还有鱼肠、巨阙、工布、昆吾、龙泉、飞虹…………等等千古名剑可供选择。
    
    名剑虽好,岂是那么容易拿得到的?
    
    你放心,还记得先前石室里面那个密码箱吗?只要你选好一把,你打开密码箱取得秘
  籍的同时,就会发现你心仪已久的宝剑正好躺在里面,爽吧。什么,你要选一把纯金打造
  重一百公斤的剑?……靠!吃我一腿先…………
    
    如果实在不喜欢用剑,刀也可以。不过选刀,就必须要有特点的刀、有个性的刀,比
  如李寻欢的小刀、傅红雪的黑刀、谢逊的屠龙刀。象什么金丝大环刀、厚背紫金大砍刀之
  类的,还是留给先前那位会五虎断门刀的彭家公子用吧。
    
    枪?枪乃百兵之王,刚猛无比,气势如虹,不能说不是一件好兵器。哦,你肯定看过
  《英雄》对不对?不然你怎么会想到枪呢?看过就看过嘛,别不承认,看过《英雄》又不
  是什么可耻的事。那场棋亭大战,甄子丹枪挑秦宫七大高手,再战李连杰,的确打得天花
  乱坠、火光四射,也确实把枪的威猛刚烈表现得淋漓尽致。不过行走江湖,一切以方便为
  先,想想长空那把银枪,起码有一百多斤,江湖险恶,兵刃不可一日离身,每天扛着那一
  百多斤的玩意儿,你当是练举重,累不累啊?
    
    行,你就当是健身,练肌肉,可你也是江湖上有头有脸的人物了,某一天你站在朝天
  门前,手持长枪,临江而立,望江水汹涌东去,如血的残阳照在你刀刻般坚毅的脸上,晚
  风拂起你额前的几缕乱发…………,你正在想这个造型能迷倒多少MM的同时,一个人走过
  来拍拍你的肩,“喂,棒棒,来把这两百斤包谷给我挑到船上去。”你几欲吐血,他却不
  依不饶“别楞着啊,看什么看,还怕我不给你钱吗?”你将来是一代大侠,你胸襟开阔,
  不可能和这人计较太多,可是,多伤自尊啊!
    
    选枪的想法就此做罢。
    
    狼牙棒?喂,大哥,今天我讲的是行走江湖,岳飞抗金的话题下回再说…………
    
    斧?这样兵器对人的外形、气质等要求甚高,你先找块镜子照照自己象不象李逵象不
  象程咬金象不象山丘之王?多半不象,那样的人几千年才出了几个。如果硬要勉强使用,
  反增其乱,你能想象东方不败扔了绣花针手拿一轮板斧千娇百媚的样子?
    
    锤?谁说的锤?来人,给我拖出去毙了…………………………嘣嘣………(枪声)
    
    九齿钉耙?………………
    
    要你命三千?………………
    
    ………………………………………………
    
    I 服了 you ,反正…………(吐了一口血),反正就这些选择了,你随便挑一样吧。
  

  七、 独行
    
    选好兵器了吧,看来你还是有头脑的人,选了一把剑,没有提根狼牙棒来见我。
    
    好,现在你基本上可以出发了,茫茫荒原,天地一色,风舞劲草,乱云飞渡,你白衣
  长剑,独行其中,脱俗离尘,飘然若仙。身负绝世武功,手持轩辕神剑,万事具备只欠东
  风,就差在江湖上创出一番大事业…………
    
    问题是这事业该怎么创呢?一切从小事作起吧,先K几个毛贼涨点经验值再说。
    
    看见了吗?前面路口站着的那位大汉,他就是以前我提到过的巨鲸帮帮众,正在那儿
  拦路抢劫呢,机不可失,失不再来,过了这个村就没这个店了,这可是扬名立万的大好机
  会,别怕,他只会一招黑虎掏心。
    
    你装成手无缚鸡之力的样子走过去(你也真够坏的),他马上开始说他的第一句台词
  :此路是他开,此树是他栽,要想从此过,留下买路财。我知道你是文盲,听不懂文言文
  ,我帮你翻译,他的意思是叫你把现金、信用卡、手机全交出来…………,靠!你还真交
  啊,你来这儿的目的可是为了除暴安良。对,先往地上唾一口,然后一个马步向前,一记
  左勾拳,右勾拳,再说一句:惹毛我的人有危险。
    
    现在你可以听到他的第二句台词了,“大侠,饶命啊,我上有八十岁的老母,下有…
  ………。”
    
    虽然你身负绝世武功,但也须知仁者无敌,作人和做妖一样,要有仁慈的心,有了仁
  慈的心…………说到哪儿去了,反正你宽宏大量,看在他八十岁老母的份上,饶了他一命
  。
    
    巨鲸帮帮众狼狈逃窜而去,围观的村民纷纷报以热烈的掌声,你报拳作揖,朗声说:
  “各位乡亲父老,大家好,小弟我初到贵宝地,望大家多多关照。我叫令狐春水大侠,年
  方二十,今后除暴安良、杀富济贫就是我的职责,望大家多多支持,多多宣传,哈哈哈…
  ………,哈哈哈哈哈…………。”(作仰天长笑状)
    
    周围的村民马上报以更加热烈的掌声和喝彩,虽然这喝彩中偶尔夹有一两句什么“这
  傻B没病吧?”“脑壳有包!”之类的,但也不必在意,须知行走江湖,脸皮不可太薄,否
  则你怒火攻心,一掌将周围的村民全部打成飞灰,岂不成了大奸大恶之徒?
    
    有个伟人说过,人要不断的取得成功,而不要站在一次成功的山顶上停滞不前。你阔
  步离开了喝彩的村民,朝村子中心走去。
    
    前面传来喧闹之声,竟然有人在光天化日之下强抢民女,张员外家的小姐被一个淫贼
  抱着正要离开。定睛一看,此人面目狰狞,手持一把金丝大环刀,竟是老熟人————先
  前提到过的五虎断门刀彭大公子。
    
    你小子真有福气,惩恶扬善的机会又来了,还等什么,上啊,不用担心,他也只是配
  角,对你构不成威胁。你大吼一声:“站住,我令狐春水大侠在此,岂容你如此为祸乡邻
  、欺压百姓,路见不平拔刀相助是我不可推卸的权力和义务,我今天…………”。
    
    行了行了,这句台词还是短一点为好,你没看见彭大公子都走到村口了啊。快点吧,
  让你把这句说完。
    
    “…………我今天就替天行道!”
    
    你冲过去就和彭大公子干上,彭大公子身负五虎断门刀绝学,无奈身为配角,不能与
  你主角相争,只好忍痛被你三招两式打得满地找牙,憋得一腔怒火准备回去一刀把导演劈 了。
      你救得小姐归来,张员外对你千恩万谢,定要设宴款待你,你该怎么办呢?
    其实要闯荡江湖也不用这么急,适当的时候拉近一下和普通百姓的距离也是好的,这 样可以让人觉得你平易近人,即使装装样子也不错。你没发现逢年过节那些领导人都要下到基层和挖煤的人握手和口臭的人聊天和要饭的人拥抱啊。
    那么你就盛情难却、勉为其难的留了下来,一夜的把盏交杯,众乡亲对你佩服万分, 员外对你感恩戴德,小姐对你芳心暗许,怎奈你心有鸿鹄之志,怎可留恋此凡脂俗粉。待众人皆醉之时,你运绝顶轻功,左脚点右脚背,右脚点左脚背,踏着满天的星光飘然仙去 。地上众人烂醉如泥、浑然不觉,只有以茶代酒的小姐,举头仰望星空,脑中回荡着你远去的背影,不禁脸上两行清泪,胸中一缕闲愁。从此其他男人皆如粪土,独身多年终看破 红尘出家峨嵋,此后晨钟暮鼓不绝耳际,青灯古佛长伴身边,日日诵经念佛、焚香点烛,乞求意中人的一世平安,这是后话。
  

  八、 思春
    
    巨鲸帮的势力,在长江以南绝对可以排在前三,而彭大公子的刀法已尽得真传,相信 西南一带使刀比他快的不会超过五人。你现在刚刚出道就接连挫败了财雄势大的巨鲸帮,又打败了五虎断门刀传人彭大公子,顿时声名鹤起,江湖上大小报刊杂志的头版上尽是你 的名字,街头巷尾也四处流传着关于你与牡丹阁头号青楼女子的诽闻,你成了公众人物,你的知名度也随着你代言的唐记飞镖和武当牌毡帽的大受欢迎而骤然升高,你现在是风流 潇洒、年少多金、好事不断、志得意满啊。
    
    那为什么你的脸上始终不见笑容?为什么你始终眉头紧锁?倾诉一下吧,对我还有什 么不能说的呢?
    靠!在我面前你还装什么算啊?我早看穿你的心肝脾肺肾了,不就是因为上一集我让 你离开了张员外家那位小姐吗?帮主,品位太差了吧!
    虽说你现在依旧茕茕孑立,形影相吊,仍然是单影无人相依偎,可是你放心,你没有 命犯天煞孤星,也不会孤独一生,以你现在的身份地位,娶个三妻四妾都不为过………… ,但是,武林豪侠一般都是用情专一、从一而终的,花心是成就正义事业的大敌啊,你不 要跟我说韦小宝,我们这里说的可是武林豪侠。
   那么,要怎样才能找到你那位独一无二的佳人呢?古语云:以铜为鉴可以正形,以史 为鉴可以清心。还是拿本历史书来看看吧。
     胡斐的老婆是谁?苗若男。苗若男她老爸是谁?苗人凤,胡斐的杀父仇人。  
  段誉最爱的是谁?王语嫣。可王语嫣她老妈恨段家的人入骨。
    郭靖他老婆是黄容,黄容他老爸和全真教向来不和。全真七子组成七星剑阵还和黄老 邪干过几架,而他们七个,正好是郭靖的师傅。
    令狐冲他老婆的老爸,也就是他的岳父任我行,其真实身份是黑道扛坝子,江湖公敌
    张无忌,明教教主,正好是赵敏她爹襄阳王通缉令上的头号恐怖分子。
    …………………………
    这样的例子太多太多。
    那现在你知道该怎么做了?想想你的敌人是谁?…………哦,你才出江湖,尚未树敌 ,那么你该想想,你将来是万人景仰的一代大侠,是英勇与侠义的化身,你的敌人还能是谁,当然只有那称霸一方,为祸江湖的黑道扛坝子了。好,现在你就去找他,他将解决你 的姻缘问题。
    可黑道老大行踪不定,神龙见首不见尾,根本就找不到嘛。不用担心,既然上天安排 你和那位佳人将来会在一起,那你不用去找她她自然也会来找你,这叫冥冥中自有天意,上天安排的,最大嘛。
  这不,前方似乎有人向你奔来,莫非你的佳人已经等不及了?你大喜过望,迎上前去 ,才发现根本不是什么绝色美女,而是先前被你打得满地找牙的彭大公子现在邀齐帮手来找你报仇雪恨。你赶忙收回那颗荡漾不已的春心,因为一场恶战已经拉开序幕了。
    你本来就双拳难敌四手,再加上先前憋了一腔怒火的彭大公子现在得到导演的允许放手一搏,就更增其威势。很快你被打倒在地,彭大公子狞笑着就要一刀取了你的性命。突然一团黑影飘然而至,一个身穿劲装(也就是紧身衣)的蒙面女侠从天而降,千钧一发之际救你于水深火热。  
    虽然女侠用黑布蒙着脸,但从她优美的身段你敢肯定她定然是绝色美女,而把脸蒙上更有一番来自阿拉伯世界的异国情调,你流着口水还希望再幻想点什么,但你很快因伤势过重而晕了过去。
    一个时辰之后,你终于清醒了,你马上就可以睁开眼睛看到你梦寐以求的仙子了,恭喜恭喜。
    慢!在你睁开眼睛之前,让我们来想一想你的仙子到底是什么模样呢?外貌就不用说了,当然是美若天仙、倾国倾城,那性格呢?这就要看你喜欢哪一种了。有典雅淑女型的,比如王语嫣、苗若兰,举手投足间尽显大家风范。有古灵精怪型的,比如赵敏、黄容,虽然有时候刁蛮一点,但更为活泼可爱。还有双面娇娃型的,对老公千依百顺,对别人冷酷凶残,比如任盈盈、梅超风…………。
  各种类型不分高下,就如夏荷冬梅、春兰秋菊,各领风骚。你选哪一种呢?
    
    双面娇娃?强!…………算你有个性。
    
    好,现在我数,一……二……三……,你可以睁开眼睛了,你首先看到的是一张纯白色的床,纯白色的被盖和蚊帐,你迫不及待的转过头,看见一个女子对你嫣然一笑,你猛的倒抽了一口凉气,昏了过去。她竟然是————如花!
    为了避免你惊恐和失望交迫而死,我必须向你解释一下,如花只不过是你仙子的丫鬟而已,在这里她的出场纯属友情客串,对你不带任何感情色彩,纯粹是为了衬托你意中人的美丽温柔大方。
  
  九、 遇美
    
    现在你可以放心了,你可以胸有成竹的第二次从昏厥中醒过来了,你一抬头就看见了你的双面娇娃。
    果然不出我所料,长得真是眼如杏、口若樱、身似蛇、肤胜雪(妖怪?),发如瀑、声如莺、胸如…………。不说了不说了,你自己看吧。
    你看得目瞪口呆、鼻血横流,可短暂的兴奋并不能掩盖你已身负重伤,你全身一震,嘴角溢出一丝鲜血。仙子惊叫一声,就要帮你敷药,可是很不巧(其实是很巧),你的伤偏偏在大腿、在腰间或者是在胯下,虽说你并不在乎你的清誉(你也有?),可古代的男女之防甚严,男女授受不亲的至理名言更是人人皆知,仙子此刻真是为难万分。本来这事可以由她的丫鬟如花来做,但算你小子有福,如花宣布她的友情客串只做先前那一幕,并且已经领了工资走人。正当仙子犹豫不决之际,你嘴角又溢出一缕血丝,逼得仙子痛下决心,一咬牙解开了你的衣襟。
    这位古代版的南丁格尔本着大无畏的牺牲精神在你臭烘烘的伤口敷上了某某派的疗伤圣药,但你显然不甘心就此作罢,还要变着法子折磨人家。所以疗伤圣药敷上后你的伤仍然不见起色,反而有加重的趋势。
    仙子暗骂了一声“倒霉!”,在要求改剧本未果之后,看在薪水的份上,她扶你坐起,双掌抵在你的后心,两股内家真气输入你的体内助你疗伤。虽然理论上你只有一成的康复机会,但那只是表面数字,多看武侠片就可知,此时你只须“哇”的喷出一口鲜血就表示你已经好了。当然,这口鲜血你也可以不喷,任由仙子那柔若无骨的双手在你背心不停的按摩,真是春风得意,其乐无穷啊。
    但这回导演可不答应了,在连喊了三声“喷”未果之后,他终于提了一把金丝大环刀站在你的面前。
    你在心中将导演的直系亲属统统操了一遍,终于喷出了一口鲜血。仙子长呼了一口气,将你放平于床上睡下。
    当你终于又醒了过来,仙子连忙告诉你,虽说男女授受不亲,但她给你敷药纯粹是因为救人一命胜造七级浮屠,是本着我佛慈悲的大无畏精神才这样干的,其根本原因在于她和白求恩一样是一个高尚的人一个纯粹的人一个脱离了低级趣味的人。其实她废这么半天话只是要告诉你,她给你敷药并不是因为她看上你了,更不是想占你的便宜。
    不过你不用失望,她只不过是出于一个良家女子应有的羞涩才那样说的,其实早在你赶走巨鲸帮喽罗又击败彭大公子的时候,就已经捕获了她的芳心,从此开始默默的关注着你,并终于逮住机会救了你一命,把你弄回了她的香闺。要不然江湖上每天砍死砍伤那么多人,她干嘛不一一救回来敷药疗伤,或者本着悬壶济世的杏林精神直接开一家武林医院?
    你眼睁睁的看着自己的伤一天天的好起来,又毫无办法,真是恨不得自捅两刀以求在此地再呆个一年半载。但男子汉大丈夫当以事业为重,儿女情长可暂且放在一边,等到最后一集再来解决。
    你们终于要分别了,或者是因为你未来的老岳父急召仙子回家过年,或者是西北某地又发生了一起灭门惨案,你要前去寻找惩恶扬善的机会,反正原因可以有多种。
    送君千里,终需一别,此地长亭古道,碧草连天,仙子劝你更进一杯酒,西出阳关无爱人。
    泣别之际,仙子取下一根发簪放入你手,脸上羞得绯红。从此你俩虽天各一方,但日日睹物思人,牵肠挂肚,乞求明月千里寄相思,却恨月也有阴晴圆缺。 
  也有大胆泼辣的仙子临别之际会送你一肚兜,从此你衣带渐宽终不悔,为伊消得人憔悴,逢年过节初一十五就从枕头下翻出来嗅上一嗅,顿时精神焕发,战无不胜。
   当然,以你现在的武功才智名望地位人品相貌,你不可能不结识其他女子,江湖中将来还会有很多女侠会对你倾心,但要牢记,花心乃武林豪侠的大忌,所以对于这些女子,你要在占尽她们便宜之后告诉她们,其实你一直拿她们当妹妹看(一般都是这样)。她们或许会恼你一时,但绝不会恨你一世,最终都会自动退出,默默的为你俩祝福。
  喂,令狐春水大侠…………,喂,发什么呆,又在想你的仙子啊?最近你的武功退步了很多哦,须知儿女情长之际最易英雄气短,大丈夫当以事业为重,你看最近你在江湖上的人气可降了不少,你代言的唐记飞镖都卖不出去了,武当集团的纳斯达克指数也因为你而降了六个百分点,你该反省反省了。
    好,抛开儿女私情,到江湖上去干点什么惊天动地的事情,重振人气吧。


  十、 除恶
    你终于又回到了江湖上,准备再K几个毛贼赚经验值,可你现在名声在外,巨鲸帮的喽罗再也不敢在你面前嚣张,彭大公子强抢民女的勾当也只有在背着你的时候才作,你整日在江湖上晃着碌碌无为没事可干,你身为一代大侠这成何体统?
    还记得你的出身吗?你是一个孤儿,这下你的身份又派上用场了吧,前面我说过,没事干的时候就去追查你的身世啊。
    有了目标,你就有了动力,从此你每天在江湖中上窜下跳东奔西走南来北往左右逢源前仆后继,或一年半载,或三年两年,你终于在某某武林元老或某某世外高人的口中得知,原来你的父母就是二十年前名震江湖的某某某大侠。为了配合你给自己取的那个惊世骇俗的名字,我们只得暂时让你老爸叫令狐某某大侠。话说令狐某某大侠夫妇在生下你后不久就被奸人害死,你现在必须给他们报仇雪恨,因为你毫无疑问是他们的亲生骨肉,这一点有你肚皮上的胎记屁股上的痔疮和脸上的雀斑为证。
    那么你的仇人是谁呢?经过一番苦苦追查,你终于找出真相,原来当年的奸人就是现在为祸武林,江湖上人人得而诛之的黑道扛坝子。
    前面说过了,黑道扛坝子神龙见首不见尾,行踪飘忽如羚羊挂角无迹可循。可是工夫不负有心人,你终于发现一些蛛丝马迹。
    虽然你没能找到黑道老大本人,但通过追查他的行踪,你发现他正在酝酿着一场大阴谋,而这场阴谋,也就是我以前提到过的武林浩劫。(靠,我简直是先知)至于这场武林浩劫,其形式是多种多样的,或者是把武林中人抓到一海外荒岛加以囚禁,或者是造谣他家祖坟里有异宝引诱大家前去撞机关而死,或者是勾结官府对武林人士加以剿杀,又或者是给每个武林中人发一个美女使其自甘堕落…………,不管怎样,反正良心是大大的坏了。  
  你是正义的化身,当然要把他的阴谋公之于众,使大家早有防备。还记得先前我介绍过的在武林中地位高如泰山北斗的几个门派吗?少林、武当、娥眉,这三个代表马上会主持召开一个名为《关于黑道扛坝子的阴谋及其他若干问题》的武林大会。不过不要对他们期望过高,大会还没开完,他们多半就会因为领导权的分配问题而打得不可开交,之后谁也不服谁,个个心高气傲的割据一方,等着武林浩劫的来临将他们个个击破。
  黑暗势力终于出动了,那些名门正派正如我所说的,都是浪得虚名之辈,三下五除二就被打得人仰马翻。当然,黑老大也没忘了对你下手,由于你最近沉迷于爱情,武功已大不如前,黑老大三招两式将你掀翻在地,眼看你就要一命归西,突然一个人跳出来横在你的咽喉和黑老大的兵刃之间,原来是你的仙子。
  接下来的事是那样的顺理成章,仙子竟然是黑老大的女儿(这一点你不应该感到奇怪),她宣布如果你被杀的话那么她也活不成,同时也苦苦哀求你不要再同她老爸为难。黑老大在长叹了一声“女生外向”之后,放下手中的兵刃对你大吼一声“滚”。而你则用坚毅的眼神勇敢的和这个黑道魔头对视着,似乎在告诉他你绝不屈服,今天一定要战斗到流干最后一滴血,不到黄河心不死不见棺材不掉泪并且见了棺材也不掉泪。
    春水大侠,别硬撑了,快走吧。英雄气概固然重要,却怎么也不如你的小命要紧,须知大丈夫能屈能伸,留得青山在不怕没柴烧,要不,今天就当是你放过他,看在仙子的份上饶他不死?
  你马上就听进了我的顺耳忠言,翻身爬起,捡起你的轩辕剑,独自一人凄然离去。 
  往后的一段时间里你将陷入痛苦的矛盾之中,那父女俩一个对你是杀父之仇,一个则有救命之恩,一个是人人得而诛之的武林公敌,一个则是你的知心爱人,你落入了取与舍的两难境地。在事业和爱情之间,你必须做出生死抉择。
  当然,以你现在的武功,你还没有选择的资格,所以在这段时间之内你将再碰上两三次奇遇,又学会几样绝世武功,其过程和第四章所讲的大致相同。所以如果这奇遇迟迟不来,你尽可往悬崖绝壁之处去,佯装不会轻功多跳它几回。
  经过一番激烈的思想斗争,你终于明白了正义事业重于一切的道理。现在江湖上的杀戮进行得差不多了,敢明着反抗的人已经全部被你的老岳父消灭干净,他已经称霸天下,自封为武林至尊了。
    显然,这时的他已经被胜利冲昏了头脑,他完全忽视了你的存在,或者是大大低估了你的实力,他在明你在暗,你可以轻而易举的找到他,进行一场最后的世纪大战。
    
    有人说武侠和A片的共同点就是最后都以一次大战收场,这也不无道理。如今你身负几种武林绝学,已非当日的吴下阿蒙,老岳父则是功力浑厚,深不可测,你们俩这场大战打得是天昏地暗,飞砂走石,刀来剑往,电闪雷鸣,刀剑齐断之后两个人又拳脚相加,打得花团锦簇,一直打了七天七夜,两个人都…………都饿得爬不起身,最后靠猜拳也好,抓周也罢,反正你赢了你老岳父一招半式。你老岳父心高气傲自认天下无敌,此刻羞愧难当
  ,“哇”的怪叫一声,跳崖自尽。
    想你老岳父处心积虑大半辈子,到头来还不是为你做了嫁衣,你摆平你老岳父部下的残余势力后,终于因拯救了武林而荣获天下第一高手奖,以及万人景仰的一代大侠提名。
  十一、归隐
  现在你昔日的梦想都已实现,走到哪里听到的都是赞誉之声,江湖上人人都景仰你,当年骂你是傻B的村民也跑来向你致以诚挚的歉意,你现在是风头正劲,如日中天啊。
  但你还有一件事情没办好。对,就是你的仙子。虽然你凭借自己的威望和地位在江湖上广布眼线,但始终无法找到佳人的下落,你陷入了深深的内疚和自责当中。
  还记得先前张员外家的小姐吗?后来到峨眉山出家那个。别怕,我的意思不是要你和她重修旧好,这回她可以帮你的大忙,她会跑来告诉你,原来佳人就隐居在峨眉山上白龙洞中,某一日在洗象池沐浴之时被她偶然看到(这佳人也真够胆大)。现在你心急如焚,马上起程直奔峨眉山,踏着旧日寻师学武的足迹,找到了你的双面娇娃。
  虽然她看上去已经心灰意冷,但在你的花言巧语之下很快就会原谅你干掉了她老爸以及违背了当初的誓言(不和她老爸为难)。你们俩就此结成神仙眷侣,笑傲江湖,纵横四方,无拘无束,逍遥自在。辛苦了大半辈子,终于可以享享清富了。
  可就在这时最不幸的消息传来,导演发话了,本故事就拍到此为止,你的江湖生涯结束了。你气坏败坏,提着刀说要杀了导演全家,几个人拦也拦不住,导演没办法,告诉你,最多再给你半个小时让你处理后事。
  你连忙买田置地,和佳人商讨归隐之事,你们择了一处清雅之地,夏日扁舟摘藕,冬 里赏雪观梅,秋来东篱采菊,春至品兰数星,人生之极乐也不过如此了。 
    慢着!我们都忽略了一个重要的问题,你老岳父可是跳崖自尽的,根据江湖惯例,跳崖者绝不会死而只会增强功力,大患未除,武林中一场更大的劫难在即,你怎可现在就封 剑归隐?
    先别高兴得太早,你不会再有出场的机会,本故事仍然得马上结束。而让你老岳父跳崖自尽,这明摆着是为写续集埋下伏笔嘛,这么简单的道理你都不懂?这么多年在江湖上你算白混了。
    你隐居于一个小村落,从此解甲归田,初时觉得新奇,日久难免生厌。你昔日在武林中过得异常精彩,所以说今天你能够安贫乐道纯粹是鬼话。你每天在村子里转悠,逮谁跟谁讲你当初闯荡江湖的牛逼经历,可就是没人相信,还骂你是疯子,这件事让你耿耿于怀,郁闷无比。
    
  幸亏科技的发展,世界变得日新月异。村子里通上了互连网,于是你灵机一动,将当年闯荡江湖的牛逼经历统统写成文章,并贴于网上,既可发泄自己的显赫身世无处炫耀之苦,又可指导武林后生如何闯荡江湖,一举两得啊。
    你们现在知道我的真实身份了吧,我就是当年…………,算了,还是不说为妙。
    怎么样?武林之路的前途还算一片光辉灿烂吧,那就快照我说的话去做啊!前程,是要靠自己去创造di…………

(转载,原出生地不祥)
小小的点评:

本文作者真可谓是得到了金大侠的真传了,我想作者完全有能力自己写部金式小说。说不定可以超过金大侠。

 

 

 

posted @ 2006-04-05 09:15 高山流水 阅读(448) | 评论 (0)编辑 收藏

1、钞票不是万能的,有时还需要信用卡;
  
  2、每个人都应该热爱动物,尤其是煮熟的;
  
  3、要节约用水,尽量和女友一起洗澡;
  
  4、要用心去爱你的邻居,不过不要让她的老公知道
  
  5、每个成功男人的背后,都有一个女人。 每个不成功男人的背后,都有两个;
  
  6、再快乐的单身汉迟早也会结婚,幸福不是永久的嘛;
  
  7、聪明人都是未婚的,结婚的人很难再聪明起来;
  
  8、成功是一个相关名词,他会给你带来很多不相关的亲戚;
  
  9、不要等明天交不上差再找借口,今天就要找好;
  
  10、爱情就象照片,需要大量的暗房时间来培养;
  
  11、后排座位上的小孩会生出意外,后排座位上的意外会生出小孩;
  
  12、现在的梦想决定着你的将来,还是再睡一会吧;
  
  13、应该有更好的方式开始新一天,而不是千篇一律的在每个上午都醒来;
  
  14、努力工作不会导致死亡,不过我不会用自己去证明;
  
  15、工作好有意思,尤其是看着别人工作;
  
  16、神决定了谁是你的亲戚,幸运的是在选择朋友方面他给了你留了余地;
  
  17、两个人的状态是不稳定的,三个人才是!
  
  18、服饰就象铁丝网,它阻止你冒然行动但并不妨碍你尽情的观看;
  
  19、学的越多,知道的越多。知道的越多,忘记的越多。忘记的越多,知道的越少。为什么学来着?

posted @ 2006-04-03 21:55 高山流水 阅读(123) | 评论 (0)编辑 收藏

***************************************/
第一章:Microsoft Windows 和 Visual C++

1,Windows应用程序中一定要有WinMain函数,用来完成某些特殊的任务,其中最主要的是创建应用次序的主窗口。

2,DOS下,所有次序的目标模块在创建过程中都被静态连接起来。而Windows允许动态连接,即一些特定结构的库(DLL)可以在运行过程中被装入和连接,并且被多个应用程序共享。

3,项目是一些相互关联的源文件的集合,这些源文件经过编译、连接,然后被组合在一起形成可执行的Wwindows应用程序或DLL。

4,几个重要Developer Studio创建的中间文件:
CLW (支持ClassWizard ) DSP (项目文件)
DSW (工作空间文件)  NCB (支持ClassView)
OPT (保持工作空间的配置) PLG (建立日志文件)

5,AppWizard是一个代码生成器,它会按照用户通过对话框指定的特性、类名、及源代码文件名来产生Windows应用程序工作架构。AppWizard所产生的代码只是一些最基本的代码,它完成的功能完全由应用程序的基类所决定。

/**************************************/
第二章:Microsoft基本类库应用程序框架


1,按照惯例,MFC库类名用大写“C”打头。

2,类CMyApp的对象theApp就代表一个应用程序。当运行该应用程序的时候,WINDOWS自动调用程序框架内部的WinMain函数,WinMain函数会去查找该应用程序的全局构造对象(theApp),该对象是有CWinApp类派生类的对象。C++中,全局对象在主程序被运行之前就已经构造好了。

3,当WinMain发现该应用程序对象(theApp)时,会自动调用虚拟成员函数CWinApp::InitInstance(),该函数会进一步调用相应的函数来完成主窗口的构造和显示工作。由于基类CWinApp中不知道我们实际需要的什么样的窗口,所以我们必须在派生出的应用程序类CMyApp中重载InitInstance()函数(CMyApp::InitInstance()),由多态性,当调用CWinApp::InitInstance()时候,会自动转向MyApp::InitInstance().

4,WinMain函数调用完InitInstance()函数后,就调用CWinApp::Run函数,CWinApp::Run函数被隐藏在基类中负责传递应用程序的消息给相应的窗口,从而维护应用程序的运转。

5,关闭应用程序(对单一框架程序来说),首先CMyFrame 对象被删除,然后退出Run,进而退出WinMain,最后删除CMyApp对象(theApp)。

6,一些Windows类库在基类为鼠标事件消息以及其他一些标准消息定义一些虚函数,如果需要,派生类会对这些函数进行重载。
MFC库应用程序框架没有采用虚函数来处理Windows消息,而是通过一些宏来将特定的消息映射到派生类中相应的成员函数上。(原因:P21。C++类对程序中用到的每一个派生类都要求有一张虚函数分发表VTABLE,在BTABLE中每个虚函数都需要有一个4字节的入口项,而不管该函数会不会在派生类中被重载。)
MFC消息控件函数要求提供函数原型,函数体,以及在消息映射中的入口。

7,文档-视图结构将数据从用户对数据的观察中分离出来,这样就允许对同一数据可以有多个视图。
MFC库应用程序中,文档和视图是由C++类的实例来描述的。
文档基类代码通常和FILE OPEN,FILE SAVE菜单项关联,而派生文档类则一般用来完成对文档对象数据的实际读写工作。
视图基类通常表示一个包含于框架窗口中的窗口,而派生视图类则常用来和稳当类相联系,负责应用程序的显示和打印机I/O。
派生视图类及其基类共同处理WINDOWS的消息,而MFC库则协调文档,视图,框架窗口,以及应用程序之间的相互作用关系,这种协调多用虚函数来实现。
文档对象既可以与一次可全部读入内存的磁盘文件相关联,也可以同数据库相关联。
 

/********************************************/
第三章:从“Hello,world!”着手学习AppWizard


1,视图:从用户角度看,视图是一个普通的窗口;从程序员角度看,试图是一个从MFC库中CView类所派生的类的对象。视图对象的行为完全由类的成员函数和数据成员决定,其中包括派生类的特定成员和基类的继承而来的成员。

2,CEx03aView类最重要的基类是CWnd和CView。CWnd提供CEx03aView的窗口属性,而CView提供它和应用程序框架其它部分之间的联系,特别是和文档及框架窗口之间的联系。

3,视图类中OnDraw成员函数:OnDraw成员函数被设计成一个虚成员函数,每次当视窗需要被重绘时候,应用程序都要调用OnDraw函数。
当用户改变了窗口尺寸,或当前窗口恢复了先前被遮盖的部分,或当前应用程序改变了窗口的数据的时候,窗口都需要被重绘。
当用户改变了窗口尺寸,或窗口需要恢复被遮盖的部分,则应用程序自动去调用OnDraw函数。
但注意,如果程序中某个函数修改了窗口数据,则它必须通过调用视图所继承的Invalidate(InbalidateRect)成员函数来通知Windows,调用Invalidate后会触发对OnDraw函数的调用。

4,WINDOW中不允许直接访问显示硬件,必须通过和窗口相关联的“设备环境”跟显示硬件通讯。MFC中设备环境由CDC类对象来表示。

5,利用Win32 Debug模式 和 Win32 Release模式开发应用程序。
(默认情况不出现BUILD工具栏,可从TOOLS菜单选择Customize项,设置显示Build工具栏,VC6中也可在工具栏上直接点击右键选择Build工具栏)

  Win32 Release模式 Win32 Debug模式   
源码调试 不能   编译器连接器都允许
MFC诊断宏 不能(定义了NDEBUG) 可以(定义了_DEBUG)
库连接  MFC Release库  MFC Debug库
编译优化 速度优化(学习版不能) 没有优化(快速编译)

我们应在Win32 Debug模式下开发应用程序,然后在发布或交付前用Win32 Release模式重建应用程序。in32 Release模式下建立的EXE文件又小又快。

6,诊断宏TRACE宏对监测程序状态特别有用。这些宏要求在允许追踪的情况下才有效,允许追踪是默认设置。
(问题:TRACE宏的应用事例与运行原理。宏TRACE的输出在在哪显示呢?在output输出框下选择Debug项,调试运行程序即可看到TRACE宏输出。)

7,预编译头文件代表了编译器在源代码特定行上进行‘快照’。在MFC库程序中,快照常紧接在#include "stdafx.h"后进行。
文件StdAfx.h包含了MFC库头文件的#include语句。该文件的内容取决于运行AppWizard时候所做的选择。
文件StdAfx.cpp只包含#include "stdafx.h"语句。StdAfx.cpp文件用来在相应项目的目录下产生预编译头文件(PCH文件)。编译开关/Yc只用于StdAfx.cpp文件,导致产生预编译头文件(PCH),而其它源文件的/Yu编译开关使可以使用一个存在的PCH文件。开关/Fp用来指定专门的PCH文件名,默认情况下为相应目标输出文件目录下与项目同名扩展名为PCH的文件。
(VC6下具体设置参见:[Project Settings属性框] [c/c++]属性页[Project Options]、[Source File Options]项)
(注意:在VC6 [Project Settings属性框]中查看StdAfx.cpp文件[Source File Options]项时候,可以看到[Project Settings, and /Yc"stdafx.h"],这里说明一下,StdAfx.cpp文件的[ /Yc"stdafx.h" ]的设置覆盖了[Project Options]设置中的[/Yu"stdafx.h"])
 

/******************************************/
第四章:基本事件处理、映射模式和滚动视图


1,消息映射:如在视窗中按下鼠标做键,会自动发送WM_LBUTTONDOWN消息,如果要对这消息有所反应的话,需

//{{AFX_MSG(CEx04aView)
 afx_msg void OnLButtonDown(UINT nFlags, CPoint point);//头文件声明消息响应函数原型。
//}}AFX_MSG
DECLARE_MESSAGE_MAP()//头文件

BEGIN_MESSAGE_MAP(CDrawView, CView)//代码文件
 //{{AFX_MSG_MAP(CEx04aView)
 ON_WM_LBUTTONDOWN()//该消息映射宏将OnLButtonDown函数和应用程序框架联系在一起
 //}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CDrawView::OnLButtonDown(UINT nFlags, CPoint point) //代码文件
{
 //event processing code here
}
说明:
为了方便ClassWizard,AppWizard生成了一些注释行。它把消息映射函数原型放在两个AFX_MSG“刮弧对”之间,在AFX_MSG_MAP“刮弧对”之间添加消息映射入口,并在代码文件中给出完整的OnLButtonDown成员函数框架。

2,视图中的OnDraw()是根据视图当前状态来绘制图象的,用户的操作可以改变这中状态。在完整的MFC库应用程序中,文档的对象掌握在应用程序(视图)的状态。

3,如果用全程变量来保存视图状态,这将在多视图情况下会遇到麻烦;(待体会)

4,CWnd::InvalidateRect函数能够触发WM_PAINT消息,该消息被窗口类如CView映射后,引起对OnDraw函数调用,从而重绘无效矩形区域。
优化窗口的绘制过程:
1)设置的无效区域越小,重画的速度就越快;
2)执行无效区域外的绘制纯属于浪费时间,OnDraw函数可以调用CDC的成员函数GetClipBox得到无效区域大小。
注意:
OnDraw函数不仅仅响应InValidate*之类的调用,它也会在窗口改变大小和窗口显露时被调用。

5,本章重要介绍函数
PtInRect(..);//测试一个点是否落在某个矩形内。
PtInRegion(..);//判断一个点是否落在椭圆(CRgn对象)内//A region is an elliptical or polygonal area within a window.
GetClientRect(..);//获得客户矩形坐标并保持在CRect对象中
SelectStockObject(..);//选择the predefined stock pens, brushes, or fonts到DC中,函数返回先前的CGdiObject 对象指针。

6,在构造函数中对类数据成员初始化。
CEx04aView::CEx04aView() : m_rectEllipse(0, 0, 200, 200)//注意这种初试化方式,m_rectEllipse是CEx04aView类数据成员CRect类对象
{
 m_nColor = GRAY_BRUSH;
}

7,[致WIN32程序员]:
 标准的基于WINDOWS应用程序会首先登记一个窗口类(不同于C++类[补:实际是个_WNDCLASS结构体]),同时在处理过程中,还需要对每个类指定窗口过程(WINDOWS PROCEDURE)。每次应用程序调用CreateWindow建立一个窗口时候,都要指定一个窗口类做为参数,这样就把新建立的窗口和窗口过程函数连接起来了。每次Windows给窗口发送消息时候,这个函数就会被调用(补:消息循环中DispatchMessage(&msg)分派消息到窗口的回调函数处理,OS调用窗口回调函数进行处理),以检查用参数传送进来的消息码,并执行适当的代码来处理该消息。
 MFC库应用程序框架有一个适用于大多数窗口类型的简单窗口类和窗口过程函数。该窗口过程函数会根据参数传进来的窗口句柄,在MFC的句柄映射表(handle map)中查找,从而得到对应的C++窗口对象指针。然后,该窗口过程函数用MFC运行时类(runtime class)系统来决定窗口对象的C++类。下一步,它从由消息分发映射函数生成的静态表中找到消息处理函数,最后用正确的窗口对象调用消息处理函数。

8,映射模式:
1)MM_TEXT映射模式:坐标被映射到象素,X值向右递增,Y值向下递增。可用它来表示[设备坐标]。
CDC::SetMapMode(..)//设置映射模式
CDC::GetMapMode(..)
CDC::SetViewportOrg(..)//设置视口原点
CDC::GetViewportOrg(..)
CDC::SetWindowOrg (..)//设置屏幕原点
CDC::GetWindowOrg(..)
2)固定比例映射模式(MM_HIENGLISH,MM_HIMETRIC ,MM_LOMETRIC ,MM_LOENGLISH,MM_TWIPS )
固定比例映射模式均X值向右递增,Y值向下递增,它们之间唯一差别是 实际的比例因子。如下:
MM_HIENGLISH   Each logical unit is converted to 0.001 inch.
MM_HIMETRIC   Each logical unit is converted to 0.01 millimeter.
MM_LOENGLISH   Each logical unit is converted to 0.01 inch.
MM_LOMETRIC   Each logical unit is converted to 0.1 millimeter.
MM_TWIPS   Each logical unit is converted to 1/20 of a point(磅). (Because a point is 1/72 inch, a twip is 1/1440 inch.)
//MM_TWIPS常常用于打印机。        
3)可变比例映射模式:(MM_ISOTROPIC ,MM_ANISOTROPIC )
这两种模式用许我们改变它们的比例因子和坐标原点。
应用这两中模式,如用户改变窗口的尺寸,绘制的图形大小也会发生响应的变化
具体如下:
The MM_HIENGLISH, MM_HIMETRIC, MM_LOENGLISH, MM_LOMETRIC, and MM_TWIPS modes are useful for applications that must draw in physically meaningful units (such as inches or millimeters). The MM_ISOTROPIC mode ensures a 1:1 aspect ratio, which is useful when it is important to preserve the exact shape of an image. The MM_ANISOTROPIC mode allows the x- and y-coordinates to be adjusted independently
常一起使用的函数:
SetWindowExt(..)//Sets the x- and y-extents of the window associated with the device context.
SetViewportExt(..)//Sets the x- and y-extents of the viewport of the device context. 

注意:
When the following mapping modes are set, calls to SetWindowExt and SetViewportExt functions are ignored:
 MM_HIENGLISH,MM_HIMETRIC,MM_LOENGLISH,MM_LOMETRIC,MM_TEXT,MM_TWIPS
When MM_ISOTROPIC mode is set, an application must call the SetWindowExt member function before calling SetViewportExt.

9,坐标变换:(具体参见P54)
许多MFC库函数只能在设备坐标下工作(尤其CRect类成员函数)。可以认为CDC的所有成员函数都一逻辑坐标作参数。可以认为CWnd的成员函数都以设备坐标做参数。(所有在实际窗口上点击获得的坐标都是逻辑坐标)。在设置了设备环境的映射模式及相应的参数以后,CDC的LPtoDP和DPtoLP函数可以用来在逻辑坐标系和设备做表系之间进行转换。
在CView的虚函数OnPrepareDC中设置映射模式要比在OnDraw函数中要好。
//*注意:
CView::OnPrepareDC
virtual void OnPrepareDC( CDC* pDC, CPrintInfo* pInfo = NULL );
应用程序将在调用OnDraw之前调用OnPrepareDC函数。
(OnPrepareDC在为屏幕显示而调用OnDraw函数之前,或在为打印或打印预览每一页而调用OnPrint成员函数之前。)

10,CScrollView支持滚动条的滚动,但不支持键盘的滚动。通过使用CWnd的ScrollWindow和SetViewportOrg函数,CScrollView类允许将视口原点移到窗口中的任何一个位置,甚至包括窗口区域的上部或窗口的原点的左边。

键盘输入是分两步处理的。OS向窗口发送类如WM_KEYDOWN和WM_KEYUP消息时用的是虚拟键盘码,在消息到达窗口之前,被翻译成WM_CHAR消息,该消息带着正常的键码。

利用对WM_KEYDOWN消息进行响应,对按键分别调用OnVScroll就可以使应用程序支持键盘的滚动。
CWnd::OnVScroll 
afx_msg void OnVScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar );
////
nSBCode:
SB_BOTTOM   Scroll to bottom.
SB_ENDSCROLL   End scroll.
SB_LINEDOWN   Scroll one line down.
SB_LINEUP   Scroll one line up.
SB_PAGEDOWN   Scroll one page down.
SB_PAGEUP   Scroll one page up.
SB_THUMBPOSITION   Scroll to the absolute position. The current position is provided in nPos.
SB_THUMBTRACK   Drag scroll box to specified position. The current position is provided in nPos.
SB_TOP   Scroll to top.
////
The framework calls this member function(OnVScroll) when the user clicks the window’s vertical scroll bar.


11,CView::OnInitialUpdate
virtual void OnInitialUpdate( );
说明:
OnInitialUpdate是视图窗口完全建立后框架调用的第一个函数。框架在第一次调用OnDraw前会调用OnInitialUpdate。
具体参见下:
Called by the framework after the view is first attached to the document, but before the view is initially displayed. The default implementation of this function calls the OnUpdate member function with no hint information .

12,MFC对140种Windows消息直接直接提供了相应的消息控制函数,当然,我们还可以定义自己的消息和相应的消息控制函数。
五种特殊Windows消息:WM_CREATE,WM_CLOSE,WM_QUERYENDSESSION,WM_DESTROY,WM_NCDESTROY.(具体参见 p62-63页。这两页强烈建议看看,这里简要笔记三个最常用最重要的)
1)WM_CREATE消息:
The WM_CREATE message is sent when an application requests that a window be created by calling the CreateWindowEx or CreateWindow function. The window procedure of the new window receives this message after the window is created, but before the window becomes visible. The message is sent before the CreateWindowEx or CreateWindow function returns.
2)WM_CLOSE消息:
当关闭窗口或父窗口被关闭时,Windows都会发送WM_CLOSE消息。可以重新定义该消息响应函数OnClose来完全控制关闭过程。
3)WM_DESTROY消息:
Windows在发送WM_CLOSE消息之后,紧接着就会发送WM_DESTROY消息(响应这个消息的时候,窗口已经消失但还没有销毁)。
(可以响应这个消息来做一些销毁当前窗口后的一些事情,例如再弹出其它对话框发送其他的消息)
 

/**********************************************/
第五章:图形设备接口(GDI)、颜色及字体

1,任何时候当程序需要直接在屏幕或打印机上绘图的时候,都需要调用GDI函数,GDI函数包含了一些用于绘制图形、位图以及文本的函数。

2,Windows的设备环境是GDI的关键元素,它代表了物理设备。每一个C++设备环境对象都有与之对应的Windows设备环境,并且通过一个32位类型的HDC句柄来标识。

3,MFC库设备环境类基类CDC包含了绘图所需要的所有成员函数,并且几乎所有派生类只有构造函数和析构函数不同(CMetaFileDC类除外)。
对于显示器来说,常用的派生类有CClientDC 和 CWindowDC,而对其它设备(如打印机或内存缓冲区),则可以构造一个基类CDC的对象。
对于显示器和打印机设备环境对象来说,应用程序框架会直接将句柄附在对象上;而对其它设备环境(如内存设备环境),为了将对象与句柄相联系,在构造完对象之后,还必须调用一个成员函数(进行初试化)。

4,CClientDC类 和 CWindowDC类
CClientDC( CWnd* pWnd );
//Constructs a CClientDC object that accesses the client area of the CWnd pointed to by pWnd. The constructor calls the Windows function GetDC.

CWindowDC( CWnd* pWnd );
//Constructs a CWindowDC object that accesses the entire screen area (both client and nonclient) of the CWnd object pointed to by pWnd. The constructor calls the Windows function GetWindowDC.

如果构造CClientDC对象,则设备环境的映射区域限于客户区域,不能在客户区域外绘图。原点(0,0)在客户区左上角。
《 如果创建CWindowDC对象,则设备环境的映射区域为整个窗口(包括标题栏、状态栏、窗口边框等)。原点(0,0)在整个窗口的左上角。》
注意:
1)视图窗口没有非客户区域.
2)视图窗口覆盖在框架窗口之上。
3)在《》中的内容,是我根据测试所理解的。翻译原文中映射区域是整个显示屏幕,原点(0,0)在整个屏幕的左上角。这显然是不对的。

5,在创建了一个CDC对象后,一定要注意在完成任务后将其删除。(如果用CClientDC 或 CWindowDC来在堆栈中构造一个DC对象,则不需要我们显式的删除它,CClientDC或CWindowDC对象会在它的生命周期结束的时候自动调用析构函数来完成删除工作)
例如:
CDC *pDC=GetDC();
...
RealeaseDC(pDC);
说明:
CDC* GetDC( );//CWnd::GetDC 获得与当前窗口相关联的CDC对象指针(映射窗口客户区域)
int ReleaseDC( CDC* pDC );//CWnd::ReleaseDC 释放与当前窗口相关联的设备环境

注意:
在MFC程序中,千万不能自己添加代码删除作为参数以指针形式传递给OnDraw(CDC* pDC)函数的CDC对象,应用程序会自动控制它的删除。

6,当利用CDC对象绘图的时候,所绘制的图形都要依赖于设备环境的状态:如画笔、画刷、字体等GDI绘图对象 和 当前映射模式的选择等。
可以使用CDC成员函数了设置所需要的饿设备环境状态。如:SelectObject()函数可将GDI对象随时选入设备环境中。

7,CPaintDC类:当需要重写OnPaint函数的时候,就需要使用CPaintDC类。默认的OnPaint函数会使用已经设置好的设备环境来调用OnDraw函数
注意:CPaintDC类的构造函数和析构函数所完成的工作都是针对显示用的。
例:
void CMyView::OnPaint()
{
CPaintDC dc(this);
OnPrepareDC(&dc);
dc.TextOut(0,0,"for the display,not the printer");
OnDraw(&dc);
}
说明:
1)CPaintDC( CWnd* pWnd );
//CPaintDC::CPaintDC Constructs a CPaintDC object, prepares the application window for painting, and stores the PAINTSTRUCT structure in the m_ps member variable.
2)CPaintDC类的构造函数自动调用BeginPaint,而它的析构函数会自动调用EndPaint.
3)CDC* BeginPaint( LPPAINTSTRUCT lpPaint );
//CWnd::BeginPaint Prepares CWnd for painting and fills a PAINTSTRUCT data structure with information about the painting.
void EndPaint( LPPAINTSTRUCT lpPaint );
//CWnd::EndPaint Marks the end of painting in the given window. The EndPaint member function is required for each call to the BeginPaint member function, but only after painting is complete.
问题:
1)在View类中一旦定义了OnPaint()函数,则WM_PAINT消息由OnPaint函数来响应。OnDraw函数不再被调用。原因?


8,GDI对象:
Class   Windows handle type

CPen   HPEN
CBrush   HBRUSH
CFont   HFONT
CBitmap  HBITMAP
CPalette  HPALETTE
CRgn   HRGN
说明:
Each graphic-object class in the class library has a constructor that allows you to create graphic objects of that class, which you must then initialize with the appropriate create function, such as CreatePen.

Each graphic-object class in the class library has a cast operator that will cast an MFC object to the associated Windows handle. The resulting handle is valid until the associated object detaches it. Use the object’s Detach member function to detach the handle.

9,CGdiObject类有一个虚析构函数,在其派生类的析构函数将与C++对象相关联的WINDOWS GDI对象删除掉。如果构造了一个CGdiObject派生类对象,则在退出程序之前,必须将其删除掉。
利用CDC类的SelectObject成员函数把自己的GDI对象选进DC的同时,保存原来的GDI对象,当任务完成后,恢复原来的GDI对象,这样就可以将自己的GDI对象的删除掉。
如:
GDIStyle *poldGdiObject=pDC->SelectObject(&newGdiObject);
...//完成任务
pDC->SelectObject(poldGdiObject);

10,Windows对任何企图删除库存GDI对象的行为都不予理会。可以利用SelectObject函数把库存GDI对象选入,从而删除当前GDI对象。
原因:
This function SelectObject may return a pointer to a temporary object. This temporary object is only valid during the processing of one Windows message.
如:
pDC->SelectObject(&newGdiObject);
...
pDC->SelectStockObject(StockCGdiObject);//如:BLACK_BRUSH

11,对于显示设备环境,在消息处理函数内部所进行GDI选择在函数退出后不再有效,因此在进入其他处理函数的时候,每次都必须重新设置设备环境。
Windows句柄是唯一能够持久存在的GDI标识。可以使用GDI对象指针调用GetSafeHandle函数可以获得它Windows句柄,再利用GDI对象类的FromHandle函数将句柄转化为对应的GDI对象。
如:
CFont *pOldFont=pDC->SelectObject(&newFont);
m_hOldFont=(HFONT)pOldFont->GetSafeHandle();//m_hOldFont为数据成员,保存先前字体对象句柄
...
pDC->SelectObject(CFont::FromHandle(m_hOldFont));//可在其他函数中,恢复m_hOldFont句柄对应的字体对象。
说明:
1)static CFont* PASCAL FromHandle( HFONT hFont );
//CFont::FromHandle Returns a pointer to a CFont object when given an HFONT handle to a Windows GDI font object. If a CFont object is not already attached to the handle, a temporary CFont object is created and attached.
2)CGdiObject::GetSafeHandle();
//Return A HANDLE to the attached Windows GDI object; otherwise NULL if no object is attached.

12,每一种Windows颜色都是 通过8位的红(R)、绿(G)、蓝(B)的值祝贺来表示的。
面向颜色的GDI函数可以接收32位的COLORREF参数。Windows的RGB宏可以将8位的红绿蓝值转化成COLORREF参数。
说明:
1)The COLORREF value is a 32-bit value used to specify an RGB color.
2)16种标准VGA纯色参见 P70页;256显示卡 多增加4种标准色参见 P71页。

13,字体是GDI对象,在使用上和其它的GDI对象完全一样。
CDC::GetTextMetrics 
BOOL GetTextMetrics( LPTEXTMETRIC lpMetrics ) const;//测量字体高度等参数

14,GetDeviceCaps();
//Retrieves a wide range of device-specific information about the display device.

 

/**************************************/
第六章:模式对话框和Windows通用控件

1,对话框也是窗口,它不当可以接受消息,而且还可以被移动和关闭,甚至可以在它的客户区中进行绘图操作。

2,模式对话框在被关闭之前,用户无法在同一应用程序的其它地方进行工作。模式对话框更易于编程。
无模式对话框在它仍保留在屏幕的同时,用户还可以在应用程序的其它窗口进行工作。

3,对话框控件既可以通过CWnd指针来引用,也可以通过资源文件定义的索引值(和#define常量相关联)来引用。对话框控件本身就是一个窗口。控件通过向上级对话框发送消息来响应用户的动作。
利用ClassWizard可以帮助产生CDialog派生类,还可以使对话框类数据成员和对话框控件相联系。

4,在现存在项目中添加模式对话框步骤:
1)用对话框编辑器创建包含各种控件的对话框资源。对话框编辑器会对项目的资源文件更新,使之包含新的对话框资源,并且该项目的resource.h文件也会被更新,以便能够包含新的#define常量。
2)利用ClassWizard创建CDialog派生类,并将它和第一步所创建的资源相连接。
3)利用ClassWizard添加控件消息响应函数,并进行编辑。
4)在其它类中需要使用地方先构造该对话框类对象,再调用DoModal显示模式对话框。
说明:
1)在产生的对话框头文件中包含一个枚举类型常量IDD,用于设置该对话框资源ID。枚举常量IDD的使用减弱了CPP文件对资源ID的依赖。
2)《在其它类中显示模式对话框后,只有当模式对话框退出后,才继续执行该类显示模式对话框代码后的代码。》

5,在组合筐中Data属性页下,添加一条后按CTRL+RETURN来结束(或添加下条item)。(VC6中按?键可以获取相关帮助提示的)。组合框有Simple,Dropdown,Drop List三中风格,可以是Styles中选择。
列表筐中,用户只能用鼠标选择选择一个条目,而且在对话框编辑器中不能输入列表框的初始选择条目。
在静态文本控件中可以内置'&'符号。运行时候,&符号后面的字符下将有一个下划线。用户在按下ALT键后同时按下相应带下划线的字母,则就可以跳转到相应的控件上去。注意同一对话框中跳转字符不能重复。

6,当DoModal被调用后,实际在幕后引起一系列如下的动作:
CDialog::DoModal->CEx06Dialog::OnInitDialog->其它的初始化->CDialog::OnInitDialog->CWnd::UpdateData(FALSE)->CEx06Dialog::DoDataExchange
用户输入数据...
用户单击OK按钮
CEx06Dialog::OnOk->...其它的确认处理...->CDialog::OnOk->CWnd::UpDateData(TURE)->CEx06Dialog::DoDataExchange->CDialog::EndDialog(IDOK)
说明:
1)virtual BOOL OnInitDialog( );
//CDialog::OnInitDialog This member function is called in response to the WM_INITDIALOG message. This message is sent to the dialog box during the Create, CreateIndirect, or DoModal calls, which occur immediately before the dialog box is displayed.
//Override this member function if you need to perform special processing when the dialog box is initialized.

2)BOOL UpdateData( BOOL bSaveAndValidate = TRUE );
//CWnd::UpdateData :Call this member function to initialize data in a dialog box, or to retrieve and validate dialog data.
//bSaveAndValidate:Flag that indicates whether dialog box is being initialized (FALSE) or data is being retrieved (TRUE).
//By default UpdateData(TRUE) is called in the default CDialog::OnOK handler and UpdateData(FALSE) is called in the default CDialog::OnInitDialog.

3)virtual void DoDataExchange( CDataExchange* pDX );
//CWnd::DoDataExchange  Called by the framework to exchange and validate dialog data.
//Never call this function (DoDataExchange) directly. It is called by the UpdateData member function.
//Call UpdateData to initialize a dialog box’s controls or retrieve data from a dialog box.

4)void EndDialog( int nResult );
//CDialog::EndDialog  makes the dialog box invisible but does not destroy it.
//Call this member function to terminate a modal dialog box. This member function returns nResult as the return value of DoModal(IDOK表示接受对话框数据,IDCANCEL表示取消对话框数据). You must use the EndDialog function to complete processing whenever a modal dialog box is created.
//注意:If you implement the OK button in a modeless dialog box, you must override the OnOK member function and call DestroyWindow from within it.

5)当DoModal函数返回的时候,对话框窗口不再存在。我们可以在堆栈中创建模式对话框对象,这样就可以保证当程序控制转向到C++对话框对象所在的范围之外时,它及时的删除掉。


7,代码解释:
void CEx06aDialog::DoDataExchange(CDataExchange* pDX)
{
 CDialog::DoDataExchange(pDX);
 //{{AFX_DATA_MAP(CEx06aDialog)
 DDX_Text(pDX, IDC_BIO, m_strBio);//
 DDX_Radio(pDX, IDC_CAT, m_nCat);
 ...
 DDV_MinMaxInt(pDX, m_nSsn, 0, 999999999);
 //}}AFX_DATA_MAP
}
说明:
1)DoDataExchange、DDX_(交换)、DDV_(确认)函数都具有双向性。如果调用UpdateData(FALSE)(参数为FALSE),则这些数据就会将与控件相关联(值关联)的数据成员的值传递给对话框中的控件;相反,如果UpDateData(TURE)(参数是TURE),则这些函数会将数据从对话框控件中传递给与之相关联(值关联)的数据成员。
2)这里DDX_Text函数被重载,具体参阅MSDN。The DDX_Text function manages the transfer of int, UINT, long, DWORD, CString, float, or double data between an edit control in a dialog box, form view, or control view and a CString data member of the dialog box, form view, or control view object.
其它DDX_函数参阅MSDN。

8,Enter键触发OnOk函数调用:
当用户按下ENTER键后,OS会自动去查找输入焦点落在哪个按钮上,获得焦点的按钮四周将被点线矩形框包围。如果所有的按钮都没获得输入焦点,则OS会自动去寻找程序或资源所指定的默认按钮(默认按钮边框较粗)。如果对话框没有默认按钮,那么即使对话框中没有OK按钮,OnOk函数也会自动被调用。
由于OnOk函数是虚函数,可以重写OnOk函数,将其函数体置空,变可以使使ENTER键无效。
分离OK按钮:改写OK按钮ID,并除掉其默认按钮(Default Button)的设置。

9,p107至WIN32程序员:强烈建议看看,下为简要笔记。
对话框控件会向他们父对话框发送WM_COMMAND通告消息。大多数窗口程序处理函数都是通过一个嵌套的switch结构了处理这些通告消息的,而MFC则更直接了当地把这些控件通知消息和其它的Windows消息放在同一个层次上处理。

10,Esc键触发OnCancel函数的调用,导致控制从对话框中退出,如果是模式对话框则DoModal的还返回IDCANCEL值。其消除方法同ENTER键。

11,事例代码涉及的一些主要函数及补充说明:
1)CWnd* GetDlgItem( int nID ) const;//可用它来获取对话框上控件指针(返回的时候,强制转换成所需要的控件指针),注意临时性。
   void CWnd::GetDlgItem( int nID, HWND* phWnd ) const;
//Retrieves a pointer to the specified control or child window in a dialog box or other window. The pointer returned is usually cast to the type of control identified by nID.
说明:如果需要包CWnd指针转化成一个控件ID,则可以使用MFC中CWnd类GetDlgCtrlID成员函数。
2)GetScrollPos  Retrieves the current position of a scroll box.
   SetScrollPos  Sets the current position of a scroll box.
   GetScrollRange  Retrieves the current minimum and maximum scroll-bar positions for the given scroll bar.
   SetScrollRange  Sets minimum and maximum position values for the given scroll bar.
3)afx_msg void OnHScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar );//CWnd::OnHScroll 
afx_msg void OnVScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar );//CWnd::OnVScroll 
3)所有的水平滚动条都绑在WM_HSCROLL消息控制函数,所有的竖直滚动条则都绑在一个WM_VSCROLL消息控制函数上。(一般控件都有自己的独立的消息控制函数,但[滚动条控件]有点不同,所以对同一个对话框多个滚动条消息处理的时候,一般都将它们的滚动范围设置一致,方便编程)


/////////////////////////
/////////////////////////
///P109-125页内容笔记待续
12,每个控件在显示之前会向其父对话框发送WM_CTLCOLOR消息,对话框本身也会发送该消息。
《对话框和对话框控件都是窗口,也可以在这些窗口中进行绘图操作。(添加OnPain函数,调用Invalidate/UpdateWindow让窗口重绘)》

13,在运行时加入对话框控件:
一般步骤:
1)在对话框类中添加一个内嵌的控件窗口数据成员。一个内嵌控件C++对象将与相应的对话框对象一起被构造和删除。
2)从View菜单中选择Resource Symbols,为新的控件添加一个ID常量。(也可以在Resource.h中用定义)
3)用ClassWizard映射WM_INITDIALOG消息覆盖(Override)基类 CDialog::OnInitDialog函数。在该函数里调用控件窗口的Create成员函数,并显示新的控件(可以用ShowWindow函数)。Windows回在删除对话框窗口的同时也删除该控件窗口。
4)在派生对话框类里,为新控件手工加入必要的通知消息控制函数。(三步:消息控制函数原型说明,消息映射,消息处理函数)

14,Win32编程经验:父窗口和控件之间是通过Windows消息进行通信的(如MFC中象CListBox::InserString函数),但适用于所有窗口类型的控件类成员函数并不发送消息,而是调用Win32函数。

15,Windows通用控件:Win95引进的象[进度指示器],[滑杆条],[微调按钮控件],[列表控件]和[树状控件]。这些控件的代码在Windows的COMCTL32.DLL文件中,其中包括了每个控件的窗口过程函数,及每个控件的注册窗口类的代码,这些注册代码在DLL加载时候被调用。当应用程序初始化对话框时,将使用对话框资源中符号化的类名,来连接到DLL里的窗口过程函数上。这样应用程序就有了控件的窗口,但代码实际上在DLL里。
除了ActiveX控件,大多数控件都是用这种方法实现的。

16,WM_NOTIFY
    idCtrl = (int) wParam; //控件ID
    pnmh = (LPNMHDR) lParam; //指向NMHDR结构指针,该结构由控件管理。
说明:
1)Sent by a common control to its parent window when an event has occurred in the control or the control requires some kind of information.
2)Not all controls will send WM_NOTIFY messages. In particular, the standard Windows controls (edit controls, combo boxes, list boxes, buttons, scroll bars, and static controls) do not send WM_NOTIFY messages.

/////////////////////////
/////////////////////////
///P115-125页内容笔记待续

 

/*****************************************/
第七章:无模式对话框 和 Windows通用对话框类

1,[无模式对话框]在它处于激活状态下还允许用户在(同一个应用程序中)其它地方工作。
   [通用对话框]则是C++和一组Windows的实用对话框之间的程序设计借口,包括File Open,Page Setup,Color等等,它们都是通过COMDLG32.DLL来实现的。

2,两种发送Windows消息:
CWnd::SendMessage//立刻导致对窗口控制函数的调用
CWnd::PostMessage//将消息放进Windows消息队列。对消息的处理可能被滞后。
具体:
1)LRESULT SendMessage( UINT message, WPARAM wParam = 0, LPARAM lParam = 0 );
//Sends the specified message to this window. The SendMessage member function calls the window procedure directly and does not return until that window procedure has processed the message. This is in contrast to the PostMessage member function, which places the message into the window’s message queue and returns immediately.

2)BOOL PostMessage( UINT message, WPARAM wParam = 0, LPARAM lParam = 0 );
//Places a message in the window’s message queue and then returns without waiting for the corresponding window to process the message. Messages in a message queue are retrieved by calls to the GetMessage or PeekMessage Windows function.

3,对话框实际上应该属于应用程序的主框架窗口,而不属于视图。(对话框默认弹出特性)
(注:还未领悟,先留着。)

4,对话框窗口的创建和取消完全取决与用户的操作,而对话框对象则将直到应用程序被终止时才会被删除。
(除了主框架窗口之外,对于几乎所有的窗口类型,DestroyWindow函数都不会将C++对象删除掉。所以要注意手动添加删除对话框对象代码)

5,Windows 常量WM_USER是用户自定义消息中可以利用的第一个消息ID。
#define WM_USER       0x0400
//The WM_USER constant is used by applications to help define private messages, usually of the form WM_USER+X, where X is an integer value.
说明:
1)CWnd::PostMessage//发送消息。利用wParam , LPARAM可以向响应消息的处理函数传送附加数据信息。
BOOL PostMessage( UINT message, WPARAM wParam = 0, LPARAM lParam = 0 );
2)在WIN32中,用wParam 和LPARAM参数来传递消息数据是最常用的手段(如:将鼠标的X,Y坐标压缩进lParam)。而在MFC库中,消息数据可以更多样的类型来传递(如:可以CPoint对象来传递鼠标信息)。
对于用户自定义消息,只能使用wParam 和LPARAM参数来传递消息附加数据信息。
3)案例说明:
在对话框类中:
#define WM_GOODBYE WM_USER + 5//定义自定义消息
m_pView->PostMessage(WM_GOODBYE, IDOK);//向View类发送WM_GOODBYE消息,附加消息IDOK存放在wParam 中。m_pView指向当前View类对象。
在View 类对象中
afx_msg LRESULT OnGoodbye(WPARAM wParam, LPARAM lParam);
ON_MESSAGE(WM_GOODBYE, OnGoodbye)
LRESULT CEx07aView::OnGoodbye(WPARAM wParam, LPARAM lParam)
{
 return 0L;
}
4)技巧:在对话框类中重载构造函数,参数为CView*指针。再在对话框类中定义一个CView*指针数据成员。这样,如果在View类中通过传入this指针来构造对话框对象的时候,对话框类中CView*指针数据成员可以在带参数为CView*指针重载构造函数里方便获取构造它的View类指针。

6,ClassWizard并不支持用户自定义消息的响应,所以当使用用户自定义消息编程的时候,必须自己编写自定义消息的处理代码。(三步,首先是消息响应函数原型声明,其次消息映射,最后是编写消息响应函数代码。这里要注意:用户自定义消息的消息映射一定要加在BEGIN_MESSAGE_MAP(..)~~END_MESSAGE_MAP()之间,//{{AFX_MSG_MAP(CEx07aView)~~ //}}AFX_MSG_MAP注释宏对之外)

7,对于无模式对话框一定要注意不要调用CDialog::OnOk或者CDialog::OnCancel函数,既在无模式对话框类中必须重载这些虚函数;否则当使用ESC键,回车键或者用鼠标单击OK|CANCEL按钮的时候,会激发对应基类函数的调用,进而导致调用Windows 的EndDialog函数,EndDialog函数只适合于模式对话框。对于无模式对话框,必须调用DestroyWindow函数。
如果需要的话,还可调用Updatedata函数来将数据从对话框控件中传到类数据成员中。

8,Windows通用对话框:
共同特点:都从用户处获得消息,但并不对信息做处理。如:文件对话框只为程序提供路径名,字体对话框只是填充一个描叙字体的结构,并不创建字体。
所有的通用对话框类都从公有基类CCommonDialog派生而来。
COMDLG32中类列表如下:
CColorDialog  允许用户选择或创建颜色
CFileDialog  允许用户打开或者保存一个文件
CFindReplaceDialog 允许用户将一个字符串换成另一个字符串
CPageSetupDialog 允许用户输入页面参数
CFontDialog  允许用户从列出的可用字体中选择一种字体
CPrintDialog  允许用户设置打印机并打印文档

9,注意:在Win32中,不能在标准文件对话框内部动态创建控件。(其它标准对话框中也应该如此吧)

10,嵌套对话框(这些内容熔入EX07B事例中讲解了,不打算重复,强烈建议看看和跟着做做,页码:P135-141。下面只对其中重要的函数做些说明笔记。)
利用MFC,从通用
1)CFileDialog::m_ofn
//m_ofn is a structure of type OPENFILENAME. Use this structure to initialize the appearance of a File Open or File Save As dialog box after it is constructed but before it is displayed with the DoModal member function.
2)CFileDialog::CFileDialog
CFileDialog( BOOL bOpenFileDialog, LPCTSTR lpszDefExt = NULL, LPCTSTR lpszFileName = NULL, DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTR lpszFilter = NULL, CWnd* pParentWnd = NULL );
//bOpenFileDialog
Set to TRUE to construct a File Open dialog box or FALSE to construct a File Save As dialog box.
3)CFileDialog::DoModal
//Call this function to display the Windows common file dialog box and allow the user to browse files and directories and enter a filename.
//If you want to initialize the various file dialog-box options by setting members of the m_ofn structure, you should do this before calling DoModal, but after the dialog object is constructed.
//When the user clicks the dialog box’s OK or Cancel buttons, or selects the Close option from the dialog box’s control menu, control is returned to your application. You can then call other member functions to retrieve the settings or information the user inputs into the dialog box.
4)CFileDialog::GetPathName
//Call this function to retrieve the full path of the file entered in the dialog box. The path of the filename includes the file’s title plus the entire directory path.
5)事例中注意设置自己创建的子对话框上的组筐控件的ID为stc32。这样才保证文件通用对话框嵌入的位置在组筐所在的位置上,否则默认为自己创建的子对话框的同宽度。(stc32应该是与文件通用对话框相关联的,具体是如何关联的哦?)
6)事例中可见到这样的代码(GetParent()->GetDlgItem(IDOK)->SetWindowText("Delete");)来获取文件通用对话框上的控件指针,这里要理解为什么要用GetParent()函数来获得父窗口指针(因为事例中自己所创建的对话框被设置成Child Style。)(Child style,None border,Group box ID=stc32这些设置都是必不可少的,自己可以试着改变这些设置,看看效果印象也就深了)
7)事例中CSpecialFileDialog::OnDelete() 函数中代码(GetParent()->GetDlgItem(0x480)->GetWindowText(m_strFileName);)通过获取文件通用对话框上文件名对应的编辑框的指针调用CWnd::GetWindowText函数来获取编辑框中的文本保存在m_strFileName数据成员中。其中0x480应该是文件通用对话框上文件名对应的编辑框的ID。
8)事例中CSpecialFileDialog::OnDelete() 函数中代码(GetParent()->SendMessage(WM_COMMAND,IDCANCEL);)向文件通用对话框发送IDCANCEL消息,该操作引起OnCancel函数的调用终止当前模式对话框同时使得CFileDialog::DoModal函数返回IDCANCEL值。
MSDN:
CDialog::OnCancel (The default simply terminates a modal dialog box by calling EndDialog and causing DoModal to return IDCANCEL.)
9)SDK函数:FindFirstFile,DeleteFile
//FindFirstFile Searches a directory for a file whose name matches the specified file name on the destination site identified by this object. It examines subdirectory names as well as file names.
//DeleteFile Deletes the given file from the destination site.
10)CFile::Remove
A static function ,deletes the file specified by the path. It will not remove a directory. (注意:用这函数删除的文件是不经过回收站的哦。)

11,在对话框标题栏添加图标:在对话框类OnInitDialog函数中添加如下代码。
 HICON hIcon =AfxGetApp()->LoadIcon(ID_MYICON);//ID_MYICON是用资源编辑器创建的图标ID。
 this->SetIcon(hIcon,TRUE);
 this->SetIcon(hIcon,FALSE);注:这里带上this指针目的是为了强调必须使用目的对话框类对象指针调用SetIcon设置图标。
比如在书EX07B事例中,由于CSpecialFileDialog类设置为子窗口类,而且所关联的资源窗口没有Tittle Bar,要在父窗口文件通用对话框Tittle Bar上添加图标,必须获取父窗口文件通用对话框对象指针来调用SetIcon设置图标。
如在书EX07B事例中:在CSpecialFileDialog::OnInitDialog函数中添加如下代码,可设置文件通用对话框标题图标: 
 HICON hIcon =AfxGetApp()->LoadIcon(ID_MYICON);
 GetParent()->SetIcon(hIcon,TRUE);
 GetParent()->SetIcon(hIcon,FALSE);


/////////////
/////////////

 

/************************************/
第八章:使用ActiveX控件

1,ActiveX控件是一个直接插入到C++程序中的软件模块,以前常称OLE控件(OCX),是基于MS-COM技术。

2,ActiveX控件与普通Windows控件比较:
相同点:ActiveX控件也可看成是一个子窗口(可以看成这样的)。
如果想在对话框上加入ActiveX控件,则只要在对话框编辑器中,把ActiveX控件放在适当的位置上,并在资源模板中标识该控件。如果要在运行的过程中建立ActiveX控件,则可以调用响应控件类的Create成员函数,而且通常在父窗口的WM_CREATE消息控制函数中调用。
不同点:属性和方法。
ActiveX控件不像普通控件那样发送以WM_打头的通知消息给它的包容器窗口,而是激发事件。事件实际上是由控件调用包容器函数。像普通的控件通知消息一样,事件并没有返回值传给ActiveX控件。事件如lick,KeyDown。但对于客户来说时间与控件的通知消息是一样的。

3,在MFC库中,ActiveX控件就像子窗口一样,但在控件窗口和包容器窗口之间有一层重要代码。实际上,ActiveX控件可能没有窗口。当调用Create函数时,并不是直接建立控件窗口,而是把控件代码载入进来,并激发一个“实地激活”(in-place activation)命令。然后ActiveX控件再建立它自己的窗口,通过MFC的CWnd类指针我们可以访问该窗口。不过客户程序最好不要使用ActiveX控件的hWnd句柄。

4,通常ActiveX控件会保存在扩展名为OCX的动态连接库中。包容器程序回根据Windows注册表利用COM技术在需要的时候装入动态连接库。
说明:
1)暂时可以这样认为,如果使用了ActiveX控件,那么在运行时候要装入该ActiveX控件代码。显然在发布含有ActiveX控件的程序时候,必须要包含相应的OCX文件,而且还得提供一个合适的安装程序。

5,安装ActiveX控件:
1)把找到的ActiveX控件动态连接库拷到硬盘上。
2)在WINDOWS注册表中登记注册。(可使用Regsvr32命令行命令)
3)在使用该控件的项目中安装该控件。(选择Project菜单,再选择Add To Project,再选择Components And Controls,再选择Registered ActiveX Controls,这时列表框列出系统已经注册所有的ActiveX控件,选择需要的控件INSERT即可。)

6,ActiveX控件包容器编程:
1)不管ActiveX控件是作为对话框控件,还是做为“子窗口”,MFC和ClassWizard都支持。
2)ActiveX控件编写者设计了ActiveX控件属性供使用者在设计时访问。所有的ActiveX控件属性(包括设计时属性),在运行时都是可以访问的,不过有些属性可能被设计成只读的。
3)当在项目中插入ActiveX控件时,ClassWizard就会产生相应的CWnd的派生类C++类,来满足对空间的方法和属性进行访问要求。控件的属性和方法都有相应的成员函数,同时生成的类还有一个构造函数可用以动态创建ActiveX控件的事例。
4)当在项目中插入ActiveX控件ClassWizard生成的CWnd的派生类C++类中,可以看到其成员函数的代码中都有对InvokeHelper函数的调用,InvokeHelper函数的第一个参数都和对应的属性或方法在ActiveX控件中的分发(dispatch)ID(标识ActiveX控件的方法或属性的)相对应。通过查看ActiveX控件hlp文件可以发现,ActiveX控件的方法在生存的C++类中都有同名的成员函数与之对应,ActiveX控件的属性都有一组Get和Set函数对其操作,其中ActiveX控件的方法和属性操作与生成的C++类成员函数相关联都是通过InvokeHelper函数的调用来完成的,InvokeHelper函数的第一个参数是由Component Gallery(控件提供者)提供的。因为经过这样的处理,所以我们如果要调用ActiveX控件的方法或对其属性进行取和设置操作,只需调用生成的C++类对应的成员函数便可。
下面对InvokeHelper单独说明:
CWnd::InvokeHelper
void InvokeHelper( DISPID dwDispID, WORD wFlags, VARTYPE vtRet, void* pvRet, const BYTE* pbParamInfo, ... );
说明:
Call this member function to invoke the OLE control method or property specified by dwDispID, in the context specified by wFlags.
其中参数:
dwDispID:
//Identifies the method or property to be invoked. This value is usually supplied by Component Gallery.

wFlags:可以为下面些值,指明调用InvokeHelper的目的。
//[ DISPATCH_METHOD ]   The member is invoked as a method. If a property has the same name, both this and the DISPATCH_PROPERTYGET flag may be set.
[ DISPATCH_PROPERTYGET ] The member is retrieved as a property or data member.
[ DISPATCH_PROPERTYPUT ] The member is changed as a property or data member.
[ DISPATCH_PROPERTYPUTREF ] The member is changed by a reference assignment, rather than a value assignment. This flag is valid only when the property accepts a reference to an object.

vtRet:
//Specifies the type of the return value.
VT_EMPTY  void
VT_I2  short
VT_I4  long
VT_R4  float
VT_R8  double
VT_CY  CY
VT_DATE  DATE
VT_BSTR  BSTR
VT_DISPATCH  LPDISPATCH
VT_ERROR  SCODE
VT_BOOL  BOOL
VT_VARIANT VARIANT
VT_UNKNOWN  LPUNKNOWN

pvRet:
//Address of the variable that will that will receive the property value or return value. It must match the type specified by vtRet.

pbParamInfo:一般都设置为NULL
//Pointer to a null-terminated string of bytes specifying the types of the parameters following pbParamInfo.
specifies the types of the parameters passed to the method or property.
...:
//Variable List of parameters, of types specified in pbParamInfo.

5)AppWizard对ActiveX控件的支持是通过在生成的应用程序类的成员函数InitInstance中插入(AfxEnableControlContainer();),同时在响应项目文件的StdAfx.h文件中插入(#include<afxdisp.h>)(原因可参考书P38一些说明)。
如果项目中不包含这两行,而又要加入ActiveX控件,则只要手工加入上面两行代码即可。

6)可以对话框编辑器来生成对话框的模板中加入一个或多个ActiveX控件,这样我们可以在对话框模板生成的类中添加数据成员或事件控制函数来获取ActiveX控件的属性或对其控制。
注意:(详细见书P159页的[致WIN32程序员])
实际上,资源模板并不是在对话框编辑器中所看的那样。函数CDialog::DoModal在把对话框模板交给WINDOWS内部的对话框过程之前,要先对模板进行预处理,即:它先会去掉所有的ActiveX控件,有剩下的控件建立对话框窗口,然后再装入ActiveX控件,激活它们并在正确的位置上创建它的窗口。
当模式对话框运行时候,MFC处理所有送给对话框消息时,是不管是有普通控件发送的,还是ActiveX控件发送的。故ActiveX控件虽然不是对话框模板一部分,但用户仍然可以用TAB键在所有的控件间切换。

7)调用UpdateData(FALSE)将会从所有的对话框控件中读取所有属性值。如果只需要得到ActiveX控件属性的话,可以调用ActiveX控件生成的C++类中Get函数(同样设置调用Set函数),这样就提高了效率。

8)事例部分代码对比说明:
代码一:
   CDataExchange dx(this,TRUE);
   DDX_Text(&dx,IDC_DAY,m_sDay);
   DDX_Text(&dx,IDC_MONTH,m_sMonth);
   DDX_Text(&dx,IDC_YEAR,m_sYear);
说明一:
CDataExchange类构造函数:(注,在MFC|SRC|AFXWIN.H中可以看到其构造函数声明,在MFC|SRC|WINCORE.CPP文件中可以看到其构造函数的定义。)
原型:CDataExchange::CDataExchange(CWnd* pDlgWnd, BOOL bSaveAndValidate);
定义:
CDataExchange::CDataExchange(CWnd* pDlgWnd, BOOL bSaveAndValidate)
{
 ASSERT_VALID(pDlgWnd);
 m_bSaveAndValidate = bSaveAndValidate;
 m_pDlgWnd = pDlgWnd;
 m_hWndLastControl = NULL;
}

//其中m_pDlgWnd和m_bSaveAndValidate是CDataExchange数据成员,可以通过这中方式给它们赋值。
m_pDlgWnd:The dialog box or window where the data exchange takes place.
m_bSaveAndValidate Flag for the direction of DDX and DDV. 详见说明二。

说明二:
//CDataExchange does not have a base class.
//The CDataExchange class supports the dialog data exchange (DDX) and dialog data validation (DDV) routines used by the Microsoft Foundation classes. Use this class if you are writing data exchange routines for custom data types or controls, or if you are writing your own data validation routines.
//A CDataExchange object provides the context information needed for DDX and DDV to take place. The flag m_bSaveAndValidate is FALSE when DDX is used to fill the initial values of dialog controls from data members. The flag m_bSaveAndValidate is TRUE when DDX is used to set the current values of dialog controls into data members and when DDV is used to validate the data values. If the DDV validation fails, the DDV procedure will display a message box explaining the input error. The DDV procedure will then call Fail to reset the focus to the offending control and throw an exception to stop the validation process.


代码二:(是为了比较代码一做些说明的)
void CActiveXDialog::DoDataExchange(CDataExchange* pDX)
{
 CDialog::DoDataExchange(pDX);//调用基类的DoDataExchange
 //{{AFX_DATA_MAP(CActiveXDialog)
 DDX_Control(pDX, IDC_CALENDAR1, m_calendar);
 DDX_Text(pDX, IDC_DAY, m_sDay);
 DDX_Text(pDX, IDC_MONTH, m_sMonth);
 DDX_Text(pDX, IDC_YEAR, m_sYear);
 //}}AFX_DATA_MAP
}
说明一:
//DoDataExchange Called by the framework to exchange and validate dialog data.
//DoDataExchange Never call this function directly. It is called by the UpdateData member function. Call UpdateData to initialize a dialog box’s controls or retrieve data from a dialog box.
说明二:
//在MFC|SRC|WINCORE.CPP文件中可以看到UpdateData函数的定义
BOOL CWnd::UpdateData(BOOL bSaveAndValidate)
{ ... 
 CDataExchange dx(this, bSaveAndValidate);//创建了一个CDataExchange对象,与当前窗口相关联
 ...
 DoDataExchange(&dx); //注意:DoDataExchange是个虚函数。子类中如果有重写了,则调用子类的。
 ...
}
说明三:
//在MFC|Include|AFXWIN2.INL文件中可有看到CWnd::DoDataExchange的如下定义(内联):
// CWnd dialog data support
_AFXWIN_INLINE void CWnd::DoDataExchange(CDataExchange*)
 { } // default does nothing
由此可见代码二中CDialog::DoDataExchange(pDX)调用好象是个‘摆设’,不起做任何事情。框架设置DoDataExchange函数目的是在我们子窗口类(这里是对话筐)中重写它,添加代码完成子窗口类(这里是对话筐)中数据成员与对话筐上控件的交互。
说明四:
如果结合UpdateData和DoDataExchange两函数整体来看,应该体会到这里代码一与代码二实质上是一会事情。代码二只是借助了框架兜了些圈子。

说明四:
摘录MSDN中Dialog Data Exchange一些E文段落对上讨论做个总结:
Dialog Data Exchange

If you use the DDX mechanism, you set the initial values of the dialog object’s member variables, typically in your OnInitDialog handler or the dialog constructor. Immediately before the dialog is displayed, the framework’s DDX mechanism transfers the values of the member variables to the controls in the dialog box, where they appear when the dialog box itself appears in response to DoModal or Create. The default implementation of OnInitDialog in CDialog calls the UpdateData member function of class CWnd to initialize the controls in the dialog box.

The same mechanism transfers values from the controls to the member variables when the user clicks the OK button (or whenever you call the UpdateData member function with the argument TRUE). The dialog data validation mechanism validates any data items for which you specified validation rules.

UpdateData works in both directions, as specified by the BOOL parameter passed to it. To carry out the exchange, UpdateData sets up a CDataExchange object and calls your dialog class’s override of CDialog’s DoDataExchange member function. DoDataExchange takes an argument of type CDataExchange. The CDataExchange object passed to UpdateData represents the context of the exchange, defining such information as the direction of the exchange.

When you (or ClassWizard) override DoDataExchange, you specify a call to one DDX function per data member (control). Each DDX function knows how to exchange data in both directions based on the context supplied by the CDataExchange argument passed to your DoDataExchange by UpdateData.

MFC provides many DDX functions for different kinds of exchange.

If the user cancels a modal dialog box, the OnCancel member function terminates the dialog box and DoModal returns the value IDCANCEL. In that case, no data is exchanged between the dialog box and the dialog object.

9)当输入焦点在某ActiveX控件上时,按下F1键引起OnHelpInfo函数调用,可在OnHelpInfo函数中设置帮助信息。
说明:
ClassWizard不能修改生成的ActiveX控件类,因而必须手工加入消息映射代码。事例代码如下:
//在ActiveX控件类头文件中加入函数原型并声明消息映射表:
 protected:
  afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo);
  DECLARE_MESSAGE_MAP()//在ActiveX控件类代码文件中添加消息映射及OnHelpInfo函数定义:
 BEGIN_MESSAGE_MAP(CCalendar,CWnd)
  ON_WM_HELPINFO()
 END_MESSAGE_MAP()
/**
 BOOL CCalendar::OnHelpInfo(HELPINFO *pHelpInfo)
{
 ::WinHelp(GetSafeHwnd(),"C:\WINDOWS\system32\MSCAL.hlp",
    HELP_FINDER,0);
 return FALSE;
}

/////////////////
//////////////
///////////

7,在运行时创建ActiveX控件:
1)在项目中插入ActiveX控件。ClassWizard会生存相应的ActiveX控件类的文件。
2)在使用ActiveX控件的对话框或窗口类中添加ActiveX控件类数据成员。
3)重写CDialog::OnInitDialog(或其它窗口中响应WM_CREAT消息),在新的函数中调用ActiveX控件类Create函数。
4)在父窗口类中,手工添加必要的与新控件有关的事件消息处理函数及原型,和相应的消息映射。

/////////
8,更多的ActiveX控件编程参见P160-167页(ActiveX控件在HTML文件中使用 和 在运行时创建ActiveX控件)。


posted @ 2006-04-03 17:41 高山流水 阅读(1993) | 评论 (0)编辑 收藏

     摘要: Ричард Фейнман. Вы, конечно, шутите, мистер Фейнман! (англ.) * OCR: "the real caterpillar". -------- "Surely You're Joking, Mr. Feynman!" by Richard P. Feynm...  阅读全文

posted @ 2006-04-03 16:39 高山流水 阅读(802) | 评论 (0)编辑 收藏

仅列出标题
共30页: First 4 5 6 7 8 9 10 11 12 Last