5.7.3 Activating Objects

When the user double-clicks on an object to activate it, the client application should check whether the object is busy by calling the OleQueryReleaseStatus function. If the object is busy, the client application should either refuse the request to open the object or enter a message-dispatch loop, waiting for the OLE_RELEASE notification (see "Handling Asynchronous Operations," earlier in this chapter).

If the object to be activated is not busy, the client application should call the OleActivate function. The client DLL notifies the client application when the server application is open or when an error occurs.

CLIDEMO.EXE activates objects as follows:

.

.

.

case WM_LBUTTONDBLCLK: // execute a verb

ANY_OBJECT_BUSY;

ExecuteVerb(OLEVERB_PRIMARY,(APPITEMPTR)GetWindowWord(hwnd,0));

break;

/*

* ANY_OBJECT_BUSY

* checks to see if any object in the document is busy. This prevents

* a new document from being saved to file if there are objects in

* asynchronous states.

*/

#define ANY_OBJECT_BUSY {\

if (ObjectsBusy()) \

break; \

}

/*

* ObjectsBusy()

*

* This function enumerates the OLE objects in the current document

* and displays a message box stating whether an object is busy.

* This function calls the DisplayBusyMessage() function which

* performs most of the work. This function is only used by the macro

* ANY_OBJECT_BUSY, defined in clidemo.h.

*

* fSelectionOnly BOOL -NOT USED?

*

* BOOL - TRUE if one or more objects found to be busy

* FALSE otherwise

*

*/

BOOL FAR ObjectsBusy ()

{

APPITEMPTR pItem;

if (iTimerID)

{

RetryMessage(NULL,RD_CANCEL);

return TRUE;

}

for (pItem = GetTopItem(); pItem; pItem = GetNextItem(pItem))

if (DisplayBusyMessage(pItem))

return TRUE;

return FALSE;

}

/*

* DisplayBusyMessage()

*

* This function determines if an object is busy and displays

* a message box stating this status.

*

* Returns BOOL - TRUE if object is busy

*/

BOOL FAR DisplayBusyMessage // ENTRY:

(APPITEMPTR paItem) // application item pointer

{ // LOCAL:

if (OleQueryReleaseStatus(paItem->lpObject) == OLE_BUSY)

{

RetryMessage(paItem,RD_CANCEL);

return TRUE;

}

return FALSE;

}

/*

* ExecuteVerb()

*

* Execute the verb for the given object.

*/

void FAR ExecuteVerb // ENTRY:

(int iVerb, // verb

APPITEMPTR pItem) // application item pointer

{ // LOCAL

RECT rc; // holds client area

// bounding rect

if (pItem->otObject == OT_STATIC) // if the object is static beep

{

ErrorMessage(W_STATIC_OBJECT);

return; // return

}

// get client area rectangle

GetClientRect(hwndFrame, (LPRECT)&rc);

// execute OLE verb

if (Error(OleActivate(pItem->lpObject, iVerb, TRUE, TRUE,

hwndFrame, &rc)))

return;

WaitForObject(pItem); // wait for async. operation

} // SUCCESS return

The OleActivate function allows the client application to display the activated object in a window of the server application. (A client application might hide the server window if an object is updated automatically.)

The first time a client application activates a particular embedded object, it should call the OleSetHostNames function, specifying the string the server application window should display in its title bar. This string should be the name of the client document containing the object. The client application does not need to call OleSetHostNames every time an embedded object is activated, because the client DLL maintains a record of the specified names.

A client application can use the OleQueryOpen function to determine whether a specified object is currently open. The OleClose function allows the client application to close an open object. Closing an object terminates the connection with the server application. To reestablish a terminated connection between a linked object and an open server application, the client application can use the OleReconnect function. To close an open object and release it from memory, a client application can call the OleRelease function.