万星星@豌豆荚 欢迎加入我们
一个吃软饭的男人!!!!!我只想写程序####
微博:http://weibo.com/wanlianwen
posts - 172,  comments - 1253,  trackbacks - 0

影子
刚回到学校,一时半会没有安定下来,呆在学校无事。走在武汉街道上,处处飘着桂花香,想起“八月桂花遍地开”歌声。前人总结的规律总是那么准确,自然忆起父辈经常在耳边的唠叨:不听老人言,吃亏在眼前。思想在钢枪铁炮的西方思潮和大刀长矛的中国传统的熏染下,人不免变得浮躁、善变,左右摇摆,骑墙观望。
前一段时间一个朋友一直叨念着让我给他做一个插件系统,他抱怨插件的消息传递不畅通,无法下手构建属于自己plugin system。我告诉他应该怎么去研究,他非要我动手给他demo一个,并且指明要“Eclipse”那样的。我没有那么好设计思想,也没有很强的技术,对Eclipse更是知之甚少,一直走在Microsoft大道上,深受billgate庇护,省去了Java开发的一堆环境配置问题。
第一次走进公司到现在有两年零几天了,作为一个学生我清楚在公司应该如何。一直没有偏离自己理想,在痛苦中成长,体会到痛并快乐着的滋味。在做系统的时候,由于对mfc知识掌握不足,dll封装UI的时候经常出现资源切换问题,Debug和Release下也会出现不同行为,就连非dll里面模态对话框的支持都是麻烦(还是资源问题)。有一个同事采用CLocalResource解决资源切换麻烦,当然大部分情况下是没有好用的,然而在两个dll互相调用有UI参与的时候还是一样回出现句柄非法。这一切让我明白,好的框架设计和软件职能分解是最只要的。于是我不遗余力的追逐plugin技术,思考软件行为,加强编程技巧。其间受到一位对我影响很大的人的帮助,我感慨万千,人生际遇很重要。

设计技术
UI技巧和算法技巧同等重要。追求过跨平台的UI库(QT、wxWidget),爱慕过小巧的UI库(WTL、fox),甚至冲动的想用Win32写框架、用ATL编写控件库。在项目里,我用ATL写对话框的时候,我尝尽了苦头,没有DDX机制,API麻烦的调用、字符串处理困难等。要解决这些问题,不得不引入其他库,考虑一下:你用的库别人熟悉吗?你用的库别人容易用吗?每个人都要引入库会不会冗余?当加入所有这些支持,恐怕比MFC不会小到那里(这里意思不是反对使用其他库而鼓吹MFC)。实际的项目很少是一人所为,所以应该选择大家都熟悉的库(是什么?)。也曾经嫌弃过MFC,现在不了,而是想如何充分利用他所有机制。
涉及到的技术有:idl、ATL、MFC。用idl文件定义系统接口,形成system的脉络。ATL制作插件,实现system的必须接口。MFC提供system的UI基础设施(Toolbar Frame Doc/View ......)。

目标
实现一般界面元素的plugin扩展支持,依次实现Toolbar plugin、menu plugin、statusbar plugin、dockbar plugin、Doc/View plugin,通过XML配置描述插件实现UI。

技术思路
一个灵活的系统必须有清晰的结构,为扩展提供必要的内建支持设施。结构的清晰保证插件可以合理操纵系统的编程点,内建支持保证插件扩展的简单性、UI统一性、UI多样性(只需系统内部修改UI样式即可实现不同风格UI)。
看几个结构模型:DOM模型、VBA、.NET的CodeDOM。

(DOM)

(.NET CodeDOM)

(VBA)
通过上面的图形,我们可以清楚看到他们都有一个顶级对象,通过该顶级对象可以获取模型中的一切可编程对象。而作为一个外界插件,需要了解系统只需获取该顶级对象即可,该顶级对象在插件加载的时候传递给插件。

框架设计

系统通过一个顶级对象IApplication可以获取所有内部对象。加载插件的时候传递该对象,插件通过该对象了解系统模型,创建UI、设置命令接口。系统拥有插件的命令接口驱动插件,插件拥有系统模型调用系统功能,彼此间互相了解,正常通信。

接口设计

[
    
object ,
    uuid(D6424B18
- 886A - 47c8 - 8D10 - A8A977C1DBF4),
    helpstring(
" IApplication Interface " ),
    pointer_default(unique)
]
interface  IApplication : IUnknown
{
    [id(
1 ), helpstring( " method GetMainFrame " ), hidden] HRESULT GetMainFrame([ out , retval]IMainFrame **  ppMainFrame);
}
;

[
    
object ,
    uuid(D59C6E9F
- 70F6 - 44b0 - 8358 - 5AA0BB6DB1D1),
    helpstring(
" IMainFrame Interface " ),
    pointer_default(unique)
]
interface  IMainFrame : IUnknown
{
    [id(
1 ), helpstring( " method CreateToolBar " ), hidden] HRESULT CreateToolBar([ in ]BSTR bstrCaption, [ out , retval]IWLWToolBar **  ppToolBar);
    [id(
2 ), helpstring( " method GetMainWnd " ), hidden] HRESULT GetMainWnd([ out , retval]LONG *  pMainWnd);
}
;

[
    
object ,
    uuid(687ACF1C
- 1EC0 - 4808 - B04C - 9455B97D3D6D),
    helpstring(
" IAddin Interface " ),
    pointer_default(unique)
]
interface  IWLWAddin : IUnknown
{
    [id(
1 ), helpstring( " method OnConnect " ), hidden] HRESULT OnConnect([ in ]IApplication *  pApp);
    [id(
2 ), helpstring( " method OnDisconnect " ), hidden] HRESULT OnDisconnect();
}
;

[
    
object ,
    uuid(1ED92132
- 09BF - 409b - 951D - EEE68706C67C),
    helpstring(
" IToolBar Interface " ),
    pointer_default(unique)
]
interface  IWLWToolBar : IUnknown
{
    [id(
1 ), helpstring( " method SetToolbarInfo " ), hidden] HRESULT SetToolbarInfo(
        [
in ]LONG lInstance,            [ in ]IWLWCommand *  pICommand,
        [
in ]LONG lBitmapResource);
    [id(
2 ), helpstring( " method AddCommand " ), hidden] HRESULT AddCommand(
        [
in ]BSTR bstrCommand, [ in ]BSTR bstrTooltip,
        [
in ]BSTR bstrMessage, [ in ]LONG lBitmapOffset);
    [id(
3 ), helpstring( " method FinishAdd " ), hidden] HRESULT FinishAdd();
}
;

[
    
object ,
    uuid(
05393789 - A95B - 4172 - 941A - E532DF38F4E4),
    helpstring(
" ICommand Interface " ),
    pointer_default(unique)
]
interface  IWLWCommand : IUnknown
{
    [id(
1 ), helpstring( " method OnCommand " ), hidden] HRESULT OnCommand([ in ]BSTR bstrCommand, [ in ]LONG wParam, [ in ]LONG lParam);
    [id(
2 ), helpstring( " method Enable " ), hidden] HRESULT Enable([ in ]BSTR bstrCommand, [ in ]LONG wParam, [ in ]LONG lParam, [ out , retval]VARIANT_BOOL *  pbEnable);
}
;


目前实现
工具栏插件基本实现,通过文本文件加载插件。处理工具栏按钮tooltip、状态栏提示、消息响应、UI状态处理。
修改意见:添加下拉式按钮、添加控件到工具栏、添加Rebar风格工具栏、定制工具栏。
插件文本:

界图:


代码下载 内含说明

学习同时谢谢提出意见

posted on 2006-10-13 14:30 万连文 阅读(2410) 评论(4)  编辑 收藏 引用 所属分类: 小作品

FeedBack:
# re: 工具栏插件设计
2006-10-15 21:50 | flyingxu
作为一个插件系统的模仿对象,vs.net可能比eclipse更容易一点,对于vc程序员来说  回复  更多评论
  
# re: 工具栏插件设计
2006-10-17 15:18 | richard
我是ATL和MFC结合使用的菜鸟,
特别是对ATL不熟,只知道添加接口。

请问怎样建立你代码中的程序呢。
是在VS中新建MFC工程还是新建ATL工程,

然后具体的步骤,万分感谢!  回复  更多评论
  
# re: 工具栏插件设计
2006-10-17 18:20 | 万连文
@richard
Exe是MFC程序支持ATL
插件是ATL程序,不支持MFC

建立多文档程序,添加接口,提示选择OK,向导自动为mfc程序添加atl支持。  回复  更多评论
  
# re: 工具栏插件设计
2009-03-04 20:10 | csdn
http://www.codeproject.com/KB/COM/AddinProjectFramework.aspx

我下载你的程序,但是我知道我上面提供的链接里已经有人实现了。  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


简历下载
联系我

<2006年10月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

常用链接

留言簿(66)

随笔分类

随笔档案

相册

搜索

  •  

最新评论

阅读排行榜

评论排行榜