2008年12月29日星期一

Pass thesis examination

今天是我这几年来的一个大日子,因为今天是我工程硕士论文答辩的日子。这是我6年前大学毕业以来第一次面对这么多老师进行严肃的答辩,再加上之前听说交大论文答辩是相当严格的,心里不免有些紧张。

答辩的学生一共有14个,我是第二个上去答辩的。因为我发现从坐下之后就开始紧张,第一位同学答辩的时候我想在脑子里面过一遍PPT的内容,结果越想越紧张。等到老师叫“第二个谁上”的时候,我觉得不能等了,越到后面压力越大,早死早超生,横竖横,拆牛棚,上了!

每 位同学的宣讲时间只有15分钟,关键是在15分钟之内将自己所作的工作阐述清楚,幸好我虽然紧张,但是思路还算清楚,比较流利的讲了下来,不过还是超过了 半分钟。最后几个老师稍微问了几个问题,就结束了答辩。总的来说,和我预期的差不多,比较顺利。毕竟我的准备工作做得很充分。


之后我就很轻松的坐在位置上看别人答辩了。当中有的同学阐述非常搞笑,老师提问,他答非所问;老师批评他,他还不服气,和老师死磕。有的同学PPT做的非常不认真,就把论文大段大段的往上贴,可想而知最后的结果是什么。


不过最后14个人都过了,但是其中7个人的论文需要修改,最严重的一个几乎要修改大半内容。最后只能说一句:态度决定一切!

2008年12月15日星期一

上海女仆咖啡店

今天无意中看到一个网友贴子,看得我热血沸腾。为啥?因为他介绍了一个上海的女仆店!不知道是不是上海第一家,毕竟我在这方面已经算是消息超闭塞人士。虽然我不是女仆控,但是看到那么可爱的女仆照片,又在自己所在的城市,心里还是激动了一把。毕竟宅男是无法抵挡女仆的诱惑的!
先给出信息,有兴趣的朋友一起去,哇哈哈哈!(感觉自己开始邪恶了!)

营业时间
上午11点 至 晚上9点
联系电话
021-63517385
地址
上海市浙江中路229号(百米香榭)204室
她们的网站是这个:
http://www.m-moe.cn/index.html

他们的blog
http://m.moe.blog.163.com/


 
女仆们排队恭候您的大驾光临!
 


在他们的网站上有每个女仆的介绍,感觉上都是初中生,高中生的样子,不知道这算不算童工啊。不过,管他呢,女仆不荫怎么行!

2008年11月19日星期三

文件搜索闪电侠

我一直很不满意Windows XP下的搜索,常常文件在那里也搜不到,每次还跑出来那只讨厌的小狗。可是公司里面不让装Google Desktop,MS自己出的MSN 搜索也不敢用,结果搜索就成了我一块心病。

前两天意外的发现了一个工具Everything, 我对其评价就如我题目写的--文件搜索闪电侠!

Everything是个小巧的工具,它能进行文件搜索,可以使用简单的正则表达式,而我最看重它的品质是,此软件小和快。小是指它的个头小,做的索引文件小,快是指做索引超快(我260G的硬盘几乎是立即完成,启动软件后就可以搜索了,官网写着速度为1分钟100万个文件),搜索文件速度快得令人发指!

其他的功能也很多,比如可以作为文件服务器,别人机器上开着这个服务,我就能去搜索他的电脑(牛逼)!

不过这个软件对我来说还有些不足,一是不能通过热键启动(就像金山词霸一样),而是不能进行全文检索。但是想想我做全文检索的几率也不大,这个就够了!

Everything的官网: http://www.voidtools.com/

另外有善用佳软小众软件对其的推荐。里面的介绍比我详细,有兴趣的人可以看看。

2008.11.28:
找到了热键启动的方法。
在Tool->Option的General标签页。设定好New window hotkey modifier 和New Window Hotkey key就可以了。

2008年11月14日星期五

有自己的域名啦!


在吗啡的多次,再三,不断地怂恿下,我终于买了一个自己的域名。

本来想买linghao.com的,可是被那种卖域名的人抢注了。而且还刚刚续了费,我只能放弃了。不过这个看起来也挺好。mog是moogle的简写,也是FinalFantasy里面飞天猪的名字,我99年一开始上网时所用的nick,挺有纪念意义的。

在吗啡的悉心帮助下(我发现我现在特懒-_-,而且对这种网络设置一窍不通,汗颜啊),一步一步把各种配置都搞好了。

以后我的blog地址变为:http://blog.mogling.com/
我的feed地址也随之变动:http://feeds.mogling.com/ (以前订阅过的朋友可以继续使用老地址,内容是一样的。)

2008年11月11日星期二

根据名字画出我的头像?

FriendFeed举办了一个24小时编程比赛Philipp的作品可以根据你的名字给你一个脸的图片。

网址:http://turnyournameintoaface.com/
 
我分别输入了我名字的拼音和中文和我最常用的网名,结果出来的是这副腾头死。

这张是linghao
这张是凌浩
 
这张是我常用的moogle
  是不是很惨,但是当我输入周杰伦,刘德华之流的名字之后,我发现我真TMD太帅了!

P.S. 2008/11/14
吗啡说用英文的没有好下场,我抱着科学的态度又求证了一下,用的是Mog,这个我最近刚捡起来的9年前刚上网时用的nick。感觉不错吧,不过就是奶油了点。

2008年11月7日星期五

File not found: ieframe.dll

When using Visual Basic 6 with Internet Explorer 7 installed, I encountered such a problem "File not found: c:\windows\system32\ieframe.dll\1" when loading a project.

Usually, the file does exist. Then why we get this problem? Well, the simplest answer is that some control referenced by your project has been replaced by ieframe.dll. I can not tell more since I am barely familiar with VB. Or to be frankly, I am neither not knowledgable of VB nor like it.

So the simplest way is to revert the reference from ieframe.dll to its ancestor. After google it, I find its ancestor is shdocvw.dll. It's in the same directory. Then register it:

regsvr32 c:\windows\system32\shdocvw.dll

Try to launch VB6.exe and load your project again, does the annoy error message disppear?

2008年11月5日星期三

pipe console program output to clipboard

I am making some demostration these days. I need run some console programs, get their output and put them into a nice slice as example. The trivial way is to redirect the output to a plain text file then open it, Ctrl+A to select all and copy, switch to PowerPoint, paste, which is exactly what I am doing.  Some days past, I feel I can't stand it anymore. A simple idea just jumped out of my mind, why not make a small tool the can read data from pipe and copy to clipboard? So I can do my jod like this(assume the program is called cmd2cb.exe):

dir|cmd2cb
type readme.txt|cmd2cb

thus, all output of dir command are read by cmd2cb and copy to clipboard. Then I simply switch to PowerPoint and Ctrl+V. Everything's done. Small tool, but cool!

When I share this tool to my colleages, it turns out that I am not the only one needs it.
So I decides to put it to my box. If you need, just download here. cmd2cb.exe (9k)
Chinese user can download from namipan(纳米盘): cmd2cb.exe (9k)

*This file can only be used in windows, console and after the pipe symbol and no warranty.
*If you're using Vista, you can use Clip.exe shipped with Vista.

2008年10月26日星期日

虬江路淘宝

自从我的磐正8RDA3G主板抽风之后,我的老电脑一直处于待业状态。我一直没有考虑好给它一个什么名份。上次为同事拍了结婚照之后,我觉得该有一台专门处理照片的机器了,我原先的配置基本不用动,只要换块主板,加个特丽珑的显示器就行了。我的CPU是Athlon XP1800+,搭配的主板可以用KT400,KT600和NF2芯片组。但我不想在上面投资太多,因此从一开始就打定主意要买二手的,花最小的代价,获得最大的利益。

原先想在pchome和pconline,taobao上面买的,但是每次都被人抢走了。于是只能瞄准上海滩最大的二手市场--虬江路。

买二手最重要是心态,就跟炒股一样。同时要做功课,认准自己要买的东西,任凭JS怎么忽悠你,都不能跟着他们走。

我在虬江路花了大概2个小时不到的时间,逛完了几乎所有的店,终于买到了一块成色非常新的工包微星K7N2主板,价格95块。可以说是非常超值。据老板说,这块板是全新的,工包批量出货拿的,我特意看了电容,散热片,PCI和AGP插槽,的确是没有用过。简直太超值了。


事实上整个虬江路NF2的主板也寥寥无几,我所有的店都兜了一下,加起来也不会超过30片。而且很多都是硕泰克,映泰之类的垃圾板子。我的原则是,二手的主板绝对不能买二流厂家的主板,要买只能买一线大厂的。为什么,因为那些二线厂家的主板寿命也就是2,3年。我的磐正主板就是活生生的例子。因此场子里面还有人推荐我磐正的,我说什么都不要。场子里面还有一块非常棒的ASUS的A7NX,可惜要150,从性价比来说不及我这块。

我这块板子是在赛格快关门前5分钟才掏到的,说来也算运气了。我之前几乎绝望了,因为场子里面基本都是754的板子了,462的板子在二手市场基本上也淘汰了。而我要的还是一线大场的NF2芯片的462主板,更是难上加难。不过我来买二手就是想买以前一手买不起的好东西的,比如可以算AGP的王者的1950PRO蓝宝石,当年2000多块的显卡,现在就布满灰尘躺在橱柜里面,罗技的蓝牙耳机之类的,这些东西看得我心痒啊。不过正事要紧,下次再来。

总的来说,在虬江路淘宝是很有意思的事情,我今年来已经很少关注硬件了,这次过去兜了一下,感觉自己还蛮喜欢这种事情的。与JS斗,其乐无穷啊。同时还能看到很多平时不知道的东西。比如我一直想买个激光打印机,全新的起码2K,而这里一个HP2015D才600;还有一套DIY的工具,包括网络工具,电工工具,都是进口的,质地看上去就不一样,开价80,感觉还行。另外就是我关注的特丽珑和钻石珑,居然让我看到一个EIZO的原膜T962,要知道这是EIZO旗舰机型,特丽珑超强色彩还原,比SONY的G520还高出一筹的极品啊。本来跟老板讲好了,可惜买好主板已经天黑,只能作罢。

2008年10月22日星期三

游戏不是这么玩的

我一向对时事很迟钝,特别是对于有微软,盗版,反黑等关键词的新闻,我从来都是略过的。但是现在我的同事已经开始用“今天你黑屏了没有?”来打招呼了,我再后知后觉也感觉到了一些不同。吗啡写了篇《整个民族心理有毛病》,仍旧秉承他一向的风格,语言尖锐,但是仔细想来的确是有道理。吗啡用的是一个IT行业从业者,受过高等教育,站在时代前端的身份来看待这件事的。而我,接触了很多不懂电脑的人,我想试着站在他们的立场上看看这件事的因果。

我在想,这件事是否是微软自食其果呢?或者是中国人自食其果呢?
在微软刚进入中国市场的时候,为了迅速扩大市场份额,他们默认了盗版的存在。反正你要用我的就成,只要不去用别人的,随你盗版还是正版。他打得好算盘,慢慢地用office 挤掉了WPS,IE挤掉了netscape,他或许想着,等到他一家独大的时候,还不是想怎么样就怎么样。他制定了这个游戏的规则。人们顺着他的规则玩了这么多年,突然,他改变规则了,那些玩游戏的还不跳起来!

当人们买电脑的时候,店里面的伙计帮他们装好了Windows,进去能看到五颜六色的界面。然后他们付钱走人。在他们付钱的时候,他们下意识的认为,这一堆铁疙瘩和里面五颜六色的界面都已经包括在他付的那点钱里面了。或许,很多人还不知道什么叫正版,什么叫盗版,版权对他们来说还是一个陌生而抽象的词语。只知道,要装软件,就去买盘。对他们来说,去街边买盘就和去菜场买菜一样。This is the way. 甚至很多人,连软件这个术语都不知道,他们可以叫出Word,IE,QQ,但是不知道这些就是软件,但这并不妨碍他们用电脑。其实美国人也这样,但是他们一开始就规定了一个正常秩序的游戏环境。

这就是这么多年来孕育出来的一种环境。这种环境的形成,政府和微软一样的领军软件企业难辞其咎。试想如果一开始,软件就是放在商店的橱窗里面出售,买电脑的时候装机店会明确告诉你价格不包含软件价格。久而久之,人们自然会习惯这样的模式。这种模式下,民众还是不用了解什么是盗版,什么是正版。有时候,你只要告诉别人,什么是对的,不用说什么是错的。这就是秩序,政府和大型软件企业在这时候就是强有力的秩序维护者。

别跟我说Windows太贵,买不起,三、四百的东西有时候还不及你一次拍拖花的钱呢。实在没钱,可以,用免费的操作系统,Linux, FreeBSD等。或许有人会说Linux,FreeBSD难用。我想说的是,这是因为在这样一个畸形的市场下面没法得到发展造成的。更何况,现在的Linux在可用性上面跟Windows相差也不多了。

或许,在这样一个环境中,不同的操作系统都能够发展起来,Windows, Linux大家各取所需,造成双赢的局面。为了构造一个独裁,垄断的环境,微软通过这种默认盗版的方式来打压其他对手,结果搬起石头砸自己的脚。政府默认这种畸形的市场不断扩大,最后不知道扼杀了多少创新成果。

有人说,就是因为盗版,中国的软件行业才能发展的这么快,我不敢苟同。我觉得正是因为盗版,中国的软件行业才发展的这么低层次,永远用别人的东西,为别人打工,我们促进了微软的发展,却限制了自己的发展。如同温水中的青蛙一样。

没必要指责那些骂微软的人,我们要骂就骂那些制定这个游戏规则的人吧。或者,像我一样,尽量离这个游戏远些。

PS: 吗啡骂那些不要脸的JS,我120%赞同。因为刚才看到有名人博客上写着“有理由相信,中国用户是全世界最热爱微软的用户”, 这句话就和“中国没有妓女”,“陈良宇没有贪污”一样可笑。

2008年10月16日星期四

Placement New的用法

在《C++中控制对象的创建》一文中,我曾经提到Placement New的一些用法。最近一段时间很碰巧用到了这个技术,因此有了更深刻的一些理解。

Placement New的原型很简单:


inline void* operator new (size_t t, void* p) {
return p;
}


可以看出,它仅仅就是返回传给他的那个指针地址,大小t不使用。
因此,我们一般先申请一块内存,然后用placement new在初始化一个对象。这里的初始化的意思就是先把那块内存映射成对象地址空间,然后再起始地址调用对象的构造函数。例如:


class Window
{
int width_, height_;
public:
....
Window(){}; // default ctor
Window(int w, int h){...}; // ctor with predefined height and width
}

void* p = (Window*)malloc(sizeof(Window));
Window* pWin = new(p) Window();
.... //use pWin
pWin->~Window();
free(p);

在上面的代码中,最后第二行很重要。一般来说,析构函数是当自动变量离开作用域时自动调用或者使用delete时调用。但是使用placement new时,不能在该对象上面使用delete操作,因此析构函数不会被自动调用。我们必须使用一种比较少见的方式——手动调用析构函数来释放在构造函数中获取的资源。

Placement new还常常用于对象数组的创建上。一般使用new[](读作array new)来创建对象数组的时候有一个缺点,就是只能调用其默认构造函数。这有时候非常不方便。

Window* pArrayWin = new Window[20]; //default ctor is called

但是使用placement new就可以让我们获得调用其他构造函数的能力。代码如下:

Window* pArrayWin = (Window*)(operator new(sizeof(Window)*20)); //
i = -1;
while( i <20){
Window* pTemp = new(&pArrayWin[i++])Window(i*i,i*i*i);
}


这里就可以使用Window类的另外一个构造函数了。在每一个Window类构造的时候就可以给其设置长和宽。
这里的Window类只有两个整型成员,这种情况下,可以不用调用其析构函数,直接delete分配的内存。因此用placement new来处理这种小型连续数据在某种程度上可以提高效率。

2008年10月11日星期六

The Big Bang Theory不太敬业

最近一直在看《The big bang theory》,因为风趣幽默,所以我反反复复的看了快第三遍了。但是今天看到一个场景,让我感觉有点失望,看看图中的包包。有没有看出来什么问题?

是的,太假了。连商标都在,宝宝里面这种鼓起来的样子一看就知道是放在商店里面展示用的,因此里面塞满了泡漠塑料,废报纸等。我估计是剧组资金不够,所以问旁边的商场借的吧,等演出结束就立刻送回去。看来美国经济大萧条已经影响很深了,连这样一个平常的包剧组都买不起了。但是我要说,这还是不太敬业,买不起就不要背包,拿演员自己的包也可以么,反正是生活喜剧。真不知道他们怎么想的。。。

2008年10月8日星期三

My VS2005 Color Scheme

我今天花了点时间改了改VS2005的配色和字体方案,把原来整体白色的效果改成了现在的灰暗的效果。主要原因是保护眼睛。白色虽然明快,对比度高,但是会反射所有的光线,而黑色则相反,可以保护程序员的视力,至少不会看着很吃力。不相信可以自己试一下,把液晶显示器的亮度调高,盯着看一段时间,然后再调暗,眼睛是不是轻松很多。

然后字体从原来的Courier New改成了现在Monaco,这个字体非常好看。也是网上很多人推荐的编程用字体。效果图如下:


我个人不太喜欢花里胡哨的配色,所以颜色看起来不是很鲜艳。这样的好处就是让眼睛少受刺激。颜色太多,眼睛受到的刺激也会增加,长时间盯着看反而会吃力。

我的配色方案如下:
Font: Monaco (size 10)
Background : RGB(25, 25, 25) Not completely black

Plain Text : White
Line Number: RGB(43, 145,175 )
Comment : RGB(135,206,235 ) bold
Identifier: RGB(207, 207, 207 ) bold
Keyword: RGB( 68, 68, 255 ) bold
Number: RGB( 0, 128, 128 ) bold
Preprocessor Keyword: RGB ( 175, 96, 255)
String: RGB(252, 71, 39) bold



在《Monospace/Fixed Width Programmer's Fonts》一文中,作者列出了他认为写程序用的字体,应该具备哪些条件:

  • Crisp clear characters.
  • Extended characterset.
  • Good use of whitespace.
  • 'l', '1' and 'i' are easily distinguished
  • '0', 'o' and 'O' are easily distinguished
  • forward quotes from back quotes are easily distinguished -prefer mirrored appearance
  • Clear punctuation characters, especially braces, parenthesis and brackets

简单的说,首先要清晰,然后才是美观。总的来说,我觉得还是有道理的。我以前一直使用Courier New就是因为这个字体很清晰,在VS2005中如果更改字体,那些加粗的都是等宽字体,也是写代码首选的字体。网上讨论的比较多的是三款字体,分别是Bitstream,Monaco,Consolas,分别是Linux,Mac,Windows三个平台上的代表字体。我选择了Monaco,这块字体乍看之下不怎么样,但是仔细看看还是很有味道的。有兴趣的朋友可以试试。

另外,这几个配色方案也是我比较推荐的:
Dark Visual Studio
Scott Hanselman's color scheme
Slimcode
Jeff Atwood

相关文章:
Programmer 最佳用字型 Monaco font
Best font for programming is...?

2008年10月5日星期日

《星球大战》中的Jedi职业级别

参考了很多RPG的规则,比如D&D,星球大战中也有职业的升级。当然这些在Wiki中都有,我当时是在看了片子之后慢慢推测出来的,后来看了Wiki之后才有了一个完整的了解。(Wiki中的条目为Jedi Rank)。这里仅限于Jedi,Sith过于神秘,影片中提到的也较少,我还没有看出明显的区别,可能游戏中有提及吧。

Youngling
拥有Force潜力的孩子,在被任何一个Jedi knight收为徒弟之前,在Jedi temple接受统一的训练(学龄前训练)。在EP2中有一段就是Yoda在训练一群孩子,Obi-Wan过去请教那颗消失的行星。在Revenge of the Sith中,Anakin残忍的杀害了所有的Youngling,另Obi悲痛不已。

Padawan
Jedi Knight或者Master的学徒,Jedi们喜欢用Padawan称呼自己的学徒,Sith则用Apprentise。在这方面,Jedi的叫法显得更加亲切。Padawan称呼自己的老师为Master。Jedi采用的是一对一的授业方式,只有Padawan通过试炼,成为了Jedi Knight之后Master才能再次申请一个Padawan。

Jedi的训练和武术、内功等一样,最好从小学起。相信大家还记得在《魅影危机》中Qui-Gon Jinn提出训练Anakin的时候,Obi-Wan说:“The boy will not pass the council's test, Master. He's too old”。那时Anakin才9岁,这说明一般的Jedi开始他们的训练要早得多。最后Qui-Gon Jinn临死前要Obi-Wan答应训练Anakin。于是在Obi-Wan的强硬要求下,Master Yoda才同意让Anakin成为Obi-Wan的学徒。

有一个细节很重要,Padawan会在脑后留一簇头发下来,就像一根小辫子。当被正式授予Jedi Knight称号之后,这个小辫子会被剪下,标志着自己的成长(当然,限于有头发的物种)。
看看下面两张图的对比,Obi-Wan在EP1:The Phantom Menance中的学徒打扮和EP2,EP3中的Master打扮。注意到第一张图中的小辫子没?


我第一次看时就有疑惑,为什么会有这个小辫子,难道是流行?那时候上海的确流行给小孩子留个小辫子,因为看起来好看。但是之后我看了The Clone War Animation之后,我才知道,这个小辫子是Padawan的标志。

用Star War Clone War中Anakin成为Jedi Knight的场景来说明一下。

经过一番激烈争论,Jedi Council终于同意Anakin Skywalker成为Jedi Knight。Kenobi对Anakin说,It's time we became BROTHERS.


进入Council,出现了激动人心的一幕。是不是特别像某些游戏中的转职的场景啊。


Yoda: Step forward, Padawan.
Anakin Skywalker,
By the right of council.
By the will of the Force.
Dub thee I do, Jedi ... Knight of the Public.

天行者阿纳金,
以议会之权,
以原力之志,
授予汝--共和国绝地武士称号!


小辫子被剪掉,Padawan正式升级成Jedi Knight。

Jedi Knight
Padawan通过一些考验,就能正式宣誓成为Jedi Knight。考验多种多样,有的是关于智力的,有的是关于技术的,有的则是心智上的。心智上的最难,一般称为“Facing the mirror”。例如Master Yoda让Luke Skywalker去面对他的父亲Darth Vader。第一次Luke失败了,第二次成功之后,Luke成为了真正的Jedi Knight。另外像Obi-Wan在EP1中击败了杀死他老师的Darth Maul而成为了Jedi Knight。总之这是一个最普遍的级别。在对外的时候,Padawan也可以自称Jedi,为了避免在称呼上的麻烦。

Jedi Master

当一个Jedi Knight成功训练了一个Padawan成为Knight,他就可以成为Master。但是如果Jedi Council觉得一个Jedi Knight已经积累了足够的经验,知识和力量,也可以提出一个考验,一旦通过此考验,就可以成为Master。

Jedi Council Member
实际上我认为这不是一个级别,而是一个职位。加入Jedi议会当然会有更多的权利,但相伴的也是更多的义务。当Council中一旦有位置空出,Council就会着手挑选合适的人进入,来填补空缺。

Jedi Grand Master
更正式的叫法是“Grand Master of the Jedi Force”。在影片中并没有提及。只出现在小说和游戏中。
只有最智慧的Master才能被推举为Grand Master。在新的Jedi Order时,Luke Skywalker也被推举为Grand Master,因为他是旧议会时代最后两个Jedi,Obi-Wan和Yoda的学生,同时创建了新的Jedi Order,以及新的议会。在整个历史上,也只有三个Jedi获此殊荣Nomi Sunrider,Yoda 和Luke Skywalker。

《The Big Bang Theory》

自从《远古入侵》结束(夭折)之后,我一直在找有意思的美剧/英剧。《老爸老妈的浪漫史》只能做开胃的小菜,但是正餐一直没有着落。

不过今天无意中看到了一个片子《The Big Bang Theory》(生活大爆炸),讲述的是四个高智商的年轻小伙子遇到了一个美女房客的故事。显然,这种故事中的美女基本上是胸大无脑,但是太过愚蠢也不招人喜欢。高智商的小伙子们也不可能情商<0。下了几集看了下,还真是有意思,尤其是美女是我喜欢的邻家女孩的类型,挺温柔的,绝对不是乱来来的那种。想想也只有这种女孩才能打动才子的心。后来看到编剧是Bill Prady我才放心,他是Gilmore Girl的编剧,擅长生活中的小幽默加上一些会心一笑,再加上一些小小的温馨,感觉不咸不淡,口味正合适。

P.S. 我终于看到比Ross更搞笑的书呆子了,而且还是4个!!!

以下摘自verycd
--------------------------------------------------------------
(译自CBS官方新闻发布稿)这是一部以 "科学天才" 为背景的情景喜剧,这倒非常罕见。主人公Leonard (Johnny Galecki, "Roseanne") 和 Sheldon (Jim Parsons "Judging Amy") 是一对好朋友,他们的智商绝对高人一等,因为他们对量子物理学理论可以倒背如流,无论你问他们什么问题,都难不倒他们。但是说到日常生活,这两个不修边幅 的男孩就彻底没了脾气--生活中柴米油盐这些看似简单的事情,却让他们有迷失在太空里一样的感觉,他们所掌握的那些科学原理在这里根本没有用武之地。
直到 有一天……隔壁搬来一位美貌性感的女孩Penny (Kaley Cuoco, "8 Simple Rules..."),顿时吸引了两人的目光。Penny是个剧作家,平时还在饭店打工,她个性开朗,待人友善,最重要的是--她最近刚刚变成单身。
但 令Leonard和Sheldon失望的是,美女对两人都没有意思,反而对花花公子Howard Wolowitz(Simon Helberg, "Studio 60 on the Sunset Strip")产生了好感。Howard绝对是那种可以俘获女人芳心的帅男,他甚至称自己是加州理工学院的"卡萨诺瓦"(1725-1798,意大利冒险 家,以所写的包括他的许多风流韵事的《自传》而著称,后来该词被引申为"风流浪子,好色之徒")。喜欢有事没事围着别人转悠,大谈特谈相对论的 Rajesh Koothrappali (Kunal Nayyar, "NCIS")也引起了Penny的兴趣。

一个美女和四个科学怪才的故事就这样在笑声中悄然开始上演……







2008年9月30日星期二

名人译书要慎读

最近我在看《C++语言的设计与演化》(英文名:The design and evolution of C++ )一书。我买技术书,只要有原版的,我基本上都是买原版,宁愿看得吃力点也要买。为什么,就是怕了那些胡乱翻译的中文版,知识没学到不说,还有可能曲解原文,把我往错误的方向上领。那我自己看原文一定就能理解正确?非也,我的英文虽说还可以,但是老实说,比起那些成天译书的人总是要差些的。但是就算我自己理解错误,那也是我自己的事,怪不得别人,但我却不希望别人来误导我。

以前,我对一些有名的学者翻译的书还是比较认可的,语句通顺,用词准确规范,还会顺带纠正些原文的错误,从实际效果看的确能加快阅读和学习的速度。一般性这些人的名字也保证了译文的质量,让我比较放心。但是现在,在这种浮躁的社会气氛下,名人也开始擦烂污了。

就拿我手上的这本《C++语言的设计与演化》来说吧。译者为国内知名学者裘宗燕老师。裘老师译过很多书,在网上评价很高。但是很不巧,我就买过这一本,因此我也只能拿这本书说事。这本书语句还是很通顺的,用词也中规中矩,符合技术书籍的性质。而唯一让我气恼的是他也有名人的通病,喜欢自创术语。大家都知道,技术术语一般都是非正式的一种约定成俗的说法。但是时间长了,大家也熟悉了。一个大家都使用,都熟悉的术语就好比标准,有利于沟通,有利于教育和学习。然而,有部分人就喜欢标新立异,他的想法是什么,我不得而知,也不想过问,但是我最恨这种做法。在《C++语言的设计与演化》这本书中,一些约定成俗的术语,比如构造函数(constructor),类型转换(casting)等都被改头换面。比如构造函数变成建构函数,类型转换偏离愿意更多,变成了“强制”。老实说,我一开始还蒙了呢,当第一次看到这个术语,我在想,C++里面有叫“强制”的特性么?后来下了本原版pdf,才知道是casting。其实,在这里用强制则完全没有理解casting在C++中的意义。类型转换本身有强制转换和非强制转换之分,怎么能一棒打死全叫强制呢。其实这里翻成类型转换或者台湾术语转型都是可以的,至少是让人比较容易接受的。但总的来说,这本书其他地方翻的还行,没有明显的逻辑错误,可能就是这几个地方裘老头犯傻了一次吧。

我见过术语篡改最厉害,翻译的最过火的莫过于翻《UML精粹》第三版的徐家福老先生了。曾有人提到这位老先生的地位,似乎也是中国计算机界的泰山北斗了。不过我对这种一向不感冒,我喜欢看到实际的东西。而我看到的却是一本几乎翻成文言文的技术书,用时下流行的话说,我被雷到了。老先生文学功底自然不俗,但是用来翻译技术书籍,除了卖弄风骚,我想不出其他评价了。当然,里面的术语几乎都被重定义过了,还好老头子没有做绝,把原文单词放在那里,也幸好我比较熟悉,直接过滤中文,看英文,最后实在受不了了,下了本原本,嗯,martin fowler的英文的确不错。

另外要说的就是挂羊头,卖狗肉,也就是俗称的贴牌。我们从代加工行业熟悉了这个词,现在已经引用到翻译技术书籍上头来了。很多书,挂着名人的牌,实际都是别人翻译的。比如一些有名的教授挂名的书,实际上都是其研究生翻译的。这也算是一种潜规则吧。想想这些教授也一大把年纪了,犯得着挑灯夜战,一句一句去翻译技术书籍么。这点稿费还不及人家走个穴呢。不过有些教授还是有良心的,至少最后校审一下,有些就是黑了心,直接挂名就发书了。大家可以想象这个书的质量。我感受比较深的有几本书,barbara liskov的《程序开发原理--抽象、规格与面向对象设计》,bjarne stroustrup的《C++编程语言特别版》等。因为里面都有对原文的曲解和误解。不过这也难怪,我也是对着那几句话反复研究才搞懂作者的真正意思的。对于译者来说,那是有时间限制的,不可能像我那样逐字逐句地去斟酌。另外,这两本书,也是我看过的最难的书。但是,我觉得越是难的书,越应该买英文原版,好处么,自己去体会吧。

说了这么多,我觉得比较好的一个模式是,买本中文书,再下载个英文原版,或者买英文版,下载个中文版。目的就是对于那种不大可能错误的地方花最少的力气,用最快的速度通过。而比较有价值又比较困难的地方,则使用原版来保证质量。这也是我现在使用的模式。

2008年9月26日星期五

C++中控制对象的创建

在C++中,可以通过很多方法来定义对象的创建方式和地点。

1. 将构造函数设为私用,可以阻止直接创建。
这个方法是最常见的,恐怕我们最熟悉的就是单件模式(Singleton)。通过类的静态方法来创建对象,以达到控制对象个数的目的。
实际上,这种情况下也就直接阻止了派生。因为C++要求派生类要显示或隐式调用基类的构造函数。但是,真的没法派生了?当你要为这个类增加功能,又不想破坏现有的代码时,你会怎么做呢?
看看下面的代码:


class B{
friend D;
B(){};
}

class D{
public:
D();
D(int);
}

D d;

class DD:public D{}; // error, DD::DD() cannot access

是的,可以通过友元来获取访问权限,这样就可以在原来基类的基础上扩充功能了。而且这个派生类仍旧延续了之前的语义,无法被继承,因为DD无法访问在最上层的B::B()。

2. 利用私有的析构函数阻止派生,堆栈和全局分配。
析构函数声明为私用就可以避免堆栈和全局分配。这样做还能防止随便使用Delete,这种类的典型使用需要一个高度优化的自由存储分配系统。

析构函数声明为私用也可以用来阻止派生。这时候,构造函数最好也设计成私有,这样可以保证创建和销毁的语义相同。当然,取巧的方法也有,只要简单的重载delete操作符即可。但是这样恐怕只能通过编译,仍然无法访问基类的析构函数,因此可能会造成内存泄漏。

3.阻止复制的语义
把复制构造函数设为私用就可以防止复制构造,同理可以用在赋值操作符上面。按照Effective C++的建议,当显式提供了复制构造函数,最好也要提供赋值操作符,同时,他们两个在复制对象内容上有一致的语义。

4.用Placement new指定对象的内存地址
Placement new语义是用户自己指定一块内存,用来存放类的对象。
一般使用new来创建对象,对象的存放位置无法控制,只能由系统来确定。
而Placement new却可以控制对象的存放位置。

Class X{
//....
}

void * pv = malloc(sizeof(X) *1000);
X* pX = new(pv) X();

事实上这和一般的new区别不大。一般的new是先申请一块空间,大小为sizeof(X)+delta。(delta是cookie的大小。cookie是用来记录在自由存储区请求内存大小及其他信息的一个系统实现,隐藏在应用程序背后,我们看不到,也不需要管,在window和unix上cookie的大小略有不同。)然后再把这块空间的首地址转换成X*,接着在上面调用X的构造函数,填充这块区域,完成初始化。

Placement new只不过是自己决定了空间的大小,以及确定了起始位置。Placement new主要用于批量构造对象,比如1000个X连续排在一起。这样一方面减少了cookie数量(从1000->1),也能够使访问更迅速(在一块连续的存储上)。

但是注意使用placement new时可能会造成内存泄漏,也就是在Placement new所返回的内存中,如果有指针指向其他的自由内存的话,当调用构造函数之后,很可能把该指针覆盖掉,这样那块自由内存就“丢失”了。

2008年9月25日星期四

Track Active Item in Solution Explorer

我现在所在的项目规模很大,在solution中的源文件就有几千个。平时编辑的时候要全部展开是不可能的,特别是对于我这样的新进员工,一下子接触到这么大的Project还真有点摸不着头脑。

这几天我发现一个问题;当我在编辑某个文件的时候,我很希望看到Solution Explorer同时帮我定位到那个文件,这样我可以看到该文件在项目中的哪个项目的哪个子目录之下,这有助于我了解程序的逻辑结构。同时也因为这个项目中的文件的物理结构和逻辑结构完全对应不上,使我没法通过物理结构直接映射到逻辑结构(也就是在Solution Explorer中的树结构)。因此,Track Active Item这个功能对我而言很有必要了。然而,当默认安装好VS2005之后,这个功能是没有的。

于是我很愚蠢的花了3个多小时时间,研究了VS2005的宏编程,写了一个宏,当我选中某个文件的时候,Solution Explorer会自动定位到那个文件,必要时会自动展开。还洋洋得意的把这个宏发给同事。结果,同事告诉我,在VS2005中早已有这样的设置,我这是在重新发明轮子的傻事。

VS2005中的设置在Tools->Option里面,如下图



另外,这里也附上我写的宏,以纪念这次愚蠢的行动。


Public Sub LocateFileInSolutionExplorer()

' Get the UIHierarchy
Dim oUih As UIHierarchy = DTE.ToolWindows.SolutionExplorer

' Check if there is solution exists
If (oUih.UIHierarchyItems.Count = 0) Then
Return
End If

' Get the top level item in UIHierarchy.(solution)
Dim oUihSln As UIHierarchyItem = oUih.UIHierarchyItems.Item(1)

' Reverse finding corressponding parent until solution node.
Dim oItem As Object = DTE.ActiveDocument.ProjectItem
Dim oPath As String = oItem.Name

While Not (TypeOf oItem Is Project)
oItem = oItem.Collection.Parent
oPath = oItem.Name & "\" & oPath
End While

'Construct item path
oPath = oUihSln.Name & "\" & oPath
'Select this file
oUih.GetItem(oPath).Select(vsUISelectionType.vsUISelectionTypeSelect)
'Activate the solution window so the selected file is hilighted
DTE.Windows.Item(EnvDTE.Constants.vsWindowKindSolutionExplorer).Activate()

End Sub




这个事情给我的教训是,当遇到问题时,首先问问周围的人,然后Google一下,再去Usenet问一下,最后才自己动手。除非是想学习某样技术,否则没有必要浪费时间重新发明轮子。

2008年9月24日星期三

The Returns of Heroes -- SE3

英雄第三季悄声无息的突然出现了。我原来以为编剧已经编不下去了,也就放弃了追片。没想到在不经意间英雄回归了,而且一下子出来了两集。不过最近实在太多事情,先下了再说,等积累到3,4集再一起看。

看了看海报,几位主角都越发显得老练。啦啦队队长克莱尔显得成熟了许多,褪去了以前的青涩,充满了魅力。一直显得很初哥的Peter从海报上看起来也不太一样了,不过他的风格就是那样,能力再强还是一副懦弱的样子。最有看头的应该还是塞拉,深陷的眼窝,聪明的头脑,超强的邪恶力量,这次终于有能对抗正义的邪恶力量了。胖子警察Matt,老实说总给我一种有着很强的力量,却一直缺乏方向感的人。这种人根本没法发挥出应有的力量。

总的来说,英雄中的“英雄”们都是平民老百姓,每个人的性格都有缺陷,不过正是因为这样,才让人觉得有意思。否则弄成生来就知道自己的使命的超人或者美国上尉就俗套了。也许80年代还能这样搞搞,现在是21世纪,人们喜欢的就是多元化。

2008年9月18日星期四

与侯捷面对面

侯捷先生这两天来我们公司做C++培训,使我第一次有机会亲眼见见这位国内的大牛。

侯先生给我的第一感觉就是儒雅,平易近人,非常认真。知道侯先生已经是7,8年前的事了,侯先生对国内计算机教学最大的贡献就是引入了很多名著,当然主要在于C++和Java编程方面。我从各种侧面都了解到侯先生的为人非常令人钦佩。这次面对面聆听他的培训,更是感受颇深。


侯先生的教学态度是我遇到过的所有培训老师中最好的。9点钟开始的培训,我8:40到发现他已经在那里了。他非常喜欢和下面的人互动,鼓励我们多问问题。每天我们都会提出很多问题,有些问题他无法解答的,他会一一记下,晚上回去做功课,第二天给我们答案或者和我们更深入的讨论。侯先生不是圣人,所以他不可能什么都懂,我们有时会提出更好的或者相对来说更合适的解答,侯先生一定会欣然接受。第二天就会在他的slice里面反映出来。


侯先生的治学严谨其实在他以往的著作中可见一斑。我以前读《深入浅出MFC》的时候就相当佩服他能够将这么大的一个库剖析的这么清楚。我也看过很多源代码,但从来没有哪次能像他那样把思路理得这么清晰。这次他给我们讲了STL中的内存管理,也就是allocator。我有一次深刻的体会到他在这方面的功力。他能把一段指针满天飞的代码,不光读懂读透,还能画出非常直观,非常漂亮的示意图出来。把对象在内存中的布局,每一步的变化,像连环画一样画了出来。如果我这样说你觉得没什么,你可以试试,拿出几百行的代码,画画它们在内存中的变化,看看你能做到什么程度。侯先生不会放过任何一个小细节,有时候简单的一句话,却包含着非常深刻的意义。看代码,学代码,真正有价值的,其实就是这些。把这些搞懂,我们才能不断进步。否则,就算我们看过无数代码,还只能停留在表面。这就是他这几天教给我的东西。


侯先生的专注相当令人钦佩。侯先生自己也是一把年纪了,但是还能这么专注的研究技术,真是让我汗颜。现在搞技术的浮躁的人忒多,很多人做了一两年基本上就想转管理了,说做技术没有前途。有些人做了几年C++,看到.net流行了,就去做.net,过会儿又做做JAVA,最后年纪也大了,却一事无成。候先生这么多年来坚持不断的在这个领域内勤奋耕耘,才能有今天的成就。其实我也是经常会摇摆不定,有时候想放弃技术,但是不知道是幸运还是不幸,每次都有客观或者主观的原因把我拉回来。

天下无不散的宴席,和侯先生的接触也就是那短短的十几个小时,但是他给我展示了另外一个更有意思的世界。

2008年9月13日星期六

dev.chromium.org被封

Chromium一出来,我就一直关注着dev.chromium.org,我知道我的能力帮不上什么忙,但是我想学习一下。毕竟这是googler写出来的程序,无论怎么样,总比我这个半吊子要强的多了吧。


但是从前天开始似乎dev.chromium.org就进不去了。公司的路由是德国的,因此我能进去,发现第一个帖子就说dev.chromium.org被G××封了。G××真是越来越霸道,简直就像以前的东厂和西厂,封人没商量。事实上G××对google的产品总是青睐有加,是不是的去捏一把,推一下。就没见它对MS,Yahoo!的产品有什么动作,这背后到底有些什么呢?

2008年9月12日星期五

英国一所大学提供Jedi武士训练课程

从08年11月起,英国的Queen's University Belfast 将会提供一门非常有创意的公开课程,这门课程将会教授学生使用星球大战中的绝地(Jedi)武士的心理学来掌握交流和发展人际关系的技巧。课程的教材叫“Feel the Force: How to Train in the Jedi way”,教程中提供了在真实生活中隐藏在Jedi们的引导别人思维的把戏(Mind Tricks)之后的心理学技巧。并且保证能为学员介绍在星球大战中的很多概念,比如平衡,命运,二重性,父性,法西斯等。这门课程价格不贵,大多数学生都能承受的起。

事实上,学校的初衷不是这门课本身,而是希望通过这种有趣的方式来传达给学生们一种持续学习的理念,使他们保持终身学习,因此学院把这门课设为公开课。学生们学习的不仅仅是星球大战的电影,还有电影中涉及到政治和社会学的问题。

在这门课之前,UK的第一个Jedi church也刚刚建成。你可能要问,什么是Jedi church,但事实上我也不知道什么意思。但它说明了一点,英国人也喜欢StarWars。否则为什么别的不选,而要选一个被称为boy film的商业电影作为研究对象呢?估计卢卡斯听到这个消息,开心的鼻子都要笑掉了。不过也可以说,Star Wars中的这种心理学技巧是简单而容易学习和应用的。该教的知识都有,书本不是枯燥的定义和文字而是电影,学院在引导人们快乐而持续的学习上真是煞费苦心了。

P.S.
Jedi的引导思维的把戏可能不一定有人注意,但是打过Star Wars游戏或者看电影比较仔细的人一定会注意到。比如在Ep 4,Qui-Gon Jinn在Tatooine上为Anakin赎身和Watto(那个会飞的丑陋奴隶主)打赌的时候就用了Mind Trick。在Eq 1,A new hope 中,Obi-wan Kenobi(老年)带着luke去飞机场时候也用了Mind Trick来控制帝国士兵躲过身份盘查。这项技巧在谈判时候特别有用。但是对于意志坚定的人(生物)是没用的。

消息引自:
http://idle.slashdot.org/idle/08/09/11/1648230.shtml
http://www.telegraph.co.uk/news/newstopics/politics/education/2798657/Star-Wars-Jedi-Knights-course-offered-by-Queens-University-Belfast.html

2008年9月10日星期三

不用stylish了

我一直使用stylish很久了,几乎把google, yahoo的很多产品都该了界面。今天,突然心血来潮想回到以前简单的界面看看。没想到这一看就出事了。

我尽然觉得意见简单的界面反而有浑然天成的美,难道是我的审美除了问题?等到我把reader, gmail, calendar等全部变回原样后,我才发现,google的产品的UI设计是真正的返璞归真,简单而和谐,感觉浑然一体,非常自然。

我决定,放弃浮华,接受朴素。再见了,stylish!

2008年8月28日星期四

马路杀手猖獗

今天我到公司又晚了,很巧的是,今天晚到的原因和我这个月第一天上班的原因一样。
我乘坐的大桥五线在花木路路口和小轿车零距离接触了一次。大桥五线是直行的,正打算进站,小轿车是打弯出来的,按照交规,小轿车应该让直行的巴士。可惜,开车的无一例外都是年轻气盛的小伙子,都妄想加速冲刺超过大桥五线展现自己的车技。结果两次都是小轿车撞到了大桥五线的尾部。这说明什么,说明大桥五线已经在很前面了,而且正在往边上靠,这时候有经验的驾驶员都不会蛮干,而往往就是这种志得意满的新晋车手会不顾一切的来上一下。这种人就是所谓的马路杀手!私家车越来越多,马路杀手也越来越多。

相撞后这种人马上就下车和巴士司机理论,就算警察来了也拖着司机不让走,搞得满满一车人气愤得直想给他两个巴掌。这时候大桥五线上的人大多是去张江上班的,大家都是算好时间坐车,这样一弄,势必要迟到,我们公司还无所谓,但是有些公司就会扣奖金。而且现在是上班高峰,坐过大桥五线的人都知道,这辆车在世界最挤的公交车中绝对能排进前三。前面一部车的人,起码后面来上十几辆车才有可能拉光。而且这个时候一辆出租车都不可能叫到,这条路上面也就大桥五线一辆公交车。这真是叫天天不应,叫地地不灵。

我是等了四辆车才勉强挤了上去。这个路口真是马路杀手高频出现地段,我一个人在24天内已经遇到两次,不知道以后的日子还会遇到多少次。我曾经搭同事的车时心里嘲笑他胆小,开车过于谨慎,要我肯定开得飞快,现在看来,如果我还有这样的想法,我势必也会成为一个马路杀手。

2008年8月25日星期一

海湾键盘再次报废

我的第三块BenQ海湾键盘终于报废了,寿命勉强超过1年。
还记得我一年前写的《海湾键盘,让我对你说爱还是恨》那时候是我第二块海湾键盘了,由于这个键盘的手感的确很好,我还是买了第三块,结果国货的质量还真是不能恭维,才一年,又坏了,先是某个键没了反应,接下去就是一大批键没反应。
BenQ键盘保证在一年内是包换的,可惜我这个键盘超过了20几天,不能换了。不过也好,让我对其死心了。BenQ键盘,就是一个绣花枕头,价格贵,要110块钱,都快赶上2块Dell标准键盘了,里面却是一包草。公司里面的Dell键盘,用了快3年了,一直好好的。家里的BenQ在使用时间上大概只有公司键盘的1/4,还一年就戈屁了。这种硬件厂商,奉劝大家还是不要去买了。
这次打算买罗技的标准键盘了,价格好像才79,除了insert,delete等键位是竖过来变成两列外,其他和标准键盘没什么两样,据说手感也不错。而且罗技的东西质量还是有目共睹的。

2008年8月20日星期三

vim很牛

新公司不能用盗版,对此我首先觉得烦恼的就是文本编辑器。Notepad是不可能了,以前一直用Emeditor,可惜也是盗版。没办法,只能重新找个替代品。正好以前一直想学习学习vim或者emacs,于是我选了Vim先学起来。这两天捣鼓了一下,弄了个模拟IDE的界面出来,在这里秀一下。

左上角是winmanager,用来浏览文件夹,创建文件/夹,增加删除文件,打开文件等。
左下角是taglist,用来显示当前文件中所有的tag,以函数,变量,宏,类等进行分类。
右边是源代码编辑窗口。

怎么样,看起来是不是和一个ide差不多。

2008年8月11日星期一

打算下NBC的奥运开幕式转播

在看完央视的开幕式之后,我总是觉得差强人意,这两天在网上逛,才发现是垃圾导播的问题。那个镜头切得烂啊,把无数人的心血弄成这样。虽然我不是张艺谋的饭,但是我也希望对他有公平的评价。全世界人民都说好的东西,不可能有如此平庸的表现。

据说NBC的转播做得非常棒,有很多我们没有通过央视看到的唯美画面。

nbc的版本可以通过bt下载,也可以在这里下载六个片断。

附上清华BBS的评论

===============================================
附:NBC文字版(转载自水木清华)
发信人: lifeforever (如何度过这段岁月), 信区: Olympic标 题: 奥运会开幕式NBC 文字版发信站: 水木社区 (Sun Aug 10 00:45:29 2008), 站内
央视就不知道以人民群总喜闻乐见的方式直播奥运开幕?!?!
该童子应该是个在美华人,主要以美国主持人的角度几乎是做了个直播,呵呵。。我们这些无福欣赏NBC版本的,可以看这个解解馋。。
1.我日,震撼!震撼!震撼!震撼!美国NBC的2008 北京奥运的宣传片,花了几分钟全面介绍中国,长城,中国人,5000年历史,桂林山水,中国人的奥运梦想;那个音乐配的,靠!让我有看Michael Jackson - History开幕的感觉!
米国人,就是比加拿大强!希望坚持住,后面不要缩卵 + 阉割!!!
2.又开始介绍,北京的城市建设,回顾老毛,哈哈哈……
到现在为此,都是正面的声音,只关注在奥运,暂时还没废话!
现在开始大势宣传奥运火炬在法国受到的侮辱,说,全中国人民愤怒了!米国人,继续扇法国人的狗脸……呵呵
开始介绍四川大地震,介绍中国的地大物博!也开始说88事件,以及中国国内存在的一些抗议的事情,但是,给人感觉,是在叙述事实,不是加拿大那种,酸溜溜的口气……
3.主持人还在不断的介绍中国,show自己的中国的朋友如何说,等等……
采访运动员了,专注在体育和金牌,和老布的全家,不错,这才是大家想知道的内容……
我们想了解奥运会,而不是一边欣赏美丽的表演,一边却不时要吃那些**加拿大CBC主持人抛出来的苍蝇!
4.开始转播老布入场,挺好玩的,老布到处开始拍别人的肩膀!
日,开始的大钟,也没看到,该死的CBC!!!
5.米国的主持很到位,什么都懂,国歌,歌唱祖国,唱歌的小孩,来源,叫什么,56个小孩子,怎么选出来的!
唉,对比一下加拿大,米国真是不错,不错,表扬一下……
对了,升旗的时候,他们专门提到了56个孩子,和升旗的军人,军人保护孩子,就是保护国家的未来,米国人,你还真了解中国人的思维!
正在介绍世界上最大的LCD屏幕,就是地上的卷轴,总算知道那是什么回事了!
6.美国主持人太T M D五毛了,看到了竹简表演了,他们开始吹嘘说,强大的中国传统文化,2500年的历史,世界上还有谁能够说比这更强?还有4大发明,不好意思,4大发明的是中国人的……
我鸡动了!我被米国人给打动了了!靠……我日你,米国人!
7.刚看完活字印刷表演,表演到鲜花的时候,一个主持人说,“It’s unbelivalbe,不知他们到底怎么做到的?”另外一个主持人回答道:“Peoples!”
Visa, 可口可乐的广告,简直就是奥运宣传片!非常有格调,给Visa卡广告做背景解说的好像是The Dark Knight里面的Morgan Freeman。
8. 评价太高了,现在开始调侃,说现在很多人,肯定在北京的麦当劳里面,买一个Big MAC,然后,坐在里面看开幕式,呵呵呵,这两个主持人,YY的能力和TF不相上下…呵呵呵,日,第一个用非美国、奥运、或者中国作为广告的竟然是“联想 ”的Lenovo ThinkPad笔记本!
我日,哈哈哈,他用日本的相扑运动员做的广告创意!!!
谁说不是呢,中国人,很强,很暴力!
9.开始赞美太极,一个主持人说,“If you love the 太极 master, how about 2008 of them?” 呵呵呵
然后开始赞美,这2008个怎么表演的呢?这么圆,而且,看起来,地上还没有什么标记一样的东西。
还说,现在的表演,寓意着,中国将消除污染的重任交给了他们的孩子们,只有孩子们,加上太极的和谐,才是中国在未来几年内的希望。
10.主题曲听完了,五毛的美国主持人,又来了:
我认为,在接下来的比赛中,可能会有一些争论;但是,今天晚上的开幕式,我不认为,任何人,可以质疑这个开幕式,It’s stunning, stunning, stunning.连续用了3个stunning,呵呵呵!
有很长一段时间,两个主持人一句话都没说,看来是沉浸在表演中了。
11.入场式已经开始了,看看美国怎么弄。
然后,开始调侃中文排序,说,如果你看到一个 letter of A 的国家在 letter of R后面出来,不要惊讶,这就是中文的排序!
12.日本入场了,主持说,中国人主办的这个奥运会,是非常温暖(warm)的一届,看他们对待日本人和中华台北的入场,就能感受到他们的热情,虽然他们和日本之间,有很不愉快的经历,和台湾之间也有一些争执。
HK入场了,开始介绍HK回归的情况。呵呵呵
13.…鉴于中文排序,老美可能转不过来,所以NBC在屏幕下方加了一个彩条,上面有5个国家的英文名字,以正在入场的为第一个,这样的话,按英文排序的人,就容易了解了。
而且,上面有这个国家的全名,缩写,人口,多少运动员参加这次奥运会,入场的时候,专门介绍这个国家的运动员,国家背景,没有乱说一些有的没的,呵呵,挺好,很专业的感觉。
14.巴基斯坦入场,呵呵呵,全场欢呼声好清楚,这一次。
主持人介绍了一下巴基斯坦现在的情况,总统为啥没来,等等,就过了。
古巴进来了,主要谈刘翔和古巴小将罗伯斯之间的这一次的争斗!
15.印度人进场了,美国主持开始公开搞笑印度的运动,说对比印度的人口和中国的人口,再比比他们在奥运会上取得成绩,等等,呵呵呵。
印度尼西亚进来了,他们说,中国人应该给印度尼西亚热情的欢迎,因为在那里,有着第二大人口的Chinese生活着。呵呵呵
16.加拿大入场了,米国老大哥,完全不顾加拿大的面子,竟然说加拿大,这么大的国家,派这么多运动员,怎么连一块金牌也没拿过!
不会吧,加拿大怎么也拿过一块金牌吧?谁来confirm一下?
17.伊拉克入场,主持人,他们应该感谢一下中国奥运,本来是来不了的,后来国际奥委会努力,最后还是来了。然后,说,中国观众给了伊拉克很大的欢呼。然后,镜头切向小布夫妻,呵呵呵。
伊朗,他们说,可以很明显的感觉到观众对待伊拉克和伊朗的不同。(暗示,伊朗的欢呼明显少很多,不过感觉好像的确如此?)
18.苏#丹来了,他们主要集中在美国运动员因为苏丹的问题而被拒绝签证,说该运动员非常生气,表示自己是关心苏#丹的问题,不是要抵#制奥运,等等……
还是围绕运动员说事,没有扩大到国际关系话题,还行。
19.开始赞美我们的白衣XS妹妹们了,呵呵呵,终于找到机会说这些漂亮的妹妹了,说这些啦啦队的妹妹,已经跳了至少1个多小时了,还有至少20多个国家还要出来……
老米心疼XS妹妹了,兄弟们不能掉以轻心哦……
20.俄国来了,介绍完了队伍之后,开始大谈俄国入侵格鲁吉亚,说俺们的小布同志这次在北京,要好好的和小普通知好好的谈谈这个问题……哈哈哈
美国进来了,美国人大吹,说,听,观众们的欢呼声,多么响亮!哈哈哈,然后,开始吹美国以前的夏季奥运会的战绩,说今年,将会面临来之中国的强大的挑战。
接下来,开始介绍运动员,看来他们对NBA球员还是很感兴趣哦!
还在介绍米国队员,呵呵呵,恨不得一个个介绍……
21.荷兰入场,主持人说,自己的老婆是荷兰的,他老婆支持荷兰运动员,他支持美国运动员,现在,就是他们的孩子,被夹在中间,不知道该支持妈妈还是爸爸,呵呵呵,很人性化,是不是?
22.正在介绍斯洛文尼亚进场的时候,其中一个五毛主持,非常感慨,又开始说了:
在奥运前,很多人都大谈政治,争斗,人权,但是,请大家看看,就在现在(in this field),你看到全世界各个国家的运动员入场,互相握手,留影,打招呼,这才是真正奥运,应该如此(the things it should to be)
23.北朝鲜来了,主持人直接解说,这是世界上最最被孤立的国家(the most isolated country),但是,看中国现在是如何对待他们,接着提到了6国会谈;还提到了什么英雄什么的,一下没记住
24.蒙古来了,呵呵呵,主持说,他们是中国的一个邻居,good luck for them with their population,嫌他们人口太少了?呵呵呵
然后,开始说,据调查,中国北京的污染,很大一部分,都是外蒙古带来的,他们住在沙漠和戈壁滩上面,北京的dust,大部分都是从他们那边飘过来的,然后,还拿美国国内的相邻的两个洲(一个是的德克萨斯,另外一个没记住)打比方。
25.德国来了,除了评价旗手NBA球员的脑袋以外(一个五环图案在左边),然后就是说,德国合并后,奖牌数量大减,世界排名下滑的很厉害;所以,近年来,德国人开始使用原来东德的方法来训练他们的运动员,借以提高他们运动员获得奖牌的能力。
26.中国出场,主持人:
呵呵呵,德国虽然用了NBA球员作为旗手,但是,他怎么可能高的过中国的姚明呢?哈哈哈,姚明比他还高半尺。详细介绍四川地震中的小孩子,他如何救他的同学,如何被压,后来媒体采访他,为他为什么这么说,孩子说:“这是我的责任!”
赞扬中国,这是个伟大的国家,13亿人口住在这里,他们非常人性化。
赞扬中国在1984到美国参加洛杉矶奥运会,没有和苏联一样抵制!
看看,这些中国运动员,一个头挨着一个头,他们里面,有可能有多都是非常专业的专业运动员,这些运动员,都会去抢金牌!
接着介绍中国体育的优势和一些细节。
91000人正在为他们的国家欢呼,全部都站起来了,欢呼,为他们的国家!
这一届奥运会,有超过400个的中国运动员,今天他们中间的369都来到了现场!
一个主持人说,我需要告诉你们,你们要到现场来,才能感觉到现场的气氛,直到中国人进场,你才会感觉到,中国人的长时间对奥运会的期待,从2001年开始的长时间的等待,终于,在今天……
主持说,看着姚明和那个地震中生存下来的小孩子,无论是你黑,还是白,是高,还是矮,你看到这个情景,你都会为这个情景所感动……
虽然还没结束,但是,我们现在就可以这么说,直到现在为止,我可以很肯定的告诉你,这个开幕式,已经大大的超越了我们的期望值……
主持人学中文,说了一句不是很标准的普通话:“百年梦想!”
27.升奥运会旗,主持人:
镜头再次给了姚明和他肩膀上的小孩。
奥运会旗子进来,中间走棋过场直接删除!
解说:奥运会会歌,是希腊语。由孩子们演唱。
解说:中国承诺给我们一个和谐的奥运,在这一个,听着孩子们唱奥运会会歌,我们感觉到了,所有中国人聚集在一起,给了我们和谐的感觉!
28.最后的火炬传递开始,Olympic Flame来了:
介绍许海峰,第一个金牌获得者……
介绍李小双……
今天有16000多对,在北京,结婚……
我们很期待,到底会怎么点火呢?应该是很刺激的,还有几分钟,就知道了……
逐一介绍每一个传递火炬的运动员!
介绍孙晋芳,介绍中国女排,特别说明了,不能说是奥运金牌,是世界冠军。
火炬传给李宁……,李宁飞起来!!!
Wooow, woooooow… 两个主持人一起惊呼了!!!
下面直接翻译主持人的话:“我们都估计错了!我们设想的点火方式,统统不是!!!
我们谈了太多次了,怎么也没想到,他们会跑到主会场上面去跑步,点火!
呵呵呵,我真的不知道,这到底要训练多久,才能这样跑???
李宁要在上面跑整整一整圈!!!
李宁,6块金牌的获得者!
30分钟前,这个火炬都没有的,怎么现在跑出来了???
点火了!
Waaa, waaa, wooooooow, 哈哈哈!两个主持人一起惊呼大笑!
主持人长时间无语,我知道,他们都鸡动啦!!!
点火后的烟火
继续无语,只是做了很官方的介绍,说Games正式开始,等等……
29.点火完毕,记者下去采访:
采访姚明:你有啥米感觉?姚明:很兴奋,不仅仅是我,所有中国人!等等大话
采:你抱着这个孩子,对中国来说,有什么意义?姚:他代表了中国的未来,20年后,你仍然会记起今天,他代表了中国的孩子,中国的希望,等等大话
回到直播室:3个主持,开始大侃,
一个问:这是我第一次参加奥运转播,请告诉我,以往的每一届奥运,都和这一届一样!
另一个回答:不好意思,他们不一样,这一切,太完美了!
接着:感谢大家观看,Good night Beijing ..

2008年8月1日星期五

static const integer member

在很多书上都对static const integer member的声明和定义做了介绍。这种常量常用来代替宏。一来,它可以被局限在类的范围之内,不会污染全局空间,也不用担心重名;二来,静态常量只有一份拷贝,不会占用太多地方。
一般来说,在类中可以使用in-class initialization的方式初始化静态整型常量,但是这还是被看作声明,因此在类声明外面,还需要对其进行定义。为了保证定义的唯一性,一般这种定义放在实现文件中(.cpp)。
比如:


test.h

class Category{
public:
static const int CATEGORY1 = 0x00000001;
//...
}

test.cpp

const int Category::CATEGORY1;

main.cpp

#include "test.h"
int main(){


//....
int _category = Category::CATEGORY1;
}


上述代码在几个编译器中的表现如下:
VC6 不支持该语法
VC8 编译通过,链接失败,报重定义
g++4.0 通过

VC6不支持该语法还情有可原,可是VC8竟然也会通不过,让我很是郁闷。为了使连接通过,只能不在test.cpp再对静态整型常量成员进行定义,我感觉这是编译器做了一些优化,使得在编译阶段,静态整型常量就已经分配了空间,并定义了符号,不再需要连接器去找了。以前看到一篇文章说VC8对C++标准的支持率已经达到了98%左右,但是很难相信如此简单又重要的一个特性,竟然也会不符合标准。可能VC编译器组的人都去忙重要的特性了吧。

写此文的目的是希望看到此文,而又不知道该问题的人能够少浪费差错的时间。这么一个小小的bug,浪费了我整整几个小时的时间去追查。你可能不以为然,但是当代码量多到一定程度时候,任何一个bug追查所花的代价都是巨大的。

2008年7月26日星期六

Windows Mobile枚举网络链接

本文适用于Windows Mobile 2003以上版本。

有很多Window Mobile(一下简称WM)的程序需要访问网络,但是在国内环境下,访问网络还是比较昂贵的。因此大多数程序都是在需要的时候自动建立网络连接,然后访问网络,做一些事情之后断开链接。所要求的也就是用户事先设定好网络连接的帐号。

要完成这样的功能,需要利用Windows Mobile SDK中的Connection Manager。只需要三个函数即可完成任务。

  • ConnMgrEnumDestinations
  • ConnMgrEstablishConnectionSync/ConnMgrEstablishConnection
  • ConnMgrReleaseConnection
需要的包含的头文件为<connmgr.h>

其实想法很简单,我们利用ConnMgrEnumDestinations枚举可用的网络,然后利用ConnMgrEstablishConnectionSync/ConnMgrEstablishConnection(前者在建立链接完毕之前不会返回,后者直接返回,本文使用前者为例),最后使用ConnMgrReleaseConnection断开链接。

示例代码如下:


HRESULT hResult = E_FAIL;
CONNMGR_DESTINATION_INFO DestInfo;
int index = 0;
hResult = ConnMgrEnumDestinations(index++, &DestInfo);
TCHAR* str1 = _T("Internet");
TCHAR* str2 = _T("单位");
while(SUCCEEDED(hResult))
{

if( _tcsstr(DestInfo.szDescription, str1) != NULL ||
_tcsstr(DestInfo.szDescription, str2) != NULL )
{
//
// try to connect
CONNMGR_CONNECTIONINFO ConnInfo;
ZeroMemory(&ConnInfo, sizeof(ConnInfo));
ConnInfo.cbSize = sizeof(ConnInfo);
ConnInfo.dwParams = CONNMGR_PARAM_GUIDDESTNET;
ConnInfo.dwPriority = CONNMGR_PRIORITY_USERBACKGROUND;
ConnInfo.bExclusive = TRUE;
ConnInfo.guidDestNet = DestInfo.guid;
HANDLE hConnection;
DWORD status;
hResult = ConnMgrEstablishConnectionSync
(&ConnInfo, &hConnection, 60*1000,&status);
if( SUCCEEDED(hResult) &&(status & CONNMGR_STATUS_CONNECTED)){
hResult = ConnMgrReleaseConnection(hConnection, FALSE);
break;
}
else{
switch(status)
{
// do something;
}
}
}
hResult = ConnMgrEnumDestinations(index++, &DestInfo);
}



程序相当简单,因为一般WM的手机都使用Internet(CMNET)或者单位链接(CMWAP)来连入网络,所以我把其他的网络过滤掉了。

注意红色标出的部分,这里表明该链接是独占的。只有这样的链接才能断开。

2008年7月8日星期二

windows绘图概述

这两天在开发的时候遇到好多绘图的问题,发现自己在绘图这块实在又是门外汉一个。于是翻出MSDN仔细研究了一下,搞懂了很多概念。我觉得这对于windows编程来说是非常重要的概念,因此仔细的把MSDN上相关的信息全部读了一遍,同时做了翻译和笔记。我贴在下面,希望对跟我一样的朋友有所帮助。
另有PDF版本可以从我的namipan下载->WindowsPaintingAndDrawing.pdf

Windows 绘图详解


几乎所有的windows程序都会在屏幕上绘图,但是由于多任务和多窗口,为了使绘制图形平滑,漂亮,应用程序使用windows作为其主要输出设备,而不是屏幕。

系统提供了与窗口一致的Device context。应用程序就使用DC把输出定向到目标窗口。


什么时候在窗口中绘图?

一个应用程序在很多时候都会在窗口中绘图。比如,第一次创建窗口的时候,当改变了窗口大小的时候,当把一个窗口从别的窗口后面拉出来的时候,当最大最小化窗口的时候,当打开文件显示内容的时候,当滚动,改变或者选择了一部分数据进行显示的时候等等。


系统会管理类似移动窗口和改变大小的操作,如果一个操作影响了窗口的内容(如果屏幕上只有一个窗口,把这个窗口在屏幕范围内不断拖动,不会引发重绘),系统会把这部分被影响了的部分标记出来,以备后面绘图时使用,然后,发送WM_PAINT消息给窗口函数。这个消息告诉了应用程序哪些地方必须被重绘,使得应用程序能够实现有效的重绘。


同样的,应用程序也可以标记需要重绘的区域,一旦标记,也会导致发送WM_PAINT消息。如果一个操作需要立刻得到回应,应用程序可以在操作的同时进行绘图,这样就不必等到下一次WM_PAINT事实上WM_PAINT产生的条件就是有部分窗口失效了。如果不出现这种情况,就不会产生WM_PAINT


在任何情况下,只要窗口创建了,应用程序就可以在里面绘图。为了能够绘图,应用程序首先应该获得一个设备描述表的句柄。在理想情况下,应用程序的大多数绘图在WM_PAINT中完成。在处理该消息的时候,通过调用BeginPaint就能获得DC的句柄。如果应用程序在其他时候进行绘图,可以通过GetDC或者GetDCEx来得到DC的句柄。


WM_PAINT 消息

当窗口的Client Area发生改变的时候,系统给应用程序发送WM_PAINT消息。系统仅在消息队列中没有其他消息的时候发送该消息给应用程序。一般的用法是在WM_PAINT中调用BeginPaint获得DC,然后进行任何GDI绘图,最后通过EndPaint释放DC


beginPaint返回之前,系统为指定的窗口准备DC。它会为DC设置裁剪区域,这块区域就是需要重绘的区域。任何在此区域之外的绘制都会被裁减掉。


beginPaint结束之前,系统还会发送WM_NCPAINTWM_ERASEBKGND两个消息给应用程序。这些消息告诉应用程序绘制Non-Client Area和窗口背景。Nonclient Area也是window的一部分,其包括title barsystem menuscrollbar。大多数应用程序依赖DefWindowProc来绘制这些区域,因此一般会把WM_NCPAINT发送给DefWindowProcWindow的背景是用颜色或者笔刷在任何绘制操作之前填充出来的。背景会盖住任何之前存在的图片或者窗口后面的屏幕。如果一个windowwindow class定义了背景笔刷,DefWindowProc用这个笔刷自动绘制背景。


BeginPaint会填充一个PAINTSTRUCT结构。该结构中包含需要绘制的区域的大小等信息。应用程序可以利用这个信息,(存放在rcpaint中)来确定需要绘制的地方。如果需要输出的内容很简单,也可以不管这个信息,直接输出,让window自己来裁剪。


BeginPaint会把需要更新的区域设为NULL,以防连续导致发送WM_PAINT消息。即没有需要更新的区域就不会发送该消息。如果一个应用程序在WM_PAINT中没有调用BeginPaint或者清除更新区域,则系统会不断发送WM_PAINT,直到更新区域为空为止。在任何情况下,应用程序都必须在离开WM_PAINT之前清空更新区域。


绘制结束,应该调用EndPaintEndPaint释放DC,使得其他window可以使用。如果之前caretBeginPaint隐藏,EndPaint会显示出来。


更新区域(The Update Region

更新区域是window的一部分,这一部分已经过期或者无效了,需要重绘。系统依靠更新区域向应用程序发送WM_PAINT消息。系统只会把无效的区域加到更新区域中去。


当系统发现有一部分需要重绘的时候,它把这部分加入到更新区域中,但不会立刻要求重绘。只有等到系统把消息队列中的消息处理完之后,系统才会检查更新区域,如果更新区域不是空的,则发送WM_PAINT消息。


应用程序可以自己设置更新区域。比如读取一个文件,然后设置更新区域,这样在之后的WM_PAINT中就可以显示文件内容了。但一般来说,应用程序不应该在数据改变的时候绘制,而应该把所有的绘制工作放到WM_PAINT中去。


更新区域的有效化和无效化( Invalidating and Validating Update Region)

应用程序可以通过调用InvalidateRectInvalidateRgn来无效化一块区域,并设置更新区域。这两个函数把指定的矩形和区域加入到更新区域中。与之前加入进去的区域结合起来。


这两个函数不会导致WM_PAINT消息。Window在处理其他消息的时候,系统不断积累无效区域,直到消息队列中不再有任何消息。


ValidateRectValidateRgn两个函数的作用则相反,用来有效化一块区域,并把这块区域从Update Region中去掉。


获得更新区域

使用GetUpdateRectGetUpdateRgn两个函数来获得当前的更新区域。前者获得最小的能全部包含更新区域的矩形,后者返回更新区域。这两个函数用来获得当前的更新区域来精确定位输出。


BeginPaint也会获得包含全部更新区域的最小矩形。该矩形就在PAINTSTRUCT中的rcPaint。因为BeginPaint是更新区域全部有效话,因此在这之后调用GetUpdateRectGetUpdateRgn返回的都是空区域。


同步和异步绘图

大多数利用WM_PAINT来实现的绘图都是异步的。即在window的部分失效之后有一个短暂的等待,才能进行绘图。在这个短暂的等待中,system从消息队列中获取其他消息,并进行处理。因为system认为WM_PAINT是个低优先级的消息。


但有时需要同步绘图,也就是在窗口的部分失效之后立刻就绘图。比如在创建主窗口之后立刻把它绘制出来等等。基本上来说,那些需要立刻绘图的都是需要和用户交互的部分,同步绘图可以保证不影响交互的性能。


UpdateWindowRedrawWindow两个用来同步绘图。如果更新区域非空,UpdateWindow能够立刻发送一个WM_PAINT消息给应用程序。RedrawWindow同样发送WM_PAINT消息给window,但是它给绘制更多的自由,比如是否要绘制nonclient区域、背景,以及是否不管更新区域非空也能发送WM_PAINT消息等等。这两个函数无论消息队列中有多少其他消息,他们都能直接发送WM_PAINTwindow


任何会消耗一定时间的绘图都应该使用异步绘图,免得程序被block住。一个程序如果经常是一小部分window无效化,最好把这些部分合起来,在一次WM_PAINT中进行处理。


不通过WM_PAINT来绘图

尽管大多数时候应用程序在WM_PAINT处理绘图,但是有时候不通过WM_PAINT而直接进行绘图可能效率更高。这一般都是用于需要立刻得到反馈的情况下,比如用户选择了一部文字,拖曳或放大缩小一个对象时。这些情况下,应用程序通常在键盘和鼠标操作中进行绘图。


不在WM_PAINT中绘图时,应用程序通过GetDCGetDCEx两个函数获得窗口的设备描述表(记住,不是client区域,而是整个窗口)。结束绘制使用ReleaseDC释放DC


当不使用WM_PAINT的时候,应用程序使用一种技巧来进行“可恢复”的绘制。比如在反选一些文字的时候,仅仅只要对那一块区域反色即可,当取消反选的时候,只要再次反色即可。


Window区域

除了更新区域,每一个window都有一个可视区域,即用户能看到的所有区域。当window的大小改变时,或者被其他Windows挡住时,或重新显示时,都要绘制这部分区域。用户没法直接改变这个区域,但是系统自动使用这个区域来表示该windowDC中的裁剪区域



裁剪区域决定了系统的那些部分允许绘图,当应用程序通过BeginPaintGetDCGetDCEx获得DC之后,系统为这些DC都设置了裁剪区域。应用程序可以通过SetWindowRgn, SelectClipPath and SelectClipRgn等函数来设置裁剪区域。


WS_CLIPCHILDRENWS_CLIPSIBLINGS这两个样式告诉系统怎么来计算window的可视区域。如果一个窗口有其中一个样式,窗口就会把子窗口或者兄弟窗口(具有相同Parent的窗口)的可视区域排除在外。


Window背景

Window背景是在进行绘图之前对client区域填充的颜色或者笔刷。背景覆盖了屏幕上窗口区域中的任何东西,擦除了以前的图像,防止之后的绘图颜色混合。


系统可以自己绘制背景,也可以在调用BeginPaint的时候给应用程序发送一个WM_ERASEBKGND消息把绘制的机会让给应用程序。如果由DefWindowProc来处理,则系统使用创建窗口时指定的笔刷进行背景绘制。如果笔刷无效或者window class没有定义背景笔刷,则设置PAINTSTRUCT结构中的fErase为非空,告诉应用程序,由应用程序来负责背景绘制。


如果应用程序处理WM_ERASEBKGND,则需要使用WPARAM来进行绘图。WPARAM包含一个窗口的DC句柄(是的,已经帮你获得了)。在绘制完毕之后,应用程序需要返回一个非空的值。这样BeginPaint就不会把fErase设置为非空值了。(从这里可以看出,WM_ERASEBKGND是通过SendMessage发送的,所以在这个函数中处理要快!)即使window class的背景笔刷已经被定义好了,应用程序还是能够处理WM_ERASEBKGND消息的。



改变window大小

当用户用鼠标拖拉window边框时,通过系统菜单选择最大最小化时或者使用SetWindowPos函数时,系统就会改变window大小。当window改变大小时,系统假设之前显示在外的内容没有被影响到,不需要重绘,系统仅仅使新暴露出来的那部分窗口失效,这样可以在处理WM_PAINT时节省时间。在这种情况下,即使window的大小减小,系统也不产生WM_PAINT

但是有些窗口需要不时的重绘,比如一个钟表应用程序,每次大小改变,都需要重绘。当横向,纵向的任意部分或者两者都发生改变时,为了强制应用程序重绘整个client区域,应用程序必须设置CS_VREDRAWCS_HREDRAW这两个样式。有了这两个样式,任何改变大小的操作都会引起重绘。



Nonclient区域

当任何一部分Nonclient区域,比如title barmenubarwindow frame需要重绘时,系统会给应用程序发送一个WM_NCPAINT息。系统也可以发送其他消息来更新一部分Nonclient区域。例如,当一个窗口被激活或者非激活时,系统发送WM_NCACTIVATE来更新Title Bar。一般来说,对普通window最好不要处理这些消息(带NC的),因为应用程序必须处理所有要求处理的Nonclient区域。

但是如果一个应用程序想要自定义Nonclient区域,则必须处理这些消息。应用程式必须使用窗口的DC来进行绘制。应用程序可以通过GetWindowDCGetDCEx来获得窗口DC。当绘制结束,必须使用ReleaseDC来释放DC

系统也会为Non-clinet区域维护一个更新区域。当一个应用程序收到WM_NCPAINT消息的时候,wParam指向一个包含一个指定了更新区域的Rgn handle。应用程序可以使用这个句柄使更新区域和DC的裁剪区域组合起来。当获得DC是,window不会自动组合更新区域,除非使用GetDCEx并且同时指定这个更新区域的handleDCX_INTERSECTRGN标志。如果应用程序不组合更新区域,则只有超出window以外的绘制操作会被裁减掉。无论是否使用该更新区域,应用程序不需要负责清空更新区域。

如果应用程序要处理WM_NCACTIVATE消息,在处理完毕之后需要返回TRUE来告诉系统完成被激活窗口的更新工作。当应用程式收到WM_NCACTIVATE时如果是最小化情况下,应用程序应该把该消息转发给DefWindowProc,在这种情况下,这个默认的函数会重绘Taskbar上面的这个icon

子窗口更新区域

子窗口是具有WS_CHILD或者WS_CHILDWINDOW样式的窗口。和一般窗口一样,子窗口通过WM_PAINT来绘图。子窗口也维护一个更新区域,应用程序和系统都可以通过设置该更新区域来产生WM_PAINT消息。

子窗口的更新和显示区域受到父窗口的影响,其他样式的窗口则不会。系统常常设置父窗口的更新区域的同时设置子窗口的更新区域,使父窗口收到WM_PAINT消息的同时子窗口也能收到WM_PAINT消息。系统把子窗口的位置限制在父窗口的client区域,超出这个区域就会被裁减掉。

无论何时,只要父窗口的更新区域包含了子窗口的一部分,系统就会为子窗口设置更新区域。此时,系统先向父窗口发送WM_PAINT消息,然后向子窗口发送消息让子窗口可以恢复被父窗口覆盖的内容。

但是如果只有子窗口设置了更新区域,系统不会给父窗口也设置。在无效化子窗口时,系统不会给父窗口发WM_PAINT(因为被覆盖住了,根本没有必要)。同样的,如果使被子窗口覆盖住的父窗口的部分无效化,系统也不会给父窗口发送WM_PAINT的。在这种情况下,无论子窗口还是父窗口都不会收到WM_PAINT消息。

应用程序如果设置了WS_CLIPCHILDREN这个样式的话,当父窗口的更新区域被设置的时候,子窗口的更新区域不会被设置。任何在子窗口下面的绘图全部被裁减掉,因此继续给子窗口发送WM_PAINT消息也是没有必要的了。

子窗口的更新和可视区域也受到兄弟窗口的影响。如果两个窗口重叠,则两个窗口都会收到WM_PAINT消息。他们受到WM_PAINT消息的顺序与z-index相反,即最上面的(z-order最高)的收到WM_PAINT消息最晚。

应用程序可以设置WS_CLIPSIBLING来避免兄弟窗口的绘制重叠。设置了这个,高z-order的窗口部分就被下面的窗口裁减掉了。

2008年7月3日星期四

fill_n与generate_n的区别

有些人对未知事物的第一印象一般比之后的印象记得牢,即使是错误的想法,也会根生地固的记得很牢。而有些人却善于用之后正确的印象来代替之前的印象。我很羡慕这种人,因为我自己是第一种人。

我对fill_n这个函数的印象就属于自以为是的错误印象,然而,这个印象被之后的正确印象所替换之后,我还不时的用错这个函数。就像程序员们老生常谈的空指针问题(现在少的多了,铺天盖地的高级语言,很少遇到这种问题了)。

我第一次看到这个函数,我就立马意识到这是初始化容器的好方法。比如

list<int> l1;
fill_n(back_inserter(l1), 200, 1000);

仅仅一行代码,就可以初始化200个元素,每个赋值为1000.多么方便啊。不过这种简单的类型我是没兴趣的。最重要的是可以初始化类,这就是我对其错误认识的开始。为了测试这个程序,我曾写下了如下代码:


//
// test.h

class TObj{
public:
~TObj(){cout<<"Deleting"<<endl;}
};
struct Dest_TObj{
template<class T> T* operator()(T* p){ delete p; return 0; }
};
int main(){
list<TObj*> tl;
fill_n(back_inserter(tl), 20, new TObj());
transform(tl.begin(),tl.end(),tl.begin(), Dest_TObj());
return 0;
}


在main函数中,第二行为tl初始化,20个元素,每个元素是一个指向TObj对象的指针,该指针指向一个新分配的TObj对象。然后在transform中对tl进行purge。如果不用这两个函数,我们只能用循环的方法:

for( int i = 0; i < 20; ++i) tl.push_back(new TObj());
for( list<TObj*>::iterator iter = tl.begin();
iter!= tl.end();++iter)
{
delete (*iter);
}

尽管看起来也行,但是总觉得比较原始,不是吗?

结果,当我满怀信心的运行程序,运行到transform时就崩溃了。我左看右看没发现问题。看看输出,有一个Deleting。那说明至少成功了一次,难道后面指针指错了?我把transform换成了上面的循环,结果也是运行了一次就崩溃了。看来问题在初始化的地方。
我把fill_n替换成上面的循环。程序欢快的跑完了。Shit,还有这事!

看来是fill_n有问题,我只能再回去仔细看fill_n的原型:
template<class>void fill_n(Out res, Size n, const T& val);
我终于注意到了最后一个参数,这是一个值参,fill_n只不过把每一个元素都用这个值进行赋值而已!因此,我希望初始化的20个TObj对象,实际上只有一个,所有的指针都指向这个对象。当第一个被delete之后,后面的就成了野指针。企图删除一块已经被释放了的内存块,当然结果是崩溃了。

如果要实现我需要的想法,只能使用generate_n。该函数和fill_n类似,只不过把最后一个参数换成了一个函数,调用该函数n次。
比如我有一个Create_TObj()的函数,返回一个新创建的TObj对象的话,我就可以把上面的代码改成:
generate_n(back_inserter(tl),20,Create_TObj());
这样程序就能顺利执行了。

不幸的是,这个错误我是屡犯不改,终于不得已写下此文,希望能长点记性。

2008年5月19日星期一

论文初稿完成

经过几天的努力,今天,国难日的第一天,我终于把论文的初稿给完成了。总共将近40,000多个字,其中90%的内容都是原创。除去之前的准备工作和编程序的时间,我真正开始动笔是在上个礼拜三,而今天当我写完的时候,我自己都感到惊讶,没想到能在这么短的时间内完成这篇论文。

可能是这几天救灾的军人们那种拼搏的精神不知不觉也有点影响了我,让我能够耐着性子把论文写完。这句话可能看起来有点虚,但是事实上我这几天,几乎没有上过网,除了每天看救灾的新闻,别的时候电视连碰都不碰一下,msn也基本不上,更别说以前一直盯着看的小说了(不过这下估计又积攒了好几十回了,可以看个够了)。

回想起来,我真的已经好久没有这么认真的做过一件事情了,最近的一次应该是两年多前刚进Thales的时候,很认真的钻研DCP的代码,还做了笔记,不过后来做着做着,人开始疲掉了,在之后的日子里更是不再有当时的激情了。

总之,找回那种感觉是好事。不过现在论文写完了,是该稍微休息一下了。接下去还有一篇小论文要写,还要去发表,大论文虽然给了老师,但是恐怕还要有很多的修改。在答辩完成之前还是不能松口气啊!

2008年5月9日星期五

淳朴的老农

这张照片是我去大盘山徒步时候拍的。当时这位老伯很热情的招待了我们。他的笑容让我想起了我已过世的爷爷,感觉很亲切。
淳朴的老农

2008年4月29日星期二

Be a Flickr Pro!

前不久一个朋友脑子一热,买了个域名。看来这种事情容易传染啊,我今天也是脑子一热,买了一年的Flickr付费服务。价格为$24.95,我个人觉得还行。

从价格上说,RMB在升值,现在已经在1:7上面徘徊了。所以这个价格折合RMB也就180RMB一年,一天5毛钱不到,这个价格相比Flickr的服务,绝对算是超值了。国内抄袭Flickr的Bababian一年也要120,还不提供无限空间,功能远比Flickr差多了。

另外我最近在不断整理照片,发现照片越来越多。另外买了单反不用就是浪费,所以我打算多拍一点,同时提高我的技术水平。pchome有位大侠告诉我,照片一定要拿出去晒,让别人拍砖才能知道自己的不足。相比单反的投资,Flickr上的投资可以算是毛毛雨了。

好了,我要开始上传照片了,大家以后多来拍拍砖:)

http://www.flickr.com/photos/ling_hao

2008年4月25日星期五

Ubuntu 8.04 LTS Release

凌晨3点,我还在公司里面加班。我刚刚完成了Release,随手就打开浏览器输入www.ubuntu.com, 因为我知道,今天是Ubuntu 8.04 LTS 正式Release的日子。一看果然Ubuntu的首页不同了,大幅的广告显得喜气洋洋。

Ubuntu 8.04 新增加了许多非常酷,非常实用的功能,Ubuntu桌面环境已经非常实用,这次对硬件支持也更加完善,而且新加入的PulseAudio也提升了其多媒体性能。Ubuntu 8.04集成了现在市面上最新的软件包,比如:Firefox 3,Compiz Fusion 0.7.4,GNOME 2.22,甚至还可以依靠Likewise与windows 的活动目录无缝链接(可以使用Windows域的打印机,可以通过域用户访问域资源)。最后,还有几近完美的升级程序,可以完美的从7.10升级到8.04。由于使用了新的引擎,Nautilus 性能提升堪称恐怖。

还在等什么呢?快去下载吧!
http://www.ubuntu.com

2008年4月15日星期二

宁被偷,不被拣

同事最近运气不好,上个礼拜四早上打的时候钱包掉了。他到公司回想起可能掉在了车子上,于是乎他到公司之后打电话给大众,期望有哪位好心得司机能拣到。可惜,等了好几天也没有任何回音。我当时还安慰他,说如果给谁拣到了,估计钱是找不回来了,但是钱包里面的身份证,银行卡等大概会还给你吧。因为曾经听到好几次说小偷偷了钱包,秉承盗也有道的精神,把身份证之类的东西放回钱包,告诉失主去某某地点去拿的事情。这样至少给失主造成的麻烦会小些。可惜,看来同事这次运气不好,没有给小偷把钱包摸了去。同事感叹道:“宁被偷,不被拣啊”。

2008年4月13日星期日

WikiMedia 2007年最受欢迎照片展

这篇绝对不是新闻,但对于我这个不通时事的人来说也算新闻了。而且照片么,什么时候看都可以的。
其中有几张特别好,人家说好照片能反映出摄影师的心灵。我在这些照片中看到了。这里推荐两张我觉得特别好的。

首先是这张,我第一样看到就特别特别喜欢。这只胖胖的小红松鼠实在太可爱了。我已经把它作为我的桌面了。至少要看个一百天,一百天啊一百天!



第二张。这张给我第一样就是一种恬静。一开始我的注意力被牛吸引,但是很快得,透过牛的眼睛,好像看到了后面的山谷,越看越远。心里也变得越来越安静,仿佛有一种与世无争却万事尽在掌握中的感觉。




第三张。仔细感受一下这张照片,犹如身处浩瀚的宇宙之中,又如身处万卷藏书的古老的图书馆中。一种沉甸甸的感觉给人一种对未知的隐隐的渴望。


其他的照片同样出色,像看原文的点下面链接:
http://commons.wikimedia.org/wiki/Commons:Picture_of_the_Year/2007

2008年4月10日星期四

装着Ubuntu Linux的“龙芯”UMPC

今天在DesktopLinux逛的时候,发现了一则消息让我很振奋。中国的龙芯卖到了国外,还被用在了运行Ubuntu的UMPC上。也许很早以前龙芯就已经出口了,但是我不知道,也可能不相信。但是现在却明明白白出现在我眼前,不由得我不信。

这是荷兰一家公司生产的ultra-mini PC(UMPC),命名为Jisus。使用1GHz 的Loongson 2F CPU。这颗由中科院设计的龙芯目标就是运行Linux,MIPS64位架构。不过Jisus估计是冲着Asus的900MHz的 Eee PC 4G去的。Jisus的参数如下:

  • Processor — 1GHz 64-Bit Loongson 2F
  • Memory — 512MB DDR2-667
  • Flash — 4GB Nand flash
  • Display — 8.9-inch LCD (800 x 480 pixels) with LED backlighting; Silicon Motions SM712 graphics; VGA port
  • Networking — 1 x 10/100 Ethernet (Realtek 8139 contoller); RJ45 port
  • WiFi — 1 x 802.11b/g
  • USB — 2 x USB 2.0 ports
  • Audio — 1 x mic port; 1 x two-channel earphone port; stereo speakers
  • Battery — 4.5 hours
  • Operating system — Ubuntu Linux (other Linux distros possible)

这款机器将于4月25日在欧洲开卖。价格为300EUR。感觉上是不是很贵。但是实用性如何就不是我能知道的了。但是最求新潮的人肯定会去买,而且它有多种颜色可以选择。对于我个人来说,我不太喜欢小的笔记本。因为我手大:(

总之由市场来见证这台装着Ubuntu的龙芯UMPC吧。

原文链接:http://www.desktoplinux.com/news/NS3294112608.html

2008年3月29日星期六

用例浅谈

用例(use case)是现代软件工程中用来采集需求和软件设计的一个常用工具。那么用例到底是什么东西?什么时候用这个工具?如何使用这个工具呢?本文就结合本人在日常工作中的实践经验来做一个简单的介绍。

用例的定义有很多,几乎每一本书的作者都有自己的理解。但是用例的本质不变,系统的使用者对系统发出的一次请求,用例描述系统完成这个目标的过程的一种方法。因此我们可以用4个词来概括用例;他们是:角色,请求,步骤和目标。 有的书上说是三个要素。一个是参与者,也就是我这里的角色。一个是用例只描述单独的任务,也就是我这里的请求和步骤;最后一个是用例必须产生一个对用户有意义的结果,也就是我这里的目标。

系统的主要角色(可能是最终用户,也可能是其他系统)启动了一个交互,他有一个用户目标(user goal)。由于用户请求的上下文不同,前提条件不同,因此这个交互可能产生多个场景。一个UC会把目标相同的场景集合起来。


用例的格式

一般来说,用例可以以多种形式编写,但是大多数情况下都是用于和非专业人员交流,因此,用纯文本方式比较好。同时可以节约时间。

对于用例的格式,很多书上面都有不同的定义,但是我个人认为,用例没有特别的格式。只要意思清晰明了即可。每个人编写的用例都是不同的。UC写作有简化版本和完全格式版本,可以根据项目规模大小选用。

使用用例来发现需求

当编写一个新系统的用例时,一般先写黑盒,然后设计人员细化时变成白盒。黑盒UC的作用主要用来引发讨论,一般由PD或者RE来写,写好之后和Dev和Test以及客户进行讨论。因此UC常常被用作是头脑风暴的工具。UC本身的功能就是捕捉已知的功能性需求并为之建模,这样可以完成高质量的需求报告,相对来说比一般方法要可靠,完全的多。

但是用UC来找出需求时需要注意两点:
1. 它是真正的需求,不是行为或者过程,应该要正确的写出系统必须做的事情,而不是如何做事情。
2. 它不是所有的需求,它们不包括外部接口,数据格式、业务逻辑以及复杂的公式等。他们组成了所有需求中的一部分。不过虽然只有一部分,但是是最重要的一部分。


用例的价值

UC很流行大抵上是因为他们一致、连贵的说明了这个系统是如何使用的。在早期提出完备的UC,系统的使用者就知道该系统可以做什么了。他们可以及早的做反馈、进行调整或者拒绝该UC。不管采用何种设计方法,需求分析阶段的用例建模工作都能发挥极其重要的作用。

有一些公司是不是用用例方法的。他们使用的是Feature。首先获取用户需求,然后由PM大致写出该系统的Feature,当然要包括所有的用户需求,然后通过头脑风暴完善Feature List。最后为每个Feature添加Function List。

事实上,系统级的黑盒UC就可以看作是Feature。每一个步骤就是这个Feature下面的功能。

UC的价值最早产生于当这个用户目标(user goal)创建,并把它们放入到系统的特性列表中去时。这个列表说明了系统可以做的事情,规定了系统的范围。

这个List会由用户代表,PM,公司专家,行业专家代表等人检查。他们会用这个Feature List估算成本和系统实现复杂度,由此确定系统的起始点。这个列表可以联系到复杂性、风险管理、成本、时间和状态检查。

第2个价值体现在UC的作者用头脑风暴的方式把主成功路线上一切可能的错误列举出来的时候。这时候,他可能会发现一些令人惊讶的事情,或者是客户没有想到的事情。这些事情可能导致新的使用者,新的UC的出现。

第三,用例可以帮助我们划分软件的开发周期,评估研发工作量。对于优先级较高的用例会在早期的迭代周期中实现,优先级较低的用例则安排在后续的迭代中完成。

用例模型在整个开发过程中都扮演着非常重要的角色。它用来驱动软件的分析和设计逐步细化。

最后,软件项目中的功能性测试用例,基本上都是根据用例模型来确定的。

用例建模

用例建模是通过分析用户的功能性需求,得到用例模型的工作过程。一般包括下面几个步骤:

  1. 确定系统边界
  2. 确定参与者
  3. 找出所有用例
  4. 确定每个用例的级别
  5. 用例描述
  6. 画出以整个系统为对象的顺序图
编写用例

不要一开始就写出所有的细节,这是违反事物发展规律的,就像荒谬地要求把需求全部搞清才能做设计一样。用例的细化一般有4个阶段。
1. Actor & Goals
列出所有参与者以及他们的用户

2. Use case brief or main success scenario
选出主要的一些UC,写出触发条件和一个大致的轮廓,也就是主成功场景。保证该系统的功能真的是Stakeholder们感兴趣的。

3. Failure conditions
完成主成功场景后,用头脑风暴的方式找出所有可能的失败,首先把它们全部列出,而不是直接就讨论系统的应对之策。

4. Failure handling
写下系统是如何处理每一个错误的。这时候,常常会有一些原本不明显的问题被渐渐暴露出来或者错误处理会突然引入新的用户或者新的用户目标。

大多数项目时间紧张,人员精力有限,在项目前该确定要工作到何种细致程度,因此我强烈建议按照上面4个顺序来。

2008年3月20日星期四

到底什么是需求?

《HFOOAD》给了一个我觉得很简单,又很好的答案。单独拿出来做个笔记。
首先我借用一下里面的图片来说明问题。


那些黑色高亮的词是需求的几个特点。

specific thing
一个需求往往是一件单独的可测的事情。因为只有可测,才能保证你完成了客户的需求。

system
系统指一个完整的应用,或者是项目程序。因为客户只能看到这个。

do
系统做的事情,或者说是行为。

work correctly
一个系统是否正确是由客户说了算的。为了使最后系统能够正确运行,我们不能漏了任何一个需求,即使客户当时忘了,我们也不能忘。要从客户那里找出潜在的,忘记了的需求。才能使系统正确工作。


给出一个比较正规的定义
需求就是一个单一的要求,该要求详细规定了指定的系统或者服务的特征和行为。

论文写作正式开始

今天终于开始论文写作了!

自从我提交开题报告到现在都有4个多月了,如果按照开题报告里面的进度计划,我应该已经在收尾阶段了。可是当中遇到了很多事情,一开始准备复习高口,想在三月份把高口考出来,论文放到高口考完之后再写,可是接下来遇到母亲生病,很多计划都打乱了,最后到三月份高口也没有考,论文也没有写,这几个月几乎什么事都没有完成。真是人算不如天算啊。

现在我就开始觉得时间有些紧了,一般来说工程硕士要在4月中旬提交论文初稿,然后在5月份修改和审批,5月底答辩。但是我现在除了一个idea,还什么都没有,心里有点不安啊。

前两天每天下班回家都会考虑两三个小时,昨天晚上基本上把写论文的过程整个想了一遍。然后做了一个简单的计划,于是今天正式启动!接下去的两个月里面,基本上就是苦难的生活了,白天上班,晚上做论文。朋友老段曾说过,做事情要一鼓作气,“一而再,再而衰,三而力竭”,我很同意这句话,这次的论文不能拖,一定要一鼓作气完成。

像我们工程硕士,写的大多是工程应用论文,我也不例外。但是我不想写些什么“XX系统的实现与改进”,这个太没有技术含量了。我写的论文跟我的工作有密切关系。我的工作是AFC系统,我的论文就是AFC系统中一个关键模块--数据采集的改进。里面涉及到一些有意思的技术,比如词法分析器,处理分发器等等,因此总的来说还是有点技术含量的。

我把这个程序看作一个小项目,完全按照一个项目来安排需求分析,设计与开发,测试与部署。希望在写论文的过程中把我这两年里面学到的各种技术总结一下,运用一下。这样,我两年的研究生也就没有白读,对得起那40000块大洋了。