To implement the IFileViewer interface, the file viewer must implement the three member functions FileShowInitialize, FileShow, and PrintTo.
This is a pre-show function. It allows a file viewer to determine whether it can display a file and, if it can, to perform the necessary initialization operations. The system calls FileShowInitialize before calling IFileViewer::Show. FileShowInitialize must perform all operations that are prone to failure; if it succeeds, IFileViewer::Show will not fail. The system specifies the name of the file that will be displayed by calling the file viewer's IPersistFile::Load member function. This function returns NOERROR if it is successful; otherwise, it returns an OLE-defined error value. In my file viewer, this function calls AddRef, creates the windows it needs, loads the file, stores the filename, and returns the error status.
STDMETHODIMP CFileView::XFileViewer::ShowInitialize (
LPFILEVIEWERSITE lpfsi)
{
METHOD_PROLOGUE (CFileView, FileViewer);
TRACE ("CFileView::XFileViewer::ShowInitialize\n");
HRESULT hr;
// Be sure that you have the file viewer.
if (pThis->m_lpfsi != lpfsi)
{
pThis->m_lpfsi = lpfsi;
pThis->m_lpfsi->AddRef ();
}
// Default error code
hr = E_OUTOFMEMORY;
// Create the windows.
pThis->m_Wnd = new CMyFrame;
pThis->m_Wnd->Create ();
// Load a file.
HGLOBAL hMem=NULL;
char szwFile [512];
if (pThis->m_pszPath == NULL)
return E_UNEXPECTED;
// This file viewer is registered for a TXT extension that
// is either in a compound file (a single stream called
"Text")
// or in a flat text file. This sample shows
// how to open and work with both types of files.
// Make a Unicode copy of the filename.
mbstowcs ((USHORT *)szwFile, pThis->m_pszPath, sizeof
(szwFile));
// CAREFUL: StgIsStorageFile returns S_FALSE if the file doesn't
// contain an IStorage object. Don't use SUCCEEDED to test the
// return value!
if (StgIsStorageFile (szwFile) == NOERROR)
{
LPSTORAGE pIStorage = NULL;
LPSTREAM pIStream = NULL;
STATSTG stat;
// It is a compound file; open it and the text stream.
hr = StgOpenStorage (szwFile, NULL, pThis->m_grfMode, NULL, 0,
&pIStorage);
if (FAILED (hr))
return hr;
mbstowcs ((USHORT *)szwFile, "Text", sizeof (szwFile));
hr = pIStorage->OpenStream (szwFile, 0,
STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE, 0,
&pIStream);
if (SUCCEEDED (hr))
{
// Determine the amount of text and allocate memory.
hr = pIStream->Stat (&stat, STATFLAG_NONAME);
if (SUCCEEDED (hr))
{
hMem = (HGLOBAL) malloc (stat.cbSize.LowPart + 1);
if (hMem != NULL)
// Now load the text into the controls.
hr = pIStream->Read ((LPVOID)hMem, stat.cbSize.LowPart,
NULL);
else
hr = E_OUTOFMEMORY;
}
pIStream->Release ();
}
pIStorage->Release ();
}
else
{
HANDLE hFile;
DWORD dwFileSize, dwBytesRead;
char *lpBufPtr;
// Open the text file.
if ((hFile = CreateFile (pThis->m_pszPath,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
(HANDLE)NULL)) == (HANDLE)(-1))
{
AfxMessageBox ("Failed to open file");
return STG_E_FILENOTFOUND;
}
// Get the size of the file.
dwFileSize = GetFileSize (hFile, NULL);
if (dwFileSize == 0xFFFFFFFF)
return STG_E_READFAULT;
// Allocate a buffer into which the file will be read.
lpBufPtr = (char *) malloc (dwFileSize);
if (lpBufPtr == NULL)
{
CloseHandle (hFile);
return STG_E_READFAULT;
}
// Read the file contents into a buffer.
ReadFile (hFile, (LPVOID)lpBufPtr, dwFileSize, &dwBytesRead,
NULL);
// Update the multiline edit control with the file contents.
pThis->m_Wnd->UpdateEdit (lpBufPtr);
// Close the file.
CloseHandle (hFile);
}
// Tell IFileViewer::Show it's OK to call it.
pThis->m_fShowInit = TRUE;
return NOERROR;
}
This function is used to display a file. The system specifies the name of the file to display by calling the file viewer's IPersistFile::Load member function. This function returns NOERROR if it is successful or E_UNEXPECTED if IFileView::ShowInitialize wasn't called before IFileView::Show. This member function is similar to the Windows ShowWindow function in that it receives a Show command indicating how the file viewer should initially display its window.
STDMETHODIMP CFileView::XFileViewer::Show (LPFVSHOWINFO
pvsi)
{
METHOD_PROLOGUE (CFileView, FileViewer);
TRACE ("CFileView::XFileViewer::Show\n");
if (! pThis->m_fShowInit)
return E_UNEXPECTED;
pThis->m_pvsi = pvsi;
// If you could not view the file, go back to the message loop.
if ((pThis->m_pvsi->dwFlags & FVSIF_NEWFAILED) == 0)
{
if (pThis->m_pvsi->dwFlags & FVSIF_RECT)
pThis->m_Wnd.MoveWindow (pThis->m_pvsi->rect.left,
pThis->m_pvsi->rect.top, pThis->m_pvsi->rect.right,
pThis->m_pvsi->rect.bottom);
pThis->m_Wnd.ShowWindow (pThis->m_pvsi->iShow);
if (pThis->m_pvsi->iShow != SW_HIDE)
{
pThis->m_Wnd.SetForegroundWindow ();
pThis->m_Wnd.UpdateWindow ();
}
// If an old window exists, destroy it now.
if (pThis->m_pvsi->dwFlags & FVSIF_PINNED)
{
pThis->m_lpfsi->SetPinnedWindow (NULL);
pThis->m_lpfsi->SetPinnedWindow (pThis->m_Wnd.m_hWnd);
}
if (pThis->m_pvsi->punkRel != NULL)
{
pThis->m_pvsi->punkRel->Release ();
pThis->m_pvsi->punkRel = NULL;
}
}
return NOERROR;
}
This function prints a file. The system specifies the name of the file to print by calling the file viewer's IPersistFile::Load member function. This function returns NOERROR if it is successful; otherwise, it returns an OLE-defined error value. This member function resembles Show in that it does not return until it finishes printing or an error occurs. If a problem arises, the file viewer object is responsible for informing the user of the problem. This is not implemented in my file viewerit's just a stub.
STDMETHODIMP CFileView::XFileViewer::PrintTo (
LPSTR pszDriver, BOOL fSuppressUI)
{
// This is a stub. Printing isn't implemented.
TRACE ("CFileView::XFileViewer::PrintTo\n");
return E_NOTIMPL;
}