All Stories

用Beamer作幻灯片后想

  昨天在公司里说到,以后要多作培训,多作交流,这种事情我倒是有点儿兴趣的。培训、交流,那么幻灯片是必不可少的,于是回来后就开始捣鼓Beamer。  因为就我了解的用LaTeX做幻灯片就只有PDFScreen和Beamer两种方式,而看过实际效果后,更喜欢Beamer生成的那种。以前也用Beamer做过一个非常简单的,这次我想好好研究一下,可以做出一些比较好看的效果来。  经过昨晚和今天上午的折腾,基本掌握了一些常用的用法。总的说来,还是比较满意的,虽然速度上比较起PowerPoint这种工具慢了不少,但心中还是比较满足的,主要还是熟练程度上的不足,以及缺少良好的工具支持(呃,就是直接拿UltraEdit编辑的)。所以更坚定了我要做一个TeX代码编辑器的想法。  因为这半年来使用MediaWiki的粗浅经验,让我对TeX的用法有了更多的理解。这所谓的“所想即所得”实在只是为了就对Word之流“所见即所得”才勉强杜撰出来的词汇。在我看来,这个TeX的设计思想,就是典型的西方人的思维方式:懒散、直接、天马行空。对于几千年来接受着严谨、务实、勤勉思想熏陶的中国人来说,一时间还真有点转不过弯来。在TeX中用这样的描述方式:我把这些文字作为标题,把那些文字作为章节名,还有些其他的就是正文,而至于标题、章节名和正文应该用什么字体,什么大小,什么颜色,什么对齐方式则不是当前我应该关心的事;而我们往往已经习惯了这样的做法:我把这些文字设置成黑体四号,居中对齐当作标题,那些字是楷体小四,左侧对齐,当作章节名,还有剩下的就宋体五号了,首行缩进两个字符,就是正文该有的格式。  就这么对比着来看,所见即所得容易催长用户做出花哨的排版,用户放了较多的精力在如何定制排版格式上;而TeX的所想即所得则比较适合于循规蹈矩的排版任务,在排版过程中可以少费脑筋。这也就是我说西方人的懒散、直接、天马行空的原因。由此也更好理解,为什么Nokia的手机里没有树型结构的文件系统,全靠文件名来索引;为什么wiki也是这样只靠文章标题进行检索;为什么国外品牌的PC机硬盘只有一个分区了……

铁打的营盘流水的兵

  在食堂跟江江、bobo一起吃过晚饭,晃晃悠悠走向F3,没想到在楼下遇到疯丫头,最近见到她有点多啊,前不久教授来深圳,一起吃饭时就见过一次,再之前是马姐姐召集大家吃饭,也见过。她在这边刚开完会,于是就和她聊起来,我告诉她我要辞职回家了,她倒是表现出一点惊讶的样子,比较有趣的是她也跟我说一个“绝密”的事,她老大同意把她调到北京去了。  这让我越来越觉得用“铁打的营盘流水的兵”这句话来形容我司实在太合适了,真是半军事化的管理,连里面的人这方面的行为都很半军事化啊!想想我进公司这4年来,陆陆续续离开(不一定是离职)的人中,有多少是跟我比较熟的。雨烟离职去了北京,跟老公一起走的;教授是最近才离职的,不过中间也是几经波折,现在是去tsinghua读博了;骨狗是个比较有趣的家伙,离职前的告别邮件还是中英文双语版;小思宇是去巴基斯坦陪彭彭的;孙同学没离职,却想方设法调到武汉去嫁人了,瀑布汗;还有一些不是很熟的同事、同学离职的;剩下几个准备行动的,这中就包括疯丫头,猫猫也许算一个吧,一直嚷嚷着要去南京;小丫头说是年底会去上海,也算是一个吧,也是一直吵着要离职的家伙……总之,大的趋势看,都是往着离自己老家近的地方挪,嗯!

Byebye,C++Builder!

  昨天熬到快后半夜,从Embarcadero官网上把Delphi/C++Builder 2010的ISO安装镜像下载了下来,并从网上找了个一年试用的license,装好了来体验一把。  在4年的大学本科生活中,可算得上用了3年半的C++Builder,在毕业后从事测试工作的那近2年的时间里,也断断续续地用着,所以总以为自己对C++Builder的感情可能是不容易割舍的。但是经过昨天晚上和今天晚上短暂的试用后,嗯,只是把一个C++Builder2007的工程转换为C++Builder2010,编译有不少通不过的。我放弃了,我想说:Byebye,C++Builder!编译不过的地方,我看了一下,都是因为Unicode这个编译选项引起的,我粗略地找了一遍工程设置,似乎没有可以修改这个选项的。说实话,我感觉最好的版本是C++Builder6,后面跟Delphi合并使用一个IDE后的版本,差不多每个大版本都装过,但都没有让我继续用下去的念头。  出2009时,我曾自己安慰自己,彻底放弃它了,这回有了2010,还是忍不住弄来装了装,真的彻底放弃了,没有一点亮点!一款C++开发工具,我关注的是三方面:IDE、编译器、类库(框架)。曾经在BCB6.0和VC6.0的年代,这三方面BCB都是占据优势的,可是这之后的7、8年来,VC在大幅进步,而BCB却是裹足不前,VC现在都已经精进到几乎没事可做的地步了!  就让它,活在回忆中好了!

图形程序设计续之零碎问题

  图形编辑功能已经做了两周了,到现在为止,也只能画出矩形框,在矩形框之间用白线、样本曲线,或贝塞尔曲线进行连接。又一次发现,只有在编码实现的时候,才会遇到很多之前没有想到的各种问题,而且有些问题要解决,也是要花费不少功夫的。  要考虑图层的问题,如何定义每个图形所在的图层,在绘制时,才得比较方便快速,而且需要可以随时修改图形所在的图层。图层的影响是多方面的,例如在绘制整张画布及图形对象时,要从底层开始绘制,而对于在某个点上点击选中一个图形对象时,却要从上到下进行遍历查找。  还考虑随时可以修改画布的大小,因为在添加图形,或修改图形位置时,是随时都可能把图形放在一个走出当前画布大小的位置上的,这时程序应该可以自动检测出需要扩大多少。对于向右、向下方向的扩大处理很方便,直接将画布大小重新定义即可。而对于向左、向上方向的扩展,则除了重新定义画布大小外,还得把超出部分归整到(0,0)这个坐标上,也就是说,要把所有已存在的图形对象的位置都调整一遍。  再要考虑子图的问题。也就是说,一张完整的图片,在某一时刻,只是显示了其中一部分图形对象,这部分当前被显示的可以作为一个子图来对象,而没有被显示,则是属于其他的子图。每个子图之间应该没有多少强相关的关系,最多是一个图形,与一个子图可以有包含(从属)关系,一个子图用来解释一个图形。常见的一种应用场景就是,双击了某个图形,就展示另外一张图片。这就同样要求设计一种灵活高效的数据结构来保存这些信息。  从当前的实现情况看,每个图形对象中,都有不少成员变量,保存了一些中间数据,这些中间数据不属于图形对象的本质属性,却对于图形在特定时刻进行动作起着重要作用,从代码美观角度讲,感觉很冗余,所以要考虑如何优化,减少这种成员变量。例如对于一些状态变量,或许可以用位域的标识。

把最幸福的事都回忆一遍

  昨天晚上,近12点,锁好门,准备熄灯上床,却听到手机的短信铃声响起。当时我就猜,在这么个时间,说不定是那小丫头发的,不,应该是我很肯定,一定是那小丫头发的。拿起一看,果然是小丫头,那个我曾经叫她宝宝,后来一直称呼为小乖的女人。短信的内容倒比较意外,说自己头好痛,眼睛也好痛,要爆了,却又睡不着。于是我便拨回去。  两个人断断续续,说着从我毕业工作以来的两个人之间的几乎每一件事情。睡在同一个屋子里,一起逛街,一起去欢乐谷玩,给她买眼霜和书,帮她买数码相机和笔记本,她大队培训期间出去玩让我在家里着急,买了里芯已经烂了的苹果给她……她问我她要结婚了我祝不祝福她。我短暂地沉默后,回答当然祝福了。然后她就在电话那头哭起来,我问她为什么哭,是不是他对她不好。她说没什么,他对她很好很好。还说她最对不起的人就是我,我说我没有怪你,是我自己给你这个机会让你对不起我的。而且就算真的很喜欢很喜欢一个人,也不是一定要生活在一起的。以前听小思宇说起过,陈奕讯在一个访谈节目中说的,他都已经有小孩的人了,到现在心中还是一直放不下一个人,惦记着一个人。我也可以。  我给她说起我妈妈,那是一个眼光很挑剔的中年妇女,我把众多女同事,女同学的照片拿回家给她看,基本上都是挑缺点的。小丫头就说,是不是她的脸那么圆,我妈妈也是不喜欢的。我解释说,你那种圆脸,我妈妈是很喜欢的,还说了脸圆圆的,屁股也圆圆的,这样的女孩子才好。小丫头说,那她最终也没能成为我妈妈的儿媳妇。我说,那是我妈的儿子没本事,没福气。说到很少见小丫头哭,其中的一次,是那年雪灾,到了机场没车回家,给我发短信,在机场一个人哭,我正在家里吃饭,我妈问我在跟谁发短信,我说了后,我妈还叫我回短信让小丫头不要哭了,不然不漂亮了,而我却说小丫头脸圆圆的,哭起来的样子很可爱的。  还说到,我曾经在她的照片袋里看到她和一个男生的大头贴,我心好酸好痛,当时怎么那么老实,没有趁上街的机会拉她一起去拍大头贴。她说,那个男生是yaya以前的男朋友,居然让人误会了,哈哈,印象中好像也只有这么一个男生一起拍过大头贴。后来她又说到,当时我千方百计把她介绍进公司,本来是希望能离得近一点的,想不到一下就被派到成都去了,是不是当时后悔得要死。我说,后悔倒没有,就是很痛恨这个命运,想不到在命运的面前真的一点能力都没有。真的,我不但痛恨这个命运,还痛恨着这个公司,就是它把小丫头弄到离我那么远的地方去了,便宜了以后可能成为她老公的那个小子。我问小丫头,如果她还是一直呆在深圳的话,我应该还是有机会的吧。小丫头轻轻笑笑。  小丫头说,很怀念以前在深圳的日子。呃,她只在深圳呆了不到半年。我说我也是,我很怀念她在深圳的日子。  几乎把我觉得最幸福的事情都回忆了一遍,最后我说,以后不要哭了,你哭我也会难过的,你已经不和我一起生活了,那就要在其他方面有所补偿,你担负着让我们两个人都快乐的责任。

图形程序设计续之困扰

  开始做那个图形编辑程序1周多了,现在遇到了瓶颈,因为原来的设计考虑得太不全面,很多很明显的问题都没有有顾及到,结果到实际编码实现到一定程度时,发现原来的程序结构有点不行了,不够用了。  主要的矛盾在于,原本我的设计上是,每种图形,都各自响应用户操作,互相不知道其他同类的存在。而实际上这是不对的,或者说不合适的,比如连接线,在端点确定前就是要知道那个位置是否贴到某个图形上了。另一方面,当某个图形上的连接点移动时,同样得通知所有跟这连接点连着的连接线,或者是某个图形被删除时,得同时删除连接在它上面的所有连接线。  本来所有图形对象都在一个管理器进行任务分派,现在看来,至少有得有一个类,可能还是这个图形对象管理器,做更多的事情,可以查询它所管理的图形对象一些特殊的状态,还要维护图形对象间的关系,可以是一个邻接矩阵,或一个邻接链表,反正就是一个图的表示法。这些不是我现在的主要困扰,我的困扰在于,图形对象怎么来调用这些查询状态的操作。本来图形对象被那个管理器对象包含了,另一方面那些查询状态的操作得知道所有这些对象,这样的循环依赖,让我感觉不爽!

有点必要学习SQL

  话说,我并不是计算机科班出身,因此很多基础的知识都是不知道的。这不,发现SQL真是有必要要好好学习一下了。最近在很多地方用到了数据库来存储东西,于是不可避免地需要写些SQL,最最基本的SELECT、INSERT、UPDATE还是会点的,不过也仅限于在单表中进行操作。  前两天发现一个可以显著提高在Sqlite3中SELECT性能的方法,那就是建索引。因为IDE需要AutoCompletion和Calltip功能,而用于这两个功能的数据都是存在一个sqlite3数据库中,该数据库目前已经有不少数据了,光是一张记录了方法的表,就有1万多条记录,从中SELECT是经常要做的操作,所以能提高点性能是很有意义的事。自从给该表建了索引后,至少感觉上非常明显,AutoCompletion几乎没有任何停顿就提示出来了,而以前的话,有个明显的停顿,虽然这个停顿的时间并不长,但已经能让人感觉出来了。这只是一点,让我觉得学习一下SQL有好处的地方,就让我尝到了莫大的甜头。还有一点就是,有不少地方的SELECT的条件,是从这次其他的SELECT中取得的数据,而我全部都是分成一条SELECT一次操作来进行的,我想,如果能把这些SELECT合并成一条语句,应该还是能再提高点运行速度吧。

图形程序设计与实现

  这周开始投入环境组网绘图功能的Demo实现。说简单点,这就是一个图形编辑器,就像Visio之类的。以前也有过自己使用GDI画图形的经历,但那时更简单的一点,没有要求图形可以移动,所以实现时做的事更少些。虽然这次说是做Demo,但我为了以后能以这Demo为基础,继续实际项目的完全实现,在初期就做了不少事情,费了好些心思。  首先是程序架构上,基本上是按照实际项目的设计来做的,以后也不用做大的修改和调整。界面上会有的元素,都留出位置了。花了近2天的时候,才把主界面的框架搭好。昨天又花了1天,把输入的数据源那部分功能也差不多完成了。今天才开始实现真正的绘图功能。  这次Demo主要就是为了预研或显示绘图功能,所以这里需要投入的精力更多。项目使用MFC开发,不使用任何其他第三方的库,传统而显而易见的作法是在CView上进行绘制。本着尽量OO的原则,最先可以想到的是,每种图形元素,可以用一个独立的类来表示,而所有这些类,有一个公共的基类,在基类中声明接口。以前的设计中,我只是让每种图形类保存了各自的位置和类型信息,并实现一个绘图接口。这次我突然发现,如果把相应的响应用户操作也放到各个图形类中实现,才更合理。比如点住鼠标进行移动,这得让图形类自己决定自己该进行什么动作,像一般的矩形,就可以直接将整个矩形进行移动,像折线,则可能只是在中间的折点进行移动。于是一般说来,这些图形类应该能处理鼠标的按键按下,弹起,光标移动等事件。现在觉得这样的设计是理所当然的,可在以前,我是绝对想不到这点的,也确实曾经把这些操作都放到外面统一分类处理。而且自从知道了Loki::Factory这个模板类后,对于这种大批类的操作,我有种近乎执着的热情想让它们不被任何除了这工厂之外的其他模块知道,直至不知道它们的存在。有了这一批图形类后,就需要一个管理器来维护这些图形类实例化出来的对象。这个管理器完全将这些图形类实例的创建、销毁、任务分派等与界面(CView)隔离开来。对于界面来说,图形对象管理器可以完成所有功能。  再说代码实现方面。这次专门看了一遍GDI+的SDK,准备试用一番,嗯,不算试用,是实际用上了。MFC中使用GDI+没有任何限制,在CView的OnDraw方法中把所有图形绘制一遍即可。当然也有双缓冲以免闪烁。网上的用GDI+实现双缓冲的文章和代码都很多,但一般说来只分两种:1、标准的GDI+做法,临时创建一个Gdiplus::Bitmap,将所有内容都画到这个Bitmap上,再将这个Bitmap画到设备上去;2、GDI风格的做法,先创建一个内存DC,GDI+都向这个内存DC画内容,最后将这内存DC都BitBlt到设备上。经过我的实验,发现第1种方法的资源消耗比较大,速度感觉上似乎也慢一点,但没具体测过,没实际数据来证明。于是我换用第2种做法,网上有一个很流行的CMemDC类,使用非常方便。但等我这样实现完后,发现移动某个图形时,需要刷新整个绘图区,还是会闪烁。上网随便搜索一下,发现一个很简单的解决办法:处理WM_ERASEBKGND消息,直接返回TRUE就可以了。

初步了解google-breakpad

  第一次知道google-breakpad这个东西,是一篇讲chrome使用的开源库的文章,当时也只是一带而过,心想这功能也能做成多平台的?  最近还是因为项目的需要,原本已经有一个这种实现的,是从FileZilla的2.x版本中抠出来的,不过有些时候会生成不了dump,让人觉得诧异,还有一些是生成了dump,但最后发现栈回调的信息太缺乏可参考的价值了。我估摸着,这可能跟如何使用dbghelp.dll里的函数的方式有关系,而这google-breakpad在我看来可能是当前功能实现得最好的一个了,就打算好好了解一下。  从svn里取得到的代码,解决方案是用于VC2005的,大概google内部VC都是用的2005吧,看到好些它的开源项目都是。直接用VC2008打开,自动转换版本后,也可以直接编译。主要看src\client\windows\目录下的代码就可以了,一般而言可以用到的有3个lib文件,分别是crash_generation.lib、exception_handler.lib、crash_report_sender.lib。如果用户程序只是为了能生成minidump,直接链接exception_handler.lib就可以了,crash_generation.lib已经被它包含了,而crash_report_sender.lib顾名思义是可以将文件发送到某个地方的,从代码上看,是通过http的上传功能来实现的,不过还没研究。另外还有一个GUI的演示程序,crash_generation_app.exe,可以测试除0异常,CRT函数参数无效异常以及纯虚函数调用异常。  通过阅读crash_generation_app.exe的代码可以大体上了解google-breakpad的使用方法。google-breakpad将这么一个小功能分成几部分来实现,首先,它分为服务器和客户端两部分,这两部分都可以生成minidump,但应用场景不同。用户程序出现未处理异常时,被ExceptionHandler捕获到,该模块会根据当前进程是否已连接到一个服务器,来决定由谁来生成minidump。在crash_generation_app.exe中默认是会去连接一个服务器的,所以如果服务器没有问题,则是由服务器来生成minidump的。而且服务器生成minidump不限于当前进程,它通过Event得到客户端的dump请求,通过管道进行其他数据的传递。使用C/S结构的好处是,可以尽量减少对被dump进程的影响,代价则是大大增加了代码实现的复杂性。如果没有可连接的服务器,客户端也可自己生成minidump,这部分的实现上网上的所有有关这个主题的代码,基本上都是相同的。唯一有点区别的是,网上其他的代码一般只接管了未处理异常,而google-breakpad则还可以接管CRT函数无效参数异常和纯虚函数调用异常。  在crash_generation_app.exe的实现中,使用服务器dump的方式,最后返回的结果总是说没成功,而实际是dump文件是生成了的,这应该算是个bug吧。还有个问题是,如果一开始尝试连接到服务器后,后来服务器又被关掉了,那之后的dump会全都失败,这可能是因为演示的缘故,没有仔细编写这种异常流程的处理代码吧。另外,算是小瑕疵吧,用google-breakpad默认好像是不能自定义dump文件的名字,只能指定个保存路径,最后的文件名是随机生成的uuid。  总的说来,对于有这方面需求的应用,使用google-breakpad是个不错的选择,它做了不少工作。