2009年4月18日星期六

【原】Boost库之program_options的使用

我们在编写程序时,有时需要解析命令行参数,比如小蜜蜂调用聊天历史记录程序,监视器调用日志管理程序等。遗憾的是,C++标准库并没有提供解析命令行参数的功能,我们必须自己来完成解析工作。如果命令行参数比较复杂,要正确地解析可能并不是一件容易的事情。即使解析正确了,代码也不一定具有通用性。那么,有没有一个封装好的功能强大而且简单易用的命令行解析类呢?答案是Boost库的program_options。

Boost库的program_options相对于手工编写代码解析命令行参数具有以下几个优点:
1.使用更容易。定义参数处理的语法简单,库自身很小,像转换参数值到指定的类型和保存参数值到变量的事情都由库自动处理。
2.错误报告更友好,可以报告错误的命令行参数。另外这个库能自动生成使用帮助,避免了手工更新使用帮助而导致的不一致。
3.参数能从不同地方读取。当命令行参数不能满足我们的要求时,可以改用配置文件。

下面介绍一下使用program_options解析命令行参数的具体用法。
首先声明一个options_description类的对象,该对象用于添加我们需要解析的选项名字。

options_description myOptions("command line options by hujian");
int nLevel;
myOptions.add_options()("help,h", "Use --help or -h to list all arguments")
("file", value<string>(), "Provide input file name")
("level", value<int>(& nLevel)->default_value(5);

其中,长选项名(比如“help”)必须在前面,短选项名(比如“h“)可有也可没有,如果有,必须紧跟在逗号之后。另外,还可以给选项名赋默认值。
添加好选项名字之后,就可以开始解析工作了。解析的结果保存在variables_map类型的对象中。

variables_map vmap;
// MFC中使用__argc和__argv
store(parse_command_line(argc, argv, myOptions), vmap);
notify(vmap);

其中,store函数可以调用多次,以将多个不同options_description的分析结果存入vmap中。解析工作完成之后,解析的结果就保存在vmap中。我们现在可以从vmap中获取想要的选项值了。

if (vmap.count("help"))
{
cout << myOptions << endl; // 打印出使用帮助
}
if (vmap.count("file"))
{
cout << "file is " << vmap["file"].as ( ) << endl;
}
cout << "level is " << nLevel << endl;

必须使用as来获得选项值;如果类型不符和,program_options会抛出异常。
总结一下,从上面的介绍可以看出,使用program_options来解析命令行还是非常方便的,推荐大家使用。

2009年4月15日星期三

【原】创世科技无线视频助阵电信3G业务新闻发布会——全国首例基于3G网络的外景视频直播

4月13日下午,安徽电信3G业务正式商用新闻发布会在五里墩电信大楼20楼演示大厅隆重举行,发布会上省电信领导向在场的几十家媒体展示了3G无线宽带的神奇魅力。手机网上观景,您足不出户,此时此刻黄山的美景尽收眼底;3G视频连线,外景记者无需庞大的卫星转播车,通过一个轻便的背包式3G无线视频终端将采访现场清晰流畅的声音和视频实时的传送到演播大厅。3G改变生活,每种应用都让人耳目一新,犹如置身于一个虚幻的世界。国内无线视频领域的领导者安徽创世科技为这些应用提供了便携终端、系统平台和现场技术支撑,展现了创世科技全球眼无线监控系统的强大魅力。

2009年4月12日星期日

【原】SuperMapObjects中最短路径分析的bug

最近在对以前SuperMapObjects最短路径代码进行了改动,用了一个成员变量 CsoPoints m_objPoints保存了设施点,结果在测试中发现最短路径分析时,得到的结果老是错误,看起来貌似最后一个添加的设施点没有在分析中起作用。于是在函数内下断点跟踪,发现经过一次路径分析后,果然是少了一个点。但是第一次分析的结果都是正确的,如果再次进行分析,则结果就是错误的。当然解决办法也是有的,就是每次分析时,都构造一个临时的CsoPoints对象传进去,这样才能保证每次的结果都正确。

【原】如何给Facilities图层添加元素

这里所说的Facilities图层是指Closest Facility图层的子图层,就是设施点图层。我上次在做最短路径分析时,得到了Facilities图层的接口,但是不知道如何给它添加元素。因为ILayer实现了IFeatureClass的接口,所以很容易就获取到IFeatureClass接口,但是是不是直接就Create一个Feature然后添加、保存上去呢?打开ArcMap,先看看它的属性,有ObjectID、PosAlong、SourceID、SourceOID、SideOfEdge等等,在帮助文档里找到了注释:SourceID是网络数据集上所定位到的图元的源ID,可以从INetworkSource::ID获得此ID;SourceOID是定位到的图元的对象ID;SideOfEdge是指在边的左侧还是右侧;PosAlong是指定位到的图元沿边的距离。要是一个字段一个字段的去计算,然后再添加,累死你,所幸ArcEngine提供了一个方法QueryLocationByPoint,可以帮我们完成这件事。
它的接口如下:HRESULT QueryLocationByPoint(IPoint* point,INALocation** Location,IPoint** outPoint,double* distanceFromPoint);AE帮助上是这种说的,Using the input Point object, the method calls QueryLocationByPoint on each of its associated NALocatorAgent classes. The corresponding NALocation, the point where the location was found, and the distance from the input point to the source feature found are all returned.
下面是实现代码
ILayerPtr ipLayer = m_map.GetLayer(0);
INALayerPtr ipNaLayer = ipLayer;
INAContextPtr ipNaContext;
HRESULT hr = ipNaLayer->get_Context(&ipNaContext);
INAClassLoaderPtr ipNAClassLoader(CLSID_NAClassLoader);
INALocatorPtr ipNALocator = NULL;hr = ipNaContext->get_Locator(&ipNALocator);
hr = ipNAClassLoader->putref_Locator(ipNALocator);
IPointPtr ipPoint;INALocationPtr ipNALocation(CLSID_NALocation);
ipNAClassLoader->get_Locator(&ipNALocator);
IPointPtr ipOutPoint(CLSID_Point);
double dbLVal = 0.0;
ipNALocator->QueryLocationByPoint(ipPoint, &ipNALocation, &ipOutPoint, &dbLVal);

2009年4月8日星期三

【原】模块间(dll, exe)使用导出变量、静态变量和外部变量的试验与结论

// Dll头文件声明

AFX_EXT_DATA int D1_nCount;

extern int D1_nCountE;

static int D1_nCountS = 0;

AFX_EXT_API int D1_GetCount();

// 结论:多模块调用时,或重复调用时,模块内的静态变量是唯一的,不会重复分配内存
int nCount = D1_GetCount();
nCount = D2_GetCount();
nCount = D1_GetCount();

// 结论:dll中声明的静态变量在每个使用的cpp下均有一份拷贝,多模块更是如此(静态变量在编译时会分别拷贝)
nCount = D1_nCountS;
D1_nCountS = 2;

// 结论:dll中声明的外部变量不能用于其他模块,链接失败(基地址都不一样,肯定不行)
nCount = D1_nCountE;
D1_nCountE = 2;

// 结论:dll中导出的数据到处都可以用,在模块内部只有一份拷贝,每个用到的模块各有一份拷贝
nCount = D1_nCount;
D1_nCount = 2;

其实上面有些结论是不太正确的,以下后续试验得出了新的结论:

// Dll头文件声明

#ifdef DLL2_EXPORTS
#define D2_API __declspec(dllexport)
#else
#define D2_API __declspec(dllimport)
#endif

D2_API extern int D2_nCount;

// 结论:dll中导出变量在其所在模块为导出,在其他模块必须为导入
// 结论:dll中导出的外部变量到处都可以用,在所有模块中都只有一份拷贝
// 结论:dll中导出的变量到处都可以用,在所有模块中都只有一份拷贝,
// 但是在其所在模块只能包含一次(否则为重定义),所以只能声明为外部变量

nCount = D2_nCount;
D2_nCount = 2;

// 总结论:dll中的变量一般情况下是以函数接口形式导出,
// 但在某些情况下可能需要在模块间直接使用,那么就有两种方法:
// 如果需要该变量在每个模块都有一份拷贝,那么可以使用static声明,
// 不过这种用途一般比较少。。还有就是使用__declspec(dllexport) extern声明,
// 一般都是需要各个模块公用一份拷贝,注意在其他模块使用时需要用
// __declspec(dllexport)导入该变量,否则就又是导出了,而且没有实现

2009年4月7日星期二

一些FLASH组件学习小结

1.关于命名:
在程序命令里,有些命令是几个单词都连接起来了,像createEmptyMovieClip,看起来很长,但你E文足够好,应该能看出来,这就是创建空的影片剪辑的英语,并且中间每个单词的第一个字母大写。Flash里边的变量名、属性 、方法、命令等等,基本都遵循这种规则。如果你希望写的程序看起来比较专业,同时还容易理解,希望一开始 就能养成良好的命名习惯,还有一点需要强调的是,flash是严格区分大小写的,所以,“myMc”和“mymc”并不 是一个东西,如果在调试中出现错误,也可以检查下这方面的问题。
2.组件样式的几种设置方法:

组件是一些组件和类的组合,有些样式是需要其它此类组件和资源中的资源,在这里讲下在非修改资源的组件样式定义。
A.对一个组件实例设置样式
这样的设置方法最直接和便捷,针对单个的组件会很方便,但也有一定的局限性,比如场景上有很多组件需要定义,就要定义不同的名称和样式了。
B.使用全局样式声明对文档的所有组件设置样式
如:_global.style.setStyle("themeColor", "0x00CCFF");这样的设置针对场景较多的组件定义会很便捷,as也很简洁明了。
C.创建自定义样式声明并应用到指定的组件实例
如:var styleObj = new mx.styles.CSSStyleDeclaration;styleObj.styleName = "newStyle";_global.styles.newStyle = styleObj;styleObj.fontFamily = "Verdana";//设置样式属性styleObj.fontSize = "10";styleObj.fontWeight = "bold";styleObj.color = "0x990000";styleObj.setStyle("themeColor", "0x00CCFF");
CompA.setStyle("styleName", "newStyle");//对组件设置样式(这里要说明下CompA,CompB,CompC是实例名)CompB.setStyle("styleName", "newStyle");CompC.setStyle("styleName", "newStyle");
D.为组件类别创建样式声明这种方法为场景内某一类型的组件定义样式,只对此类别有效。
如:var btn = _global.styles.Button=new mx.styles.CSSStyleDeclaration();//为Button类型定义btn.fontFamily = "Verdana";btn.fontSize = "12";btn.fontWeight = "bold";btn.color = "0x000000";var rb = _global.styles.RadioButton=new mx.styles.CSSStyleDeclaration();//为RadioButton类型定义rb.fontFamily = "Arial";rb.fontSize = "12";rb.fontWeight = "bold";rb.color = "0x003399";
3.常用的属性设置:
themeColor 主题颜色:如果对色彩样式配置不想过多的去设置的话,themeColor是一个选择。它可以让你选择一种基本色彩,然后组件的边框,外观等色彩将会以此色彩为基础构成一组缺省的样式,组件均可使用此样式属性。
arrow  设置滚动条和下拉菜单中箭头元件的颜色
background 设置列表框、组合框、单选钮和复选框组件背景部分的颜色 
backgroundDisabled 设置被禁用的列表框、组合框、单选钮和复选框组件背景部分的颜色
darkshadow 设置组件内边框和暗面阴影部分的颜色 
face  设置组件的主要颜色 
foregroundDisabled 设置被禁用的列表框、组合框、单选钮和复选框组件前景部分的颜色 
hinglight    设置当组件被选中时,其内边框和暗面阴影部分的颜色          
highlight3D 设置当组件被选中时,其外边框和亮面阴影部分的颜色 radioDot 设置单选钮被选中后其间中圆点的颜色
scrollTrack 设置滚动条中滚动槽的颜色
selection 设置列表框、组合框组件中选定项目的突出部分显示的颜色
selectionDisabled 设置被禁用的组件中选定项目的突出部分显示的颜色
selectionUnfocused 设置当组件不在焦点状态时,选定项目突出部分显示的颜色
shadow 设置组件外边框或亮面阴影部分的颜色 textAlign 设置组件中文字对齐的方式,其值有“right”、“left”和“center”
textBold 设置组件中文字是否使用粗体
textColor 设置组件中文字的颜色          
textDisabled 设置当组件被禁用时文本的颜色
textFont 设置组件中文字的字体名称
textIndent 设置组件中文字的缩进
textItalic 设置组件中文字是否使用斜体
textLeftMargin 设置组件中文本左边留白的宽度
textRightMargin 设置组件中文本右边留白的宽度
textSelected 设置列表菜单中被选定文本的颜色 textSize 设置组件中文字的大小
textUnderline 设置组件中的文字是否有下划线

2009年4月6日星期一

【原】引玉系列之AE特效——Shatter

在工作中经常会遇到文字特效的制作,以往多是使用flash软件,或者flash相关字体插件制作,这次尝试了一下After Effects的文字特效。
相关图片:

说明:
使用Shatter特效,重点是要掌握Shatter的各项参数作用和意义,以及做路径shatter的方法。由于可以使用预处理的图片,所以在文字样式上有相当灵活的选择。而且可以实现各种不同的shatter效果,甚至模拟合成较为真实的爆炸场面,运用在一些电影电视特效中。

引玉系列之UI设计心得

注:文中的一些观点和结论并非原创,只是做了分析整理。
UI的本意是用户界面,是英文User和interface的缩写,基本上分为三个方向,分别是:用户研究、交互设计、界面设计。
软件界面设计就像工业产品中的工业造型设计一样,是产品的重要卖点,一个友好美观的界面会给人带来舒适的视觉享受,拉近人与电脑的距离。界面设计不是单纯的美术绘画,它需要定位使用者、使用环境、使用方式并且为最终用户而设计,是纯粹的科学性的艺术设计。
界面设计里有一个很重要的组成部分,就是界面图标设计。图标设计在很大程度上决定了软件界面设计的好坏。
图标应该有趣,色彩丰富而且充满活力,因为系统支持32位图标,并且边缘非常光滑。图标设计要从三个方面考虑,创意,细节,整体性。
设计图标时,要使用已有概念以确保真实表达了用户的想法。考虑图标在用户界面环境中以何种形式出现,以及如何作为图标集的一部分使用。考虑图形的文化背景。避免在图标中使用字母、单词、手或脸。必须用图标表示人或用户时,请尽可能使其大众化。如果图标中的图像由多个对象组成,应考虑如何使图像尺寸更小。建议在图标中使用的对象不超过三个。对于 16×16的尺寸大小,还可考虑删除某些对象或简化图像使之更容易辨认。
XP系统下常用的图标尺寸有四种:
(1) 48×48像素
(2) 32×32像素
(3) 24×24像素
(4) 16×16像素。
图标样式的特性:
(1) 色彩丰富,是对WindowsXP外观的补充。
(2) 不同的角度和透视特性为图像增添了动态活力。
(3) 元素的边角十分柔和,并略微有些圆滑。
(4) 光源位于图标的左上角,同时有环绕光照亮图标的其它部分。
(5) 渐变效果使图标具有立体感,进而使图标的外观更加丰满。
(6) 投影使图标更具对比度和立体感。
(7) 添加轮廓可使图像更清晰。
(8) 日常对象(如计算机和设备)具有更现代化的个人外观。
在Denis Kortunov的文章里描述了图标设计中比较容易犯的一些错误,在我们的设计中,应该要尽量避免:
1. 图标之间没有明显的差异化(太相似,难以辨识)
2. 在一个图标中设计了太多的元素(windows vista的图标是反面教材)
3. 加入不必要的元素
4. 一套图标中的图标统一性不足(颜色主题,透视角度,尺寸,绘图技法等)
5. 在小图标中(24X24以下)使用不必要的透视和阴影
6. 过度原创使语义不明确(比如将回收站设计成碎纸机的样式)
7. 国家区域和文化特征没有被考虑进设计中
8. 在图标中使用纯界面化的元素(比如泛滥的mac aqua效果,用户会认为你的产品是苹果的产品)
9. 在图标内部使用文字(特别是不容易辨识的)
10. 图标外部边缘没有做像素化处理

2009年4月4日星期六

【原】Boost库之function的使用

Boost库的function是一组函数对象包装类的模板,实现了一个泛型的回调机制。Boost库的function与函数指针相比,优点在于它允许用户在目标的实现上拥有更大的弹性,即目标既可以是普通函数(自由函数),也可以是函数对象和类成员函数,而且可以给函数添加状态。

使用Boost库的function,可以很好地与现有的代码融合在一起。另外,function还可以与Boost库的bind和lambda配合使用,从而极大地扩展了function的适用范围。function库支持的函数参数个数最多为10个,其头文件为function.hpp或functionX.hpp(其中,X为0到10之间的整数)。如果你的程序中只使用了X个参数的function,那么你可以只包含对应的functionX.hpp,当然,你也可以只包含function.hpp(它包含了所有的functionX.hpp)。
下面介绍function库的具体用法。

◆ 普通函数(自由函数)用法
int Add(int x, int y)
{
return x+y;
}
function<int (int,int)> f; // 或者 function2<int, int, int> f;
f = Add;
cout << "f(2, 3)=" << f(2, 3) << endl;
其中,模板参数的第1个int为返回值类型,后两个int为参数类型。

◆ 函数对象用法
class CStudent
{
public:
void operator() (string strName, int nAge)
{
cout << strName << " : " << nAge << endl;
}
};
function<void (string, int)> f; // 或者 function2<void, string, int> f;
CStudent stu;
f = stu;
cout << "f(\"hello\", 25)=" << f("hujian", 25) << endl;

◆ 成员函数用法
struct TAdd
{
int Add(int x,int y)
{
return x+y;
}
};
TAdd tAdd;
function<int (tAdd *,int,int)> f; // 或者 function<int (tAdd &,int,int)> f;
f = & TAdd::Add;
cout << f(&tAdd, 2, 3); // 如果前面的模板参数为值或引用,直接传入tAdd即可
其中,模板参数的tAdd *为类的实例的指针,当然也可以传入类的实例或其引用,只不过调用时需要做相应的修改。

使用function时,可以通过empty函数或与0比较来判断其是否指向一个有效的函数。如果function没有指向一个有效的函数,调用时会抛出bad_function_call的异常。function的clear函数可以使其不再关联到一个函数或函数对象,如果该function本身就是空的,调用该函数也不会带来任何问题。
以上介绍了function库的最基本的一些用法,关于function库的其他应用,大家可以参考《Beyond the C++ STL》。

2009年4月1日星期三

常用HTML转义符

在blogger里发贴、修改网页模板的时候,经常需要将一些符号转义才能正常显示,blogger这点确实非常不便...这里给出一个常用HTML转义符的参考:http://114.xixik.com/character/

2009年3月31日星期二

【原】Boost库之assign的使用

Boost库的assign可以帮助我们把一系列的值赋给容器,并且语法更加清晰和简洁。下面我主要以vector和map容器为例,介绍assign中比较常用的赋值方法。其他容器的赋值方法与此类似,故不再赘述。

1. 使用重载操作符+=
vector<int> vctTemp;
vctTemp += 1, 2, 3;
// 打印出1,2,3
copy(vctTemp.begin(), vctTemp.end(), ostream_iterator<int>(cout, " "));

2. 使用push_back
push_back(vctTemp)(4)(5)(6); 或者
push_back(vctTemp) = 4, 5, 6;
另外,如果某容器有push_front函数,也可以使用assign中对应的push_front。

3. 使用list_of
vector<int> vct2 = list_of(7)(8) (9); 或者
vector<int> vct2 = list_of(7)(8) (9) .to_container(vct2);
array<int, 3> ay = list_of(1)(2)(3); 或者
array<int, 3> ay = list_of(1)(2)(3) .to_array(ay);
stack<int> sk = list_of(1)(2)(3).to_adapter(sk);
注意:用list_of给容器适配器赋值时,必须使用to_adapter,否则无法编译通过。

4. 使用tuple_list_of
vector<tuple<int, string, int> > vctTuple = tuple_list_of(1, "hi", 2)(3, "hu", 4);
BOOST_ASSERT(get<1>(vctTuple[1]) == "hu");

5. 使用repeat
push_back(vctTemp)(7)(8)(9).repeat(3, 10);
其中repeat函数的第1个参数为重复的次数,第2个参数为参数的值。

6. 使用range
push_back(vctTemp)(7)(8)(9).range(vct2.begin(), vct2.begin()+2);
其中range(iterBegin, iterEnd)函数使用的数值范围为[iterBegin, iterEnd)。

7. 使用insert
map<int, string> mapTemp;
insert(mapTemp)(1, "Hello")(2, "world")(3, "crearo");

8. 使用map_list_of(只能用于map容器)
map<string, int> map2 = map_list_of("hefei", 1)("nanjing", 2)("wuhan", 3);

2009年3月30日星期一

【原】设计3+2之认识粒子

3D中有着很炫很吸引人的一项功能就是粒子系统,它在模仿自然现象、物理现象及空间扭曲上具备得天独厚的优势。(烟云、火花、爆炸、暴风雪或者瀑布、雨、雪、流水和灰尘等)随着功能的逐步完善,粒子系统几乎可以模拟任何富于联想的三维效果,同时为了增加物理现象的真实性,结合了空间扭曲能对粒子流造成引力、阻挡、风力等仿真影响。使其更加震撼我们的眼球。目前,粒子系统技术被广泛用于电影、电视及大型3D游戏地制作。还记得《蜘蛛侠3》中的可以随意变换并操控沙子的沙人吗,《指环王》里大型的战争场面,《最终幻想》中美幻的空间场景吗....
可以说你的想象力就是三维创作的领域!

放个很土很山寨的粒子尝试:

2009年3月29日星期日

【原】ArcGIS中最短路径的实现(二)

上次介绍了用几何网络实现的“最短路径”,姑且这么叫吧。这次我们用网络数据集实现真正的最短路径功能,跟上次一样,我们先准备数据。
  1. 先打开ArcCatalog,连接到目标文件夹,假定该文件下有一个名为road的道路图层。
  2. 在road图层上右键新建一个网络数据集,并按照其默认设置直至完成。
  3. 打开该地图的工作空间,把刚才新建的网络数据集添加工作空间中。
  4. 在网络分析菜单中选择新建最近设施点。

这时在工作空间里,可以看到多了一个名为“Closest Facility”的图层。它下面还有4个子图层,名字分别为“Facilities”,“Incidents”,“Barriers”,“Routes”。“Facilities”就是设施点图层,也就是目的点,“Incidents”的意思就是出发点,“Barriers”是障碍点,意思就是地图某条道路附近有一个障碍点,如果障碍点与道路距离在容限范围内,则表示此道路不通,“Routes”就是最终的结果。这样我们编程实现最短路径的思路就出现了:

  1. 添加出发点。
  2. 添加目的点。
  3. 生成最优路径,获取结果。

这里的添加出发点或者目的点,是往“Facilities”或“Incidents”图层上添加元素。获取结果也是从“Routes”中获取Polyline。往“Facilities”或“Incidents”图层上添加元素用到的主要方法是INALocator的QueryLocationByPoint函数,生成路径主要接口是INASolver和它的Solve方法。获取结果是按属性查找,因为“Routes”类其实就是一个图层类,只不过只是存在于内存,这个查找方法网上很多。

相关链接:ArcGIS中最短路径的实现(一)

【原】Boost库之timer的使用

我们在编程中有时需要计算运行某一段代码所花费的时间,通常的方法是通过计算该段代码首尾的GetTickCount的差值来获得。这种方法虽然可取,但需要调用两次GetTickCount函数,总让人觉得有些繁琐。Boost库的timer提供了对计时特性的封装,简化了代码的编写,并且它具有跨平台的优点。

Boost库的timer主要封装了timer、progress_timer和progress_display这3个计时类,使用起来非常简单,下面逐一介绍。

timer类的构造函数会在内部获得一个起始时间并开始计时,其elapsed成员函数会计算所消耗的时间,其restart函数重新开始计时。示例代码如下:
timer tx;
Sleep(1000);
cout << tx.elapsed() << endl;

progress_timer类是对timer类的进一步封装,使用起来更加方便,它会在析构函数中自动打印出所消耗的时间。示例代码如下:
{
progress_timer pro;
Sleep(1000);
}

progress_display类以图形化的方式给出了当前所花费的时间刻度占总时间刻度的比例。其构造函数为:
explicit progress_display(unsigned long expected_count, std::ostream &os = std::cout, conststd::string&s1="\n", const std::string & s2 = "", const std::string & s3 = "" );
其restart函数用于重新开始计时,count函数用于获得当前所花费的时间刻度,expected_count函数用于获得总的时间刻度。另外,progress_display类还重载了+=和前缀++操作符,用于增加当前的时间刻度值。示例代码如下:
progress_display pd(15, cout, "hello:\t", "hujian:\t", "Start:\t");
for (int i = 0; i < 15; i++)
{
Sleep(100);
++pd;
}

这3个类的实现比较短,均在timer.hpp和progress.hpp头文件中,大家有空可以阅读一下源代码,以加深对这3个类的理解。

2009年3月26日星期四

【原】关于Visual Assist X(VC助手)几个最新版本的比较与破解下载——更新到10.5.1715.0

下面归纳下VA近期几个版本的问题:

1557:对宏的支持不好,经常无法提示;跟以前的所有版本一样,注释超过一定行数就被“...”代替了,郁闷。

1561:比以前版本最大的改进就是注释能够显示完全,超爽;对宏的支持也好多了,但是在有些情况下宏的提示还是有问题,并且goto不到源代码。

1626和1640:VA工具栏耳目一新;增加了一些更加人性化的配置选项;但先天有一个超级大Bug,AutoText在系统是中文用户名的情况下不会自动提示(这个问题VA提供了一个变通的解决办法,参照相关文章1),而且听说在有些用户的环境下对中文的支持很不好(我用的时候没有发现问题)。后来又发现一个问题是当VC工程打开一天或者更久后,所有建议和颜色都会失效,不过这个ms是由于破解不彻底导致的。

1649:修复了1626和1640的一些重要Bug, 包括上文提到的系统中文名下AutoText失效和对中文支持不好的问题,并且开始了对VS2008的支持。但是我只试用了几分钟就又遇到了两个很让人郁闷的问题。第一个是注释格式错乱:(图1:1561的注释 vs 图2:1649的注释 )

1561的注释 1649的注释

第二个是高亮关键字这个过程效率很低,我在新打开一个文件的时候都是先看到字是黑色的,然后才变成蓝色或其他对应的颜色,这个过程看的一清二楚,让人非常不爽。

1711:这个版本是目前最新的(其实最新的已经到1715了,但据说1715的破解版不是很稳定,所以还是用回1711),但是1649的那两个问题依然存在。

所以对比之下我总结出的结论就是,如果不用VS2008,那么就选择1561,问题算是最少了,对于VA的最新版本,可以尝试一下,一定会有全新的感受,不过新鲜劲儿过了可能就只剩下失望了,让你不得不换回以前的老版本^_^;如果用VS2008,那么只能选择最新的1711。不过我们还是继续期待着tomato能够尽快推出更加稳定、性能更好、更适合中文用户的新版本。

Visual Assist X 破解版本下载地址:1561 1711

关于1649版本Bug的官方解答:http://www.wholetomato.com/forum/topic.asp?TOPIC_ID=8244
关于1640版本Bug的官方解答:http://www.wholetomato.com/forum/topic.asp?TOPIC_ID=7965
关于1626版本Bug的官方解答:http://www.wholetomato.com/forum/topic.asp?TOPIC_ID=7948

【原】Boost库之format的使用

Boost库的format提供了类似于C标准库函数printf的格式化字符串功能,并且它是强类型安全的。由于format重载了%操作符,因此,通过单次或多次调用%操作符可以非常方便地格式化字符串。
format的基本语法结构为:format(需要格式化的字符串 ) %参数1 %参数2 …%参数n。下面介绍format的几种使用方法。
1. 直接使用format
cout << format("%2% and %1% and %2%")%16 %"hello" << endl;
其中%1%表示第一个参数,%2%表示第二个参数,其他依此类推。另外,参数是可以复用的。

2. 使用format的str函数
format fmt("%2% and %1%")%16 %"hello";
string s = fmt.str();
cout << s << endl;

3. 使用全局的str函数
format fmt("%2% and %1%")%16 %"hello";
string s = str(fmt) ;
cout << s << endl;

4. 多次调用%操作符
format fmt("%2% and %1%");
fmt %16;
fmt %"hello";
cout << fmt << endl;

5.使用printf风格
cout << format("%d and %s")%16 %"hello" << endl;

6. 使用混合风格
cout << format("%2$s and %1$d")%16 %"hello" << endl;
其中%后面是参数的序号,$后面是printf风格的格式符。

另外,format还提供了一些其他的格式说明符。比如:%nt用于产生一个固定在第n列的\t;%nTx可以将x作为填充字符以代替当前流的填充字符(默认是一个空格)。当实际传入的参数个数与格式化字符串中需要的参数个数不一致时,format会抛出异常。举例如下:
cout << format("[abc%10t]") << format("[%10T*]") << endl;
try
{
cout << format("%1% and %2%") %16 << endl;
}
catch (exception &e)
{
cout << e.what() << endl;
}

最后谈一下使用format时需要注意的两点。一是使用默认的format风格(如%1%)输出浮点数类型时,只是将浮点数转换为对应的字符串,无法保证精度,如果需要保证精度,可以使用printf风格(如%f)输出浮点数类型;二是format不支持直接使用CString作为参数,需要先将CString转换为字符指针(如format("%1% ") %(LPCTSTR)szText)。

2009年3月21日星期六

【原】Boost库之tokenizer的使用

在tokenizer出现之前,如果我们要对一个字符串进行分割,可能要自己封装一个函数。如果有n种不同的分割规则,那么你要封装n个不同的分割函数……太麻烦了!现在好了,Boost库的tokenizer封装了统一的语法来分割字符串,并且提供了三种常用的分割方式,足以满足我们的绝大多数编程需求。
tokenizer主要由分割器和迭代器两部分组成。分割器用于指定字符串的分割规则,如果不指定任何分割器,则tokenizer默认将字符串以空格和标点(键盘上除26个字母(包括大小写)和数字外的其他可打印字符)为边界进行分割。迭代器用于保存字符串分割后的结果。下面着重介绍tokenizer的三种分割器。

■ char_separator是默认的分隔器,它以一组特定的字符来分隔字符串,其构造函数为:
explicit char_separator(); (默认构造函数)
explicit char_separator(const Char* dropped_delims, const Char* kept_delims = "", empty_token_policy empty_tokens = drop_empty_tokens);
其参数的详细说明如下:
◆ dropped_delims和kept_delims:是两个字符数组,这两个数组中的每个字符都是一个分割符。不同的是,dropped_delims中的分割符本身被丢弃,而kept_delims中的分割符本身作为一个单独的记号被保留在迭代器中。默认构造函数的dropped_delims为空格符,kept_delims为标点符号。
◆ empty_tokens:是否保留长度0的记号。它有两个可选值,keep_empty_tokens表示要保留空记号,而默认的drop_empty_tokens表示丢弃空记号。默认构造函数的empty_tokens为drop_empty_tokens。

■ offset_separator主要用于解析长度和格式都固定的字符串,如身份证或电话号码等。其构造函数为:
template<typename Iter> offset_separator(Iter begin,Iter end,bool bwrapoffsets = true, bool breturnpartiallast = true);
其参数的详细说明如下:
◆ begin和end:指向一个整数容器开始和末尾的迭代器,其中每个元素表示要分割的字段的字符数。
◆ bwrapoffsets: 如果字符串长度大于整数容器中所有字段长度的和,是否重复解析字符串。
◆ breturnpartiallast: 当字符串解析到末尾剩余部分的长度(注意:包括结尾的空字符)小于字段长度时,是保留还是丢弃剩余部分。

■ escaped_list_separator主要用于解析包含转义符、分隔符和引号的字符串。其构造函数为:
explicit escaped_list_separator(Char e = '\\', Char c = ',',Char q = '\"');
explicit escaped_list_separator(string_type e, string_type c, string_type q);
其参数的详细说明如下:
◆ e:为单个转义符或包含多个转义符的串。转义符后跟引号表示引号,转义符后跟n表示换行,连续两个转义符表示作为普通字符的转义符本身。
◆ c:为单个分割符或包含多个分割符的串,字符串以该分隔符为边界进行分割。
◆ q:为单个引号或包含多个引号的串,两个引号中间出现的分隔符不再作为分割标志,而是作为普通字符处理。

最后给出一组简单的测试题,大家既可以借此看看tokenizer的语法,也可以根据回答结果来考察一下你对tokenizer的用法有没有理解透彻。稍后我会在评论中给出正确答案。
a) string s = "hello, crearo-sw blog";
tokenizer<> tok(s);
for (tokenizer<>::iterator beg=tok.begin(); beg!=tok.end(); ++beg)
{
cout << *beg <<endl;
}

b) string str = ";!!;miaocl|zhangwh ||-hujian--terry|";
typedef tokenizer<char_separator<char> > tokenizers;
char_separator<char> sep("-;", "|", keep_empty_tokens);
tokenizers tokens(str, sep);
for (tokenizers::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter)
{
cout << "<" << *tok_iter << "> ";
}

c) string s = "20090321";
int offsets[] = {4,2,3};
offset_separator f(offsets, offsets+3, true, false);
tokenizer<offset_separator> tok(s,f);
for(tokenizer<offset_separator>::iterator beg=tok.begin();
beg!=tok.end(); ++beg)
{
cout << *beg << endl;
}

2009年3月20日星期五

【原】Team Logo

创作思路概要:
1.以CREARO-SW软件团队的英文首字母“S”为主体,体现本Team的软件开发相关内涵。
2.以蓝橙色为主色凋,两只交汇的箭头组成的“S“为主形体,蓝色代表科技、高端、时尚、而橙色体现着创意、
情、活泼,同时也寓意着团队中工程师和设计师思维的相互学习交融。
放图(原创作品,请勿盗链):

【原】svn服务器与客户端hooks脚本的使用

——主要谈提交前阻止空信息(pre-commit)和提交后自动发邮件(post-commit)这两个功能

本文用到的所有代码及工具下载:svn-hooks.rar
——包括pre-commit.bat,Post-commit.bat,blat.exe,maillist.txt等。

关于svn几个常用的hooks网上写的不少,相关代码被改的五花八门,很难有可以直接拿来用的(拿来主义总不像想象中的那么顺利...)。我这里只写Windows平台的,也不用python或者perl之类的需要装解释器的脚本,麻烦,只用bat,能达到目的不就行了嘛。

总的来说服务器脚本更实用一些,除了传入参数之外,更多参数可以通过svnlook命令来获得,所以能得到更多的信息来组织邮件内容;而客户端脚本虽说有传入参数比较多,但有些重要参数还是无法获得,所以并不好用。比如提交后自动发邮件的脚本,有些版本库我想实现只有管理员提交才发邮件,而其他人提交则不发邮件的功能。本来我想在管理员所用的客户端上加post-commit脚本,但很无奈版本库和提交文件列表两项参数无法获取(可能有绕弯的方法但我没找到),所以后来就在服务器脚本里加了对提交者的判断,从而达到了过滤的目的,也比较easy。
  • 提交前阻止空信息(pre-commit.bat)
这个比较简单,用svnlook log可以查询到log内容,判断它为空或者少于n个字符都可以返回错误并反馈到客户端,可参照附件Server目录下的pre-commit.bat。
  • 提交后自动发邮件(post-commit.bat)
主要实现思路是把提交版本的相关信息合成一封html邮件,再利用blat(一个著名的无界面邮件客户端)将邮件发送给配置好的邮件列表,相关附件为blat.exe、maillist.txt和Server目录下的Post-commit.bat。blat.exe最好放到系统盘System32目录下,这样在使用时就不用带绝对路径了,用之前首先要初始化一下,调用blat -install <server> <username> <try> <port>,<server>是smtp服务器的url,<username>是登录用户名,<try>是尝试重发次数,<port>是smtp发送端口,比如blat -install 192.168.1.254 xxx@crearo.com,后面两个参数如果不需要改可以默认。

最终发邮件时调用:blat "%LOG_FILE%" -tf %MAIL_LIST% -f %SENDER% -s "[svn] %REPOS_CP%, rev %REV%, %AUTHOR%" -base64 -charset Gb2312,这是针对发送邮件不需要认证的的命令。如果服务器需要进行用户认证,那么就要加上-u <username> -pw <password>,即用户名和密码。经过我的调研发现,Gmail不能用,因为它需要SSL认证,要用也可以,需要配合stunnel一起使用,太麻烦了;163邮箱需要认证,因此要带上用户名和密码;而创世内部邮箱无需认证,所以最终还是选用了公司邮箱,其他邮箱没有再作调研。最后snv自动发送的邮件截图如下:


其实除了发邮件,还可以根据自己的需要添加其他功能脚本,比如向公司内部即时通信软件发消息等,沟通效率会更高。这就可以任由你来发挥了,呵呵。

svn hooks科普教材:
http://www.worldhello.net/doc/svn_hooks/svn_hooks.mm.htm

2009年3月18日星期三

【原】引玉系列之“启航之旅”实习生计划海报设计心得

创意以及技巧上的东西就不多说了,主要写下整体设计思路及制作过程。
首先由“启航之旅”进行分析创意,设计草图,主要画面构思:海天一线的蓝色画面,蓝天上的白云,水面上的白帆。确定了思路之后着手进行海报制作:


1. 新建文件,确定画面色调,模拟天空水面。


2. 在已确定的色调基础上进行水面波纹效果制作。主要运用图层模式,做多图层的叠加效果,让水面和波纹融为一体。

3.这时候,水面的感觉还不够清澈,没有深度感。对其做光照处理,模拟真实水面的光线折射效果。

4.做水面上的白云,找合适的图片用蒙版进行编辑融合,然后用画笔工具进行局部及边缘调整,或者按所需要的形状重新绘制。PS自带的圆头笔刷,注意云彩的走向以及结构即可。

5.增加高空的云彩,根据透视原理及光的漫反射分析,这里的云层应该更加透明一些,饱和度略低于水面上的云。制作方法同上。

6.添加一个光晕效果,丰富画面。

7.在天空和水面之间加入一片绿地,标识地平线。弱化中间的部分,强调透视。
8.按照最初的构思寻找合适的帆船素材,抠图。


9.调节至合适大小,放在画面的预留位置上。
10.对船和水面进行合成,主要是处理船身的投影,以及驶过划开的波浪。

11.添加画面元素,空中的飞机,水面飞鸟。找合适的素材进行抠图处理。

12.对添加的画面元素进行合成加工,如飞鸟的倒影,飞机划过天空的尾气。
到这一步,整个海报画面已经基本完成。在以上的步骤中不断对画面整体色调进行微调。

13.按设计草图添加画面的主题文字内容以及辅助文字部分,完成整个海报的制作。