<?xml version="1.0" encoding="UTF-8"?><!-- generator="WordPress/2.6.2" -->
<rss version="0.92">
<channel>
	<title>Oasis Feng</title>
	<link>http://blog.oasisfeng.com</link>
	<description>Challenge your imagination!</description>
	<lastBuildDate>Sun, 05 Oct 2008 07:44:26 +0000</lastBuildDate>
	<docs>http://backend.userland.com/rss092</docs>
	<language>en</language>
	
	<item>
		<title>让Dropbox同步任意位置的文件</title>
		<description>最近因为需要在办公室和家里两地同步文件，开始寻觅合适的解决方案，在网上摸索了一阵子，发现了Dropbox。这个软件的设计思路确实不错，实时监视My Dropbox文件夹中的变化并自动同步到服务器或从服务器同步。由于同步过程是异步进行的，因此避免了映射型网络存储访问时的高延迟。但遗憾的是，它要求必须将需同步的文件放置在预定义的My Dropbox文件夹下，这就大大制约了其应用范围，充其量只能当做一个网络U盘使用了。

我希望的是一个可以指定任意位置的文件进行同步的工具，而且需同步的文件在各同步终端上可能存放于不同的位置。比如我需要同步FlashFXP的站点配置文件sites.dat，并且我在家里将FlashFXP安装在D:\Programs\FlashFXP中，而在公司的安装位置是C:\Program Files\FlashFXP。到Dropbox的官方论坛兜了一圈，发现这个特性尚在Medium Term Plan中。没办法，只好先自己动手解决这个问题。

首先尝试在My Dropbox下创建一个指向需同步文件的符号链接(Vista/Win2008的NTFS新增特性，使用命令mklink)，看起来Dropbox确实正确同步了该符号链接的源头，并传到了服务器上。不过在识别更新上出现了问题，无论实际文件如何变化，Dropbox都不会进行同步。估计是因为符号链接的日期不会随实际文件而更新的缘故吧。这条路看来是走不通了……

软的不吃来硬的，在My Dropbox下创建一个NTFS的“硬链接(Hard Link)”（使用命令mklink -h），结果仍然面临与符号链接相同的识别更新问题。虽然硬链接在表现上看起来与正常文件完全一致，但当你从一处修改了文件后，其它硬链接的文件描述信息（例如文件尺寸、修改日期）并未更新，除非你再次打开硬链接（即使并不改写）。引用MSDN上的一句原话：

However, directory entries for hard links are updated only when a user accesses a file by using the hard link.

再试了“文件夹联接(Junction)”，结果依旧…… 真是无语了，没想到NTFS进过几代的变革，依然这么落后，比起Linux/Unix的实现差远了啊。

看来，只能上土办法了。用DSynchronize这个小工具自己定义了一个实时同步规则，从FlashFXP的程序文件夹中将sites.dat同步到My Dropbox。这样，总算糅合了两个工具，实现了我的两地同步需求。

最后，值得一提的是DSynchronize这个小工具，之所以用它来做实时同步，不仅因为它支持以系统服务方式于后台运行，还具有很多与我的软件选择价值观相符的特征：无需安装、体积小巧（不足200k）、节省资源（低于3M内存）、界面朴实、无冗余功能。唯一的遗憾是，它的实时同步竟然是通过每隔5s的文件夹轮询实现的，对于层次较深的文件夹可能会有性能负担。 </description>
		<link>http://blog.oasisfeng.com/2008/10/05/sync-files-anywhere-by-dropbox/</link>
			</item>
	<item>
		<title>FireGestures的实用脚本</title>
		<description>浏览器中，我选择FireFox，因为它有强大的插件框架，可以充分发挥DIY的精神；Firefox的手势插件中，我选择FireGestures，因为它有开放的脚本扩展，可以随意打造你所需要的手势。千万别小看甚至忽视了FireGestures的脚本功能，下面几个脚本将彻底颠覆你对FireGestures的认识！（注：脚本代码均系转载）

»快速移除页面中的元素（引用来源）
var node = FireGestures.sourceNode;
node.parentNode.removeChild(node);
非常实用的功能。是居家旅行，消灭广告，毁尸灭迹的必备武器！
巨幅广告、飘悬广告、Flash动画…… 通杀！

友情提示：由于FireGesture手势不能从Flash对象上开始，所以请找一个贴近Flash对象的边缘划出手势，一般可以将Flash所在的容器元素（DIV或SPAN）连带Flash一并干掉。

»关闭当前标签页并选中左/右侧的标签（引用来源）
var tab = gBrowser.mCurrentTab;
if(tab.previousSibling)
  gBrowser.mTabContainer.selectedIndex--;
gBrowser.removeTab(tab);
var tab = gBrowser.mCurrentTab;
if(tab.nextSibling)
  gBrowser.mTabContainer.selectedIndex++;
gBrowser.removeTab(tab);
尽管Tab Mix Plus/Lite或是Tab Kit都提供了所谓的“关闭标签页后智能切换标签”，但给我的感觉根本谈不上智能，甚至很多时候只能用“弱智”来形容…… 所以，我更倾向于自己掌握关闭标签页后的去向。于是，我在FireGestures中配置了“下左”和“下右”两个动作，分别用来在关闭当前标签页后选中左/右侧的标签。

»让“在新标签页中打开链接”也能与Tab Kit兼容（引用来源）
// Open Link in New Tab [Alternative] (Tab in Background)
// Opens a new tab by faking a click on the link.

const IN_FOREGROUND = false;

// Check if it's a link the gesture ...</description>
		<link>http://blog.oasisfeng.com/2008/08/27/useful-scripts-for-firegestures/</link>
			</item>
	<item>
		<title>当心PayPal支付中的汇率陷阱</title>
		<description>用PayPal在境外进行网上支付可以有效的保护你的信用卡安全，但倘若不注意其中的汇率陷阱，则很可能因此被收取一笔不菲的费用。

如果信用卡的币种与待付款项不一致，PayPal将在支付流程的提供两种不同的兑换选项：

兑换选项

在您与持有不同币种的卖家进行购买交易的时候，PayPal提供了两种方式来兑换货币。

    * PayPal币种兑换程序
    * MasterCard 与 Visa 币种兑换程序

请您选择以下的选项：

(1) 用PayPal的兑换程序完成使用我的卡货币的交易。

为了我的方便，原始交易币种和我要支付的兑换金额将被披露。我理解MasterCard与Visa有一个币种兑换程序。我已选择不使用MasterCard与Visa币种兑换程序，并且不会就与此兑换有关的任何事求助于MasterCard与Visa。

(2) 在给我的账单中使用卖家列出的币种。

直到我收到来自发卡方的卡账单后，才会知道此次交易所采用的外汇汇率。我知道若选择此选项，发卡方将决定用于此次交易的外汇汇率，而且直到我向发卡方支付费用后才会被告知所采用的外汇汇率或者额外的外汇兑换费用。

听起来有点头大吧？实质上很简单！

第一种方式是PayPal负责货币的兑换，并收取兑换手续费。计入信用卡账单的将是PayPal折算后的本币金额。这是PayPal默认的兑换方式。

第二种方式是信用卡发卡银行负责货币的兑换，并收取兑换手续费（因银行或信用卡种不同，可能没有手续费）。计入信用卡账单的将是待付款项的币种。

听起来似乎差不多，只不过兑换手续在不同的角色处完成。但是，陷阱就在其中！

PayPal的兑换程序采用其自己维护的当前汇率，且不说其屡被批评与国际汇市的同步滞后，PayPal自身还会收取2.5%的固定手续费。但不同银行不同卡种的信用卡，其兑换手续费就有很大差别了。为此我专门打电话咨询了招商银行的信用卡客服，招行VISA金卡支付美元账单是“没有”手续费的（但美元以外币种有手续费），汇率按照信用卡账单扣款日的招行购入汇率执行。

PayPal支付页面中所显示的其当前“人民币/美元”汇率为：1 人民币 = 0.141144 美元（含手续费）。而招行客服告知的招行当前美元购入价为￥6.87。两者竟然相差3%以上！

相信各位已经看出这之中所隐藏的巨大陷阱了吧。如果马马虎虎的直接按照PayPal默认兑换方式支付，则可能额外支出超过3%的金额。

另外值得一提的是，由于信用卡是按照扣款日，而非支付时的汇率执行，在大部分情况下，其间隔可长达数十天。这其中就不可避免的面临一个汇率的波动，恰当掌握汇率的波动周期，在合适的时机还款也可能为你小小的节约一笔哦！ </description>
		<link>http://blog.oasisfeng.com/2008/08/25/beware-the-exchange-rate-of-paypal/</link>
			</item>
	<item>
		<title>奥运门户网站真让人失望</title>
		<description>想看看20号的男篮比赛时间，打开新浪奥运频道，结果只有小组编号标示的赛程：

14:30	   B2 vs A3
16:45	   A1 vs B4
20:00	   A2 vs B3
22:15	   B1 vs A4

两组的排名状况是怎样的？在新浪逛了半天愣是没找到……

好在搜狐给了结果：

A组积分榜(带*为已经出线)
名次 	球队 		胜/负 	积分
1 	立陶宛*		4/1 	9
2 	克罗地亚*		3/2 	8
3 	澳大利亚*		3/2 	8
4 	阿根廷*		3/1 	7
5 	俄罗斯(淘汰)	1/3 	5
6 	伊朗(淘汰)	0/5 	5

B组积分榜(带*为已经出线)
名次 	球队 		胜/负 	积分
1 	美国*		5/0 	10
2 	西班牙*		4/1 	9
3 	希腊*		3/2 	8
4 	中国*		2/3 	7
5 	德国(淘汰)	1/4 	6
6 	安哥拉(淘汰)	0/5 ...</description>
		<link>http://blog.oasisfeng.com/2008/08/18/olympic-china-sites-suck/</link>
			</item>
	<item>
		<title>深入探究MODVERSIONS的实现原理</title>
		<description>最近在分析Linux内核模块与内核之间的版本耦合关系时，在实验中发现了一些有趣的结果：在同一Linux版本基础上经过不同裁剪的内核，甚至是在跨度不大的两个内核版本间，内核模块可以自由互用，而且内核本身似乎具备检查这种兼容性的能力。这与之前所知的情况是不同的。在我久远的记忆中，Linux的是依靠内核模块构建时自动产生的“vermagic”标识检查是否与当前内核版本一致的，如果不一致则拒绝加载。除非在insmod/modprobe时指定参数强制忽略vermagic，但这样做的代价是如果使用错误版本的内核模块就可能导致内核崩溃。

看了一下内核这部分的源代码（所参考源码的内核版本为2.6.17.11），发现了两种不同截然的处理方式，由一个内核构建宏“CONFIG_MODVERSIONS”所控制。在它关闭的情况下，加载内核模块时，将对vermagic作全字符串的完整匹配，任何不一致均会阻止该内核模块的加载；而倘若这个宏被开启，则只有vermagic第一个空格之后的部分会参与匹配，也就是说形如“2.6.5-7.191-bigsmp”这一段内核版本标识其实并不要求一致。事实上，当上述宏开启后，除了对vermagic后半段的匹配性检查外，内核还会进行额外的“内核接口指纹”检验，才最终决定是否允许加载该内核模块。

何谓“内核接口指纹”？其实这是Linux内核在试图解决跨版本内核模块兼容性问题上的一个积极尝试。通过在内核构建流程中插入一个特殊的“内核接口指纹”提取阶段，由一个专用的GNU工具“genksyms”为内核的源代码生成“指纹”信息。这里的“指纹”其实是一组特殊的CRC，它们分别对应着内核符号表中的每一个符号。生成CRC的输入包括这个符号的完整定义，以及其中所有参数涉及的数据类型定义，包括typedef、enum、struct、union。其中typedef将展开至最原始的标准数据类型；后三种类型将包含其定义的完整组成部分（例如结构体的成员、枚举的清单），对于组成成员也将递归应用上述原则。也就是说，“指纹”信息代表了对内核接口有兼容性影响的绝大部分要素，一旦其发生变化，则意味着接口的兼容性可能已经被破坏。

除了内核本身的构建在CONFIG_MODVERSIONS打开后会包含上述指纹信息外，内核模块的构建是否包含指纹信息还依赖于构建该内核模块的内核构建环境中此宏的状态。只有当两者均包含上述指纹信息时，上述检验机制才能真正生效。想要知道当前内核是否包含了内核接口指纹，只需提取/proc/config.gz并查看其中CONFIG_MODVERSIONS的取值；而若想知晓一个内核模块是否包含指纹信息，则需要用到modprobe的下面这个参数：

modprobe --dump-modversions &#60;module&#62;

其实，就如Linux在内核编译菜单中对CONFIG_MODVERSIONS解释，也用了一个“hopefully”。这个机制本身的出发点是很好的，而且也尽了最大努力去校验。但事实上，接口的兼容性很难仅仅用定义来保证，因为接口所体现的功能部分是无法在定义中反应出来的，这也是程序尚无法完全取代人类的判断能力。因此，MODVERSIONS可以作为版本不配套时的后备选择（尤其对非开源的驱动程序），但不能依赖它作为兼容性的判定依据。

---
参考文献：Kernel Symbols and CONFIG_MODVERSIONS </description>
		<link>http://blog.oasisfeng.com/2008/08/12/all-about-modversions/</link>
			</item>
	<item>
		<title>澳门游记·漫步篇——见证繁华与沧桑</title>
		<description>在深圳待了四载，去了两回香港，赴澳门还是第一次。从零碎的信息中拼凑出来的澳门，想象中应该是一个在浓郁欧陆风情的外表下，包裹着纸醉金迷的诱惑都市，骰子撞击的声响和教堂悠扬的钟鸣共同构成了这个城市的基调。

这次好不容易请动深居简出的Konca兄同行，还是看在签证快要过期的份上。不过事实终究佐证了我的英明，有Konca兄地道的粤语撑场面那是免了不少麻烦~ ;)



厌倦了窝在空调大巴里一路风尘仆仆的旅行方式后，这一次我们选择了从海上登陆澳门。在深圳福永码头踏上TurboJet快艇后，只用了1小时10分钟左右就顺利抵达了澳门的新港澳码头。从规模上看，这座码头在澳门的对外交通中占据了显著的地位，也可以看做是对殖民时期葡萄牙航海传统的继承。



走出码头后，可以很容易的在显著位置发现来往于澳门各大赌场和酒店的免费豪华大巴，但为了让澳门之行更加紧凑和充实，我们没有先去酒店，而是直接向就近的东望洋松山公园进发。在绕者偌大的公园转了半圈之后，我忍不住开始诅咒这些所谓的地图，没有一个画出了公园的大门方向…… 最后只好请Taxi为我们领路，才辗转跨进公园。攀上山顶后，我们见到了作为早期澳门标志之一的“东望洋松山灯塔”。虽然看起来着实很不起眼，但遥想当年其不可或缺的地位和所见证的澳门外港沧桑变迁，却也让人礼敬之情油然而生。



灯塔旁紧邻的就是“圣母雪地殿教堂”，这是一座历史相当悠久的教堂，不过随着灯塔的荒弃，也仅仅作为一个旅游景点保留了下来。（关于教堂的介绍留待另一篇中详述）灯塔和教堂所在的平台上还陈列着一门大炮，那么这里自然就是“东望洋炮台”了。地图中标注的三个景点原来就挤在这么不足一百平米的小小露台，还颇费我们在“Z”字型的蜿蜒山路上花了那么多力气……



下山之后已经快2点了，饥肠辘辘之下，赶紧打的直奔澳门著名的东南亚美食聚集区——三盏灯。这里的小巷透着浓厚的东南亚集市风情，夹杂着路边那些不时带着南亚口音的吆喝，就仿佛一下子置身好莱坞电影中时常出现的泰国、缅甸等地的布景中了。找了一家看起来颇有些老字号味道的缅甸面馆，点了一份最具特色的“咖哩鸡捞面”，配上一瓶店家招牌特酿的香浓豆浆，倒也别有一番风味。

到酒店check-in之后，卸下沉重的行囊，便开始了澳门旧城区之行。



此行的起点是澳门的民政总署，这是一栋典型的葡式风格建筑，透着庄重与简朴的气息。从民政总署的正门方向望过去，就是著名的议事厅前地。地面波浪式的地砖铺设就是议事厅前地最独立的一道风景线，它一直延伸到圣母玫瑰堂和更远处的大三巴牌坊，正好是澳门旧城区旅游线路的主轴。



这一带集中了澳门旧城区的几大代表建筑以及澳门最富盛名的几座教堂，是澳门历史风貌和宗教建筑的浓缩展现。其中的“卢家大屋”是一座保存最为完好的澳门传统富家大宅，建造距今已有一个多世纪，后经过澳门政府的修葺，完整的还原了初时的风貌。这是一座古旧的典型民居，为三间三进、上下两层的格局，建筑风格上则兼用了中西方的装饰手法，既有中国传统的雕棱和飞檐，亦有融入了欧洲特色的青花瓷、铸铁栏等。



偏厅门檐上精巧的灰塑雕图充分展现了当时富贵人家对细节艺术的追求和钟爱。



在参观了众多教堂和宗教展馆后，我们来到了旧城区线路的最后一站——“大三巴牌坊”，这也是被旅游宣传用的最多澳门标志性景观。出乎我意料之外的是，这样一座看似宏伟的建筑完全就置身在闹市之中。说它看似宏伟，是因为当你拾级而上到达牌坊之前时，却也感受不到那种期待之中的气势感。不过，你要是了解到它的由来历史，自然就可以释然了。



从大三巴牌坊旁边的小道上山，就来到了澳门最大的炮台群——“大炮台”。嗯，来一张“炮轰葡京大酒店”的特写吧。



这里同时还坐落着澳门的市立博物馆，不过由于时间关系，博物馆已经在我们来之前打烊了。从外面看去，这是一座很正统的葡式建筑，甚至可以说造型有些呆板。（简直就一个方盒子嘛……）



下山之后，我们在就近的“咀香园饼家”品尝了澳门地道的葡式蛋挞。话说这葡挞还真是跟在麦当劳吃到的蛋挞不同，外层酥软的衬底是采用类似千层饼的烹制手法，一咬下去，入耳的满是松脆；中间蛋挞部分烤的嫩软恰到好处，入口稍卷即溶，险些害的舌头惨遭牙齿的因妒生恨…… 在店家的盛情邀请下，我们又免费品尝了其招牌的“凤凰紫菜肉松卷”。嗯，我不敢再说下去了，怕是今晚要因此失眠了。#_# 



（由于一时嘴馋，忘了拍照留念，只好借大众点评网的图片一用。嗯，绝对的“咀香园”大三巴店正版葡挞哦~）

夕阳的余晖已经悄然离去，只剩下逐渐亮起霓虹灯的街道。我们第一天的澳门漫步也基本告一段落，但澳门真正刺激的夜生活才刚刚开始……

（敬请期待：澳门游记&#183;博彩篇） </description>
		<link>http://blog.oasisfeng.com/2008/08/08/macau-tour-a-walking/</link>
			</item>
	<item>
		<title>云计算与互联网基础承载结构的矛盾</title>
		<description>今天听了电信领域战略专家刘南杰关于“互联网基因与电信发展”的一个主题讲座，了解到了一些从互联网最早期日子一路过来，在互联网公司和电信运营商之间那些貌合神离的微妙关系，以及在互联网经历爆发性增长后电信运营商所面临的转型压力。其中一个关于“云计算”的有趣话题引起了我的更多思索。

“云计算”这个词最近实在太热了，以至于只要是个互联网公司，要是还没有自己的“云战略”，那简直是抬不起头见人了。但是，云计算在承载了众多期望与理想的同时，是否真的是未来互联网服务的大趋势呢？云计算的未来究竟应该是怎样的形态？很遗憾，我也无法回答这些问题，但至少眼下，我们必须看到云计算所面临的现实问题。

众所周之，互联网的物理基础是由传统分组交换的语音承载网过渡而来的，即使是在向全IP演进的过程中，电信承载网络的结构也并没有发生本质的变化。这种结构是为传统电话业务而生的，它天然的符合语音依靠“虚电路”分组传输的需求。但是这种结构是否符合现今的互联网呢？答案是否定的。先让我们来看看电信承载网的结构到底是什么样的：（借用Wikipedia上的一副图片）



可能在不少人的概念里，Internet是扁平的，是由大量网状分布的路由器汇聚起来的。这个理解从抽象层面是正确的，但在物理层面，传输网络实际是分层汇聚的。比如你从家里的ADSL访问Google.com，中间途径了运营商的接入网，城域交换网，骨干传输网，国际关口，骨干传输网，城域交换网，然后可能才到达Google的服务器。如果希望直观的了解这个过程，可以traceroute一下google.com，然后分别查询各跳IP的地理信息。

在地理拓扑上，电信网络是大致均匀分布的，这也是因语音呼叫的概率分布而决定的。假如我们能得到运营商的传统语音业务统计数据，然后铺开在地图上，我们可以看到一个大致均匀的分布（不考虑人口和经济发展的不平衡性），且所有节点的呼叫量基本是呈正态分布的。但是，互联网所展现的却是一幅完全不同的光景。倘若将互联网中涌动的数据流同样铺开在地图上，我们看到的是高度不均匀的分布状况。以Web服务为例，占全球不足0.01%的Web服务器却汇聚互联网80%以上的流量，而所有网络节点的流量呈幂次定律分布。这就是互联网的“无尺度性 (Scale-free)”。



它解释了为什么虽然电信运营商在不停的扩充其网络带宽，而我们也都在用宽带接入，但仍旧无法从很多主流互联网应用中体验到满意的速度，尤其是富媒体应用。比如国内的用户访问YouTube的速度就根本无法与访问本土视频网站相比，通常差了一个数量级。大量的数据汇聚到骨干传输网上，即使是拥有逼近TB级别传输速率的光纤网络也难以承受如此重负，尤其是在这个视频服务风行的年代，电信运营商早已叫苦不迭。

“云计算”的出现无疑更进一步的加剧了这种互联网流量的不均匀性。因为无论是Amazon的EC2还是Google的App Engine，都鼓励网络应用服务商商直接购买其提供的运算和存储能力，也就相当于租用Amazon或Google数据中心里的虚拟主机。倘若按照它们期望的趋势发展下去，互联网上更多的流量都最终汇聚到了少数巨型数据中心。在当前这个网络承载基础上，“云计算”真的能成为应用服务商和用户的双赢么？我看未必。除非现有的云计算能够向大规模分布式的方向演进。



大规模分布式的“弥散云”是理想的，但在现实中实施起来却是困难的，即使大如Google这样的互联网企业，在全球也只能兴建为数不多的数据中心。对于分布在世界各个角落的用户，可能仍然不得不借助业已饱和的电信传输网络，在跨越众多中转节点后才能访问到最近的数据中心。其实，这个矛盾并非没有解决的对策，也不必对当前的电信基础网络作大规模的改造。问题在于，掌握着解决之道的人尚未真正意识到这一点，更没有找准自己的角色。虽然Google这样的互联网巨头在急不可耐的想要代劳，但事实上却显得力不从心。Google可以在互联网领域称霸，并不意味着它同样擅长其它领域。

反观如今全球的电信运营商，无不视互联网服务为新的战略增长点，纷纷大举进军传统互联网公司的领地。中国电信早在多年前就开始大力推广互联星空网络购物，而中国移动也将矛头直指竞争激烈的即时通信领域。可惜它们都希冀在一个自己所不擅长的领域内有所建树，却置自己真正的优势领域于不顾。试想，究竟是谁坐拥着遍布每一个城镇、通达每一个乡村的网络设施？这距离用户最后“1公里”的宝贵资源不正是令Google这些云计算倡导者垂涎欲滴的最彻底的分布式网络么？只可惜在习惯了以自己的意志主导各种电信服务并不断强加给用户之后，这些电信运营商，又怎能真正理解什么是互联网最需要的呢？

故步自封固然会彻底被互联网的高速发展所淘汰，转型是必须的，但如果看不清自己的定位，一味的去和互联网公司竞争又岂是电信运营商的出路所在？我相信，如果大型的电信运营商依靠长期积累而成的基础网络优势，通过适当延伸其网络设备的处理能力，用来提供类似Amazon EC2和Google App Engine的分布式云计算平台，甚至哪怕仅仅提供分布式存储服务，就足以发挥分布式云计算的真正优势，同时还可以大幅度缓解互联网高速发展所施加在电信主干承载网上的重负，一举两得，不是么？

 </description>
		<link>http://blog.oasisfeng.com/2008/07/30/cloud-computing-against-the-infrastructure-of-internet/</link>
			</item>
	<item>
		<title>DIY雷柏9200的16个可编程按键</title>
		<description>今天入手了雷柏9200无线鼠标，因为在这个价位中，它提供了绝对有竞争力的“8按键”+“二维滚轮”。再加上双模式的切换和滚轮，总共可以使用多达19个功能键！

但遗憾的是，纵然拥有如此多的按键，但官方所提供的驱动程序却只能支持对其中仅仅两个按键定制功能，不能不说是完全埋没了9200的天赋……

好在DIY精神就是要突破限制，明知不可为而为之！利用AutoHotkey，我们可以实现对其中最多16个键的功能随心定制，充分发挥你无边无际的想象力和炉火纯青的弹指神功！

经过分析，在标准模式（办公模式）下，拇指位的两个键分别是Windows标准的“第四”和“第五”鼠标键，与其它大部分鼠标一致。而“放大/缩小”两个键在安装驱动前是没有作用的，而雷柏的驱动程序固定将其模拟为“Ctrl+滚轮”，即常见软件中的缩放功能。

当切换到多媒体遥控模式后，除基本的左右键和水平滚轮外，其它按键均被赋予新的作用：拇指位的两个键现在等同于多媒体键盘上的“上一曲”和“下一曲”按钮，而原本的两个缩放键则分别产生“播放/暂停”和“启动播放器”两个功能，也是多媒体键盘上常见的功能键之一。鼠标纵向滚轮则成为了“音量调节”，按下滚轮是“静音”。

通过以上分析，我们很容易找到上述全部16个可编程按键在AutoHotkey中对应的按键名称：

【通用】
左键：LButton
右键：RButton

【办公模式】
中键：MButton
滚轮向上：WheelUp
滚轮向下：WheelDown
拇指上：XButton2
拇指下：XButton1
缩小：^WheelUp
放大：^WheelDown

【遥控模式】
静音（中键）：Volume_Mute
音量增大（滚轮向上）：Volume_Up
音量减小（滚轮向下）：Volume_Down
下一曲（拇指上）：Media_Next
上一曲（拇指下）：Media_Prev
播放/暂停：Media_Play_Pause
启动播放器：Launch_Media

“CPI”键由于只是控制鼠标自身状态，并不与电脑交互，所以是无法定制的。而水平滚轮由于AutoHotkey本身无法支持，所以也暂时不能实现定制。

需要特别说明的是，“放大/缩小”两个按键的效果是依靠雷柏的驱动程序模拟“Ctrl+滚轮”产生的，因此如果直接在AutoHotkey中简单重映射^WheelUp和^WheelDown的话，则会导致如果真正用“Ctrl+滚轮”也会被拦截，无法手动进行缩放操作。解决的办法是使用AutoHotkey的物理按键状态判断功能：

$^WheelUp::
If GetKeyState("Ctrl", "P") = 0
  MsgBox ZoomIn ; Replace it with whatever you want.
else
  Send ^{WheelUp}
return

; Zoom Out
$^WheelDown::
If GetKeyState("Ctrl", "P") = 0
  MsgBox ZoomOut ; Replace it with whatever you want.
else
  Send ^{WheelDown}
return

仅以此文献给各位“雷友”，让你真正成为手中鼠标的主宰！ </description>
		<link>http://blog.oasisfeng.com/2008/07/27/diy-programmable-keys-for-rapoo-9200/</link>
			</item>
	<item>
		<title>C语言小技巧：带扫尾工作的宏</title>
		<description>前两天为了在C下编写一个类似Erlang式消息传递的框架，需要定义一个receive宏，使得coroutine处理函数的编写可以类似这样：

int foo()
{
    ...
    receive(msg)
    {
        // Deal with the message
    }
    ...
    receive(msg)
    {
        // ...</description>
		<link>http://blog.oasisfeng.com/2008/07/27/c-macro-with-tail-work/</link>
			</item>
	<item>
		<title>在线旅游服务网站初体验</title>
		<description>由于筹划最近去澳门玩一趟，打算尝试通过网络预定旅游服务，因此在网上挑选了两个较大的旅游服务网站“携程旅游网”和“芒果网”，仔细研究了一下它们各自的“澳门自由行”产品，根据初步印象总结了一下我对这两家网站的感受：

【旅游产品】单以“澳门自由行”作对比，仅供参考
携程：提供的酒店档次偏高，同等情况下价格不如芒果网优惠（比如澳门旅游塔门票就要贵30%）。
芒果网：提供了较多的细节选择（比如长途巴士可以换为海上快艇），价格较实惠。

【网站交互】
携程：对Firefox的支持很完美，不过因为没有下订单，不清楚在线支付系统对Firefox的支持情况。交互体验感觉很舒适，有针对用户便捷操作的UI优化。
芒果网：对Firefox支持的很糟糕，不得不换IE来访问。账号密码竟然只能用数字，简直像是回到了上个世纪！另外，中途遇到了一个糟糕透顶的网站问题，差点让我改投携程……（后面详述）

【在线支付】
携程：在线支付较为完善，支持绝大多数信用卡的线上支付。
芒果网：不支持在线支付，只能通过电话委托信用卡支付。

【客户服务】
携程：没有实际下单，在此不作评价。
芒果网：服务态度感觉不错，主动跟踪客户订单并电话确认细节。对我提出的疑问也解释的也比较细致。


附：在芒果网遭遇的一个非常糟糕的体验

由于很早前在芒果网注册的账号，尝试了几次密码都不成功（谁能想到芒果网竟然只能用数字作密码？！完全看不到任何提示……）。于是只好尝试“取回密码”，输入了账号、验证码，选择“手机取回”。点确定后，提示“未注册手机”。那好吧，换成“邮箱取回”，结果弹出一个意想不到的提示：

“您在30分钟内只能取回一次密码。”

且不说这个限制本身是否真的合理，但我压根就还没有取到密码呀。就因为先选择了一个实际没有效果的“手机取回”，而导致我在30分钟内无法登陆账号下订单…… 再尝试了几次密码未果后，我开始对芒果网很无语了。

还好对Web开发的专业敏感让我发现了芒果网这个破机制的致命弱点——纯粹基于客户端Cookie的时间限制。只要清除Cookie后，就可以重新选择“邮箱取回密码”了。

对用户来说，无法登陆账号就意味着无法进行任何订购，而且忘记密码的用户通常都是有一段时间没有访问的客户，在这种可能挽回潜在回头客户的关节眼上竟然犯下这种让用户感到抓狂的错误…… 可能大部分普通用户已经在考虑改用其它旅游服务网站了，这是多么不值呀！ </description>
		<link>http://blog.oasisfeng.com/2008/07/24/online-tour-service-first-impression/</link>
			</item>
</channel>
</rss>

<!-- Dynamic Page Served (once) in 0.817 seconds -->
