虽然很痛恨MFC,但还是要经常使用MFC开发界面,虽然MFC怎么怎么的不好,但还是可以应付一般的界面要求,而且其运行效率也可以接受,关于这一点,它在WINDOWS3.1之时,就已经能胜任了,并且在下现在使用MFC,基本上也能随心所欲了,想怎么整就怎么整。为了减少以后浪费在MFC上的时间,我决定重构一套著名的MFC上的界面库。界面库这个东西,大家都知道,其各种美观的界面,基本上都是一笔一笔画出来的,代码中大量地使用了DC的各种操作,不可避免,就一再出现了好比以下类似的代码:
这些代码,既无味,写起来又容易出错,它存在3个很明显的问题:1、SelectObject使用了类型转换,一不小心,自然就转换错了,MFC中通过对象指针,内部做了转换,避免了这个问题;2、要将旧有的GDI对象选回DC中,很容易就遗忘了这一步代码,并且如果要同时操作几个DC的时候(这种情况较少见),在选回旧GDI对象时,那就更容易出错了;3、还要删除对象,这个,MFC中通过GDI对象的构造函数来消除这个问题。这样也罢了,但还有一个问题最让人不能忍受的,就是,代码中要定义一个旧的GDI对象变量,以最后选回设备环境之中,因为我最讨厌定义新变量,新函数了,每次都要变量名和函数名琢磨半天,当然,最讨厌的还是编写重复的代码了。于是,我决定编写一个类,以免总是要写这些毫无新意的重复代码,希望这个类是这样使用的:
不需要定义旧的GDI对象变量,画图完成之后,也不需要选回设备环境之中了,也不需要手工删除之前创建的GDI对象,一切,这个类都帮你代劳了,咦,这么神奇,它是如何做到的,自然是析构函数,再次向伟大的析构函数致以最高敬意。这个类,比之于刚开始的手工打造,它需要执行构造函数,以保存hDC到内部成员变量,很明显,多了一步赋值操作,此外,可以预料,这个类里面应该还有其他的初始化操作,这又是不可避免的多余代码。当然,这里的多余,都是我能接受的,我也深知,既要马儿,又要马儿不吃草,那是不可能的神话。但是,在实现这个类的时候,我想了种种办法,包括模板元编程也祭上了,始终还是存在其他多余的操作,再次审视刚刚开始的一段代码,不得不承认,它丑是丑了点,但执行的效率确实真他妈的高,而且所占的空间也很少,全部没有一丁点多余之处。好了,进入我们的类的实现。
整个类的定义的还是很直观。只是那一组创建GDI对象的成员函数,显得有点格格不入,根据单一职责原则,实在不应该加入这些东西,但是,加入这些操作,确实会给使用的时候带来极大的方便。至于禁用了拷贝和赋值函数,感觉有点多此一举,但是为了满足某些C++洁癖者的强迫症,我还是做了妥协。这个类其他代码的实现,相当简单,我就不赘述了。
公道自在人心,这个类在选入选出GDI对象,毫无疑问,确实方便安全,但是它以牺牲执行效率和空间为代价。代码编写,不外乎是在做各种各样的权衡,有时付出类型安全,以换取更大的灵活性;有时又以付出灵活性,以换取类型的安全;有时以通用性换取效率;有时又要以效率换取通用。不能简单地说这种权衡好不好,只能说更加合适而已,在某一处上,比较强调什么,就以牺牲其他的特性来得到,谨记80%、20%的原则。C++的深入人心,在于它不剥夺程序员选择的权利,同时它又提供了丰富的特性,以供你做各种各样的交换。通用、灵活、效率、安全,这四者总是不可协调的矛盾。MFC框架的最大错误就在于:牺牲了很大很大的灵活、效率、通用,最后只获得了一点点类型安全,这无疑是失败的交换。
posted on 2012-06-01 10:56 华夏之火 阅读(1223) 评论(5) 编辑 收藏 引用
GDI对象有对应的MFC类,选择器选择新的对象,增加一个方法reset,功能是选回老对象,以在任何时机可以调用,而在析构函数实现中调用reset即可。 回复 更多评论
不希望代码只限于MFC中。关于reset的方法,之前也考虑过,但觉得没有太多的必要,现在类中多增加一个可有可无的方法,都觉得很难受。@春秋十二月 回复 更多评论
呵呵,你的类接口是句柄就行,在win32中一样可用,反正我觉得你的选择类创建GDI对象,那是不明智的做法。 回复 更多评论
不用某个方法,不等于不存在这个需求和必要性。随着时间推移,当改进完善你的类时,就会作出变化的。 回复 更多评论
确实创建GDI对象,是有点不明智,但使用起来,确实很方便,它是创建了GDI对象之后,就选入DC中,最后析构函数中或者再选入新的对象,会被选出来,然后给予删除。至于那个reset,你说的也有道理,但是原本的职责中,本来就不想给用户提供reset的机会@春秋十二月 回复 更多评论
Powered by: C++博客 Copyright © 华夏之火