星期一, 九月 11, 2006

003 - 对比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只是侧重点在于提供界面开发的解决方案,但它不只是局限于界面库的范畴。

星期六, 九月 02, 2006

002 - WINX概览:高级特性

*) 进程间通讯(IPC)
 –拖放/复制粘贴
 –IDataObject
 –暂时屏蔽

*) 自动完成(AutoComplete)
 –Edit/ComboBox控件的自动完成
 –可保存历史到Windows注册表或者文件。

*) XP风格化
• Common Control
 –用InitCommControls()和manifest文件搞定。
• User Custom Control
 –#include "winx/Theme.h"
 –需要引入theme,自己绘制出XP风格的界面。
• Menu
 –用WINX_APP_MENU指定XP风格(建议选自动),或者用WINX_APP_LOOKNFEEL。
 –暂时屏蔽
• WebBrowser
 –ActiveX控件中,IE控件的XP风格化需要调用IE控件相关接口支持。

*) 让Win2000支持XP Style?
• 这个问题我这样看:既然用户选择了Windows 2000,说明他喜欢2000的精简风格,那么你又何必自作多情非要把你自己喜爱的XP风格强加给他?
• 风格一致性。

*) 自动化支持(Automation)
• #import
 –编译器的支持
• DispObject
 –Invoke 的包装
 –暂时屏蔽
• 接收连接点事件
 –DispEventBaseImpl
 –DispEventSimpleImpl
 –WINX_SINK_BEGIN
 –WINX_SINK_DEFI
 –WINX_SINK_END

002 - WINX概览:窗口行为(WindowBehavior)

*) 窗口行为
• 可以施加于任何窗口上的行为特征。
• WINX_BEHAVIOR
• 目前支持的行为列表
 –DefaultBehavior(无行为)
 –Moveless(不可移动)
 –WithinScreen(不可出屏幕)
 –LimitScreenTop/Left/Right
 –AutoHiddenTop/Left/Right(在上/左/右方自动隐藏)
 –AutoHiddenAnySide(自动隐藏)
 –FullScreenDockable(全屏停靠在窗口的左/右方)

*) 窗口行为的切换(Switch)
• BehaviorPermit
 –是否允许一个行为
 –即:在某种行为与DefaultBehavior之间切换
• BehaviorSwitch
 –在多种行为之间切换

002 - WINX概览:属性(Property)

*) 属性
• 基于属性的编程,容易向可视化发展。
• Delphi中优良的用户体验
• 区别于Delphi:如果某个特性没有使用,不会带来额外的代价。

*) 属性的命名规则
• 规则
 –WINX[_适用范围]_属性[_属性子类]
  • WINX_BKGND_PATTERN
   –其中,BKGND为属性,PATTERN为属性子类。
  • WINX_APP_ICON
   –其中,APP为适用范围,ICON为属性。
  • WINX_SYSICON
   –有时,为了减少宏名长度,在属性子类可以表意的情况下,可以省略属性。如:WINX_SYSICON,完整名应该称为WINX_ICON_SYSICON。
• 适用范围
 –WINX_XXX
  • 该属性所有窗口均适用
 –WINX_DLG_XXX
  • 该属性只在对话框类中使用。
 –WINX_APP_XXX
  • 该属性属于Application属性,应该在WinMain函数中使用。这类属性比较特殊,属于全局设置,作用于所有窗口。
 –......

*) WINX支持的属性列表
• 快捷键(Accel)
• 窗口图标(Icon)
• 窗口背景(Bkgnd)
• 窗口子控件统一背景(CtlBkgnd)
• 窗口Resize最小大小(MinInfo)
• 窗口布局(Layout)
• 窗口锚点(Anchor - todo)
• 应用程序图标(AppIcon)

*) WINX_ACCEL
• WINX_ACCEL
 –指定一个窗口的快捷键表
• WINX_DLG_ACCEL
 – 对话框及其子控件支持快捷键,默认不支持。
• TestTranslateAccel
 – 快捷键派发机制的修正。因为父窗口可能截获子窗口的快捷键。故此提供一个修正机会。

*) WINX_ICON
• 设置窗口的图标
 –WINX_ICON
 –WINX_ICONSM
 –WINX_SYSICON
 –WINX_SYSICONSM

*) WINX_BKGND
• 设置窗口背景
 –WINX_BKGND_COLOR
  例:WINX_BKGND_COLOR(COLOR_WINDOW);
 –WINX_BKGND_BRUSH
  例: WINX_BKGND_BRUSH(GRAY_BRUSH);
 –WINX_BKGND_PATTERN
  例:WINX_BKGND_PATTERN(IDB_BKGND);
  功能:以资源文件中的一幅位图作为窗口背景
 –WINX_BKGND_NULL
  功能:透明背景。

*) WINX_CTLBKGND
• 类似于WINX_BKGND,但是是统一设置某类型的子控件背景。
 –WINX_CTLBKGND_COLOR
 –WINX_CTLBKGND_BRUSH
 –WINX_CTLBKGND_PATTERN
 –WINX_CTLBKGND_NULL
 –WINX_CTLBKGND_NULL_ALL

*) WINX_MININFO
• 设置窗口的最小SIZE
 –WINX_MININFO
 –WINX_MININFO_PT
 –WINX_MININFO_DEFAULT

*) 设置窗口布局
• 提供以下方案:
 –WINX_DLGRESIZE_BEGIN
 –WINX_DLGRESIZE
 –WINX_DLGRESIZE_END
• 这是利用WTL 提供的DLGRESIZE_MAP 实现,使用上略有简化。

*) WINX_APP_ICON
• 设置应用程序图标。
• 这将使得所有有标题的弹出窗口自动设置了该图标(除非该窗口使用WINX_ICON自己设置了图标)。
• 包括MessageBox。

002 - WINX概览:消息(Message)

*) 消息分派(DispatchMessage)
• 消息分派机制是WINX的特色之一。
• 区别于WTL或者MFC,你不需要主动写一个消息分派的映射表。
• WINX易用性的第一体现。
• 高性能
 –WINX 为了实现消息分派使用了一个庞大的虚表?NO !
 –对比产生的汇编代码表明,WINX 的消息分派产生的代码比WTL 和MFC 更为短小精悍。

*) WINX和WTL消息分派的比较
• 各有特色
 –WTL:强灵活性,容易进行第三方的功能扩展。缺点是看起来比较丑陋。
 –WINX:强调易用性,并且实现了用户不需要某个特性时无额外开销。故此,系统可以不断的进行新特性的添加(但是缺点是不能以第三方的方式添加—— 注:当然你可以按WTL 的方式进行功能扩展,在WINX 中这是允许的,但与WINX 的设计理念有背)。

*) 消息分类
• 位置事件(MouseEvent)
• 焦点事件(Keyboard、Accel、Command)
 –目标的不确定性,是焦点事件(Focus Message)最显著特征。
• 绘制事件(Paint/NcPaint/EraseBkgnd等)
• 定时事件(Timer)
• 通知事件
 –子通知父
 –系统通知
 –广播

*) 命令分派(Command)
• 命令事件
 –WINX_CMDS_BEGIN[_EX]
 –WINX_CMD
 –WINX_CMD_EX
 –WINX_CMDS_END[_EX]
• ForwardCommand
 –WINX_CMDS_BEGIN_EX/END_EX 配对,区别与WINX_CMDS_BEGIN/END 的是,如果消息自身没有处理,会发给活动的子视图处理。

*) 命令状态(UpdateUI)
• WTL 的命令状态维护机制不错,但是ModalDialog 不完全支持该机制。主要的问题在于没有OnIdle 消息。
• WINX的UpdateUI基于WTL的命令状态维护机制实现,并作出改进。

*) 键盘与快捷键(Keyboard&Accel)
• 和命令一样,属于焦点事件,有事件的目标窗口不确定性。
 –考虑用况:整个应用程序支持Undo/Redo,但是程序某个时刻处于一个Edit控件中,此时希望Undo/Redo是Edit控件的文本,而不是应用程序一级的Undo/Redo。
• 解决方案:
 – 使用ForwardCommand
 – 使用TestTranslateAccel (见后文)

*) 通知消息分派(Notify)
• WINX_NOTIFY_BEGIN
• WINX_NOTIFY
• WINX_NOTIFY_END

*) 反射(Reflect)
• WINX_REFLECT
 –反射,即将子窗口发给父窗口的消息返回给子窗口自己处理。反射机制通常用于解耦。
• WINX_REFLECT_CMD
• WINX_REFLECT_CMDS_BEGIN
• WINX_REFLECT_CMD
• WINX_REFLECT_CMDS_END
• WINX_REFLECT_NOTIFY
• WINX_REFLECT_NOTIFY_BEGIN
• WINX_REFLECT_NOTIFY
• WINX_REFLECT_NOTIFY_END

*) 鼠标滚轮消息
• WM_MOUSEWHEEL
 –Note: SetFocus();

002 - WINX概览:窗口类(WindowClass)

*) 窗口类(WindowClass)的注册
• MFC、WTL弱化了窗口类的注册,与此相反,WINX强调窗口类概念,并要求用户主动注册窗口类。
 –表面上看,WINX的用法比MFC、WTL繁琐了(多了主动RegisterClass过程),但是深究下去,你将发现这恰恰是WINX推崇可视化界面开发的关键点。
• 窗口类注册相关
 –WINX_CLASS
 –WindowClass::RegisterClass
• 只有普通窗口、窗口超类(Superclass)需要注册。子类化窗口、普通对话框不需要注册。
 –RegisterClass 相关的例子:
  • 普通窗口
  • 超类(Superclass )
  • 对话框超类

*) 控件列表
• Static/Button/Edit/ComboBox
• ScrollBar/FlatScrollBar
• ListBox/DragListBox
• ListCtrl/HeaderCtrl/TreeCtrl
• ToolBarCtrl/ReBarCtrl
• SliderCtrl(即:TrackBarCtrl)
• SpinButtonCtrl(即:UpDownCtrl)
• TabCtrl/ToolTipCtrl/StatusBarCtrl/ProgressCtrl
• HotKeyCtrl/AnimateCtrl/IPAddressCtrl
• DateTimeCtrl/MonthCalCtrl
• ComboBoxEx/RichEdit
• LinkCtrl

*) 使用高版本特有控件
• SafeCtrl
 –这是一个特殊的窗口类。在以下用况使用:
  • 高版本Windows提供了一个控件(例如LinkCtrl)。我们希望在该版本的Windows版本使用它,而在低版本的Windows下,我们提供一个替换控件(AltCtrl)。
  • 我们使用了一个第三方控件。我们希望在用户安装了该控件时使用它,否则使用替换控件(AltCtrl)。
• 概念
 –OrgCtrl/OrgClassName
  • 高版本Windows提供(或第三方提供)的控件
 –AltCtrl/AltClassName
  • 替换控件。你需要实现的。
 –SafeCtrl/SafeClassName
  • 安全控件。WINX提供的。例如SafeLinkCtrl。

002 - WINX概览:句柄类(HandleClass)

*) 窗口句柄类
• WindowHandle - ATL::CWindow
• AxCtrlHandle - ATL::CAxWindow
 –ActiveX控件句柄类
• StaticHandle - WTL::CStatic
• ButtonHandle - WTL::CButton
• EditHandle - WTL::CEdit
• ComboBoxHandle - WTL::CComboBox
• ScrollBarHandle - WTL::CScrollBar
• FlatScrollBarHandle - WTL::CFlatScrollBar
• ListBoxHandle - WTL::CListBox
• DragListBoxHandle - WTL::CDragListBox
• ListCtrlHandle - WTL::CListViewCtrl
• HeaderCtrlHandle - WTL::CHeaderCtrl
• TreeCtrlHandle - WTL::CTreeViewCtrl
• ToolBarCtrlHandle - WTL::CToolBarCtrl
• TabCtrlHandle - WTL::CTabCtrl
• ToolTipCtrlHandle - WTL::CToolTipCtrl
• StatusBarCtrlHandle - WTL::CStatusBarCtrl
• SliderCtrlHandle/TrackBarCtrlHandle - WTL::CTrackBarCtrl
• SpinButtonCtrlHandle/UpDownCtrlHandle - WTL::CUpDownCtrl
• ProgressCtrlHandle - WTL::CProgressBarCtrl
• HotKeyCtrlHandle - WTL::CHotKeyCtrl
• AnimateCtrlHandle - WTL::CAnimateCtrl
• ReBarCtrlHandle - WTL::CReBarCtrl
• ComboBoxExHandle - WTL::CComboBoxEx
• DateTimeCtrlHandle - WTL::CDateTimePickerCtrl
• MonthCalCtrlHandle - WTL::CMonthCalendarCtrl
• IPAddressCtrlHandle - WTL::CIPAddressCtrl
• PagerCtrlHandle - WTL::CPagerCtrl
• RichEditHandle - WTL::CRichEditCtrl

*) 资源句柄类
• BitmapHandle - WTL::CBitmapHandle
• Bitmap - WTL::CBitmap
• IconHandle - WTL::CIconHandle
• Icon - WTL::CIcon
• CursorHandle - WTL::CCursorHandle
• Cursor - WTL::CCursor
• MenuHandle - WTL::CMenuHandle
• Menu - WTL::CMenu
• AcceleratorHandle - WTL::CAcceleratorHandle
• Accelerator - WTL::CAccelerator

*) GDI句柄类
• RgnHandle - WTL::CRgnHandle
• Rgn - WTL::CRgn
• PenHandle - WTL::CPenHandle
• Pen - WTL::CPen
• BrushHandle - WTL::CBrushHandle
• Brush - WTL::CBrush
• FontHandle - WTL::CFontHandle
• Font - WTL::CFont
• PaletteHandle - WTL::CPaletteHandle
• Palette - WTL::CPalette
• EnhMetaFileHandle - WTL::CEnhMetaFileHandle
• EnhMetaFile - WTL::CEnhMetaFile

*) GDI句柄类 – DC
• DCHandle - WTL::CDCHandle
• ClientDC - WTL::CClientDC
• WindowDC - WTL::CWindowDC
• PaintDC - WTL::CPaintDC
• MemoryDC - WTL::CMemoryDC
• EnhMetaFileDC - WTL::CEnhMetaFileDC

*) 其他句柄类
• ImageListHandle - WTL::CImageList

002 - WINX概览:基础支撑

*) 基础支撑的实现原则
• 不假设自己是用户独立使用的库。
• 所以尽量检测用户是否使用了某种流行的库,选择该库已有的。
• 举例:WINX_ASSERT
  #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

*) 不完全列表
• 基础类,多数来自WTL
 –CPoint
 –CRect
 –CSize
 –CString
 –CFindFile
 –CRecentDocumentList
 –WindowRect
 –ClientRect
• 通用
 –_offsetof、parent_class_ptr、countof
 –MsgBox
 –WINX_DEFINE_IID、WINX_UUID
• 调试/诊断
 –WINX_ASSERT
 –WINX_ASSERT_OK
 –WINX_ASSERT_ONCE
 –WINX_ASSERT_DERIVE
 –WINX_REPORT
 –WINX_VERIFY
 –WINX_VERIFY_OK
 –WINX_TRACE

002 - WINX概览:WINX中的基本概念

• 基础支撑
 –基础类(BasicTypes),多数来自WTL
 –辅助:调试诊断等
• 句柄类(HandleClass)
 –Win32 SDK中的句柄的简单包装
 –WINX的所有句柄类直接取自ATL/WTL
• 窗口类(WindowClass)
 –消息(Message)的接收者
 –窗口类不一定要保存有窗口句柄(!!!)
• 消息(WindowMessage)
 –消息分派(DispatchMessage)
• 属性(Property)
 –属性编程(类Delphi),易往可视化发展

002 - WINX概览:WINX的目标

• 轻巧、易用、“傻瓜式”
• 属性编程(类Delphi)
• 可视化
 – 事实:WTL 的很多关键特性在模态对话框中不可用。例如PreTranslateMessage (包括快捷键的支持)、UpdateUI 等等。
 – 与WTL 对模态对话框的“ 轻视” 相反,WINX 极大化的强化模态对话框的能力。从而使得多数的界面设计可以以可视化方式完成。