TweetFollow Us on Twitter

OLE In-Place Activation
Volume Number:11
Issue Number:1
Column Tag:Microsoft Technology

In-Place Activation with OLE

Select, modify, and manipulate, all without leaving the application.

by Michael Fanning, Microsoft

Note: Source code files accompanying article are located on MacTech CD-ROM or source code disks.

This article is the second in a series describing the evolution of a simple OLE2 object server and will show you how to implement the Visual Editing feature of OLE for the Macintosh. A general familiarity with OLE and its underlying architecture (the Common Object Model, or COM) is assumed, a passing familiarity with the OLE interfaces for embedding OLE objects would be helpful. At a minimum, I’d suggest reading the first article which examines a simple (non-in-place) object server and also has a nifty glossary of essential OLE terms and concepts. If you haven’t read it, don’t have a copy, are uncertain of what OLE is and/or have used the word more often at bullfights than in technical discussions, don’t worry; we’ve included it on a CD that’s bound into this magazine. In fact, the CD holds the entire OLE for the Macintosh Software Developer’s Kit in its final form, for both 68K and Power Macintosh. The only thing that could possibly make it easier to implement Visual Editing in your own code would be a roadmap in the form of commented pseudo-code drawn from a working in-place server.


Back in the August issue, the editorial page predicted readers would find the piece “ more pleasant than dissecting a frog” - I thought this was generous, ‘equally pleasant’ was probably sufficient - “and at least as instructional”. I sincerely hope this last goal was met, dissection can set a high standard on information returned weighed against effort put forward. I’d be more comfortable if there was more life in the imagery, realistically the comparison turns to vivisection at that point, so let’s stick with the dissection metaphor and sharpen up the code scalpels.

OK, onwards.


Visual Editing, also known as in-place activation, is the feature of OLE that customers care about the most. It’s what allows them to edit any kind of data in any kind of document; to them, that’s what OLE is. Dissecting the implementation of an in-place server doesn’t spark much interest, that’s best left to people my younger sister always describes to me as ‘kinda geeky, like you’. Visual Editing is without question the most important user interface feature that’s defined by the OLE specification.

In-Place, Defined

In-place activation is a user interface standard by which an object can be selected, modified, and generally manipulated by the user, all while appearing to remain within the application which contains it. The object provides the functionality, the container provides the visual context. The editable state of the object is evident in certain user interface (UI) clues: a composite menu bar that contains both server and container menus, server toolbars or floating windows that appear on activation, and a shaded or hatched border which surrounds an in-place active object, grow handles optional. The net UI illusion is that an embedded object’s data is modified without (apparently) leaving the container application. Instead, the server’s functionality is brought into the container’s context, reinforcing a notion that the user’s document is central and that each kind of data in the document should be seamlessly editable without the user needing to worry about which application to invoke.

One of the Macintosh OLE developers compares the process to implementing a kind of “well-defined” dialog. The container provides a context which it describes to the server. The server provides a service, or feature, including the UI. Cooperative communication between the apps according to a protocol defined in OLE allows the server’s UI and feature to blend seamlessly into the container’s context.

Com, Redux, Revisited, In Short, Re-revealed

Before continuing I’d like to review the basic ideas which comprise the Common Object Model, and therefore OLE itself. If you haven’t grabbed the first article from the CD for a read-through, you should. It’s one of those, grab-your-nose, it’s-got-to-go-down-at-some-point and it-may-as-well-be-sooner-rather-than-later, cod-liver oil kind of articles. Anyone who’s inclined to skip past a COM/OLE recapitulation can look ahead for the next reference to in-place in bold caps.

OLE0 - a set of interfaces which define essential protocols for interoperability.

Interface 0 - a table (or vtable) of function pointers to constituent routines, commonly known as methods.

Method 0 - a member function of an interface.

There are specific interfaces for each of the general areas of functionality OLE defines; they include Uniform Data Transfer, Linking (Naming and Binding), Embedded Objects (Compound Document Management), Drag and Drop, Visual Editing, Automation (Programmability), and Structured Storage (disk- and memory-based persistent storage). Inter-object communication is facilitated by notification and concurrency-related interfaces.

OLE is the protocol, COM is the means

COM itself can be reduced to a small set of simple and powerful concepts which are the quantum building blocks of OLE. Essentially, the Common Object Model defines how objects should interact, both in the context of a single application (as an in-process server or object handler on Power Macintosh) and across application boundaries. While OLE defines specific protocols of communication, COM provides the means and supporting mechanism which allows transparent communication between applications.

What this means is that a user of an object (i.e., the one calling an interface method) doesn’t need to know where the code that’s called exists. It might be in-process, or in a separate background application. In the near future, it might reside across the network or be running in a different operating system altogether. The client is completely insulated from any concerns related to how the call makes it to the server and how the result makes it back.

COM Concerns

The basic contract for a COM object or its client is not particularly demanding. 1) COM applications follow a convention for retrieving and/or providing pointers to their supported objects known as interface negotiation, a simple idea which yields powerful returns. 2) COM defines a set of rules and methods which guarantee the lifetime of an object while it is in use by any COM client.

Interfaces and their Negotiation - Strictly speaking, interfaces are nothing more than abstract base classes comprised of pure virtual member functions. This basically means that the member functions are defined by OLE without providing any implementation. COM objects derive from the supported interface and implement all its methods, without exception.

After retrieving the initial pointer to an object (which is really just a pointer to one of the interfaces the object implements), pointers to different interfaces (representing different functionality) also implemented by the object can be retrieved through interface negotiation (IUnknown::QueryInterface).

Object Lifetime - COM defines a method for incrementing an object’s reference count (IUnknown::AddRef) and a method for decrementing it (IUnknown::Release). All objects ultimately derive from IUnknown and therefore must implement these two methods. An object increments its own reference count whenever it hands out a pointer to one of its interfaces (usually in response to QueryInterface). When the code that requested the interface is done with it, it calls the object’s Release method which decrements the object’s reference count. If the reference count drops to zero, that indicates that no one is using the object and it can safely delete itself. This simple set of rules allows an object to track how long it needs to exist since it always knows how many clients still have a reference to one of its interfaces.

Interface negotiation and reference counting are provided through a single interface, IUnknown, which serves as the base class for all COM objects. These two concepts are basic to COM and a good place to start gaining a general understanding.

COM addresses other subjects that are beyond the scope of this article:

• Identification (Globally Unique Identifiers)

• Memory Allocation/Deallocation

• Error and Status reporting

• Location/Dynamic Loading/Reuse of Object Code

• Security/Encapsulation

• Remoting

The glossary in the August MacTech article covers some of these topics in greater detail.

Hold On, I Know There’s Something About
In-Place In Here Somewhere

Subsequent sections of this article will cover the following, in order:

1. The OLE Interfaces specific to in-place capable servers

2. The series of calls between a container and server which result in an embedded object

3. The basic sequence of steps for activating an object in-place

4. A list of possible OLE object states and definitions

5. A pointer to the activation logic used by SimpleIPServer, in pseudo-code

6. Exit

Item #5 (and the SimpleIPServer source) is payoff for anyone looking for a leg up implementing visual editing in an object server. The logic in this pseudo-code is a clear roadmap for activating objects in-place on the Macintosh. I’ll upload a similar file detailing deactivation/close logic to the MS BBS on AppleLink and to the Macintosh library (lib 12) of the MS OLE forum on CompuServe (GO WINOBJ) in the not too distant future.

Visual Editing in Two Easy Interfaces + Assorted Logic

The server-side of in-place editing is limited to two interfaces, IOleInPlaceObject and IOleInPlaceActiveObject, which define 4 and 5 unique methods, respectively. Both interfaces derive (as all in-place interfaces do) from IOleWindow, which itself has only two methods (GetWindow and ContextSensitiveHelp).

This doesn’t sound like much work and in fact, you can get an in-place server up and running with most in-place related methods stubbed out. A more advanced in-place server will have code related to toolbar negotiation, menu merging, context-sensitive help and undo support, which will flesh out the in-place interfaces. The fundamental work of an in-place server, however, lies in its activation and deactivation logic.

The following section describes the negotiation and necessary steps to activate an embedded object for visual editing, beginning with a container’s call to IOleObject::DoVerb.


As you may recall from the first article, a container fully instantiates an embedded OLE object before requesting that the server execute its primary verb, the step that actually brings the object to the foreground and makes it visible. On inserting a SimpleIPServer object in the SimpleIPContainer sample app, the sequence of calls leading up to DoVerb is identical with their non-inplace counterparts from the August article. (You can view the LRPC communication between OLE applications by running LRPCSpy, an OLE SDK utility I find extremely effective for monitoring and debugging OLE applications. I’ve spent some time developing SimpleIPServer’s debug output to take even better advantage of the tool, most of the code for which is located in debug.cp).

The following few paragraphs and LRPCSpy output tracks creation of an embedded SimpleIPServer object:

Before LRPC communication can begin between an OLE container and server, there must be one of each in memory. The typical means to get there is to display a dialog and let the user choose from a list of available objects. As it happens, we get this for free by calling a routine from the OLE User Interface library. The UI Library contains helper functions for a variety of OLE tasks, all of which already conform to the OLE User Interface guidelines. The routine which invokes the standard Insert Object dialog is OLEUIInsertObject.

Once the user chooses an object type, the Insert Object dialog returns the CLSID (class identifier) associated with that type of object. The container then calls OleCreate, passing in the CLSID of the object and the ID of an interface to query the object for (this is usually IID_IOleObject). OLE uses the Registration Database to locate the server associated with this CLSID, then launches the server and sends it a specific AppleEvent to tell it that it’s being launched to service an OLE object. The server creates its Class Factory and registers it with OLE, at which point OLE calls CreateInstance and passes in the desired interface ID. It’s at this point that COM really starts to strut its stuff. In returning the interface pointer to the container, COM does a little magic and creates a connection between the two apps so that when the container calls a method on the interface, the corresponding code in the server gets executed. Remember, to the container, this interface acts just like a normal C++ object.

OLE has now accomplished a fundamental task in object interoperability: it has delivered a pointer to a server object to an OLE client. Tips are greatly appreciated, a gratuity of 15% will be charged for parties of 6 objects or more.

In the output below, distilled from LRPCSpy, ‘sIPs’ refers to the SimpleIPServer, ‘OTIC’ is OutlineInplaceContainer, a C-based in-place sample from the OLE SDK:

// [Caller > Callee]   [Interface ID]          [Method]       [Arguments]
 1) OTIC > sIPs: IID_IClassFactory   CreateInstance  
 2) OTIC > sIPs: IID_IStubManager    QueryInterface  (IID_IPersistStorage)
 3) OTIC > sIPs: IID_IPersistStorage InitNew         
 4) OTIC > sIPs: IID_IStubManager    QueryInterface  (IID_IDataObject)
 5) OTIC > sIPs: IID_IStubManager    QueryInterface  (IID_IOleObject)
 6) OTIC > sIPs: IID_IOleObject      SetClientSite   
 7) OTIC > sIPs: IID_IOleObject      Advise          
 8) OTIC > sIPs: IID_IDataObject     QueryGetData 
 9) OTIC > sIPs: IID_IDataObject     Advise          
10) sIPs > OTIC: IID_IAdviseSink     OnDataChange    
11) OTIC > sIPs: IID_IOleObject      SetHostNames    
                                      ("OutlineInPlaceContainer", "Object 
12) OTIC > sIPs: IID_IStubManager    LockConnection  (FALSE, FALSE)
13) OTIC > sIPs: IID_IOleObject      GetExtent       
14) OTIC > sIPs: IIDIOleObject       DoVerb          (OLEIVERB_SHOW, 
                                            iface*, -1, WindowPtr{"untitled")

In the above, OLE calls SimpleIPServer’s CreateInstance method (item 1, above) in response to a request from OutlineInplaceContainer (i.e., OTIC has called OleCreate, passing SimpleIPServer’s CLSID). OTIC QI’s for IPersistStorage (2) and calls InitNew (3), passing a pointer to the storage it has created to hold the SimpleIPServer object. The container retrieves interfaces for data transfer (4) and basic object communication (5) with the embedded object (IDataObject and IOleObject). OTIC calls IOleObject::SetClientSite (6), which provides the server with a reference to the container’s IOleClientSite interface, then sets advises on IOleObject and IViewObject (which shows up on the server side as an advisory connection on its IDataObject interface). When creating each advisory connection, the container passes a reference to its IAdviseSink interface to the method call. Both OLE and the server hold a reference to this interface and each of them notifies the container of specific events (such as when the object is closing, or the object’s presentation has changed and should be redrawn). The object is queried for support of PICT representation (8) and another advise is set, this time on IDataObject in order to receive word of any change in the object’s data (9). sIPs sends a notification of data change resulting from initialization (10). The container passes the container and object names as strings (11). OLE calls an internal function in the code that’s managing the connection on the server side to ensure that it stays active for the lifetime of the conversation (12). A call to GetExtent returns the size of the server object (13). Finally, OTIC calls DoVerb() with the verb OLEIVERB_SHOW, thus passing the reins to the server and instructing that it proceed with the process of showing itself.

In Situ, Bruté?

There hasn’t been a single in-place call up to now, and there won’t be unless the server decides to initiate a discussion on the topic in DoVerb. The basic steps in negotiating an in-place session look something like this:

1) The server QI’s for IOleInPlaceSite.

2) The container agrees to activate in-place and provides context details.

3) The server creates a menubar to hold menus from both applications and passes it to the container to let it insert any menus it will use during visual editing.

4) The server negotiates for any additional screen territory required for toolbars, etc.

5) The server moves its window into place and makes itself the foreground app.

6) On coming frontmost, the server installs its UI component (menu, toolbars, etc.) and makes itself visible.

It’s fairly apparent from this description that the server is the active agent throughout the procedure. After instantiating an object and calling DoVerb on it, the container remains more or less passive during activation, i.e., its interface implementations will be called by OLE when its participation is required. OLE itself is calling the container as the direct or indirect result of the server’s activation logic. The server is busily steering a course for activation, determining the container’s capabilities, and putting together special UI components to use while visual editing.

if (m_pAuthor->m_pMind->m_fIsLosingKeenEdge)
 hresult = (IDissectOLETopic)m_pTemp->StopCuttingStartStepping();

That’s all for now. All that’s left is to step through the SimpleIPServer code. To assist in this, I’ve made some modifications to SimpleIPServer’s trace functionality. The sample builds a debug version by default which has two menus absent from the non-debug build, Debug and Trace. The Debug menu contains options to continuously display global data tracking object state, redirecting debug information to various outputs (the LRPCSpy utility, MacsBug, a logfile), setting a ‘verbose’ debug mode, and rejecting incoming LRPC messages (a standard test app functionality allowing observation of container behavior in scenarios where a server is not responding to outside calls).

The Trace menu has several options for tracking progress of the inplace code through trace output. The nature of inplace activation makes source-level debugging problematic for some server-container-debugger combinations. Debuggers like to pull themselves to the foreground, and for obvious reasons this can disrupt the inplace relationship of a server and container in mid-negotiation. One workaround is to use a low-level debugger such as MacsBug or The Debugger while debugging your inplace code. Neither of these debuggers causes a context switch when activated so they don’t interfere with inplace negotiation.

If you plan to use the THINK Debugger, you should install a special version of the OLE Libraries which resolves a compatibility problem that appears when debugging an OLE application with this debugger. The OLE Libraries patch LoadSeg in the application’s trap table so that they’re able to load additional segments while running in the application’s context. In order for this to work OLE needs to intercept certain LoadSeg calls and not pass them along (this only happens if it’s a segment in the OLE Library). It turns out that the THINK Debugger patches both the LoadSeg trap as well as the trap dispatcher itself. By patching the trap dispatcher, it’s able to detect that a LoadSeg call is about to execute and prepare itself internally for the pending LoadSeg call. When OLE intercepts a LoadSeg call and doesn’t pass it along, the THINK Debugger is left in an unstable state and bad things start to happen.

The special version of the OLE Libraries is called “Microsoft OLE Extension.ThinkC” and can be found in “SDK:Think” on the OLE SDK CD. This version preloads all segments in the OLE library and thus ensures that it never needs to intercept a call to LoadSeg. It does require a larger partition since all the code is preloaded.

As mentioned before, in-place activation begins with a call from an OLE container to execute a server verb (i.e., an operation or action the object supports, defined by the system or by the object itself). The following pseudo code is a reliable path a typical server might follow in handling activation to support visual editing. If you plan to code an OLE server yourself, you should find it an extremely useful implementation guide.

We’ve placed a copy of this article, including the following pseudo-code and comments, at the root level of the SimpleIPServer folder. To get the most the remainder of this article, I’d suggest you take a moment to scan the release notes on the OLE CD. Go ahead and install the OLE libraries according to the instructions you’ll find there. The steps are few in number and extremely straightforward; after copying the OLE bits to the usual haunts in the System Folder, you’re actually be ready to run OLE applications.

One useful point regarding the MS OLE Extension is that it does not have to load at startup in order for OLE to work; every bit of OLE functionality aside from Visual Editing is present even after a shift-boot. Visual Editing does require the extension to be loaded in order to work, however, so go ahead and restart so you can play around with the compiled version of the SimpleServer.

Debugging Tip - At times, you might find it useful to guarantee that one particular build of the OLE libraries in in memory when testing an OLE application, this can also be useful when debugging situations where an OLE app launches and immediately quits again without indicating what accounted for the load failure. (One possible reason accounting for this might be an application set with a memory partition larger than the system can reasonably support. On startup, the app claims all available memory for itself without leaving room for the OLE code to load inside the system heap. Prelaunching the OLE library insures sufficient memory for it to load and the app is content with the amount that remains, a figure below its preferred, but well above its minimal partition size.)

To prelaunch a specific build of OLE, simply change the type of the library you’re interested in from ‘INIT’ to ‘APPL’ and double-click. Retail builds will load as faceless background apps that won’t be visible in the Mac application menu (you will see the standard UI signs of a launch within the Finder, however). Debug builds actually appear in the application menu and can be pulled to the foreground and quit from the File menu. This isn’t necessary when everything’s working properly; under these conditions, the OLE libraries will stay resident in memory as long as necessary to handle container-server communications, after which it unloads.

You may find that attempting to invoke OLE in the usual way after changing its Type is not successful (meaning the OLE libraries fail to load in response to an Insert Object dialog request, etc.) The likely cause here is that the extension is no longer named properly (or wasn’t named properly in the SDK to begin with, such as MS OLE Extension.Think), in the absence of an expected signature, the MS OLE Extension name itself is used to locate the file. You can either switch the type back to ‘INIT’ and try to call OLE again, prelaunch the build you want to test or work with, or rename the ‘APPL’ OLE extension to the original name which shipped with the first release of Mac OLE.

In any event, the easiest way to invoke the OLE libraries is to follow the instructions in the latest OLE docs, restart the Macintosh (to enable in-place) and double-click the OLE application. Take a second to do this and run SimpleIPServer and a few of the other applications which are already compiled on the CD. Be sure to launch LRPCSpy to watch SimpleIPServer’s trace output as it does nothing more than create and close windows, renders and deletes simple shapes, etc. Experiment with the various trace and debug options.

At some point, bring LRPCSpy forward and hit cmd-backspace to clear all output windows. Pull up the SimpleIPServer ReadMe document and look for a section titled ‘Tracing SimpleIPServer Execution With the Pseudocode from MacTech InPlace article, January ‘95’. This section will contain any last minute features I can squeeze in. If there’s a logical way to put it in place, I’d like to enable a specific trace option for tracking the server’s progress in context of the following section. This ReadMe will also contain information for building the sample in a number of different development environments, the end of the document has a brief section on SDK test tools, some debugging tips, and a list of the most common development obstacles (and solutions) that a developer new to OLE is likely to encounter.

When you’re ready to dive in, launch an OLE Visual Editing container application. Any OLE in-place capable container will do, a sample or test app from the CD, or any shipping OLE application which supports visual editing. Pull up the Insert Object dialog and scan the list of embeddable objects. SimpleIPServer registers on launch, so you should see an entry for a Simple InPlace Server Document in the insert object listbox. Select it, click OK, and get ready for your first look at the guts of an in-place application at work.

The next section contains SimpleIPServer’s activation logic in detailed and well-commented pseudo-code (InPlace Logic.sIPs, in the same folder as the ReadMe). You can use this file as a roadmap for stepping through the code sample, or as a guide in implementing your own visual editing server. There are similar documents in-progress for other aspects of in-place development which will be available on CompuServe, AppleLink, and in future versions of the OLE for Macintosh SDK.

Activation Logic - A Walkthru

As stated previously, the moment of truth for an In-place application comes with a call to IOleObject::DoVerb, a method which is exposed (i.e., implemented and made available to the container by means of a provided interface pointer) by an OLE served. A visual editing server first raises the subject of in-place activation with a container in this context. The following pseudo-code functions are logically arranged to follow the course an object might take in order to activate successfully. The breakdown of routines, the tasks completed in each, and the global data documented in their pseudo-implementation represents a viable schematic for an in-place app to follow. It’s not just playing a visual app on TV. Here’s hoping you find it instructional; pleasant can come along for the ride if there’s room, but will have to take a back seat.

To fully explore the logic and gain familiarity with the underlying negotiations, you’ll want to try embedding SimpleIPServer into a number of different containers, including OLE 1.0 client-containers, and OLE 2.05 containers which don’t support visual editing. Following the pseudo code while tracing other in-place servers in LRPCSpy is informative, too, revealing the many approaches that can be taken to accomplish a end in OLE ends as well as the common paths most travel.

We now join the activation in progress




[ a series of lprc calls documented above and in the August ]

[ article which fully instantiate and initialize an OLE object. ]

[ at this point, the container is ready to activate the object ]

[ and let it take focus. let’s see what happens next. ]



HRESULT DoVerb(long iVerb...)
/* The following verbs mean that we should go inplace active if we can, which we do, generally speaking. 
 Support for visual editing doesn’t carry any responsibility to go in-place, however, the process is entirely 
cooperative and can be abandoned at any step by either participant 

 if not IPActive    // IPActive == InPlaceActive state
 call DoIPActivate()// DoInPlaceActivate transition, etc., etc.
 else if not UIActive 
 call DoUIActivate(UIACTIVATE)// flag that says we
    // were already ipactive
    // if either of the above calls failed, fall through to the OLEIVERB_OPEN code

/* The UIActive state is the moment at which all negotiation is settled between a container and server when 
all UI components are ready to go but are still hidden.  This is the state an active object would go to on being 
sent to the background due to a mouse click in the Finder.  All that remains is to go UIVisible, which is accomplished 
by bringing the app to the foreground and showing the relevant ui components. */

 // this verb means to start open editing, even if we support inplace
 if iVerb is OLEIVERB_OPEN
 if IPActive
 DoIPDeactivate()// get completely out of inplace to open edit
    // continue into open edit mode

 if our window is visible and we’re not IPActive
 call DoUIActivate()

HRESULT DoIPActivate(void)
 // this function shouldn’t get called if we’re already ipactive
 if IPActive
 assert and return

 // confirm that our state is as follows:
 ASSERT(ipactive == false, uiactive == false, uivisible == false)

 // check if our window is already visible and fail inplace if so
    // (this means we’re already in open edit mode)
 if our window is visible
 return E_FAIL

 // if the container has never called SetExtent, store defaults
 if extent is 0,0
 extent = default size

 // on a failure we call DoIPDeactivate which only procedes if ipactive == true
 IPActive = true;

 // this is our first chance to see if the container supports inplace
 if (IOleClientSite->
 QueryInterface(request IOleInPlaceSite interface) 
 returns NULL)
 return E_FAIL

 // does the container want to allow inplace right now?
 if IOleInPlaceSite->CanInPlaceActivate() doesn’t return S_OK
 return E_FAIL

    // GetWindowContext returns references to the container’s IOleInPlaceUIWindow 
    // and IOleInPlaceFrame interfaces, the rect where we should put ourselves, a
    // pointer to the container’s window (that we’ll be inplace in), and three regions 
    // that we pass to OLE later (with the OleSetInPlaceRects call)

 // hOleMBar contains a list of the menus that the container wants inserted 
    // while inplace
 if stored hOleMBar is NULL

 // create new OleMBarHandle

 // let container insert its menus into this OleMBarHandle

 // notify container that we’re ipactive (still need to go uiactive and uivisible)

 // the IPACTIVATE flag indicates that we’re doing the inplace negotiation
    // from scratch
 call DoUIActivate(IPACTIVATE)

HRESULT DoUIActivate(short wAction)
 // on entry to this function, wAction is one of:
    //  IPACTIVATE: starting inplace negotiation from scratch
    //  UIACTIVATE: starting inplace negotiation from ipactive state

    // this function shouldn’t get called if we’re already uiactive
 if UIActive
 assert and return

    // confirm that our state is as follows:
 ASSERT(ipactive == true, uiactive == false, uivisible == false)

 // on a failure we call DoUIDeactivate which only procedes if uiactive == true
 UIActive = true;

    // if uiactivating (was already ipactive), need to get parent window pointer
    // again in case we’re being activating in a different window
 if wAction == UIACTIVATE

    // give our IOleInPlaceActiveObject interface to IOleInPlaceFrame and 
    // IOleInPlaceUIWindow (when inplace has been nested several levels deep, 
    // the IOleInPlaceFrame interface is our channel of communication with the 
    // outer-most container, and the IOleInPlaceUIWindow allows us to communicate 
    // with the container we’re directly embedded in).
 SetActiveObject(our IOleInPlaceActiveObject interface)
 SetActiveObject(our IOleInPlaceActiveObject interface)

    // we don’t need any space on the document (UIWindow) so pass NULL

    // calculate how much space we want around the frame, request it, and if this
    // succeeds, set that much space and show our frame tools
    // NOTE: if we don’t have frame tools, simply pass NULL to SetBorderSpace again 

    // get the current bounds where frame tools might be placed
    IOleInPlaceFrame->GetBorder(pointer to BORDERWIDTHS)

    // calculate how much frame space we need
 FrameSpaceNeeded(pointer to BORDERWIDTHS)

 if IOleInPlaceFrame->RequestBorderSpace(pointer to 
 if IOleInPlaceFrame->SetBorderSpace(pointer to 
 enable our frame tools (show toolbars and status bar
   around frame)

    // if any of the above calls failed show frame tools as floating windows
    // NOTE: we might also jump to this block if FrameSpaceNeeded determined
    // that there wasn’t enough room to place our tools around the frame
 if any of the above calls failed
 show frame tools as floating windows

    // if uiactivating (was already ipactive) or if frame negotiation succeeded,
    // need to get current position again
 if wAction == UIACTIVATE or frame negotiation succeeded

    // move and size inplace window so it conforms to position retrieved from
    // GetWindowContext or GetObjectRects (if we wanted object adornments we 
    // would adjust the location of our window before calling MoveWindow and 
    // SizeWindow)
 MoveWindow(our inplace window)
 SizeWindow(our inplace window)

    // the following code calls OleSetInPlaceWindow until it either succeeds or our 
    // timeout expires.  when OleSetInPlaceWindow returns an error this means 
    // another app still has an inplace window set.  we give the other app time to finish 
    // getting out of inplace instead of just failing immediately (this timing problem can 
    // occur if the user is quickly switching between two inplace sessions)
 while true
 if OleSetInPlaceWindow() returns NOERROR
 break out of loop

 if exceed timeout
 assert and break out of loop

 WaitNextEvent() // yield so other apps can process

    // give OLE our current position (including any adjustments if we added
    // object adornments) and the regions from GetWindowContext

    // notify container that we’re uiactive (still need to go uivisible)
 if IOleInPlaceSite->OnUIActivate() returns OLE_E_NOT_FRONT_PROCESS

    // OLE_E_NOT_FRONT_PROCESS means the user switched to another app, 
    // unset the inplace window and exit without failing (leave ourselves uiactive)
 return NOERROR

    // call the document’s generic show routine which eventually calls
    // DoIPShowDocument (after showing the window, etc).  when ShowDocument
    // calls DoIPShowDocument it passes UIACTIVATE
 call ShowDocument()


HRESULT DoIPShowDocument(short wAction)
    // on entry to this function, wAction is one of:
    //   UIACTIVATE:  starting inplace negotiation from ipactive state
    //   DOCACTIVATE: starting inplace negotiation from uiactive state
    //           (OnFrameWindowActivate or OnDocWindowActivate call)

    // if we’re already uivisible, don’t bother proceeding
 if UIVisible

    // confirm that our state is as follows:
 ASSERT(ipactive == true, uiactive == true, uivisible == false)

    // on a failure we call DoIPHideDocument which only proceeds if uivisible == true
 UIVisible = true;

    // if we’re called from OnFrameWindowActivate or OnDocWindowActivate, the 
    // user has just switched apps or documents so that the inplace container 
    // document has been activated.
 if wAction == DOCACTIVATE

    // get our position in case it changed (this can happen if the container
    // window moved while we weren’t uivisible and consequently didn’t get
    // the SetObjectRects call)

    // move and size inplace window so it conforms to the new position
 MoveWindow(our inplace window)
 SizeWindow(our inplace window)

    // see code in DoUIActivate for explanation/elaboration of these two calls

    // give our IOleInPlaceActiveObject to IOleInPlaceFrame and 
    // IOleInPlaceUIWindow
  SetActiveObject(our IOleInPlaceActiveObject interface)
  SetActiveObject(our IOleInPlaceActiveObject interface)

    // clip all server windows so they appear to be behind the container
 OleClipWindows(first window in WindowList)

    // save the current menubar (gets restored when going uivisible(false)
 hSavedMBar = GetMenuBar()

    // delete any of our menus that shouldn’t be available while inplace
 DeleteMenu(id of File menu)// for instance, the File and
 DeleteMenu(id of Window menu)// ...Window menus

    // this call inserts the container’s menus into our menubar

    // force the the menubar to redraw

    // notify container that we’re uivisible (only needed if responding to either
    // OnFrameWindowActivate or OnDocWindowActivate)
 if wAction == DOCACTIVATE

    // show the inplace window and make sure it’s frontmost
 ShowWindow(our inplace window)
 SelectWindow(our inplace window)

    // the call to OleSetInFrontOf attempts to bring us the the foreground
 if OleSetInFrontOf() returns NOERROR

    // wait until we’ve come to the front (use GetCurrentProcess(),
    // GetFrontProcess(), and SameProcess() to detect when we’re frontmost)
    // NOTE: this call is implemented in SimpleIPServer’s CApp object

    // hilite the container’s window (got from GetWindowContext or
    // GetWindow).  this helps maintain the illusion that the container is
    // the frontmost app even though the server is in the foreground
 HiliteWindow(container’s window)


    // OleSetInFrontOf fails if the user clicked to another app during
    // inplace negotiation (it simply checks if the container is still the
    // frontmost app).  if we didn’t check for this condition and simply brought
    // ourselves to the foreground, another application would end up between
    // the container and the server and the illusion of inplace would be destroyed.
    // instead we leave ourselves in the uiactive state so that we’ll go uivisible
    // if the container’s inplace window is activated again.

In-Place At Last

There it is - the heart of activating an OLE object in-place. It’s a satisfying moment to see a server in development activate in-place for the first time. There’s something compelling about seeing your own code integrated with another application - surfacing in someone else’s context with a relevant toolbar and menu or two, then sinking back again on a mouse click in another window: it flat-out breaks through indifference and makes you go ‘wow’. After which, you can feel your thinking click forward a notch to the future.

Where to Go From Here

Bound into this issue of the magazine, you’ll find the Mac OLE 2.05 SDK CD. Feel free to play with it, to bang on it, to implement support for OLE in your Macintosh applications, and to ship those applications to your customers, all without charge or fee to Microsoft. Along the way, you can get technical support on CompuServe, by entering “Go WinObj” at the prompt, and looking for Section 12, where you’ll find lots of late-breaking information about Mac OLE. The library for this section usually has the most current OLE bits (right now it holds the 2.05 SDK broken into individual files which download as self-extracting archives). Keep an eye out for more sample code and supporting files over the next few weeks, including a simple link-server, linking container, etc.

On AppleLink, the OLE SDK is uploaded to the MSObjects topic located inside the Microsoft BBS. To get there, navigate through Third Parties:H-O:Microsoft and double-click the objects folder.

Again, the CD contains all the SDK files (and none of the download time) including Mac OLE help with all of the latest information in electronic form. If you prefer the heft and portability of a printed book, you can order the Macintosh OLE Programmer’s Reference by Barry Potter from M&T Books by calling 1-800-488-5233 (US) or 801-972-2221 (from outside of the US), entering 3 at the menu to reach Henry Holt Publishing, and asking for M&T Books, requesting information on the Macintosh OLE 2.0 Programmer’s Reference. Microsoft gets no money from M&T for the book; we supplied the content free as a service to the Macintosh development community, in order to keep the price as low as possible.

Once you’ve implemented support for OLE in your Macintosh application, we have a number of comarketing opportunities available to you. For more info, send email to

In the meantime, happy hacking - I mean, “dissecting”!


Community Search:
MacTech Search:

Software Updates via MacUpdate

NeoFinder 7.4.1 - Catalog your external...
NeoFinder (formerly CDFinder) rapidly organizes your data, either on external or internal disks, or any other volumes. It catalogs and manages all your data, so you stay in control of your data... Read more
Tunnelblick 3.8.0 - GUI for OpenVPN.
Tunnelblick is a free, open source graphic user interface for OpenVPN on OS X. It provides easy control of OpenVPN client and/or server connections. It comes as a ready-to-use application with all... Read more
Tweetbot 3 for Twitter 3.3.1 - Popular T...
Tweetbot is a full-featured OS X Twitter client with a lot of personality. Whether it's the meticulously-crafted interface, sounds and animation, or features like multiple timelines and column views... Read more
Monosnap 3.5.9 - Versatile screenshot ut...
Monosnap lets you capture screenshots, share files, and record video and .gifs. Features Capture Capture full screen, just part of the screen, or a selected window Make your crop area pixel... Read more
Monosnap 3.5.9 - Versatile screenshot ut...
Monosnap lets you capture screenshots, share files, and record video and .gifs. Features Capture Capture full screen, just part of the screen, or a selected window Make your crop area pixel... Read more
Tweetbot 3 for Twitter 3.3.1 - Popular T...
Tweetbot is a full-featured OS X Twitter client with a lot of personality. Whether it's the meticulously-crafted interface, sounds and animation, or features like multiple timelines and column views... Read more
Tunnelblick 3.8.0 - GUI for OpenVPN.
Tunnelblick is a free, open source graphic user interface for OpenVPN on OS X. It provides easy control of OpenVPN client and/or server connections. It comes as a ready-to-use application with all... Read more
Bookends 13.2.5 - Reference management a...
Bookends is a full-featured bibliography/reference and information-management system for students and professionals. Bookends uses the cloud to sync reference libraries on all the Macs you use.... Read more
Quicken 2019 5.11.2 - Complete personal...
Quicken makes managing your money easier than ever. Whether paying bills, upgrading from Windows, enjoying more reliable downloads, or getting expert product help, Quicken's new and improved features... Read more
Bookends 13.2.5 - Reference management a...
Bookends is a full-featured bibliography/reference and information-management system for students and professionals. Bookends uses the cloud to sync reference libraries on all the Macs you use.... Read more

Latest Forum Discussions

See All

Void Tyrant guide - Tips and tricks for...
Void Tyrant continues to get a lot of play in these parts. Probably because the game is just so deep and varied. The next stop on our guide series for Void Tyrant is class-specific guides. First up is the Knight, as it’s the first class anyone has... | Read more »
Summon beasts and battle evil in epic re...
Imagine a tale of conlict between factions of good and evil, where rogueish heroes summon beasts to aid them in them in warfare and courageously battle dragons over fields of scorched earth and brimstone - that's exactly the essence of epic fantasy... | Read more »
Upcoming visual novel Arranged shines a...
If you’re in the market for a new type of visual novel designed to inform and make you think deeply about its subject matter, then Arranged by Kabuk Games could be exactly what you’re looking for. It’s a wholly unique take on marital traditions in... | Read more »
TEPPEN guide - The three best decks in T...
TEPPEN’s unique take on the collectible card game genre is exciting. It’s just over a week old, but that isn’t stopping lots of folks from speculating about the long-term viability of the game, as well as changes and additions that will happen over... | Read more »
Intergalactic puzzler Silly Memory serve...
Recently released matching puzzler Silly Memory is helping its fans with their intergalactic journeys this month with some very special offers on in-app purchases. In case you missed it, Silly Memory is the debut title of French based indie... | Read more »
TEPPEN guide - Tips and tricks for new p...
TEPPEN is a wild game that nobody asked for, but I’m sure glad it exists. Who would’ve thought that a CCG featuring Capcom characters could be so cool and weird? In case you’re not completely sure what TEPPEN is, make sure to check out our review... | Read more »
Dr. Mario World guide - Other games that...
We now live in a post-Dr. Mario World world, and I gotta say, things don’t feel too different. Nintendo continues to squirt out bad games on phones, causing all but the most stalwart fans of mobile games to question why they even bother... | Read more »
Strategy RPG Brown Dust introduces its b...
Epic turn-based RPG Brown Dust is set to turn 500 days old next week, and to celebrate, Neowiz has just unveiled its biggest and most exciting update yet, offering a host of new rewards, increased gacha rates, and a brand new feature that will... | Read more »
Dr. Mario World is yet another disappoin...
As soon as I booted up Dr. Mario World, I knew I wasn’t going to have fun with it. Nintendo’s record on phones thus far has been pretty spotty, with things trending downward as of late. [Read more] | Read more »
Retro Space Shooter P.3 is now available...
Shoot-em-ups tend to be a dime a dozen on the App Store, but every so often you come across one gem that aims to shake up the genre in a unique way. Developer Devjgame’s P.3 is the latest game seeking to do so this, working as a love letter to the... | Read more »

Price Scanner via

Apple’s $1489 clearance price on refurbished...
Apple has Certified Refurbished 2018 13″ 2.3GHz 4-Core Touch Bar MacBook Pros available starting at $1489. Apple’s one-year warranty is included, shipping is free, and each MacBook has a new outer... Read more
New 2019 13″ 2.4GHz 4-Core MacBook Pros on sa...
Apple resellers B&H Photo and Amazon are offering the new 2019 13″ 2.4GHz 4-Core Touch Bar MacBook Pros for $150 off Apple’s MSRP. These are the same MacBook Pros sold by Apple in its retail and... Read more
B&H drops prices another $50 on clearance...
B&H Photo has dropped prices on clearance 2018 13″ MacBook Airs by a further $50 with models now available for $250 off Apple’s original MSRP. Overnight shipping, or expedited shipping, is free... Read more
Find the best sales & lowest prices on Ap...
Our Apple award-winning price trackers are the best place to look for the best sales and lowest prices on Apple gear. Scan our price trackers for the latest information on sales, bundles, and... Read more
Apple has clearance 2018 13″ MacBook Airs now...
Apple has Certified Refurbished 2018 13″ MacBook Airs available starting at only $849. Each MacBook features a new outer case, comes with a standard Apple one-year warranty, and is shipped free. The... Read more
Save $400 on the 8-Core iMac Pro today at Ama...
Amazon has the base 8-core iMac Pro on sale today for $4599 including free shipping. Their price is $400 off Apple’s MSRP, and it’s the currently lowest price available for an iMac Pro. For the... Read more
Flash sale! New 11″ 1TB WiFi iPad Pros for th...
Amazon has the 11″ 1TB WiFi iPad Pro on sale today for only $1199.99 including free shipping. Their price is $350 off Apple’s MSRP for this model, and it’s the lowest price ever for a 1TB 11″ iPad... Read more
Weekend Deal: 2018 13″ MacBook Airs starting...
B&H Photo has clearance 2018 13″ MacBook Airs available starting at only $999 with all models now available for $200 off Apple’s original MSRP. Overnight shipping, or expedited shipping, is free... Read more
Apple has clearance 10.5″ iPad Pros available...
Apple has Certified Refurbished 2017 10.5″ iPad Pros available starting at $469. An Apple one-year warranty is included with each iPad, outer shells are new, and shipping is free: – 64GB 10″ iPad Pro... Read more
Apple restocks refurbished iPad mini 4 models...
Apple has restocked Certified Refurbished 32GB iPad mini 4 WiFi models for $229 shipped. That’s $70 off original MSRP for the iPad mini 4. Space Gray, Silver, and Gold colors are available. Read more

Jobs Board

Best Buy *Apple* Computing Master - Best Bu...
**711495BR** **Job Title:** Best Buy Apple Computing Master **Job Category:** Store Associates **Location Number:** 000882-Waterfront-Store **Job Description:** The Read more
Best Buy *Apple* Computing Master - Best Bu...
**711597BR** **Job Title:** Best Buy Apple Computing Master **Job Category:** Sales **Location Number:** 000873-Colma CA-Store **Job Description:** **What does a Read more
Best Buy *Apple* Computing Master - Best Bu...
**711346BR** **Job Title:** Best Buy Apple Computing Master **Job Category:** Store Associates **Location Number:** 001095-Chesterfield-Store **Job Description:** Read more
Best Buy *Apple* Computing Master - Best Bu...
**704899BR** **Job Title:** Best Buy Apple Computing Master **Job Category:** Sales **Location Number:** 000135-Pleasant Hill-Store **Job Description:** **What does Read more
Best Buy *Apple* Computing Master - Best Bu...
**707083BR** **Job Title:** Best Buy Apple Computing Master **Job Category:** Sales **Location Number:** 000045-Rockford-Store **Job Description:** **What does a Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.