16
votes

When I am editing a Word document in an OleContainer (inplace) and I switch to another Word document and then I switch back, I cannot use my rightmouse button anymore. The context menu will not show up.

This happens on Word 2000, not on Word 2007 (I don't know about other versions).

How can I get rid of this behaviour?

How to reproduce:

  • Create a new VCL Application
  • Add a menubar
  • Add a TOleContainer, Align alClient, AllowInPlace and AllowActiveDoc True.
  • With the TOleContainer, insert an Word 97-2003 document
  • Add a menuitem 'Close' to the menubar, in its eventhandler, add OleContainer1.DestroyObject, so you are able to stop editing
  • Run this application, doubleclick on the OleContainer so it goes in editmode
  • Now open Word 2000
  • Switch back to your application, the contextmenu will not work anymore.

Edit: I reproduced above behavior on the following system (using Citrix):

Windows Server 2003 Enterprise Edition
Version 5.2 (Build 3790.srv03_sp2_rtm.070216-1710 : Service Pack 2)

Microsoft Word 2000 (9.0.6926 SP-3)

I used Delphi 7 (build 8.1) to create the application.

3
can you please tell which versions and service pack level you are using (OS, Delphi, Word)?pastacool
Does this error occur outside of Citrix?Judah Gabriel Himango
@Judah Himango: I don't have a system available with Word 2000 outside of Citrix, so unfortunately I cannot answer your question.The_Fox
Ok. Keep in mind we saw some weird focus and window activation behavior in Citrix about a year or two ago. You might want to confirm this error occurs outside Citrix.Judah Gabriel Himango

3 Answers

4
votes

When hosting Office apps via ActiveX, you'll find some versions of some Office apps are ridiculously touchy about being informed of window activation changes and this can especially affect their context menus.

Basically, if you don't tell them whenever they lose or gain the focus and also whenever your top-level window gains or loses focus (even if their child control in the window isn't gaining focus), then they can go haywire.

It's something I fought with for a long time and especially frustrating when you're having to tell the applications things that they are in a better position to know than you are (like when they lose or gain the focus directly... or when they create a pop-up menu which takes the focus away from them and has to be handled differently to some other app/window taking the focus, which you are left to divine... Ugh.

Anyway, the Office apps should expose an IOleInPlaceActiveObject interface and you should ensure you call its OnFrameWindowActivate method to tell it about activation / deactivation.

From memory, and a quick look at my own code for hosting Office, that is one of the most important things. It is also an easy thing to overlook, thinking "Nah, it can't matter that much... Why would anything care that much about whether the window is active or not?" You might think it could only lead to some minor cosmetic issues (like appearing active when it isn't) but it can lead to the whole thing locking up or crashing. Trust me, Office cares way too much about such things! I get the impression that under the covers of Office there is still a very old, single-threaded design from the days of co-operative multitasking clunking away and it can get very confused when two of its windows seem to be active at once.

Sorry that I cannot give more advice than just pointing in that direction... Writing ActiveX hosts is a black art (all the documentation is geared towards being hosted, not being the host :( ) and the only way I got my own code to work was through months of trial and error and a hell of a lot of debug-out. It's a nightmare, unfortunately.

One last piece of advice: Don't be afraid to hardcode kludges for particular applications. This is what IE itself does, with registry settings to control which kludges get applied to what (and I suspect some more hardcoded into the code). ActiveX is such a poorly-defined mess that various controls have their own quirks and bugs and it's impossible to write a clean, generic host that works with all of them. (A change that fixes one will break another.) You'll also find things that only work if you try interfaces in the same order that IE does, just because they've only been tested with IE; do things slightly differently and they fall apart. :(

0
votes

I wonder whether you could catch any Lost Focus type event from the form containing the OLE container, at which time you could destroy the document in the OLE container but keep it in memory. Then, on any Got Focus type event for the form, you could check to see if you have that document; if so, re-load it into the OLE container.

Would that work for you?

0
votes

Maybe you can use a component to invoke the application. I never had a problem creating a custom compoment to invoke word through interfaces and then registering special commands at the menu. In a container can you not design a special menu on the form? There are a few WordSink Evenets that will help in saving and closing that could be used in conjunction with the word com objects.