This invention relates generally to a computer method and system for caching presentation data and, more specifically, to a method and system for retrieving and maintaining multiple entries of presentation data in a presentation cache.
Some computer system environments allow data from one application to be integrated with data from another application in such a way that all of the data appears to a user to be managed by one application. The data belonging to the application providing a containment environment for all of the data is typically referred to as native data. The containment environment is typically referred to as a container and the application responsible for providing and managing the container is typically referred to as a container application or container program. The data being incorporated into the native data that is generated by and managed using another application is typically referred to as non-native data. Users can embed non-native data within the native data of a container application by inserting the non-native data into the storage structure of the container application. Or, users can link non-native data into the native data of a container application by storing an indicator to the non-native data in the storage facilities of the container application. When embedded or linked, such non-native data is referred to as source data and the program used to manipulate the source data is referred to as the server program. Consequently, the container program is also referred to as a client program because it is a client of the source data maintained by the server program.
For example, a user may wish to create a document using a word processing application containing a chart created by a spreadsheet application. Such a document is sometimes referred to as a compound document.
Within an environment such as that shown in
If the client program desires to display the non-native data in a format different from that which it has stored (or has access to via a link), then the client program can request the data again from the server program but in a different presentation format. For example, a client program may wish the data in another presentation format to print the native and non-native data together in a paginated format. The client program can then render the data in the new presentation format received from the server program. Requesting the data again from the server program requires the server program to be reloaded and re-executed.
Also, in prior systems that support an object-oriented environment, if the non-native data belongs to an object (objects are discussed further below), then the client program typically invokes a function member of the object requesting the object to draw itself in a particular location or context. Note that this latter technique gives the client program little control over how the object renders the object's data.
The present invention is described below using some object-oriented techniques; thus, an overview of well-known object-oriented programming techniques is provided. Two common characteristics of object-oriented programming languages are support for data encapsulation and data type inheritance. Data encapsulation refers to the binding of functions and data. Inheritance refers to the ability to declare a data type in terms of other data types. In the C++ language, data encapsulation and inheritance are supported through the use of classes. A class is a user-defined type. A class declaration describes the data members and function members of the class. A function member is also referred to as a method of a class. The data members and function members of a class are bound together in that the function operates on an instance of the class. An instance of a class is also called an object of the class. Thus, a class provides a definition for a group of objects with similar properties and common behavior.
To allocate storage for an object of a particular type (class), an object is instantiated. Once instantiated, data can be assigned to the data members of the particular object. Also, once instantiated, the function members of the particular object can be invoked to access and manipulate the data members. Thus, in this manner, the function members implement the behavior of the object, and the object provides a structure for encapsulating data and behavior into a single entity.
To support the concept of inheritance, classes may be derived from (based upon the declaration of) other classes. A derived class is a class that inherits the characteristics—data members and function members—of its base classes. A class that inherits the characteristics of another class is a derived class. A class that does not inherit the characteristics of another class is a primary (root) class. A class whose characteristics are inherited by another class is a base class. A derived class may inherit the characteristics of several classes; that is, a derived class may have several base classes. This is referred to as multiple inheritance.
A class may also specify whether its function members are virtual. Declaring that a function member is virtual means that the function can be overridden by a function of the same name and type in a derived class. If a virtual function is declared without providing an implementation, then it is referred to as a pure virtual function. A pure virtual function is a virtual function declared with the pure specifier, “=0”. If a class specifies a pure virtual function, then any derived class needs to specify an implementation for that function member before that function member may be invoked. A class which contains at least one pure virtual function member is an abstract class.
An advantage of using object-oriented techniques is that these techniques can be used to facilitate the sharing of objects. For example, a program implementing the function members of an instantiated object (the server program) can share the object with another program (the client program). To allow an object of an arbitrary class to be shared with a client program, interfaces are defined through which an object can be accessed without the need for the client program to have access to the class definitions at compile time. An interface is a named set of logically related function members. In C++, an interface is an abstract class with no data members and whose virtual functions are all pure. Thus, an interface provides a published protocol for two programs to communicate. Interfaces are typically used for derivation: a program defines (implements) classes that provide implementations for the interfaces the classes are derived from. Thereafter, objects are created as instances of these derived classes. Objects instantiated from a derived class implementing particular interfaces are said to “support” the interfaces. An object supports one or more interfaces depending upon the desired functionality.
When a client program desires to share an object, the client program needs access to the code that implements the interfaces for the object (the derived class code). To access the derived class code (also referred to as class code), each class implementation is given a unique class identifier (a “CLSID”). For example, code implementing a spreadsheet object developed by Microsoft Corporation may have a class identifier of “MSSpreadsheet,” while code implementing a spreadsheet object developed by another corporation may have a class identifier of “LTSSpreadsheet.” A persistent registry in each computer system is maintained that maps each CLSID to the code that implements the class. Typically, when a spreadsheet program is installed on a computer system, the persistent registry is updated to reflect the availability of that class of spreadsheet objects. So long as a spreadsheet developer implements each function member defined by the interfaces to be supported by spreadsheet objects and so long as the persistent registry is maintained, the client program can access the function members of shared spreadsheet objects without regard to which server program has implemented them or how they have been implemented.
Since an object may support some interfaces and not others, a client program would need to determine at runtime whether a particular object supports a particular interface. To enable this determination, every object preferably supports the interface IUnknown, which contains a function member, QueryInterface, that indicates which interfaces are implemented for the object. The method QueryInterface is defined as follows:
The limitations of prior systems are overcome by the present invention, which is a method and system for retrieving and maintaining presentation data in a presentation cache. In a preferred embodiment, a presentation data cache is provided for caching presentation data of a source object. A program requests that presentation data in a particular format be cached in the presentation cache. This presentation data is then retrieved from a source object and stored in the presentation cache in the requested format. The presentation data previously stored is later retrieved upon request.
In one embodiment of the invention, the presentation data stored in the presentation cache is available even though the server program implementing the source object for the presentation data is unavailable to respond to requests for more presentation data.
In another embodiment, a client program can precisely control which entries in the presentation cache are updated and the frequency of when they are updated.
In another embodiment, presentation data stored in the presentation cache is also stored in the persistent storage of the source object. Methods are available for controlling the frequency and the content of what is stored.
In another embodiment, a client program requests presentation data from a server program that implements a source object. The requested presentation data is cached in a presentation cache such that multiple presentations are available to the client program for rendering the object in different contexts. The client program can further request advisory notification of when the presentation data cached within the presentation cache is updated by the source object.
Embodiments of the present invention provide methods and systems for retrieving and managing multiple instances of presentation data in a presentation cache. A presentation cache is a data structure that stores presentation data in particular formats.
A client program can render the source object data on an appropriate device using the presentation data from any of the cache entries shown in
The presentation cache for a source object is conceptually part of the source object and is stored with the source object when the cache is stored persistently. Client programs can render source object data by requesting the desired data in a particular presentation format and retrieving the presentation data using a data transfer mechanism provided by the underlying system (e.g., the operating system, a language support environment, the object linking and embedding facilities, or other such similar environments). The client program requests presentation data from the source object through the presentation cache object belonging to the source object. The presentation cache object responds to the client program with the requested presentation data if it can satisfy the request from its cached presentation entries. If not, the presentation cache object requests the data from the source object directly.
In addition to requesting and rendering presentation data, the client program can request that particular formats of presentation data be cached and can request how often particular cache entries are to be updated. The server program and the code implementing the presentation cache object can also control the update frequency of the cache entries. Also, the server program can request the presentation cache object to notify the server program when particular formats of presentation data are changed in the source object.
In these interactions, the presentation cache object acts as an intermediary between the client program implementing the container object and the server program implementing the source object. One advantage of the existence of an intermediary presentation cache object is to enable the client program to receive source object data when the server program is not running. This advantage enables container objects containing embedded or linked source objects (non-native data) to be moved to other computing environments where the server program may not be always available. (Note, however, that the presentation cache object may not be able to keep updated presentation data if the server program is not available.)
In a preferred embodiment, the methods and systems of the present invention are implemented on a computer system comprising a central processing unit, a display, a memory, and input/output devices. The preferred embodiment is designed to operate in an object-oriented environment, such as an environment that supports the Microsoft OLE 2.0 (“OLE”) protocol established by Microsoft Corporation in Redmond, Wash. One skilled in the art will also recognize that embodiments of the present invention can be practiced in a non-object-oriented environment as well.
In one aspect of the present invention, a preferred embodiment allows a client program to communicate with (e.g., transfer presentation data to and from) a source object using a presentation cache object. Each server program preferably provides an object handler for each class of source object that the server program implements. The object handler is implemented by object handler code preferably stored as a dynamic link library (“DLL”) which is linked as needed into the code execution memory address space of a client program to help the client program communicate with the server program that implements the source object. All communication between the client program and the server program is preferably directed through the object handler code. Thus, in order for a client program to obtain presentation data for an embedded source object, the client program preferably requests and receives presentation data through the object handler corresponding to the embedded source object. The object handler assists the client program by implementing a presentation cache object for caching presentation data of the source object as requested by the client program.
Specifically, in
In order to dynamically link the object handler DLL into its address space when it loads the embedded object, the client program determines the location of the object handler DLL corresponding to source object 5A04 from the persistent registry. (Recall that each object class has an entry in the persistent registry, based upon the object's CLSID, for maintaining information concerning the location of code supporting the object class and concerning other preferences.) The linking of the object handler DLL is performed by the underlying system automatically when the client program attempts to load the embedded object stored within the persistent storage of container object 5A01.
Once the object handler DLL is linked, the container object 5A01 invokes methods on the object handler 5A02 to request and retrieve presentation data from source object 5A04. In order to facilitate the retrieval and maintenance of such presentation data, object handler 5A02 implements a presentation cache object 5A03. Because the presentation cache object 5A03 is part of the object handler 5A02, the presentation cache 5A03 is conceptually part of the source object. The presentation cache object 5A03 caches (stores) presentation data when it is requested to do so by the client program implementing container object 5A01. Note that the client program need not request that any presentation data be cached within the object handler. Instead, it can request transfers of the presentation data as it needs from the object handler and the object handler will in turn delegate these requests to the source object. One advantage in using the presentation cache object 5A03, is that the object handler DLL, which is linked into the code execution address space of the client program (independent of the state of the server program), can satisfy client program requests for presentation data from presentation cache object 5A03 without executing the server program that implements source object 5A04.
The presentation cache object 5A03 can either cache presentation data in memory or it can also permanently store the presentation data (cache entries) as part of the persistent storage for the source object 5A05. The client program has fine grain control over when the presentation cache 5A03 is updated with new presentation data from the source object 5A04 and over when the information stored in presentation cache 5A03 is stored persistently. In this manner, the client program can control the ability to move the container object 5A01 to other computing environments where the server program implementing source object 5A03 may not be available.
In
Link object 5B02 for the purposes of discussing the present invention provides functionality similar to object handler 5A02 discussed with reference to an embedded object. Link object 5B02 can service some client program requests without actually causing the server program corresponding to the linked object to be run. However, if necessary, the server program for the linked object is executed and the linked source object is placed in the running state. Source object 5B04 represents the linked source object in a running state.
The code implementing link object 5B02 is loaded and dynamically linked into the client program code execution address space in an analogous manner to the manner in which object handler DLL 5A02 is loaded and linked into the client program that implements container object 5A01. Specifically, the CLSID for stored link object 5B02 indicates the appropriate DLL to be dynamically linked when the client program loads the linked object from persistent storage 5B05. Once the DLL implementing the linked object is dynamically linked into the code execution address space of the client program, container object 5B01 invokes methods on link object 5B02 to request and retrieve presentation data from source object 5B04.
In order to facilitate the retrieval and maintenance of presentation data, and in a manner similar to object handler 5A02, the code implementing link object 5B02 implements a presentation cache object 5B03. The presentation cache object 5B03 is similar to presentation cache object 5A03. However, when presentation cache object 5B03 desires to permanently store its cached presentation data, it stores the presentation data as part of the persistent storage for link object 5B02 rather than as part of the persistent storage for source object 5B04. Thus, the cached presentation data is stored with the link, not with the data.
Specifically, in
For the purposes of caching presentation data, the architectures supporting linked versus embedded objects are similar. Thus, the remainder of this description refers primarily to embedded objects. One skilled in the art will appreciate that the description of the preferred embodiment applies to both embedded and linked objects.
Generally speaking, when a client program wishes to display an object, it can do so in three ways. First, the client program can ask the source object to draw itself in a particular context. The object provides a draw method (e.g., the IViewObject::Draw method) in order to support this mechanism. Second, the client program can request the presentation data for the source object in a particular format and render the presentation data. In a typical environment, the object provides a data transfer retrieval method (e.g., the IDataObject::GetData method) to retrieve the presentation data from the source object. Third, a client program can request the object handler to cache presentation data in a presentation format, selected by either the server program or the client program, and can retrieve the cached data and render the data immediately or at a later time (e.g., using the IOleCache::Cache and IDataObject::GetData methods discussed below). Embodiments of the present invention are primarily concerned with supporting this third mechanism.
In a preferred embodiment, the underlying system provides a data transfer mechanism for sending data and getting data to and from objects. Preferably, an IDataObject interface is defined for sending and receiving data that can be rendered whenever the invoking object desires. Preferably an IViewObject interface is defined that contains a Draw method and that can be invoked by a client program to ask the object to draw itself. These data transfer interfaces are typically defined by the underlying object-oriented environment and are discussed in detail in the OLE2 Programmer's Reference. The methods of these interfaces are discussed in detail only as they provide support for or are involved in rendering source object data using presentation formats.
One of the methods provided by the IDataObject interface is the DAdvise method. The IViewObject interface provides a related method, SetAdvise. These methods are used in conjunction with the IAdviseSink interface to set up an advisory connection between two objects. An advisory connection is a connection that exists between two objects such that one object can notify a second object by invoking a method of the second object. Specifically, the DAdvise and SetAdvise methods are called by a client program in order to request a server program to tell the client program when particular data changes. The client program provides a callback routine (which is typically a method of the IAdviseSink interface such as the OnDataChange method) to the source object when the client program invokes the DAdvise or SetAdvise method. Later, when the data changes, the source object invokes the callback method previously provided to let the client program know that data has changed.
With respect to rendering presentation data, two callback routines are used depending upon whether the advisory connection is set up using the DAdvise or SetAdvise method. The (callback) method OnDataChange is invoked by the server program when the presentation data that corresponds to the presentation format requested in the DAdvise connection setup changes. Analogously, the (callback) method OnViewChange is invoked by the server program when the presentation data that corresponds to the advisory connection requested using the IViewObject::SetAdvise method changes. This might happen, for example, if the server program decided to update the data it would normally use to draw itself when requested using the method IViewObject::Draw.
In order to support this communication between the object handler 602 and the server program that implements the source object 603, an advisory connection is established between them using the IDataObject interface of source object 603. The object handler invokes the IDataObject::DAdvise method of source object 603 passing an indicator to its IAdviseSink interface. The server program implementing object 603 can then invoke the OnDataChange method of the IAdviseSink interface of object handler 602 when data within the source object changes. The object handler can then relay these changes to the client program that implements container object 601 through the advisory connections already established as described.
Although not shown in
The following sections provide a detailed discussion of the structures and mechanisms provided by a preferred embodiment to implement and manage a presentation cache for rendering object presentation data.
As can be seen in
The cfFormat member of the FORMATETC structure describes the data format of the presentation data being requested or transferred. The ptd member specifies the destination device for transferring the presentation data (e.g., a printer). The dwAspect member allows a client program to request different parts of the data from an object. The Iindex member further parameterizes the dwAspect member. The tymed member indicates the type of medium to be used for transferring the presentation data.
More specifically, the dwAspect member requests a particular aspect of the object data. An aspect defines a representation of an object. An object can have many representations such as a browsing representation, which is appropriate for viewing only, or a print representation in which the data is formatted for printing. Therefore, by appropriately setting the dwAspect member of the FORMATETC structure, a client program may request a particular part of the object data. In a preferred embodiment, there are preferably at least four values appropriate for the dwAspect member: DVASPECT_CONTENT, DVASPECT_THUMBNAIL, DVASPECT_ICON, and DVASPECT_DOCPRINT. The DVASPECT_CONTENT value signifies a request for a representation of the object appropriate for displaying the object. The DVASPECT_THUMBNAIL value signifies a request for a representation of the object suitable for browsing. The DVASPECT_ICON value signifies a request for an iconic representation of the object. The DVASPECT_DOCPRINT value signifies a request for a printed representation of the object (i.e., formatted as a sequence of pages). One skilled in the art will recognize that the number and type of values can vary.
The lindex member is interpreted based upon the current value of the dwAspect member. When the value of dwAspect is DVASPECT_CONTENT, lindex is preferably a −1. When the value of dwAspect is DVASPECT_DOCPRINT, Iindex indicates a range of pages in the printed representation of the object. Otherwise, Iindex is ignored.
As stated, the tymed member indicates the type of medium for transferring the presentation data. The values for the tymed member correspond to bit positions, thus a client can request any combination of the appropriate values by combining the values using a logical “OR” Boolean operation. The values for the tymed member thus enable a client program to request data transfer over one of a number of media. Typical values for the tymed member are listed in Table 2.
As described earlier, a client program can display objects either by asking the object to draw itself, requesting presentation data and rendering it, or by caching presentation data in a presentation format and then rendering the presentation data at its convenience. Recall also that because the presentation cache is implemented by a presentation cache object within the object handler (which resides in the code execution address space of the client program), the client program can access the presentation data stored within the presentation cache even though the server program implementing the source object is not available or is not running.
Consequently, there are two basic styles for presentation cache usage by a client program. First, the client program can set up the presentation cache and the advisory connections it desires for particular presentation formats so that it can be notified by the object handler when the associated data changes within the source object. Alternatively, the client program can request the object handler to cache data in particular presentation formats, but not request any notification when the associated data changes. Depending upon the request and whether or not the server application is running, the presentation cache entry will be filled at various times. If the client program has not requested any advisory connections, then the client program is not notified of any data changes. However, the client program can explicitly request presentation data preferably at any time and then render it.
As discussed with reference to
IOleCache Interface
The IOleCache interface is used to provide control of what presentation data is actually cached inside an embedded source object (or inside a link object that references a linked source object) and what will therefore be available to a client program even when the server program implementing the source object is either not running or simply not available. Table 3 lists a preferred IOleCache interface. Each method is described in detail following the table.
IOleCache::Cache
The Cache method indicates that the presentation data described by the designated formatetc should be cached. The parameter pformatetc indicates the specific presentation data to cache. The parameter pformatetc can specify either data or view caching; the latter is indicated by passing a zero data format: pformatetc→cfFormat=0. (With view caching, the source object itself, through the object handler, decides what formats to cache in order to handle a future client program request to draw.) The pdwConnection parameter indicates a returned token value that can be used with IOleCache::Uncache( ) to turn off the caching of specific presentation data. The grfAdvf parameter contains a group of flags indicating when the cache should be filled or updated with presentation data. Preferred values for the grfAdvf flags include the following:
The ADVF_NODATA flag is used to indicate that the cache should not be filled by changes in the object (data should not be passed between the source object and the object handler when the source object data changes). Rather, the client program fills the cache by making explicit IOleCache::SetData calls to fill in data. The ADVF_ONLYONCE flag indicates that the cache is to be updated one time only, upon receipt of the first OnDataChange notification from the source object. After this update is complete, the advisory connection between the source object and the presentation cache (through the object handler) is disconnected. The ADVF_PRIMEFIRST flag indicates that the cache is to be filled immediately, not waiting for the first time that the data changes. If the object is not currently running, the cache is in fact filled the first time that the running state is entered. Note that the combination of ADVF_ONLYONCE|ADVF_PRIMEFIRST provides, in effect, an asynchronous cache update because the cache is filled in response to invoking this method and then is not updated subsequently (unless update control is modified or an explicit update is requested). The ADVFCACHE_NOHANDLER flag is reserved for future use. The ADVFCACHE_FORCEBUILTIN flag is used to indicate that the presentation cache object needs to explicitly cache the requested presentation data in persistent storage (even if the presentation cache doesn't normally actually persistently cache the data) to ensure that the presentation data can be retrieved by the client program even when the server program or any customized handler code is not available. Because the stored presentation cache can preferably always be read by an underlying system supplied default handler, once the data has been forcefully cached, the client program is ensured that it can access presentation data using only the underlying system. The ADVFCACHE_ONSAVE flag is used to indicate that the cached presentation data should be updated when the source object containing the presentation cache is saved. (The cache is also updated when the source object transitions from the running state back to the loaded state because a subsequent save operation would require rerunning the object.)
Explicit caching means that the handler has been requested to physically cache the presentation data and to save it with the object storage in order to satisfy client program requests to render an object. Implicit caching, on the other hand, means that the object handler directly supports the presentation data formats that can be requested by a client program and therefore does not need to explicitly store the data in these data formats in persistent storage or in memory. Implicit caching typically occurs when a server program provides a custom object handler that knows how to access and manipulate the source object presentation data directly from persistent storage. The custom object handler in this case directly accesses the IStorage of the object. Note that a client program can insist upon explicit caching by specifying the ADVFCACHE_FORCEBUILTIN flag in the grfAdvf parameter to this method. If explicit caching is being performed by the object handler, then in step 705, the method allocates persistent storage for the cache entry. In step 706, the method gets the presentation data corresponding to the requested presentation format from the source object by invoking the DataObject::GetData method of the source object.
In step 707, the method determines whether the ADF_ONLYONCE update flag was requested by the client and, if so, continues in step 708, else continues in step 709. In step 708, the method sets up an advisory connection with the source object for the client requested data presentation data format and continues in step 709. When the ADVF_ONLYONCE flag is specified by the client program, the cache is updated once when the object handler is notified of the corresponding data change by the source object (through, for example, the object handler's IAdviseSink interface). Thus, for the object handler to fill this cache entry, the object handler needs to set up an advisory connection with the source object as shown in step 708 to receive the data change notification from the source object (e.g., using the method OnDataChange). In step 709, the method returns a unique token associated with this particular presentation cache entry, and returns.
IOleCache::Uncache
The Uncache method removes a cache entry, and any of its associated data connections, as previously set up with IOleCache::Cache. The method has a single parameter, dwConnection, which is a unique token identifying a previously set up presentation cache entry. This parameter value was returned through the pdwConnection parameter in a prior IOleCache::Cache call. If this value does not actually indicate a valid connection, then an error is returned.
I0leCache::EnumCache
The EnumCache method returns an enumerator interface implementation (an instance of an enumerator class) that can enumerate the cache entries presently established. The implementation of this method is dependent upon the data structure used to store the presentation cache. Preferably, enumerators provide methods to return the contents of the next item and to reset to the beginning of the data structure. For example, the enumerator returned would typically enumerate each field in the presentation cache data structure shown in
IOleCache::InitCache
The InitCache method fills the presentation cache as needed from data available from a designated data object. The method has one parameter: a pointer to the IDataObject interface of an object. This method is typically used in the process of creating an object from the clipboard or through a drag-drop operation. The purpose of this method is to fill the presentation cache in the embedded object from other data formats provided on the clipboard or in the drop operation.
IOleCache::Set Data
The method SetData initializes an entry in the presentation cache with designated presentation data. The method has two parameters: a formatetc indicating the particular format of the presentation data and a pointer to the storage medium where the designated presentation data is stored. This method is similar to the IOleCache::InitCache method, but only sets a single presentation cache entry. Another difference between the two is that the InitCache method will preferably not fill up cache entries tagged with ADVFCACHE_NODATA, but SetData will preferably do so.
A client program can use this function in order to maintain a user-set or container-set icon aspect of an object. (Some container objects allow themselves or users to override the icon corresponding to an embedded or linked object.) If the client program desires to set up a cache entry for the icon aspect and fill it with an icon provided by the client program, then the client program creates a cache entry by calling the IOleCache::Cache method with ADVF_NODATA|ADVF_ONLYONCE|ADVF_PRIMEFIRST. The ADVF_NODATA flag specifies that the source object preferably does not provide presentation data when the data changes. The ADVF_ONLYONCE flag prohibits the source object from overriding the cache entry by breaking the advisory connection with the source object (from the object handler) once the cache entry has been filled. The ADVF_PRIMEFIRST flag specifies that the object handler should fill the cache entry immediately. The initialized presentation cache entry can be used to satisfy IViewObject::Draw requests to draw the icon aspect.
CreateDataCache
The CreateDataCache helper function creates and returns a new instance of a presentation cache object implementation provided by the underlying system. The instantiated object supports the IOleCache, IOleCache2, and IOleCacheControl interfaces for controlling the cache, the IPersistStorage interface for getting the source object bits in and out of persistent storage, and the IDataObject, IViewObject, and other interfaces. Typically, this object is used by authors of a server program for a source object implemented as a DLL instead of as a separate executable program (a server DLL).
IOleCache2 Interface
IOleCache2 interface is an extension of the IOleCache interface. It adds the ability for a client program to update with precise control each of the various presentation cache entries currently being maintained. Not all presentation cache objects implement this interface, though it is preferably implemented by the default presentation cache object provided in the system supplied default handler. Table 4 lists a preferred IOleCache2 interface. Each method is described in detail following the table.
IOleCache2::Update Cache
The UpdateCache method initializes the indicated presentation cache entries with the presentation data found in the designated object. The parameter pDataObject is a pointer to an object that contains presentation data for initializing the cache entries (used analogously to the IOleCache::InitCache method). The pointer pReserved is preferably null and is reserved for future use. The parameter grfUpdf is a group of flag bits indicating which presentation cache entries to update. Typical values for grfUpdf are preferably one or more of the following flag bits:
The flags are preferably interpreted as follows. The flag UPDFCACHE_NODATACACHE requests the UpdateCache method to update those cache entries created with the ADVF_NODATA flag in a prior call to IOleCache::Cache. The flag UPDFCACHE_ONSAVECACHE requests the UpdateCache method to update those cache entries created with the ADVFCACHE_ONSAVE flag in a prior call to IOleCache::Cache. The flag UPDFCACHE_ONSTOPCACHE requests the UpdateCache method to update those cache entries created with the ADVFCACHE_ONSTOP flag in a prior call to IOleCache::Cache. The flag UPDFCACHE_NORMALCACHE requests the UpdateCache method to update the other cache entries: the cache entries that were not created with explicit caching update control. These other cache entries are preferably updated on receipt of a data change notification from the running object. The flag UPDFCACHE_IFBLANK requests the UpdateCache method to update those cache entries which are presently blank. The flag UPDFCACHE_ONLYIFBLANK requests the UpdateCache method to update preferably only those cache entries which are presently blank and no others.
IOleCache2::DiscardCache
The DiscardCache method flushes the presentation cache entries presently found in memory, saving them out to persistent storage if dirty or just discarding them (and thus losing them forever) depending on the setting of the parameter dwDiscardOptions. The parameter dwDiscardOptions has one of two values: DISCARDCACHE_SAVEIFDIRTY to indicate a request to update the permanent cache entries stored persistently before discarding the memory version or DISCARDCACHE_NOSAVE to indicate a request to discard the presentation cache entries completely. In the DISCARDCACHE_NOSAVE case, subsequent presentation data requests from the client program will be satisfied by disk based data. Thus, this method allows a client program to synchronize the state of the in-memory version of the presentation cache.
IOleCacheControl Interface
The IOleCacheControl interface is typically used internally in an object handler or server DLL as the means by which the presentation cache part of the handler is connected to the IDataObject interface on the running object. The connection enables the presentation cache object to receive notifications from the running object and to thus maintain its presentation cache entries correctly. The IOleCacheControl interface is preferably supported by the presentation cache object provided by the system supplied default object handler. Table 5 lists a preferred IOleCacheControl interface. Each method is described following the table.
IOleCacheControl::OnRun
The OnRun method alerts the presentation cache object that the source object, which is the data source for the presentation cache, is now in running state. The pDataObject parameter is a pointer to the IDataObject interface of the source object. The presentation cache object will set up advisory notifications as it deems necessary with the source object using the pDataObject interface. If the presentation cache object already believes the source object is running, then this function does nothing. Some server DLLs may choose to use the presentation cache object in a passive manner and to not call the OnRun method. Rather, these programs preferably use IOleCache2::UpdateCache, IOleCache::InitCache, or IOleCache::SetData to fill the cache at the appropriate times.
IOleCacheControl::OnStop
The OnStop method informs the presentation cache object that it should terminate any existing connections with the data source object previously set up using the IOleCacheControl::OnRun method. No indication is given as to whether a connection existed or not.
IAdviseSink Interface
As mentioned earlier, some of the data transfer interfaces are implemented by an object handler to enable controlled access to the presentation cache. The IAdviseSink is an interface used to receive asynchronous notifications that result from a change in the source object. These changes typically occur when an object changes in such a way, for example, that its embedding and linking clients should update their cached presentations of the object. To establish an advisory connection between the source object and the object implemented by the client program (the sink object), the sink object invokes IDataObject::DAdvise on the source object, which eventually results in an IAdviseSink::OnDataChange callback on the sink object. A preferred definition of the IAdviseSink interface is listed in Table 6. The methods of the IAdviseSink as they relate to presentation caching are discussed in detail following the table.
IAdviseSink::OnDataChange
The OnDataChange method reports to the specified sink object that the presentation data for which it has previously requested notification has now changed. The previous request for notification originated by setting up an advisory connection with the source object using the IDataObject::DAdvise method of the source object. For example, as shown in
IAdviseSink::OnViewChange
The OnViewChange method notifies a sink object that the presentation data for which it has previously requested notification has now changed. This notification corresponds to a presentation format chosen by a source object (by its object handler) for rendering the object data (a view). The notification request was made by setting up an advisory connection using the IViewObject::SetAdvise method of the source object. The method has two parameters: the dwAspect parameter specifies the part of the object of concern (e.g., its content, thumbnail sketch, icon, or docprint aspect), and the lindex parameter identifies which subpart of the aspect has changed and is interpreted relative to the dwAspect parameter. The OnViewChange method as implemented by a client program is analogous to the OnDataChange method as implemented by an object handler (shown in
DataObject Interface
The IDataObject and IViewObject interfaces provide basic data transfer mechanisms. The IDataObject interface is used to send and receive client program specified presentation data formats, whereas the IViewObject interface is used to render presentation data in a source object specified data format. The IDataObject interface provides nine methods for data transfer support including GetData, GetDataHere, QueryGetData, GetCanonicalFormatEtc, SetData, EnumFormatEtc, DAdvise, DUnadvise, and EnumDAdvise. A preferred IDataObject interface is listed in Table 7. The methods of the IDataObject interface that are related to presentation caching, as they are typically implemented by an object handler, are discussed in detail following the table. The other methods are listed here for completeness and are discussed in detail in the OLE2 Programmer's Reference.
IDataObject::GetData
The GetData method allows a client program to retrieve presentation data from a source object through the object handler. The client program retrieves data presentations from the source object according to the preferences of the client program. Thus, the client program may request a specific format, a specific aspect, a format for a specific device and conveyance through a specific medium.
The method GetData has two parameters: a requested presentation format and a return parameter containing the retrieved presentation data. The pformatetc parameter is a pointer to a FORMATETC structure described in detail earlier. The members of the FORMATETC structure specify the preferences of the client program for receiving the presentation data. The tymed member of the pformatetc parameter indicates at least one medium type by which the client program would like to receive the presentation data in the specified format. If the object handler can support the requested preferences and one of the requested media, the object handler returns the requested data through the medium designated by the pmedium parameter. Otherwise, if the object handler cannot support the preferences or the requested media, the method GetData returns an error.
IDataObject::GetDataHere
The GetDataHere method is similar to the GetData method, but enables a client program to specify the medium that is to be used for transferring the requested presentation data. Since the method receives a reference to the medium as a parameter, the method copies the requested presentation data onto the medium specified by the parameter. The method preferably still determines whether the object handler can support the requested preferences. The pformatetc pointer is the same as described with reference to the method GetData, except that tymed preferably indicates the type of medium designated by pmedium. The client program preferably allocates the storage medium designated by pmedium.
IDataObject::GetCanonicalFormatEtc
The GetCanonicalFormatEtc method enables a client program to determine what presentation formats will generate unique presentation cache entries for a given input FORMATETC parameter. Thus, the method GetCanonicalFormatEtc enables the client program to determine whether it will receive presentation data equivalent to presentation data the client program has already received. Therefore, if the client program has already requested presentation data caching for a particular presentation format, the client program can use the GetCanonicalFormatEtc method to optimize caching and prevent using memory or disk space for unnecessary duplicate copies.
The method GetCanonicalFormatEtc has two parameters. The pformatetcin input parameter is a pointer to a FORMATETC structure that contains a presentation data preference. The pformatetcOut output parameter is a pointer to a FORMATETC structure that contains the characteristics of the requested presentation data that would be returned by the object handler if presentation data were requested for the format indicated by pformatetcIn. A value is returned to indicate whether the presentation data characteristics of pformatetcOut are the same as the characteristics designated by pformatetcIn.
IDataObject::SetData
The SetData method enables a client program to send data to an object handler to pass on to the source object. Invocation of this method on the object handler has no effect unless the source object is currently in a running state. If the source object is in a running state, the call is delegated to the server program by the object handler DLL.
IDataObject::EnumFormatEtc
The EnumFormatEtc method enumerates the available characteristics of presentation data that can be sent to or received from a source object. This method allows a client program, before requesting or sending data, to determine whether the data can be received or sent according to client program preferences. When invoked on an object handler, the handler provides an instance of an enumerator class that preferably provides methods to return the next available format and to reset to the “beginning” of any structure it keeps. These methods preferably search the presentation cache first for available presentation formats, before delegating the request to the server object (if the server object is running). That is, when a client program requests enumeration of the next formatetc, the enumerator exhausts all of the presentation cache entries first and then, if the object is running, the enumerator delegates the request on to the source object. When the source object responds that it can support no other formatetcs, the object handler indicates that it has enumerated all possibilities. If the source object is not running, the object handler signals that it has enumerated all possibilities when it has exhausted the presentation cache entries. Note that presentation data formats can be registered statically with the persistent registry. In this case, an object handler may choose to use the static list.
The method has two parameters. The wDirection parameter indicates whether the request is for characteristics supported for a SetData or a GetData method. The ppenumFormatEtc is a pointer to an enumerator which enumerates the available formats for the presentation data of the object.
IDataObject::DAdvise
The DAdvise method establishes an advisory connection between an object handler and a sink object. An advisory connection is a logical connection between a sink object and a source object where, when the data of the source object changes, the source object notifies the sink object of the change. (See also the description under the IAdviseSink interface.) The sink object is any object supporting the IAdviseSink interface. To support presentation caching, advisory connections are established both between the container object and the object handler and between the object handler and the source object. A client program calls the object handler's DAdvise method to request the object handler to notify it when the designated presentation data changes and in what manner the client program wishes to be notified. For example, the client can request that the object handler suppress the transfer of data in the notification or that the object handler perform only one notification. In response to the client setting up an advisory connection, the object handler sets up a corresponding advisory connection with the source object. Later, when the data in the source object changes, the source object invokes the IAdviseSink::OnDataChange method of the object handler, which in turn invokes the IAdviseSink::OnDataChange method of the object managed by the client program (see
IViewObject Interface
IViewObject interface enables a client program to request a source object to display a pictorial representation of itself by drawing on a client program provided device context. A device context is a structure provided by the underlying system for communicating to device drivers in order to render data. Independent of the drawing device context, the client program can specify a target device to be used by the source object to compose the picture. The picture can thus be composed for drawing on one target device but can then be drawn on a device context belonging to another device. Different kinds of pictures can be produced from the source object: The client program can ask for a content representation (e.g., to display as an embedding), an iconic representation, etc. In addition, the client program can request an advisory connection so that it can be informed when the data rendered in the picture produced by the object changes.
IViewObject interface is similar to the IDataObject interface, but the source object decides the presentation format to be rendered. The IViewObject interface is typically implemented by the object handler for the source object. That is, the IViewObject interface is typically not implemented by the server program because one role of the object handler is to manage presentation data rendering when the server program is unavailable or not running. The object handler, on behalf of the source object, determines which presentation format to use for drawing presentation data. Preferably, the default object handler provided by the underlying system satisfies a request to draw using one of three data formats in the following order: CF_METAFILEPICT (a metafile script for producing a picture), CF_DIB (a device independent bitmap), and CF_BITMAP (a device dependent bitmap). A custom handler object can be provided if the source object prefers to use a different format. Table 8 lists a preferred IViewObject interface.
When asked to do presentation caching on a source object determined format, the first time that the source object is placed in running state, the object handler invokes the IDataObject::GetData method of the source object with a succession of data formats in order to determine what presentation formats are actually available from the running object. It tries, in order, the following clipboard formats: CF_METAFILEPICT, CF_DIB, and CF_BITMAP. Thus, server programs who choose to rely on the default object handler (that is, do not implement custom handlers) will preferably support these formats in their IDataObject::GetData methods. Internally, the default handler preferably converts CF_BITMAP data to CF_DIB data before storing it persistently.
The method Draw is the primary method used in conjunction with presentation data caching. The other methods are listed here for completeness and are discussed in detail in the OLE2 Programmer's Reference.
IViewObject::Draw
The Draw method requests the object handler to draw a piece of an aspect of the source object on a supplied device context with formatting, font selection, and other compositional decisions made as if the source object were going to be drawn on the designated target device. The method has ten parameters.
Several parameters are the same as those defined for a FORMATETC structure. The dwAspect parameter indicates what kind of picture of the object is requested. Legal values for this parameter are analogous to those described previously for the FORMATETC structure. Preferably only one value is specified. The parameter lindex indicates a range based upon dwAspect. The relationship between the dwAspect parameter and the lindex parameter is analogous to that described previously for the FORMATETC structure. The ptd parameter is a pointer to the target device for which the data is preferably drawn by the object.
The other parameters are as follows. The parameter pvAspect is reserved for further parameterization of what is to be drawn. This parameter is typically NULL. The parameter hicTargetDev is an information context on the ptd target device. It may in fact be a full device context instead of a mere information context, but the object handler should preferably not rely on that. The hdcDraw parameter is a device context onto which the drawing should preferably be done. The lprcBounds parameter points to a structure which indicates the rectangle on the device hdcDraw context on which the presentation data should be drawn. This parameter controls the positioning and stretching of the object. The lprcWBounds parameter is NULL unless hdcDraw is a metafile device context. (Recall that a metafile is a script of graphical drawing calls with the data included.) If non-NULL, then lprcWBounds points to a structure defining the bounding rectangle of the metafile underneath hdcDraw. The rectangle indicated by lprcBounds is nested inside this rectangle; they are in the same coordinate space. The pfnContinue parameter is a callback function that the object handler should call periodically during a lengthy drawing operation to determine whether the operation should be aborted. A return of false (zero) from the callback indicates that the client program desires the drawing to stop, and that the Draw call should return an abort indicator. The callback function is preferably an exported function from the client program. The dwContinue parameter is a value that should be passed back as the argument to pfnContinue.
As mentioned earlier, cached presentation data may or may not be stored persistently. If stored persistently, they are stored as part of the source object's (or the link object's) persistent storage. Because this persistent storage is available to the object handler for the source object once the embedded or linked source object is loaded, the server program implementing the source object need not be running in order to access presentation data from a persistently stored presentation cache.
Presentation cache entries are considered persistent across sessions. That is, when a container object is closed and then later reopened, when its embedded or linked objects are loaded, presentation cache entries stored in the persistent storage are resurrected in order to fill an in-memory version of the presentation cache for use by the object handler. Thus, the presentation cache is persistent, although the advisory connections between the client program, the object handler, and the server program need to be reestablished upon reopening the container object.
The presentation cache object provided by the underlying system supports implicit and explicit caching of presentation data as mentioned earlier. Recall that explicit caching means that the presentation data cached is stored in memory and saved on the source object persistent storage by the time the object is closed. Implicit caching, on the other hand, means that the object handler directly supports access to the source object presentation data from the native data in persistent storage. (The object handler need not even store an in-memory copy in this case.) The presentation cache object provided by the underlying system preferably supports both implicit and explicit data caching. Thus, a custom object handler that wants to access native data can be designed to use the system supplied presentation cache object.
In a preferred embodiment, the underlying operating environment provides structured storage for storing objects. In the Microsoft OLE 2.0 environment, persistent storage for objects is provided through the IStorage and IStream interfaces. These interfaces are discussed in detail in U.S. patent application Ser. No. 07/909,533, entitled “Method and System for Storing and On-Demand Loading of Objects,” which is hereby incorporated by reference. For the purposes of understanding the present invention, the IStorage interface is supported by storage objects, which can contain other storage objects or stream objects. Stream objects are objects that support the IStream interface. The IStorage interface defines methods, among others, for creating and opening child storage and stream objects and for committing transactions to the storage object. The IStream interface defines methods, among others, for reading and writing stream objects. Roughly speaking, the IStream and IStorage interfaces as implemented by specific object implementations support the storage of objects in an analogous manner to the way files and directories support the hierarchical storage of files in a file system.
Typically, objects within the Microsoft OLE 2.0 environment are stored in storage objects that support the IStorage interface even if the object only makes use of one stream within the storage object (for its persistent data). Preferably, each cached instance of presentation data is stored as an object connected to the same storage object to which the source object data is connected (the “parent” storage object). That is, in an abstract sense, both the source object and its cached presentation data are connected to the same parent storage object.
Preferably, the stream object used to store an instance of cached presentation data is named according to a reserved naming scheme for easy recognition by an object handler. For example, in the preferred embodiment, the name of the stream object is prepended with a “\0x02” for recognition purposes. One skilled in the art will recognize that other names are possible.
There are several ways a client program and a server program can assert control over the retrieval or caching of presentation data. As described in detail earlier, a client program can control the updating of cache entries in a presentation cache through the update flags in its request to an object handler to cache a particular format of presentation data (e.g., the grfAdvf parameter in the IOleCache::Cache method). Recall that these flags enable a client program to indicate that the cache is to be filled immediately, or only the first time the data changes, or never automatically by the object handler. In addition, the client program can specify that a particular cache entry should be always persistently saved or saved in persistent storage when the source object is closed. The client program also has control over updating particular cache entries by using either the IOleCache::InitCache method to initialize cache entries from a designated object or by using the IOleCache::SetData method to initialize a single cache entry from designated data. Also, if a presentation cache object supports the IOleCache2 interface, then a client program can use the UpdateCache method to update a series of cache entries from client program supplied data based upon the original update criteria of the cache entries. In addition, the client program can synchronize its non-native data with its native data by using the DiscardCache method to flush the in-memory version of the presentation cache and to optionally save the cache entries in persistent storage.
A server program can also control the contents of the presentation cache associated with the source object. First, within the bounds of the client program request, an object handler for a server program can preferably choose whether or not to persistently store a cache entry and whether or not to request updated data. In this manner, the object handler can optimize interprocess accesses to the server program. Second, a server program can provide a customized object handler instead of relying upon the default object handler provided by the underlying system. One reason a server program might want to provide a customized object handler is to respond to client program-requests for the object to draw itself by providing data in a format other than the three formats supported by the system provided default object handler (CF_METAFILEPICT, CF_DIB, and CF_BITMAP). For example, a server program might desire to draw the source object in its own scripting language instead of the metafile format. In order to do this, the server program typically provides its own custom object handler. Preferably, the custom object handler incorporates the default object handler to enable the server program to delegate all functionality it does not wish to handle to a system supplied object. In addition, the custom object handler preferably instantiates an instance of the system supplied presentation cache object unless the server program wishes to implement its own cache control. Note that in an environment such as the OLE 2.0 environment, objects can be incorporated into other objects using a mechanism known as aggregation. Aggregation is discussed in detail in the OLE2 Programmer's Reference.
As mentioned earlier, there are two basic styles a client program uses to render data using a presentation cache. First, the client program can set up the presentation cache and advisory connections for the particular presentation data changes for which the client program wishes to be notified. Second, the client program can request the object handler to cache particular presentation formats, but not request any advisory connections or notifications of data changes.
Specifically, in step 1701, the client program sets up the presentation cache for all presentation data desired. In response, in step 1704, the object handler code sets up the requested cache entries. In step 1705, the object handler code determines whether the object is running and, if so, continues in step 1707, else continues in step 1706. In 1706, the object handler code continues other processing or waits until the source object transitions to the running state. In step 1707, the object handler code requests presentation data from the object corresponding to the presentation cache entries whose update flags indicate that updating is requested. In step 1708, once the data has been received from the server program, the object handler code fills the appropriate cache entries. In step 1709, the object handler code sets up advisory connections with the server program for cache entries where necessary. In step 1610, the object handler code determines whether it has been notified of a data change and, if so, continues back in step 1707 to retrieve the corresponding presentation data from the server program. Otherwise, the object handler code continues in step 1611 to wait for other data changes or to perform other processing.
The server program once it transitions to running state, notifies the object handler code in step 1612 that it is now running. (This notification is detected in step 1705 in the object handler code.) Sometime later, in the server program message handler for receiving interprocess communication requests, the server program continues in step 1613. In step 1613, the server program determines whether the message received is a request for presentation data and, if so, continues in step 1614, else continues in step 1615. In step 1614, the server program sends the presentation data to the object handler code in the requested format. In step 1615, the server program determines whether the message received is a request to set up an advisory connection and, if so, continues in step 1616, else continues with other message processing. In step 1616, the server program sets up the proper advisory connection depending upon the request. At some later point in the server program processing, when the source object data has changed, the server program will preferably notify any objects that have previously set up advisory connections for the data. In step 1617, the server program determines whether any data has changed and, if so, continues in step 1618, otherwise performs other processing. In step 1618, the server program sends notification to the proper callback routines of the advisees of all advisory connections for that particular presentation data. (This notification is received in the object handler code in step 1610.)
Independent of the object handler code processing and the server program processing, the client program at any time can request data from the source object. For example, in step 1702, the client program sends a request to the object handler to get data from the presentation cache. This request will be answered by the object handler routine responsible for getting data from the presentation cache or for delegating the request to the source object. (For example, see the IDataObject::Get method as described with reference to
One skilled in the art will recognize that there are many ways to combine the methods and interfaces previously discussed in order to render objects using presentation data from a presentation cache.
Although the present invention has been described in terms of preferred embodiments, it is not intended that the invention be limited to these embodiments. Equivalent methods, structures, processes, steps, and other modifications within the spirit of the invention fall within the scope of the invention. The scope of the present invention is defined by the claims which follow.
Number | Date | Country | |
---|---|---|---|
Parent | 08744406 | Nov 1996 | US |
Child | 09314550 | May 1999 | US |
Number | Date | Country | |
---|---|---|---|
Parent | 09314550 | May 1999 | US |
Child | 11137458 | May 2005 | US |
Parent | 08227970 | Apr 1994 | US |
Child | 08744406 | Nov 1996 | US |