WinxGui Official Blog

2006年9月的存档

WINX与ATL/WTL/MFC的关系,以及跨平台问题

说WINX基于ATL/WTL,其实不是准确的说法。实际上WINX的最核心组件(Windows、Dialog、Control)与WTL没有任何关系。只是WINX的句柄类(CWindow、Gdi句柄如CPen等)、资源类(CMenu等)是WTL的实现。

虽然说从重用角度来讲,WINX确实是:ATL -> WTL -> WINX。但对于WINX的性能是不需要担心的。WINX之所以基于WTL,完全是因为并不希望重复制造轮子。但是WINX的窗口机制是独特的,完全区别于现有各种界面库。对COM的连接点事件(ConnectPoint)更是比ATL好得多,使得C++可以如VB、C#一般方便地接收来自ActiveX控件的事件。

我在开发WINX的时候,参考了众多的界面库,如:MFC、ATL/WTL、QT、wxWidgets、SmartWin++,还有sourceforge上的win32gui、vgui等。

我所遇到的第一个问题,是兼容谁的问题。这里的兼容主要是指使用界面的兼容。这个问题不是谁说了算。看看google趋势:


可以看出,MFC、QT用户占了绝大多数。这就为WINX的开发建立了基调:尽量让MFC、QT用户感到熟悉、感到Happy。

另外,我发现一个值得注意的问题:几乎所有的库均有一个“不良倾向”,就是让自己包罗万象,给用户一个完整的解决方案 —— 网络、界面、自动化、XML、OLE等等。 特别是QT、wxWidgets,这种倾向及其明显。

为了明确我不是万能的,WINX不是万能的,在开发之初,我就给WINX一个规则:接纳现有的库,如果不能够提供得更好,就告诉(建议)用户用什么。如果某个问题有多个卓越的解决方案,那么,用户可以自由选择其中一个。

所以,在WINX中,库的关系是平行的:
 WindowSDK:Gdiplus (GDI+)、MSXML、等等
 Xerces-C
 DirectX
 ATL/WTL
 MFC
 STL
 Boost
 Loki
 …
 WINX

而不是:
   /— WindowSDK、Gdiplus、MSXML、DirectX
WINX —- ATL/WTL
   \— STL、Boost、Loki、Xerces-C

试图让自己成为用户唯一所见,这是一个危险的想法,我认为是这样。

举个例子,用户希望读取xml文件。那么用MSXML,还是用Xerces-C,还是expat?我不能确定用户想要什么。有一点可以肯定的是,WINX不会开发出另外一个XML Parser。如果WINX的代码需要一个XML Parser,我会尽量在一个比较抽象的层次,为以上三者提供一个共同的界面(当然,不是抽象所有的功能,只是WINX所需要的),就如我们抽象WINX_ASSERT一样。

我们回头看WINX_ASSERT这个例子。WINX中是这么实现的:

#if defined(ASSERT)
#define WINX_ASSERT(e) ASSERT(e)
#elif defined(_ASSERTE)
#define WINX_ASSERT(e) _ASSERTE(e)
#else
#ifdef _DEBUG
#define WINX_ASSERT(e) assert(e)
#else
#define WINX_ASSERT(e) 0
#endif
#endif

这意味着什么?ASSERT来自MFC,_ASSERTE来自MSCRT(参见crtdbg.h)、assert来自C标准库。这里没有检测ATLASSERT,是因为ATLASSERT就是_ASSERTE。

尽管实现ASSERT功能并不复杂(肯定远远简单于实现XML Parser),但是我决定还是不自己去做。原因很简单:我没有打算对它作出改进。

最后我们谈谈跨平台。其实我一直在尝试找到一个方案,可以把平台的差异屏蔽。然而,有一点让我感到不安,因为没有谁可以真的做到平台无关,无论我作出多少努力。我要在Linux平台(甚至更多的平台)提供提供Gdiplus(Mono在做这件事)?DirectX?COM?OLE?还是我去告诉用户,不要用Gdiplus,不要用OLE,不要用COM,喏,这里有一个跨平台的方案,你照着办吧。

我会尝试让WINX跨平台。当然我相信只是最核心部分值得这样做。问题的重心仍然在于,你无权阻止用户喜欢用Gdiplus来开发。所以,跨平台的方案,永远有很多种。

评论

对比WINX与MFC、WTL

尽管对MFC有这样那样的批评(这其中也包括我本人),但是MFC无疑是C++ GUI领域最成功的。WTL源于ATL,由于它的灵活、高效,而赢得了不少人的赞赏。然而要说WTL获得了成功,个人认为言之过早。看起来WTL似乎是“叫好不叫座”,并没有多少成功的产品是真正基于WTL进行GUI开发。

仔细分析一下,这样的结果并不奇怪。虽然MFC产生的代码笨拙,但是MFC的成功除了Microsoft大力推动之外,在于它生逢其时。它简陋的可视化开发界面,和自动代码生成,在当时基本上都是全手工界面开发的情况下,立即获得了青睐。而WTL恰恰是“生不逢时”,它出现于MFC大行其道之时,并且它的关注点在于“灵活,高效”,没有向导支持,所有代码手工完成,这无疑是一种倒退(MS可以强行开发基于WTL的可视化环境,但是WTL的特性并不太适合这样做,因为它“太灵活”了,这是它的优点,也是它的致命伤)。所以WTL仅仅获得少数有特殊需求的,对生成的代码尺寸非常注重的开发人员的推崇,但是Microsoft官方却弃之不顾(试为MS设想WTL可能的推广策略),其中道理不难理解。

WINX关注一个目标:简单而高效(MOST SIMPLE BUT EFFECTIVE)。WINX肯定了WTL技术上的先进性。故此WINX基于WTL,大量重用了WTL的代码。但是WINX除了高效外,更关注的是简单(SIMPLE)。

为了使得界面开发对程序员而言更为简单舒畅,WINX关注点不是在技术上,而是在对开发手段的革新上。WINX重用WTL只是一种手段。WINX重用的是它的实现,不是它的使用界面。

针对MFC的“长处”——半可视化开发,WINX引入了类似Delphi中的属性编程,使得多数常见的效果可以以窗体属性的方式进行表示。尽管目前尚且没没有专门针对WINX进行可视化界面开发的工具,但是它是WINX的发展方向。而且即使是在目前的简陋条件下,你仍然可以象MFC程序员一样,进行半可视的界面开发。

WTL脱离MFC程序员的习惯有点远了。这也是它让初学者畏惧的一个原因。WINX其实是更接近MFC的WTL:它提供了更接近于MFC的使用界面,并努力使得MFC代码可以更加容易地移植到WINX中。关于MFC代码移植,我们已经在WINX中提供了几个样例。有一点你需要理解的是,WINX并不十分关注将一个MFC应用程序移植到WINX下,因为那只有学术价值,但并不具备商业价值,我个人并不推荐你这样做。关于MFC移植,我的侧重点始终在于移植一些具备可重用性较高的MFC代码,例如MFC编写的控件等。

WINX可以取代MFC吗?对于这个问题我只能笑笑。我没有这个奢望。对于我而言,只是试图把我对C++程序员的几大困惑(内存管理、界面编程、自动化——Automation)的解决方案公诸于世,让更多人得益于它而已。从这个意义上来说,WINX只是侧重点在于提供界面开发的解决方案,但它不只是局限于界面库的范畴。

评论