我想做一个类似Word的具有向客户抛标准COM的二次开发接口的应用程序,不知道如何下手??????

sunmz_wjxy 2008-09-19 03:04:38
对于这个技术我比较好奇:
1.MDI的EXE和二次开发组件我猜应该是两个独立开发的程序.
2.那么这个EXE程序是如何和二次开发COM组件进行联系的呢?
3.Word 有打开文件之前的事件,类似这样的事件又是如何从EXE抛到二次开发接口的组件呢?
......

希望有高手指点一二,最好有点例子.谢谢!!
...全文
119 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
jameshooo 2008-09-22
  • 打赏
  • 举报
回复
没有独立的资料,全靠API和对COM基础的理解。
实现一个支持自动化的应用程序原理上相对还是比较简单的,先按照普通EXE的方式建立项目,然后设计自己的对象模型,至少应该设计一个根对象(就像word里的Application对象),同时实现根对象的类厂,当应用程序启动时创建并登记这个类厂。应用程序应该通过命令行参数来区分自己是被用户启动的还是被自动化启动的,自动化启动方式会收到一个/automation参数。实际上这样做就已经是一个进程外组件了。
如果是ATL向导来创建项目,可以直接生成进程外组件。
sunmz_wjxy 2008-09-22
  • 打赏
  • 举报
回复
非常感谢胡兄在百忙之余还来回答我的问题.

不过就像下面这位兄弟,只有一些零散的想法,离成功的程序框架还有相当的距离.

[Quote=引用 8 楼 sjdev 的回复:]
胡哥,有没有相关资料?
我最近也需要实现类似功能,不过稍有差别。
自己也有一些想法,不过很零散,感觉离一个成功的程序框架还有相当的距离。
[/Quote]

不知道胡兄和各位高手们有没有相关的资料,非常感谢
wangweixing2000 2008-09-20
  • 打赏
  • 举报
回复

2.Word应用程序可以通过MSWord.olb达到后台启动,而且可以链接上已经启动的Word应用程序,这一点又是如何办到呢?

MSWord.olb只是个类型库,你到通过GetActiveObject连接到你的程序,只要通过ole自动提供的RegisterActiveObject注册你程序内部包装的app对象即可,这种逻辑和COM的机制很类似的,先
注册后调用,GetActiveObject等同于COM库提供CoCreateIntance方法,这些都是由ole库提供的
功能,下面是它提供几个方法:

/*---------------------------------------------------------------------*/
/* Active Object Registration API */
/*---------------------------------------------------------------------*/

/* flags for RegisterActiveObject */
#define ACTIVEOBJECT_STRONG 0x0
#define ACTIVEOBJECT_WEAK 0x1

WINOLEAUTAPI RegisterActiveObject(IUnknown * punk, REFCLSID rclsid,
DWORD dwFlags, DWORD * pdwRegister);

WINOLEAUTAPI RevokeActiveObject(DWORD dwRegister, void * pvReserved);

WINOLEAUTAPI GetActiveObject(REFCLSID rclsid, void * pvReserved,
IUnknown ** ppunk);
sjdev 2008-09-20
  • 打赏
  • 举报
回复
胡哥,有没有相关资料?
我最近也需要实现类似功能,不过稍有差别。
自己也有一些想法,不过很零散,感觉离一个成功的程序框架还有相当的距离。
jameshooo 2008-09-19
  • 打赏
  • 举报
回复
明白你的意思了,你这样做的目的不是外部插件,而是要把应用程序实现成可自动化。只需要把你的应用程序设计成进程外组件即可。如果想知道文档打开前或者打开后的事件,可以在连接点接口里设置BeforeDocumentOpen和AfterDocumentOpen两个方法。

支持自动化和支持插件是两个不同的范畴。
sunmz_wjxy 2008-09-19
  • 打赏
  • 举报
回复
1.
外部插件->Automation->EXE

外部插件想要DocumentOpen方法,那么Automation必须要实现对应的连接点.当外部插件调用Automation的OpenDocument方法时,则会触发连接点.问题是最终打开文档的是EXE,而不是Automation,那么Automation如何知道文档打开前事件还是打开后事件呢?


2. 以Word为例:
	IUnknown *pIUnk = NULL;
hr = GetActiveObject(CLSID_Application,NULL,&pIUnk);
if (SUCCEEDED(hr))
{
m_WordRun = TRUE;
m_pWordApp = pIUnk;
m_pWordDocs = m_pWordApp->GetDocuments();
}
else
{
m_WordRun = FALSE;
TESTHR(m_pWordApp.CreateInstance(CLSID_Application));
m_pWordDocs = m_pWordApp->GetDocuments();
}
jameshooo 2008-09-19
  • 打赏
  • 举报
回复
你可以实现IApplication和/或其它的各种接口,希望某些事件能通知到插件,这一点通过连接点来实现。
例如可以添加一个IApplicationEvent的连接点接口(也是由插件来实现,应用程序只定义接口规范),有一个DocumentOpen()方法,当发生文档打开事件时,应用程序调用连接点实现者的DocumentOpen方法。连接点不是一定要求插件实现的,插件只需要实现感兴趣的连接点即可。连接点是COM中的事件通知规范。

第二点没看明白,在运行中olb文件是不起任何作用的。后台启动是什么意思?是指在word启动之后安装的插件也一样能被加载?
如果是,这个属于应用程序的功能,它只要定时扫描注册表项,发现有新的插件被安装了,就自动按照前面介绍的流程加载该插件。当然还有另一种方式,就是做一个插件管理器,可以让用户选择加载/卸载某个插件。
sunmz_wjxy 2008-09-19
  • 打赏
  • 举报
回复
我的理解是:
MSADDNDR.DLL只是抽象的实现了_IDTExtensibility2接口,而外部插件需要继承并实现这个接口,而在Word里会调用这个接口的方法.所以和你说的一样,只要我按照这个接口的原理设计自己的接口,没有必要一定实现它.这个问题我明白了.

基本术语:
EXE为我需要做的MDI.
Automation组件是我需要对外的二次开发接口组件.


EXE启动时,会创建外部插件A和Automation的某个接口(IApplication接口),并调用A的接口OnConnection方法,把IApplication接口传出去.于是A就得到IApplication接口.

1.把类型库从exe中抽取出来单独保存到一个文件中,这个过程肯定会遇到很多的问题,比如关于打开文档前后事件,怎么抛到外部插件A呢?

2.Word应用程序可以通过MSWord.olb达到后台启动,而且可以链接上已经启动的Word应用程序,这一点又是如何办到呢?


不知道你有没有这方面的例子,我想深入的研究一下.
jameshooo 2008-09-19
  • 打赏
  • 举报
回复
不是对外抛,_IDTExtensibility2接口是由外部插件实现的,word本身并不实现它,只会从组件请求这个接口而已。这个接口的类型库是在MSADDNDR.DLL文件中提供的,它属于操作系统,放在common files文件夹。

olb文件跟exe文件没有必然的联系,它只是把类型库从exe中抽取出来单独保存到一个文件中,因为office的对象模型很大,接口众多,所以类型库信息也很庞大,而这个类型库仅仅在开发时才需要,所以独立出来,使得exe运行时占用更少内存。
sunmz_wjxy 2008-09-19
  • 打赏
  • 举报
回复
首先谢谢你来回答这个问题.
我以前做过Office插件,所以基本的东西我是明白的.
但我想知道的是:
1.winword.exe和MSWord.olb这两个东西是如何联系起来的.我就是明白这个东西.
2.是MSWord.OLB组件库对外抛的_IDTExtensibility2这个接口吗?
jameshooo 2008-09-19
  • 打赏
  • 举报
回复
office和VS的插件规范是统一的,要求组件实现_IDTExtensibility2接口,你也可以完全模仿它们定义插件也必须实现_IDTExtensibility2接口。
使用方式大致如下:
1、应用程序启动时,扫描注册表中某一个特定的子键,比如Software\yourapp\plugins,枚举其下所有的子键,并寻找某个值(代表组件的CLSID)。
2、按照这个CLSID,调用CoCreateInstance来启动该插件,获得_IDTExtensibility2接口。
3、调用该组件接口的OnConnection方法,给它机会进行初始化。
4、在退出前调用该组件接口的OnDisconnection方法,给它机会进行各种清理工作。
5、调用接口的Release方法释放组件。
6、应用程序退出。

通常,在OnConnection方法里面要传递给插件足够的信息,以便工作过程中插件能利用这些信息执行工作,有条件的话在应用程序中实现一些对象模型供插件使用,在这些对象中提供连接点用于发生某些事件时能通知组件(就像你说的打开文件事件)。当然不用连接点也完全可以。

当然你完全可以不用这套规范,自己设计一个插件接口(比如IxxxPlugin,提供Init和Uninit方法),原理跟上面都是一样的。

3,245

社区成员

发帖
与我相关
我的任务
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
  • ATL/ActiveX/COM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧