好久没更新博客了,不是偷懒,而是考试前期太忙了,什么作业都要开始交,上周末就完成了三门课的实验报告,还有一部分课要提前考试。比方说最无聊的文献检索。没办法进行新的学习。等考试结束后,大概就要全面攻RHCE了。

今天验收Windows大作业,这个程序让我花费了很多力气,但是验收时并不怎么顺利。虽然结构和类封装让老师对我的C++水平印象深刻,但是在一段动画上却出了问题,动画不够流畅。

这段动画是一个辅助型的效果,一个Google的Logo的移动动画,要有透明效果。这段动画我完全没有采用过去常用的动画在时间类回调函数里做法,而是把动画做在WM_PAINT里,时间类回调函数仅仅只是更新Logo的位置,并请求刷新界面。问题就出在这里,刷新信息是放在消息队列里的,程序必须接收到重绘消息才会绘图,如果重绘消息过多就不会多次重绘,而是只重绘一次就草草结束(有点掏浆糊)。显然13帧的重绘消息程序是不可能一一处理(虽然我的电脑性能较好,程序处理了大部分信息,如果没有经验,是断然看不出他的不流畅),因此跳帧就出现了。解决方法还是按照老路子走,直接在时间类回调函数内取得HDC,让他动,流畅性将大大提高。

另外,之所以有时界面会闪烁,根本原因是重绘前的一瞬间,界面这块区域被涂白了(通常是因为发送了EraseBackground消息或是BitBlt最后一个参数是WHITENESS),涂白后又立刻在上面绘图,Windows的图形速度并不是很快,这一瞬间还是能被人眼捕捉到,这样就看上去在闪烁。对此的解决方案是,如果是因为EraseBackground的话,请尽可能限制Invalidate系列函数的使用,即使要用,也要尽可能把他的最后一个参数设置为FALSE,如果图像较复杂就干脆用兼容DC做缓冲,使用兼容DC的话是永远没必要EraseBackground的。如果是因为BitBlt的话,那么就尽可能缩小WHITENESS的区域,不让其实就不需要WHITENESS的区域变成WHITENESS,这样闪烁基本上就可以抑制住。再次强调,闪烁不是因为过快频率的重绘,也不是因为过大范围的重绘,而是过多次的瞬间残留影像,一定要对症下药。

虽然验收不顺利,成绩仅仅是A-,但是能获取这么多经验,还是好的。本周五晚上还要在忙活一晚,把程序的这些问题全部去除,争取第二次验收得A。

关于C execlp函数的理解

2010年9月29日 19:05

execlp(從PATH 環境變量中查找文件並執行)

相關函數
fork,execl,execle,execv,execve,execvp
表頭文件 #include<unistd.h>
定義函數 int execlp(const char * file,const char * arg,……);
函數說明
execlp()會從PATH 環境變量所指的目錄中查找符合參數file的文件名,找到後便執行該文件,然後將第二個以後的參數當做該文件的argv[0]、argv[1]……,最後一個參數必須用空指針(NULL)作結束。
返回值
如果執行成功則函數不會返回,執行失敗則直接返回-1,失敗原因存於errno 中。
錯誤代碼
參考execve()。
範例
	/* 執行ls -al /etc/passwd execlp()會依PATH 變量中的/bin找到/bin/ls */
#include<unistd.h>
main()
{
    execlp(“ls”,”ls”,”-al”,”/etc/passwd”,(char *)0);
}
//執行
//-rw-r--r-- 1 root root 705 Sep 3 13 :52 /etc/passwd

其实上面的描述很奇怪,如果能从PATH中找到第一个参数指定的文件,那何须第二个参数呢,没意义啊?

然后Google了下,看到了www.lslnet.com/linux/f/docs1/i34/big5260214.htm中别人同样的质疑。

这张帖子的楼主索性猜测:execlp函數在實際執行的時候根本沒有用到第二個參數。

说真的,这个猜测过于草率了。

楼下有一张回帖给出了一个反例:execlp("ls","flw","-?",(char *)0)。

应该是execlp("ls","flw","--help",(char *)0)吧,ls是Linux命令,-?是Windows的写法,不能同时运用,疑为他的笔误。这句语句在我电脑上的效果:

Usage: flw [OPTION]... [FILE]...

List information about the FILEs (the current directory by default).
Sort entries alphabetically if none of -cftuvSUX nor --sort.
 
自已在终端上永远试不出这个结果,因为明明调用的是ls命令,不可能显示出Usage: flw来。
再仔细看看上面关于这个函数的描述“然後將第二個以後的參數當做該文件的argv[0]、argv[1]……”
我猛然想到了以前说过main函数是可以传入参数的,我于是尝试了这样的代码:
	int main(int num_args,const char* args[])
{
	for(int i=0;i<num_args;++i)
	{
		std::cout << args[i] << std::endl;
	}
        return 0;
}

在终端而不是IDE里运行这个程序,运行的时候给他带点参数,结果自己打的命令出现的在args[0]的位置,后面的参数出现在了args[1],args[2],args[3]....的位置,可见C程序总会把你运行这个程序用的命令传入args[0]。这样这个问题就解开了。execlp第一个参数是让程序从PATH中找到指定程序运行,第二个参数将传入这个程序的args[0]。

execlp("ls","flw","--help",(char *)0)出现Usage: flw,是因为ls命令在显示帮助的时候会动用args[0],这么设计很正常,因为如果用户打错了命令,总希望用最接近他命令的方式指导他怎么做才对,直接使用他的命令是最方便的。平时args[0]几乎总是等于ls,这是因为ls在PATH中,没必要指示他的位置,但如果使用/bin/ls这样的命令,就可以看出来了。

twitter logo GDI绘制

2010年9月27日 07:09

这次的作业,用GDI绘制任意卡通图,我不会画什么卡通图,于是就画了个twitter的logo。

按1(MM_TEXT),7(MM_ISOTROPIC),8(MM_ANISOTROPIC)会有不同的GDI映射。缩放窗口可以看出他们的区别。

继续阅读

相信C++中Private和Protected继承是最冷门的语法之一吧,以至于以后大多数以C++语法作为模板的语言都没有继承这个语法。我C++学的不算差,学完后几乎每学期都在使用,但是也把这个语法点忘的差不多了。不过今天在和Deltamaster讨论C++如何选择性继承的时候(只继承一部分接口,另一部分接口不继承,如果用户去使用这些不被继承的接口,必须在编译期间报错),他提出了用Protected或Private继承的思想。实现如下:

#include<iostream>
class Parent
{
public:
	void get()
	{
		std::cout << "get" << std::endl;
	}
	void set()
	{
		std::cout << "set" << std::endl;
	}
};
class Child:protected/*private*/ Parent
{
public:
	void get()
	{
		Parent::get();
	}
};
int main()
{
	Child c;
	c.get();
	//c.set();
	system("pause");
	return 0;
}

允许子类继承父类的get方法,而不继承set方法,就是先让子类Protected(或Private)继承父类,使父类所有接口在子类中一律为Protected(或Private),然后重写一个Public的get方法,在其中调用父类的get方法即可,这样就可以做到正常调用子类继承自父类的get方法,而如果调用子类继承自父类的set方法就会编译出错。

以上代码是在Microsoft Visual Studio 2010编写并编译的,本来想在Linux下用Eclipse写,但总感觉CDT有BUG,编译通不过,所以还是在Visual Studio下写。下次装Eclipse再也不装CDT了。

最近在Linux下开发,由于长期使用Visual Studio 2010,对代码提示功能情有独钟,现在在Linux下,使用Eclipse做开发,当然免不了怀念Visual Studio强悍的代码提示,于是在网上搜索了一些文章,整理出关于Eclipse代码提示功能设置的方法。

 

Java:

增强Eclipse 的代码提示功能,具体怎么样来配置?下面开始说步骤:
1. 打开Eclipse,然后“window”→“Preferences”
2. 选择“java”,展开,“Editor”,选择“Content Assist”。
3. 选择“Content Assist”,然后看到右边,右边的“Auto-Activation”下面的“Auto Activation triggers for java”这个选项。其实就是指触发代码提示的就是“.”这个符号。
4. “Auto Activation triggers for java”这个选项,在“.”后加abc字母,方便后面的查找修改。然后“apply”,点击“OK”。
5. 然后,“File”→“Export”,在弹出的窗口中选择“Perferences”,点击“下一步”。
6. 选择导出文件路径,本人导出到桌面,输入“test”作为文件名,点击“保存”。
7. 在桌面找到刚在保存的文件“test.epf”,右键选择“用记事本打开”。
8. 可以看到很多配置Eclipse的信息
9. 按“ctrl + F”快捷键,输入“.abc”,点击“查找下一个”。
10. 查找到“.abc”的配置信息如下:
11. 把“.abc”改成“.abcdefghijklmnopqrstuvwxyz(,”,保存,关闭“test.epf”。
12. 回到Eclipse界面,“File”→“Import”,在弹出的窗口中选择“Perferences”,点击“下一步”,选择刚在已经修改的“test.epf”文件,点击“打开”,点击“Finish”。该步骤和上面的导出步骤类似。
13. 最后当然是进行代码测试了。随便新建一个工程,新建一个类。在代码输入switch,foreach等进行 测试。你立即会发现,果然出了提示,而且无论是敲哪个字母都会有很多相关的提示了,很流畅,很方便。
 
C/C++:
 
打开终端:输入:$ gcc- v
得到类似的:gcc 版本 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)
很容易就看到你当前使用的版本了。
启动Eclipse.进入:Windows-->Preferences-->C/C++找到Environment。增加两个变量:
CPLUS_INCLUDE_PATH: /usr/include/c++/4.1.3(我的gcc版本) 
C_INCLUDE_PATH: /usr/include
 
C/C++的代码提示只在.和->下触发,虽然没有Java下这么强大,不过也够了。因为这里是代码提示最容易发挥威力的地方。
 
补充:Ctrl+Space也能触发代码提示,而且功能更强,几乎总能给出符合需求的提示,不过我不知道如何才能让Eclipse在更多情况下自动触发提示,如果能做到,Eclipse就和Vistual Studio一样强了。
 
本文参考:
http://developer.51cto.com/art/200907/136242.htm
http://blog.chinaunix.net/u/21684/showart_462486.html