This is the big step. To implement the object, you must first add the interface definitions and member variables to the header file FILEVIEW.H. Another very helpful macro, DECLARE_INTERFACE_MAP, supplies the basic COM interface definition. Interface maps are similar to message maps. They provide the standard implementation of the IUnknown interface of the CCmdTarget class, maintaining a reference count and aggregation support.
After declaring the interface map, you need to define the interfaces your object will supportin this case, both IFileViewer and IPersistFile. The BEGIN_INTERFACE_PART macro marks the beginning of the definition, and the END_INTERFACE_PART macro marks the end:
class CFileView : public CCmdTarget
{
§
// Declare the interface map for this object.
DECLARE_INTERFACE_MAP ()
// IFileViewer interface
BEGIN_INTERFACE_PART (FileViewer, IFileViewer)
// IFileViewer stuff
STDMETHOD(ShowInitialize) (LPFILEVIEWERSITE lpfsi);
STDMETHOD(Show) (LPFVSHOWINFO pvsi);
STDMETHOD(PrintTo) (LPSTR pszDriver, BOOL fSuppressUI);
END_INTERFACE_PART (FileViewer)
BEGIN_INTERFACE_PART (PersistFile, IPersistFile)
// IPersistFile
STDMETHODIMP IsDirty ();
STDMETHODIMP Load (LPCOLESTR pszFileName, DWORD dwMode);
STDMETHODIMP Save (LPCOLESTR pszFileName, BOOL fRemember);
STDMETHODIMP SaveCompleted (LPCOLESTR pszFileName);
STDMETHODIMP GetCurFile (LPOLESTR __RPC_FAR *ppszFileName);
STDMETHODIMP GetClassID (LPCLSID pClsID);
END_INTERFACE_PART (PersistFile)
public:
// Member variables
LPFILEVIEWERSITE m_lpfsi; // file viewer site
CLSID m_clsID; // CLSID of this
// file viewer
char m_pszPath [MAX_PATH]; // path from
// IPersistFile::Load
DWORD m_grfMode; // open mode for file
BOOL m_fLoadCalled; // Load already called?
BOOL m_fShowInit; // ShowInitialize called?
CMyFrame *m_Wnd; // viewer frame window
LPFVSHOWINFO m_pvsi;
}
When creating your own file viewer, you need to be concerned about both the IPersistFile interface, which is used to get the path for the file, and the IFileViewer interface, which is notified when a file viewer should show or print a file. For your file viewer to work, it must implement functions for each interface. These interfaces also include the IUnknown member functions AddRef, Release, and QueryInterface.
NOTE: It is extremely important to specify the definitions of the interfaces exactly as they are defined in the header file (in this case, SHLOBJ.H). If you don't do this correctly, your object won't work.
In the FILEVIEW.CPP file, you must also use a few macros to implement a data table that CCmdTarget uses to implement IUnknown, including entries for both IFileViewer and IPersistFile. The first parameter is the name of the class containing the interface object; the second parameter is the IID that is mapped to the embedded class; and the third parameter is the name of the local class:
BEGIN_INTERFACE_MAP (CFileView, CCmdTarget)
INTERFACE_PART (CFileView, IID_IFileViewer, FileViewer)
INTERFACE_PART (CFileView, IID_IPersistFile, PersistFile)
END_INTERFACE_MAP ()