上下文菜单随Word自动化消失

时间:2010-06-01 12:44:51

标签: delphi automation ms-word contextmenu ole

当我在OleContainer(inplace)中编辑Word文档并切换到另一个Word文档然后切换回来时,我再也不能使用我的rightmouse按钮了。上下文菜单不会显示。

这种情况发生在Word 2000上,而不是Word 2007上(我不知道其他版本)。

如何摆脱这种行为?

如何重现:

  • 创建新的VCL应用程序
  • 添加菜单栏
  • 添加TOleContainer,AlClient,AllowInPlace和AllowActiveDoc True。
  • 使用TOleContainer,插入Word 97-2003文档
  • 在菜单栏中添加一个菜单项“关闭”,在其事件处理程序中添加OleContainer1.DestroyObject,以便您可以停止编辑
  • 运行此应用程序,双击OleContainer,使其进入editmode
  • 现在打开Word 2000
  • 切换回您的应用程序,上下文菜单将不再有效。

编辑: 我在以下系统上重现了上述行为(使用Citrix):

Windows Server 2003企业版
版本5.2(Build 3790.srv03_sp2_rtm.070216-1710:Service Pack 2)

Microsoft Word 2000(9.0.6926 SP-3)

我使用Delphi 7(build 8.1)来创建应用程序。

3 个答案:

答案 0 :(得分:4)

通过ActiveX托管Office应用程序时,您会发现某些Office应用程序的某些版本对于了解窗口激活更改非常敏感,这尤其会影响其上下文菜单。

基本上,如果你没有告诉他们什么时候失去或获得焦点,并且当你的顶级窗口获得或失去焦点时(即使他们的窗口中的孩子控制没有获得焦点),那么他们可以去干草。

这是我长时间奋斗的事情,特别令人沮丧的是当你不得不告诉应用程序他们比你更了解他们的事情时(比如当他们失去或直接获得焦点时...或者当他们创建一个弹出式菜单时,将焦点从他们身上移开,并且必须以不同的方式处理其他需要关注的应用程序/窗口,这样你就可以神圣了......呃。

无论如何,Office应用程序应公开IOleInPlaceActiveObject接口,您应该确保调用其OnFrameWindowActivate方法来告诉它有关激活/停用的信息。

从内存中,快速查看我自己的托管Office代码,这是最重要的事情之一。这也是一件容易被忽视的事情,我想:“不,这可能无关紧要......为什么窗户是否活跃会有什么关注呢?”您可能认为它只会导致一些轻微的化妆品问题(例如,当它不存在时显示活动),但它可能导致整个事件锁定或崩溃。相信我,Office对这类事情的关心太多了!我得到的印象是,在合作多任务处理过程中,在Office的封面下仍然存在一个非常古老的单线程设计,当它的两个窗口似乎同时处于活动状态时,它会变得非常混乱。 / p>

很抱歉,我不能提供更多的建议,而不仅仅指向那个方向......编写ActiveX主机是一种黑色艺术(所有文档都是为了托管,而不是主机:()和我得到的唯一方法自己的代码工作是通过几个月的试验和错误以及大量的调试。不幸的是,这是一场噩梦。

最后一条建议:不要害怕为特定应用程序硬编码kludges。这就是IE本身所做的,使用注册表设置来控制哪些kludges应用于什么(我怀疑一些硬编码到代码中)。 ActiveX是如此糟糕的混乱,各种控件都有自己的怪癖和错误,并且不可能编写一个干净的,通用的主机,它可以与所有控件一起使用。 (一个修改一个的更改将打破另一个。)你也会发现只有你按照与IE相同的顺序尝试接口才能工作的东西,因为它们只是用IE测试过;做事略有不同,他们分崩离析。 :(

答案 1 :(得分:0)

我想知道您是否可以从包含OLE容器的表单中捕获任何Lost Focus类型事件,此时您可以销毁OLE容器中的文档但将其保留在内存中。然后,在表单的任何Got Focus类型事件上,您可以检查是否有该文档;如果是这样,请将其重新加载到OLE容器中。

这会对你有用吗?

答案 2 :(得分:0)

也许您可以使用组件来调用应用程序。我从来没有遇到过创建自定义组件以通过接口调用word然后在菜单中注册特殊命令的问题。在容器中,您可以不在表单上设计特殊菜单吗?有一些WordSink Evenet可以帮助保存和关闭,可以与单词com对象一起使用。