zoukankan      html  css  js  c++  java
  • 纪念一个曾经的软件产品(九)——皮肤编辑器及其它

    [回目录]

    十、皮肤编辑器

    10.1、我的第一个.net程序

    在这之前,我基本上只懂C++,之所以打算用.net来做这个皮肤编辑器,那是因为公司里除了我之外,别的人都只有.net的技术经验,我想让这个东西以后更容易找人维护,所以就决定用.net。而事实上,皮肤编辑器完成之后,也差不多结束了……不过,用.net来做而不是C++确是很正确的选择,因为:当我用上了C#之后,我发现编程原来可以这么简单。

    强大的开发工具Visual Studio给于C#的支持要远多于C++,比如其中的重构(Refactor)功能,C++就没有(我不知道最新的版本是否加上了),这个功能能够很方便地让开发者修改一个变量的名称,如果这是一个全局性的变量,你能想像这功能会带来多大的便利,当然其功能远不只是这个;当使用C#的时候,Visual Studio还有相当完整的代码编辑提示,给我的感觉是想写错都难,而C++就不具备这么智能的提示;运行时出错.net也是处理得非常完美,异常(Exception)不像C++的那么鸡肋,它总是能给你带来明确的出错提示……太多太多可圈可点之处了。

    我上手C#花的时间却不长,皮肤编辑器花了三个星期就基本OK了,对于我这个新手来说,这个速度还真是挺不错的,正好印证了过去广为流传的一个观点:从C++转去做.net或java是很简单的。反过来呢?却不是那么简单了,至少本人认为这样。

    10.2、复合文件与混合编程

    在一开始的时候,SoSoPi的图片文件是不打包的,直接存放在磁盘上,能轻易看到png,jpg啥的,但随着文件越来越多,每次拷贝部署就越来越不方便的了,于是我考虑把文件打包,但以一种什么样的格式呢?我理想的需求是:文件中的文件系统。就像zip文件那样,打包文件就相当于一个文件系统,里面有多个文件,还有目录结构,可以单独提取某个文件出来而无需显式地解包。

    一开始我为这个事情烦恼不已,因为Windows Mobile下代码资源比较匮乏,找不到适合使用的现成代码,我甚至都打算自己来写一种文件打包的格式了。直到我一个朋友对我说:“用‘复合文档’如何?”

    复合文档,这个名词对很多人来说有点陌生,但是我说doc、xls和ppt都复合文档,那么大家是否有点恍然大悟?它相当于把许多文件整合到一个文件中,这样传播起来就方便了。

    复合文件可以用上图这个叫“Compound Document Viewer”的工具打开查看其内容,从图中看出,wood.srf这个皮肤包含了很多的子目录,子目录下又有若干个png图片文件,复合文档的相关的API函数有:

    • StgOpenStorageEx - 打开复合文档
    • StgCreateStorageEx - 创建复合文档
    • IStorage::CreateStorage - 创建存储(即复合文档中的目录)
    • IStorage::CreateStream - 创建流(即复合文档中的文件)
    • IStorage::Write - 给复合文档中的文件写入内容
    • IStorage::Release - 用完记得释放

    这些API是以本地代码(Windows Native API)的形式提供的,C++能够直接使用,而.net则不行,于是我在这里面使用了混合编程,用C++实现对一个目录打包成srf(SoSoPi Resource File)的功能,封装成dll的形式,对外导出“MakeSRF”和“UnpackSRF”两个方法,然后用.net写的主程序来调用这个dll:

    //External DLL functions prototype.
    [DllImport("SRFMaker.dll", CharSet = CharSet.Unicode)]
    private static extern Int32 MakeSRF(string strFolder, string strSRF);
    [DllImport("SRFMaker.dll", CharSet = CharSet.Unicode)]
    private static extern Int32 UnpackSRF(string strSRF, string strFolder);

    这也是我唯一的一次用.net代码调用C++代码,之后就再没有过了。

    10.3、层次渲染及刷新

    皮肤编辑器之所以能显示出和真机类似的效果,那是因为:我相当于把真机的渲染过程重头再实现了一次。真相就是这样……别的,我真想不出什么办法了。

    实际上在Windows上绘图比Windows Mobile上简单太多太多了,可以肯定的是:资源枯竭的问题是不会遇到的了,也不需要考虑性能的问题,所以程序主要做的就基本上是贴图。

    在这个程序中,我还真正地实践了一把传说中的“面向对象编程”,上面那些华丽花哨的小图片,文字啥的,我都把它们抽象为一个个对象。我抽象了一个“CPaintObj”类,作为所有界面元素的“基类”,这个基类具有所有界面元素共同具备的那些属性:

    • ObjectDescription - 描述文本
    • Selectable - 是否可选择
    • DrawThisItem - 是否绘制
    • X - x坐标
    • Y - y坐标
    • Width - 元素宽度
    • Height - 元素高度
    • ……
    • Draw - 虚函数,由子类各自实现具体绘制

    再从“CPaintObj”中派生出各种子类,实现各种不同的绘制。每个页面上都包含若干个界面元素对象,如下面这个“首页”,就包含了23个界面元素对象:

    其中有些对象是重叠的,所以看起来并不是那么显著。

    在各种对象的处理过程中,比较麻烦的就是文字对象,一张图片,宽度高度都是确定的,而文字却不是,还是那句话,你不把文字真正绘制出来你就不知道它实际上尺寸如何,为此,我在文字这个类的绘制处理中也费了不少心思,我先要把文字的尺寸计算好,再确定它的显示位置。这时候,C#所提供的“属性”就是个好东西,你想想我要取一个文字对象的X坐标,跟取一个图片对象的X坐标,做法肯定不一样吧,利用“属性”就能把“获取这个有差异的X坐标”封装得看起来一样,不管你里面怎么处理,反正我拿X坐标这个属性就OK了。用上了C#之后,我感觉我回头去做C++的代码就有些费劲了,事实上也如此,在今年初,我有一个小小的C++程序要做,感觉“咋这么麻烦的?”

    再讲讲刷新,由于我不可能给用户提供图片编辑工具,所以在这个里面,我是让用户自行选择适合自己的图片编辑器,(我想绝大多数人都会用Photoshop吧?)现在问题来了,如果用户更新了一个文件,那界面如何得知呢?是不是我得去监视目录的文件变化情况方可?——是的,等等,咋这么熟悉?这个事情我做过,想起来了,没错,就是SoSoPi看图模块!不同的是,这里使用的是C#代码——简单多了。.net对这个进行了很好的封装,这里有个叫“FileSystemWatcher”的类,专门干这个事情。

    其实细节还很多,但总体上来说,这玩意儿真是比SoSoPi简单太多了。

    10.4、皮肤编辑器的意义

    意义重大,我从来没见过有一款软件的皮肤编辑有SoSoPi的那么简单易用。皮肤编辑器一上线,我几乎不需要增加任何说明,用户就噼里啪啦地弄了很多新皮肤出来,真是令我惊讶,其实这也是一个友好的软件所追求的:免说明书,上手即用。皮肤编辑器基本做到这点了。

    这个简单的软件使得SoSoPi的皮肤数量激增,许多对软件皮肤制作没什么经验的用户都能凭借它做出不错的皮肤来,当然了,原先美工底子好的用户有了它做起皮肤来更是得心应手了。

    我想:程序,不就是要用户用起来“爽”么?如何才能“爽”?不就是简单好理解么?——Oh,将来的目标!

    十一、一些零碎的功能

    11.1 多语言与国际化

    多语言和国际化绝对不是把中文翻译成英文那么简单,其中涉及到太多太多方面了,翻译仅仅是其中之一,这里就不展开了。

    其实对SoSoPi这么个小软件来说,还远远没到需要“国际化”的时候,老吴提起国际化,也是由于我们的程序“惊动”了老外,记得有个俄罗斯的玩家,直接修改了sosopi的exe文件,实现了“俄语版”,当然由于是直接修改二进制文件的,俄化并不完美,所以老吴想是不是可以把字符串都单独提出去,让懂翻译的用户自己去弄不同的语言版本。

    嗯,这做的只是国际化的一小小部分——翻译,仅此而已。对于国际化有过一定经验的我,经过考虑,认为是可行的,于是就动手,本来打算采用类似Android的那种用xml描述的方式,但考虑到程序中的字符串过多,要给每个字符串创建一个key并和程序中的key对应起来也是有点麻烦的事,所以后来就干脆一行一行写,这样带来的可维护性就差一些,字符串的含义看起来并不是那么显而易见了,现在回头想想,还是用xml比较好,多出来的这点标签开销其实不算什么。

    单纯的文本翻译其实并不难,但我说了,要做国际化的话,这仅仅是其中之一,剩下的工作一点都不轻松,就拿SoSoPi来说吧,我们做的天气功能仅仅在中国用得比较好,因为我们的天气源是weather.com.cn,想要国际化,就得加入不同国家的更多城市的支持,你想应该怎么做?我们没那么强大的实力啊,后来我只能公开天气功能的Web Service接口,看看有没有哪个懂编程的老外替我们来做这个事情了。

    真正要做国际化的话,还得考虑单位转换,文本尺寸,风俗习惯(比如节日)甚至国家政策。

    总之,SoSoPi所做的这点工作算不上真正意义上的“国际化”,你可以理解为,仅仅是一些文本翻译而已。

    11.2、个性化调整

    手机是个性化体现的一种重要工具,这就是为什么这么多人喜欢去折腾他们的手机的缘故,SoSoPi在最后的开发阶段里也加入了不少个性化选项,比如字体、文字大小、文字颜色、背景图片、动画调整和两种不同的滑块区风格。

    滑块区风格有两种,一种是仿马尼拉的,另一种是老吴自创的,叫“SoSoPi”风格:

    十二、其它

    12.1、手机

    我第一个智能手机是2007年11月买的,Samsung的i718,这也是三星的第一款智能手机,我算是第一个吃螃蟹的人么?这样都敢买,不知会出什么问题啊!当时国内最广为人知的智能手机的品牌我想应该是多普达,但价格贵啊,最便宜的一款也要三千多,而我买的i718只要两千出头,还配备两电两充,外观嘛,个人觉得也比多普达好看些,外观一向是三星的强项,所以就选了三星。对某些人来说,看好的东西就买,从不计较价格,但对我来说,价格一直是考虑是否购买的重要因素,我2009年的时候继续买了Samsung的另一部智能手机i780,最主要的原因也是因为它便宜(比类似的Nokia E71便宜800,而且一样的两电两充),记得那时候是在taobao上购买的(从那时候起我买手机就再也不去实体店了),中午时候下的单,第二天上午就收到货了,深圳寄到上海,可谓神速。现在回想,i718真是不怎么好用,屏幕有严重的问题,输入会间隙性的出现乱跳的情况,屏幕还是凹进去的,用笔尖点屏幕边缘的时候常常受到影响,明显地三星在智能手机领域经验不足啊,到了i780情况就好多了,触屏乱跳的事情是没有了,而且屏幕的显示效果一级棒,各个方向用近180度的角度去看,居然还能看得清,我想要是电脑的显示屏也有这种效果就好了,它还是我见过的唯一一款带鼠标的手机。我拿到i718之后,就在上面编写了我第一个Windows Mobile程序,很简单很简单的一个小小猜谜游戏,但没什么成就感,也没觉得在这上面弄程序会有什么前途,就不继续研究了。直到我碰到老吴,看到htc hd2,我才对Windows Mobile有了新的认识。

    HTC hd2无疑是革命性的,震撼的,在这之前,我不知道一款手机的性能可以这么强悍,即便在它推出了两年之后再看,也不觉得它配置落伍,更重要的是,它被机友们称赞为“机神”,能够通刷Windows Mobile、Windows Phone 7和Android系统,世界上恐怕也只有这一款手机。见过老吴的htc hd2之后,我就一心想买一台,但考虑到昂贵的价格,我只好再等等,我直到2011年初才出手了一台,而恰恰是这年,Windows Mobile迅速没落,Android迅速崛起。htc hd2可谓Windows Mobile的巅峰之作,但也可以说是绝唱了(htc后出的几款Windows Mobile手机与hd2比皆无突破)。历史有时候就是那么带着戏剧性,2010年之前我不知道htc是什么东西,也没料到它在2011年一举到达了顶峰,更未曾想过接下来它就迅速没落以至沦落到现在无人问津的地步。

    SoSoPi项目结束后很长一段时间,我自己都是SoSoPi忠诚的用户,而老吴早就一直是iPhone了,他现在依然还是,当然我也在今年上半年的时候“接手”了他的老iPhone4——真希望以后也能这样,我就不用再花钱买手机了。

    12.2、开发社区

    想当初来做这个项目之前,我从来没想过可以通过QQ群来寻找技术答案,因为以前公司不让上QQ,QQ给人感觉嘛,偏向于娱乐的工具。老吴提起用QQ群,我就这么干了,通过搜索,我找到了一些群,其中人气最旺的一个叫“DevDiv Windows Mobile开发群”(大概是这个名字),这个群是属于一个论坛的,论坛地址是DevDiv.net,上面有个Windows Mobile的开发版块。群里应该还是有不少高手的,我的一小部分问题是在群里得到解决的,只是大家都比较忙,互相交流的时候其实并不多,另外还有些别的群,但人气太低,甚至有些群看似不少人在线,但几天下来都没人说一句话的,传说中的鬼群。

    DevDiv.net是国内难得的一个好社区,上面的Windows Mobile开发版块还是有些人气的,而人气最高的当属Sybian版块,iOS和Android版块上面也是有的,但人气相对就低一些——很奇怪对吧,但事实上就这样,所以,这个论坛后来的发展你也许也想到了,没落呗,再后来,没有后来了,反正现在上不去了,至于那个群,很早的时候就被创建者直接解散了,没有任何理由,我想大概是创建者觉得大家都用群交流,不上论坛,导致论坛上人气不高。

    在DevDiv.net群里,最德高望重的当属小李匪盗(人称“刀哥”),他甚至自己出了一本Windows Mobile开发的电子书,供大家免费下载阅读,可谓大公无私,也许是太忙,他在群里很少说话,但在论坛上却经常能找到他过去很多有用的回帖,他的blog是http://blog.csdn.net/pknife/(但好久不更新了,不知道有没有新blog)。

    论坛上还有个活跃分子——阿康(egmkang),貌似年龄不大,但能力很强,自古英雄出少年啊,也给过我不少帮助,他的blog是:http://www.cnblogs.com/egmkang

    在其它的社区,如CSDN等,还碰到些技术达人,如Jake Lin(林永坚),blog:http://www.cnblogs.com/procoder/,他后来还翻译过Charles Petzold的《Windows Phone程序设计》一书。

    还有开源项目iToday(在Window Mobile平台下的一个类iPhone的界面)的发起人的王克伟,blog:http://www.cnblogs.com/wangkewei/,虽然iToday也无果而终。

    当然,还少不了微软官方的论坛:Visual Studio Smart Device Development - Native C++ Project(我不知道这个论坛还能开多久)

    12.3、网站和其他人

    由于本文主要讲SoSoPi这个软件,所以主要提到我和老吴,但在结束前,也想提提其他人,不是说在“最鼎盛”的时候,直接参与项目的一共有七个人么?

    一是雨夜星空,负责了SoSoPi大部分的图片的制作和界面设计,在项目停止后不久离队,现在貌似在继续做设计相关的工作;另有四人从事SoSoPi网站的开发,其中三人也在项目停止后陆续离队,剩下的一位一直到现在,angle360便是他。近这两年里,我们做的事情其实跟SoSoPi已经没什么关系了。

    老吴的在网站上也费了不少心思,比如在想到做用户积分的时候,甚至都整晚在琢磨,到底叫什么名字好呢?“到底‘王’高还是‘皇’高?”“‘侯’和‘将’如何?”“‘侠’和‘客’貌似不错!”……小图标老吴也向我们征集了一些建议,我的的建议是用一些小动物图标,小鸡小鸭是比较搓的等级,而老虎狮子等级较高,但老吴不同意,最后采用了“类勋章”的图标,最低级是木头的,接下来依次是:铁、铜、银、金、宝石……等,但我感觉银和铁很难分辨。

    用户对我们的推动力当然也是非常重要的,其中又以清明落落最让我印象深刻,他们都有非常强大的美工能力,对SoSoPi皮肤的理解甚至比我还深刻,老良宝贝皇神威也对SoSoPi给了不少建设性的意见,老良的皮肤更新速度可谓神速,SoSoPi一更新,他的皮肤紧接着就更新了,还有很多人了,如蓝色炫影,给我们的网站指出了不少问题……可惜后来服务器坏了,网站也就这样没了,我倒是挺希望能找回数据,毕竟很多人在这里面都曾经投入过不少精力。

    再谈谈老吴,表面上看,他接近于产品经理的角色,其实,他远不只是产品经理,他基本上参与了除程序开发之外的所有的工作,提需求,做设计,做测试,和用户交流,还做SoSoPi的推广(嗯,还搞过一些有奖活动),甚至还自己画图,老吴Photoshop还是用得有两下子的,一个小的团队,每个人都要负责很多东西,蛮锻炼人的。

    12.4、未完成的功能与老吴的秘密

    本系列文章已经接近尾声了,显然,上面提到的所有的这些,都是不盈利的,程序中也没有任何广告,事实上,我们也没有赚到一分钱,那老吴做这个东西的初衷是什么呢?——其实我也不太清楚,因为这是一个没有最终完成的产品,老吴的想法很多都没有实现。

    然而,在和老吴闲聊的时候总有意无意地收听到他原本的一些“远景目标”,在SoSoPi未完成的模块当中,有一个模块叫“家园”,老吴说这才是他真正要做的。家园这个名字,让人想起了如“QQ空间”之类的SNS应用,而SoSoPi则只是一个入口。想想当下国内的几家互联网公司为了所谓“入口”争得血雨腥风,我感觉得到老吴的一些想法可是相当有前瞻性,只不过我们的实力远不足以实现那些想法罢了。

    老吴说:通过SoSoPi,用户之间可以交流玩机心得,开发甚至发售自己做的皮肤,阅读模块到时候也可以加入收费内容,照片可以分享出来,还可以组织线下活动等……OK,打住!现在看来这些想法是否有些天马行空的味道?当然,老吴现在也很清楚了,要完全实现这些东西,非得一家实力相当强大的公司不可,在当下,更多的互联网公司的产品必须追求小而美而不是大而全。

    故事差不多就讲到这里,感谢你能看到最后,这些事,现在看起来感觉挺遥远了,尤其是对于发展这么快的这么个行业来说。童话故事的结局往往都是王子和公主从此过上了美满幸福的生活,因为童话故事不愿意告诉你他们之后发生的事,而人生则是连续的过程,你不可能说自己解决了所有的问题从此之后一直都可以高枕无忧了。老吴的故事当然也不可能就此结束,我还真希望以后还有机会再接着讲讲老吴后来的故事。当然,肯定不是像现在写的那么凌乱又掺杂过多技术细节的了。

    [回目录]

  • 相关阅读:
    Java通过Mybatis实现批量插入数据到Oracle中
    SpringMVC+Spring+Mybatis整合,使用druid连接池,声明式事务,maven配置
    图片懒加载原理
    js参考---sort函数
    css参考---纯css实现三角形
    css参考---实现元素水平垂直居中
    javascript疑难问题---13、函数防抖
    javascript疑难问题---12、函数节流
    闭包执行注意(函数节流为例)
    javascript疑难问题---11、回调函数
  • 原文地址:https://www.cnblogs.com/guogangj/p/3380726.html
Copyright © 2011-2022 走看看