8.2 Data Handler Interfaces

only for RuBoard - do not distribute or recompile

8.2 Data Handler Interfaces

Data handlers implement two interfaces: IPersistFile and IDataObject . Everything that needs to be said about IPersistFile has already been said (see Section 5.2.1 in Chapter 5). Conversely, we know almost nothing about IDataObject . And even when we are done with this chapter, there will still be much that has not been said about this interface. The world of IDataObject is huge. It is one of the fundamental interfaces involved in OLE data transfers.

8.2.1 IDataObject

Table 8.1 shows all nine methods of IDataObject , but only three are required when writing data handlers in Visual Basic: QueryGetData , EnumFormatEtc , and GetData .

Table8.1. The IDataObject Interface

Method

Description

GetData

Retrieves data from a data object, as defined by a FORMATETC structure. The data is then transferred through a STGMEDIUM structure.

GetDataHere

Similar to GetData except the caller is responsible for allocating and freeing all memory associated with FORMATETC and STGMEDIUM .

QueryGetData

Given a FORMATETC structure, this method determines if a resulting call to GetData will be successful.

GetCanonicalFormatEtc

Determines if two different FORMATETC structures would produce the same data, providing a means to eliminate a second call to GetData .

SetData

Allows another object to send data to the data object.

EnumFormatEtc

Provides a means to enumerate all the ways a data object can describe data in a FORMATETC structure.

DAdvise

Creates an event sink between the caller and the data object, allowing the data object to be notified when data changes.

DUnadvise

Releases the event sink created by DAdvise .

EnumDAdvise

Enumerates the active event sinks between the caller and the data object.

8.2.1.1 QueryGetData

This method determines whether the data handler is capable of providing data in the format that is being requested by the shell. This method has the following syntax:

 HRESULT QueryGetData(FORMATETC *pFormatEtc); 

When a data handler is first loaded, the shell calls QueryGetData several times in order to determine what formats the handler can provide. You can picture the shell asking the handler, "Do you support text? Do you support bitmaps? Do you support wave files?" The query comes in the form of a FORMATETC structure. This structure is used to describe data that will be involved in a transfer. It is defined like this:

 typedef struct tagFORMATETC {      CLIPFORMAT cfFormat;      DVTARGETDEVICE *ptd;      DWORD dwAspect;      LONG lindex;      DWORD tymed;  }FORMATETC, *LPFORMATETC; 

Its members are as follows :

cfFormat

Contains the particular clipboard format of interest. This can be one of the following values in the CLIPFORMAT enumeration (this is defined in vbshell.odl ) :

 typedef enum {     CF_TEXT             = 1,   'Text format     CF_BITMAP           = 2,   'Handle to a bitmap     CF_METAFILEPICT     = 3,   'Handle to a metafile picture format     CF_SYLK             = 4,   'Microsoft Symbolic Link format     CF_DIF              = 5,   'Software Art's data interchange format     CF_TIFF             = 6,   'Tagged-image file format     CF_OEMTEXT          = 7,   'Text format in OEM character set     CF_DIB              = 8,   'Memory object containing BITMAPINFO     CF_PALETTE          = 9,   'Handle to a color palette     CF_PENDATA          = 10,  'Data for pen extensions     CF_RIFF             = 11,  'Audio data     CF_WAVE             = 12,  'Audio data in WAV format     CF_UNICODETEXT      = 13,  'Unicode text format     CF_ENHMETAFILE      = 14,  'Handle to enhanced metafile     CF_HDROP            = 15,  'Handle that identifies list of files     CF_LOCALE           = 16,  'Handle to locale identifier     CF_MAX              = 17,  'Undocumented????     CF_OWNERDISPLAY     = 0x0080, 'Owner display format     CF_DSPTEXT          = 0x0081, 'Text in private format     CF_DSPBITMAP        = 0x0082, 'Bitmap display in private format     CF_DSPMETAFILEPICT  = 0x0083, 'Metafile in private format     CF_DSPENHMETAFILE   = 0x008E  'Enhanced metafile in private format } CLIPFORMAT; 
ptd

This member is a pointer to a DVTARGETDEVICE structure that contains information about the target device for which the data is being readied. We will not discuss this parameter for two reasons. First, it would really complicate our discussion. If you need to write a data handler that dumps data to a printer, then you would need this parameter (see the documentation for the Platform SDK). Second, the data handler we will write (and most of the ones you will probably write) are device-independent, so this parameter is meaningless. It will most likely always be 0.

dwAspect

This member can be one of the following values from the DVASPECT enumeration, which is defined like so:

 typedef enum tagDVASPECT {     DVASPECT_CONTENT = 1,     DVASPECT_THUMBNAIL = 2,     DVASPECT_ICON = 4,     DVASPECT_DOCPRINT = 8 } DVASPECT; 

A single clipboard format can support multiple views, or aspects. Think about Explorer when the view is configured as "View as Web Page." If you select a graphics file in the shell, a thumbnail image is shown to the left of the files listing. The data handler involved in this process most likely received a request for the data with this parameter set to DVASPECT_THUMBNAIL .

The members of this enumeration have the following meaning:

Constant

Description

DVASPECT_CONTENT

Returns the data in a format that is ready for the screen or the printer.

DVASPECT_THUMBNAIL

Presents the data in a 120 figs/u00d7.gif 120, 16-color, device-independent bitmap.

DVASPECT_ICON

Provides an iconic representation of the data.

DVASPECT_DOCPRINT

Provides a view of the data on the screen as though it were printed on a printer using the File figs/u2192.gif Print command. The data might represent a series of pages.

lindex

Part of the aspect when the data is split across page boundaries. The most common value is -1, which identifies all of the data. For the aspects DVASPECT_THUMBNAIL and DVASPECT_ICON , this value is ignored.

tymed

One of the TYMED enumeration constants used to indicate the type of storage medium being used to facilitate a data transfer. The enumeration is defined like so:

 typedef enum tagTYMED {     TYMED_HGLOBAL = 1,     TYMED_FILE = 2,     TYMED_ISTREAM = 4,     TYMED_ISTORAGE = 8,     TYMED_GDI = 16,     TYMED_MFPICT = 32,     TYMED_ENHMF = 64,     TYMED_NULL = 0 } TYMED; 

We will use the value TYMED_HGLOBAL to tell the shell that our data transfers will take place via global memory. But as you can see, there are many more options.

8.2.1.2 EnumFormatEtc

Before the shell can get data from the data object, it must retrieve the formats that the object supports. It does this by calling IDataObject::EnumFormatEtc . This method has the following definition:

 HRESULT EnumFormatEtc(DWORD dwDirection,                       IEnumFORMATETC ** ppenumFormatetc); 

Its parameters are:

dwDirection

This is a value from the following enumeration:

 typedef enum tagDATADIR {DATADIR_GET = 1,                          DATADIR_SET = 2, } DATADIR; 

If the value of dwDirection is DATADIR_GET , the shell is asking the data handler to supply all of the formats that can be passed to GetData successfully. Conversely, if dwDirection equals DATADIR_SET , then the shell wants to know which formats will work with a call to SetData . A data handler will not be asked for SetData formats.

ppenumFormatetc

This is an IEnumFORMATETC reference provided by the data object that the shell will use to enumerate all of the formats that the object supports.

8.2.1.3 GetData

Called when the client (Explorer) is ready to receive the data. The function is defined as:

 HRESULT GetData(FORMATETC * pFormatetc, STGMEDIUM * pmedium); 

GetData returns the data in the format described by pFormatetc and transfers this data through pmedium .

FORMATETC should already be familiar to you from the discussion of the IDataObject interface's QueryGetData method. STGMEDIUM , however, requires some explanation. The structure looks like this:

 typedef struct tagSTGMEDIUM {     DWORD tymed;      union {          HBITMAP hBitmap;          HMETAFILEPICT hMetaFilePict;          HENHMETAFILE hEnhMetaFile;          HGLOBAL hGlobal;             LPWSTR lpszFileName;          IStream *pstm;          IStorage *pstg;      };      IUnknown *pUnkForRelease;  }STGMEDIUM; 

Here's how the structure works: the tymed member contains a value from the TYMED enumeration, which has already been seen in our discussion of QueryGetData . This value determines which value of the union is valid. So if tymed is equal to TYMED_HGLOBAL , the hGlobal member of the union should contain the data for the transfer. If tymed is equal to TYMED_ISTREAM , the data should be made available through the IStream * member of the structure.

There is a problem with this structure, however: VB does not support unions. Remember, though, that members of a union occupy the same physical address in memory, so a workaround is fairly simple. We can define the structure like this:

 typedef struct {     TYMED    tymed;     long  pData;            IUnknown *pUnkForRelease;   } STGMEDIUM; 

This works because, naturally, every member of the union is essentially a 4-byte value (a pointer or a handle).

The last member of this structure that needs to be discussed is pUnkForRelease . Remember the ReleaseStgMedium function (see Chapter 4)? This function is called to free the storage allocated by STGMEDIUM . Well, if pUnkForRelease is NULL , then ReleaseStgMedium uses its default methods to release this memory. If it's not NULL , then ReleaseStgMedium uses the IUnknown pointer specified by this member to free the storage. It does this by calling IUnknown::Release .

The IDL listing for IDataObject is shown in Example 8.1.

Example 8.1. IDataObject IDL Definition
 //--------------------------------------------------------- // IDataObject //--------------------------------------------------------- typedef enum {     DV_E_FORMATETC             = 0x80040064,     DV_E_DVTARGETDEVICE        = 0x80040065,     DV_E_STGMEDIUM             = 0x80040066,     DV_E_STATDATA              = 0x80040067,     DV_E_LINDEX                = 0x80040068,     DV_E_TYMED                 = 0x80040069,     DV_E_CLIPFORMAT            = 0x8004006A,     DV_E_DVASPECT              = 0x8004006B,     DV_E_DVTARGETDEVICE_SIZE   = 0x8004006C,     DV_E_NOIVIEWOBJECT         = 0x8004006D } DV_ERROR; typedef enum tagDATADIR {     DATADIR_GET = 1,     DATADIR_SET = 2 } DATADIR; [     uuid(0000010e-0000-0000-C000-000000000046),     helpstring("IDataObject Interface"),     odl ] interface IDataObject : IUnknown {     HRESULT GetData(  [in] FORMATETC *pformatetcIn,   [in,out] STGMEDIUM *pmedium);  HRESULT GetDataHere(  [in] FORMATETC *pformatetc,   [in,out] STGMEDIUM *pmedium);  HRESULT QueryGetData(  [in] FORMATETC *pformatetc);  HRESULT GetCanonicalFormatEtc(  [in] FORMATETC *pformatectIn,   [in,out] FORMATETC *pformatetcOut);  HRESULT SetData(  [in] FORMATETC *pformatetc,   [in] STGMEDIUM *pmedium,  [in] BOOL fRelease);     HRESULT EnumFormatEtc(                    [in] long dwDirection,                    [in,out] IEnumFORMATETC **ppenumFormatEtc);     HRESULT DAdvise(  [in] FORMATETC *pformatetc,  [in] long advf,                    [in] long pAdvSink,                    [in] long pdwConnection);     HRESULT DUnadvise(                    [in] long dwConnection);     HRESULT EnumDAdvise(                    [in] long ppenumAdvise); } 

Notice that throughout the IDL listing for IDataObject , explicit pointers to FORMATETC and STGMEDIUM are used as parameters to several of the methods. This is possible because the members of both of these structures are all automation compatible.


only for RuBoard - do not distribute or recompile


Visual Basic Shell Programming
Visual Basic Shell Programming
ISBN: B00007FY99
EAN: N/A
Year: 2000
Pages: 128

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net