File ViewersFile Viewers*
*



Contents  *



Index  *Topic Contents
*Previous Topic: File Parser Constants
*Next Topic: Help

File Viewers


A file viewer is an OLE COM object implemented inside a 32-bit in-process server dynamic-link library (DLL), which is associated, in turn, with the file viewer's class identifier. A file viewer provides the user interface for viewing a file. Menu items, a toolbar, and a status bar are standard parts of the file viewer interface. A file viewer can optionally add other functionality for further shell integration.

arrowy.gifAbout File Viewers

About File Viewers

The shell allows users to browse through the information in the file system and on the network. Using the Quick View feature of the shell, the user can view the contents of a file without running the application that created it; the application doesn't even have to be installed on the user's computer. To view the file contents, the user selects a file and chooses the Quick View command from the context menu of the selection (or from the File menu). The following illustration shows the context menu.

The context menu.

In response to the user choosing the Quick View command, the shell activates a file-specific viewer for the selected file. The shell uses the extension of the file to determine which viewer to activate. A file viewer associates itself with file classes and file name extensions in the system registry.

A file viewer object, which is separate from the class factory object in the in-process server, uses the standard OLE IPersistFile interface as well as the IFileViewer interface. The shell does not interact directly with file viewer objects. Instead, the shell starts an instance of a small program called Quick View (Quikview.exe) for each file to be viewed. Each instance of Quick View defines a process for a file viewer, giving the viewer its own message queue. Although Quick View is a Microsoft® Windows® executable file, it is not a complete application. It associates a path with a file viewer, creates an instance of the file viewer object, and instructs the file viewer to load and display the file.

Because a file viewer is an OLE COM object, additional interfaces and functionality can be added in future versions of Windows to support new features. For example, a file viewer can act as an OLE container application and can perform in-place activation of embedded objects inside the file being viewed. A file viewer can let the user make a selection in a document and copy the selection to the clipboard or use the selection in a drag-and-drop operation. However, such functionality is entirely up to the developer of the file viewer. This overview describes the basic functionality that a file viewer must provide and discusses user interface guidelines that all developers of file viewers should follow.

Adding or Replacing File Viewers

The file viewer interfaces allow you to add file viewers to Windows. For example, you may need to add a file viewer that supports a new file format or provides additional functionality. To understand how to add a file viewer to Windows, it is important first to understand how the default file viewers work.

The shell calls the Quick View program to display a file. Quick View manages the file viewing process and presents error messages for error conditions returned by the display engines—a collection of DLLs that draws the viewer window and displays the file. Windows includes display engines for word processor documents, spreadsheets, databases, vector graphics, and raster graphics. File parser DLLs are associated with a particular display engine and are specific to a type or class of files. For example, spreadsheet and database files are associated with the spreadsheet and database display engines, respectively. These DLLs are typically between 25K and 75K in size and do all the low-level parsing of the files to be viewed.

There are two methods to add file viewing functionality to Windows. First, a particular file parser DLL may be added to the system. The advantage of this method is that file parsers are relatively straightforward to write and debug. The disadvantage is that the limitations built into the default display engines (such as no printing and no cut, copy, or paste operations) remain even when a new file parsing DLL is used. For more information about the interface between file parsers and display engines, see File Parsers.

The second method of including file viewing functionality in Windows is to add one or more DLLs that work directly with Quick View. An example of one of these file viewing systems for ASCII files is found in the Samples subdirectory of the Microsoft Platform Software Development Kit (SDK). The main advantage of this method is that the code you write can support whatever file viewing functionality you wish to provide. This may be particularly important if your file format does not display well with one of the four default display engines. For example, an accounting package might have this problem because its file format is not recognized by one of the default display engines. The main disadvantage of this method is that writing for the Quick View interface requires additional development and testing effort.

The file viewing technology used by the Quick View feature was developed jointly by Microsoft Corporation and Systems Compatibility Corporation.

File Viewer Registration

During installation, a file viewer should ensure that entries exist in the registry that accurately associate a file with the class identifier of the file viewer's in-process server DLL. The file viewer's installation program may merge the contents of a registration (.reg) file into the registry. A file viewer can register itself for more than one file type if it can handle multiple file formats. If a file type has more than one registered file viewer, the shell activates the most recently registered viewer for the file type when the user chooses the Quick View command.

Determining file types

The Quick View program attempts a simple association using the file name extension. If there is no file name extension or if there are no file viewers registered for the file name extension, Quick View calls each registered file viewer to see if any of them recognize the file. If more than one file viewer is registered for the same file name extension, Quick View calls each file viewer starting with the last one in the list. If Quick View cannot find a file viewer that can read the file, the Quick View operation fails and Quick View displays the following message:

There are no viewers registered for this type of file. Would you like to try the default viewer? 
 

The default viewer displays a hexadecimal dump using the word processing engine.

Structure of registry entries

The following registry structure is required for Quick View to associate a class identifier or file name extension with the class identifier of a file viewer.

HKEY_CLASSES_ROOT 
    \QuickView 
        \<extension> = <human-readable document type> 
            \{<CLSID>} = <human-readable viewer name> 
            \{<CLSID>} = <human-readable viewer name> 
            \{<CLSID>} = <human-readable viewer name> 
 
        ...[More extension entries for additional file types] 
            ... 
 
    \CLSID 
        \{<CLSID>} = <human-readable viewer name> 
            \InprocServer32 = <full path to file viewer DLL> 
                            = ThreadingModel = "Apartment" 
 
        ...[More class IDs for file viewers and other object servers] 
 

A description of the registry entries follows.
Entry Description
HKEY_CLASSES_ROOT Root of the registry.
QuickView Top-level key under which associations are stored.
CLSID 16-byte OLE class identifier spelled out in hexadecimal digits in the form of 12345678-1234-1234-1234-1234567890AB (with the hyphens included). All class identifiers are surrounded by curly braces when stored in the registry.
human-readable document type String describing the file type associated with the class identifier or file name extension that can be displayed to the user. A file viewer can change the type when it is installed so that the name always reflects the preferred viewer. For example, this string might be "Windows Write Document."
human-readable viewer name String that describes the vendor of the file viewer, as it might be displayed in an About box, such as "Company ABC Write Document Viewer."
<extension> Three-character file name extension with the period, as is consistent with the standard 8.3 file name format (for example, .wri).

CLSID and InprocServer32 are standard OLE (32-bit) subkey names. The "ThreadingModel = Apartment" entry is required for file viewers. The apartment threading model, which is new for OLE in Microsoft Windows 95 and Microsoft Windows NT® version 3.51, allows the OleInitialize and CoInitialize functions to be called from multiple threads.

The QuickView key can have any number of file name extension subkeys, each representing a registered file type. Each file name extension subkey can have one or more class identifier subkeys, each representing a registered file viewer object. The most recently registered file viewer appears first in the list of class identifier subkeys, and it is the first one found when Quick View enumerates the registered file viewers.

Note The file viewer class identifier should always differ from the file type class identifier because the application that created the file may already be using the file type class identifier to identify the application as a compound document server.

Each class identifier stored under the file name extension subkeys must correspond to an entry of the same class identifier stored under the top-level key called CLSID. This is the standard location for storing information for OLE object servers. For file viewers, there must be an InprocServer32 subkey under the file viewer's class identifier key. The value of the InprocServer32 subkey is the full path to the file viewer DLL. You should store the full path and not depend on the DLL being in the path of the Windows 95 environment. InprocServer32 is a standard OLE subkey where the path to a COM object server is stored. Using this subkey allows the Quick View program to use standard OLE methods to access and create objects from file viewer servers.

Registering a file viewer

This section shows how to register a hypothetical file viewer for "AcmeWord Document" files with the .awd file name extension. The file viewer is implemented in an in-process server DLL called Acmewrdv.dll. The DLL has this class identifier: 00021116-0000-0000-C000-000000000046. The program that installs the file viewer creates the following registry entries:

HKEY_CLASSES_ROOT 
    \QuickView 
        \.AWD = AcmeWord Document 
            \{00021117-0000-0000-C000-000000000046} = AcmeWord Document 
                                                      Viewer 
    \CLSID 
        \{00021117-0000-0000-C000-000000000046} = AcmeWord Document 
                                                  Viewer 
            \InprocServer32 = c:\acmeword\acmewrdv.dll 
                            = ThreadingModel = "Apartment" 
 

The .reg file, which is an ASCII text file, contains these entries. (Note that wrapped lines are indented on the second line.)

HKEY_CLASSES_ROOT\QuickView\.AWD = AcmeWord Document 
HKEY_CLASSES_ROOT\QuickView\.AWD \{00021117-0000-0000-C000-
    000000000046} = AcmeWord Document Viewer 
HKEY_CLASSES_ROOT\CLSID\{00021117-0000-0000-C000-000000000046} = 
    AcmeWord Document Viewer 
HKEY_CLASSES_ROOT\CLSID\{00021117-0000-0000-C000-000000000046} 
    \InprocServer32 = c:\acmeword\acmewrdv.dll 
                    = ThreadingModel = "Apartment" 
 

The Quick View program uses these registry entries to associate a path with the class identifier of a file viewer's in-process server DLL.

Quick View Program

The Quick View program (Quikview.exe) acts on behalf of the shell to locate and activate a file viewer for a given path. There is a one-to-one correspondence between each running instance of Quick View and each file being displayed in a file viewer. Each instance of Quick View defines a process for a file viewer, giving the file viewer its own message queue. Quick View turns over execution of the process to the file viewer until the file viewer shuts down.

Quick view execution and error conditions

The lifetime of each instance of the Quick View program consists of the following steps.

  1. When the user chooses the Quick View or Print command, the shell starts an instance of Quikview.exe for each selected file (by using the Microsoft Win32® CreateProcess or WinExec function). The shell may specify a Show command, and Quick View passes the command to the file viewer. The command-line argument that the shell passes to Quick View has the following options.
    Option Meaning
    -f:pathname Path of the file to view or print. Universal Naming Convention (UNC) file names are allowed. If this option is not specified, Quick View terminates without displaying any messages.
    -v File to be opened for viewing in the file viewer. If this option is specified, Quick View ignores all of the options described below. This is the default option in the absence of both -v and -p.
    -d Quick View and the file viewer will suppress all user interface elements if -p is also specified. Quick View suppresses any error messages, and the file viewer should not display any dialog boxes for printing. Quick View ignores this option in the absence of -p.
    -p File to be opened for printing. If -v is also present, Quick View ignores this option.
    -&:pathname Printer driver to use to print the file. Quick View ignores this option in the absence of -p. If -p is present but -& is not, Quick View instructs the file viewer to use the default printer driver.
  2. Quick View starts and checks for a path on the command line. If there is no path, the user has attempted to start Quick View by itself and the program immediately terminates without displaying any messages.
  3. Quick View parses the file name extension from the path given in the -f option. If no file name extension is given, Quick View proceeds to stage E1 (error condition 1). Otherwise, Quick View uses the following procedure to find a file viewer class identifier associated with the given file name extension.
    A. Quick View attempts to open the HKEY_CLASS_ROOT\QuickView\extension key, where extension is parsed from the path.
    • If the file name extension maps to a type such as HKEY_CLASS_ROOT\extension = typename and there is a registry entry with the form HKEY_CLASS_ROOT\typename\QuickView = *, Quick View looks for file viewer class identifiers under HKEY_CLASS_ROOT\QuickView\*. If a key with the HKEY_CLASS_ROOT\*\QuickView = * form exists, the system attempts to use all the viewers listed under the "*" section.
    • Otherwise, Quick View begins enumerating the file viewer class identifiers under the HKEY_CLASS_ROOT\QuickView\extension key. If the enumeration fails (that is, there is nothing in the registry to enumerate), Quick View closes the key and proceeds to stage E2 (error condition 2). Otherwise, Quick View reads the first file viewer class identifier in the enumeration and proceeds to step 4.
    B. If an error occurs in step 4, the enumeration continues until all file viewer class identifiers have been tried. If no file viewer is activated, Quick View closes the key from A and proceeds to stage E2.
  4. When given a class identifier of a file viewer DLL, Quick View attempts to create an instance of a file viewer object of the given class by using the following procedure:
    A. Quick View calls a function to create an instance of a file viewer object, specifying parameters that include the class identifier and the IID_IPersistFile interface identifier. This instructs OLE to load the DLL listed under the class identifier's InprocServer32 subkey, obtain an instance of the object from the DLL, and return an IPersistFile interface pointer to the object. If the instance cannot be created because of lack of memory, Quick View proceeds to stage E4. If it fails for some other reason, Quick View proceeds to stage E3. (Note that, because DLL objects are involved, any call to QueryInterface will not fail with REGDB_IID_NOTREG, which typically signals a corrupted registry. That error is generated only when LRPC proxies and stubs are involved.)
    B. When given the IPersistFile interface pointer pIPersistFile, Quick View calls the IPersistFile::Load method, specifying the path of the file and the STGM_READ and STGM_SHARE_DENY_NONE values, which instruct the object to open the file for read access. If Load fails, Quick View calls the Release method of pIPersistFile and proceeds to stage E4 if the error is due to a lack of memory. Otherwise, Quick View proceeds to stage E3.
    C. Quick View obtains the file viewer object's IFileViewer interface by specifying the IID_IFileViewer interface identifier in a call to the QueryInterface method of pIPersistFile. Quick View calls the Release method of pIPersistFile, regardless of the outcome. If this call fails due to lack of memory, Quick View proceeds to stage E4. Otherwise, Quick View proceeds to stage E3.
    D. (1) If the -v option was present or both the -v and -p options were absent, Quick View calls the ShowInitialize method of pIFileViewer, which instructs the file viewer to load the file and perform any initialization prone to failure (including the creation of windows, the loading of resources, and so on). This is the file viewer's one chance to fail. If it fails, Quick View proceeds to stage E4 if the error is due to lack of memory or to stage E3 otherwise. If ShowInitialize succeeds, Quick View calls the Show method of pIFileViewer, specifying the show command that was passed to Quick View's WinMain function. Show does not return until the user closes the file viewer, and it always returns NOERROR in that case. If Show is called before ShowInitialize, it returns E_UNEXPECTED.
    (2) If the -p option was present (and the -v option was absent), Quick View calls the PrintTo method of pIFileViewer specifying the path of the printer driver provided in the -& option (or NULL if -& was absent) and a value indicating if the -d option was present on the command line (user interface suppression flag). PrintTo does not return until printing is complete or an error occurs. If an error occurs, the file viewer is responsible for notifying the user if the user interface suppression flag is FALSE.
    E. When Show or PrintTo returns (whichever was called in steps D1 or D2), Quick View calls the Release method of pIFileViewer, regardless of the return value. If the file viewer successfully executed the IFileViewer::ShowInitialize method, the Release method will not fail. Release fails only if it is called before ShowInitialize. If PrintTo fails but the -d option was not specified on the command line, Quick View assumes that the file viewer displayed a message to indicate printing failed, and Quick View fails without displaying a message in that case. In any case, Quick View proceeds to step 5.
  5. Quick View releases any interface pointers it has and calls OleUninitialize. Quick View then terminates normally.

Quick View may encounter these four error conditions (stages E1 through E4) during the lifetime of an instance:

E1 If Quick View fails to associate the path with a file viewer class identifier (using a file name extension), it displays this message.
There are no viewers for this type of file. Would you like to try the default viewers? 

If the user clicks No, Quick View terminates. If the user clicks Yes, Quick View displays the Searching dialog box, enumerates all registered file viewers (regardless of file type or file name extension), and attempts to have each one load and display the file. Quick View tries each file viewer of a given class identifier once. If no file viewer successfully displays the file, Quick View removes the Searching dialog box and displays this message.

Error opening or reading file. 
When the user closes the dialog box, Quick View terminates.
E2 If Quick View successfully determines the file type but fails to enumerate any file viewers associated with the file name extension, it displays the Searching dialog box and attempts to have each registered viewer display the file, trying each file viewer class identifier once. If that fails, the Quick View removes the Searching dialog box and displays this message.
There are no viewers capable of viewing human-readable document type files. 
When the user closes the dialog box, Quick View terminates.
E3 If Quick View successfully locates an initial file viewer but fails to view the file for any reason other than an out-of-memory condition, Quick View displays the Searching dialog box and continues enumerating viewers under the class identifier or file name extension key currently in use. If Quick View tries all viewers registered for the type unsuccessfully, processing continues as in stage E2 by trying all registered viewers regardless of registered type.
E4 If an out-of-memory condition occurs for one file viewer, it is likely that other viewers will not succeed either. In that case, Quick View displays a dialog box (using MB_ICONEXCLAMATION) with this message.
There is not enough memory to view or print file name. Quit one or more files or programs, and then try again. 

A file viewer can return a number of error values to Quick View. When Quick View receives an error value, it displays an error message. Quick View recognizes the following error values:
FV_E_BADFILE ((HRESULT)0x8534E102L)
FV_E_EMPTYFILE ((HRESULT)0x8534E108L)
FV_E_FILEOPENFAILED ((HRESULT)0x8534E105L)
FV_E_INVALIDID ((HRESULT)0x8534E106L)
FV_E_MISSINGFILES ((HRESULT)0x8534E104L)
FV_E_NOFILTER ((HRESULT)0x8534E100L)
FV_E_NONSUPPORTEDTYPE ((HRESULT)0x8534E101L)
FV_E_NOVIEWER ((HRESULT)0x8534E10AL)
FV_E_OUTOFMEMORY ((HRESULT)0x8534E107L)
FV_E_PROTECTEDFILE ((HRESULT)0x8534E109L)
FV_E_UNEXPECTED ((HRESULT)0x8534E103L)

Pinned windows

The shell can request that Quick View display a new file in the same window used by the previous file viewer; this is called pinning a viewer window. Quick View communicates the shell's request by sending a WM_DROPFILES message to the file viewer. The message contains an internal drop files structure whose members include the path of the new file to be displayed. A file viewer uses the same code to handle both the pinned state and drag-and-drop operations in which the file viewer displays a file the user has dropped on the viewer window.

Quick View implements the IFileViewerSite interface, which allows a file viewer to retrieve the handle to the current pinned window, if there is one, or set a new pinned window. When Quick View calls a file viewer's IFileViewer::ShowInitialize method, the file viewer receives the address of Quick View's IFileViewerSite interface. If the file viewer saves the address of the interface, it should call the AddRef method to increment the reference count.

Only one pinned window can exist at a time. A file viewer uses the IFileViewerSite::SetPinnedWindow method to set a new pinned window and the IFileViewerSite::GetPinnedWindow method to retrieve the handle to the current pinned window.

When Quick View calls the file viewer's IFileViewer::Show method, the file viewer receives the address of an FVSHOWINFO structure that includes an optional RECT structure. A valid RECT structure is a hint from the shell that the file viewer window should be pinned; the file viewer should set the size and position of its window based on the information in the structure.

If the file viewer window receives a WM_DROPFILES message, it should fill in the strNewFile member of the FVSHOWINFO structure with the path of the new file to be displayed, fill the rect member with the size and position of the viewer window, and set the appropriate values in the dwFlags member. The file viewer should also fill the punkrel member with the address of an interface that the new file viewer should call to release the previous file viewer. Doing this allows the previous file viewer to perform cleanup operations. The new file viewer may be the same as the current file viewer if the current one supports the new file. If the old file viewer is the same as the new one, the release does not do anything because the reference count is greater than zero.

If a file viewer returns a file but Quick View cannot find a viewer for the new file, it calls the IFileViewer::Show method for the old file viewer with the FVSIF_NEWFAILED value. The file viewer can either terminate or continue showing the previous file.

Searching dialog box

When Quick View must enumerate more than one file viewer from the registry, it displays a dialog box containing a message that reads as follows:

Searching for a viewer to display or print the <human-readable 
document type> in <file name>. Press Cancel to stop the search. 
 

If the document type is not known, the following message appears:

Searching for a viewer to display or print <file name>. 
Press Cancel to stop the search. 
 

Quick View animates the magnifying glass icon in the dialog box to indicate that Quick View is searching the hard disk. Pressing the Cancel button stops any search in progress and closes Quick View without performing any further actions or providing any user interface.

File Viewer Structure and Implementation

A file viewer is an OLE COM object in an in-process server DLL that implements the IPersistFile and IFileViewer interfaces. The in-process server exports the DllGetClassObject and DllCanUnloadNow functions, implements a class factory object with the IClassFactory interface, and implements the file viewer object with the interfaces required. The following illustration shows the structure of a file viewer.

Structure of a file viewer.

There are a number of reasons why a file viewer is best implemented in a DLL with the given interfaces. In general, a DLL is faster to load and usually comes in a small package. In the future, these same DLLs will provide other nonuser interface features, such as content indexing, and a COM object DLL will be the fastest and most efficient way to access those features. In some cases, a file viewer object may need to display pop-up windows and process messages through its own message loop as in Windows 95. The DLL structure still allows this when used in conjunction with a stub process like Quick View, which gives the file viewer DLL the right to execute a message loop.

The IPersistFile interface in the file viewer object is intended to be a general mechanism through which the object is given a path for a file. Once the IPersistFile interface is obtained, the component that loaded the object can ask it to do any number of things with the file. Through Quick View, the Windows 95 shell asks the object to show the file by using the IFileViewer::ShowInitialize and IFileViewer::Show methods or asks the object to print the file to a specific printer by using the IFileViewer::PrintTo method. In the future, the shell may ask the object to perform content indexing, which would happen through an interface other than IFileViewer. For this reason, the file loading methods of IPersistFile are separate from the IFileViewer file methods, which is why IFileViewer was not just extended with its own Load method. Extending IFileViewer would have been more efficient (because it avoids IPersistFile entry point functions that are not implemented), but the current design is easier to extend.

IFileViewer interface

The shell uses the IFileViewer interface to print the file or to tell a file viewer object when to show its user interface for the file being viewed. In addition to the usual IUnknown members, the interface includes the IFileViewer::ShowInitialize, IFileViewer::Show, and IFileViewer::PrintTo methods.

Before calling IFileViewer::Show, the shell calls IFileViewer::ShowInitialize to instruct the file viewer to perform any necessary initialization. ShowInitialize can fail, whereas Show cannot because Quick View needs to know, before anything becomes visible and before transferring control to the file viewer, whether the file viewer can show the file. If the file viewer can show the file, Quick View hides its Searching dialog box before the file viewer window appears.

The ShowInitialize method should return the FV_ error codes listed in the Structure of registry entries section. Although the sample file viewer included in the Microsoft Platform SDK uses a more generic form of error codes, new file viewer DLLs should use the FV_ codes.

The Show method is similar to the Windows ShowWindow function in that it receives a Show command indicating how the file viewer should initially display its window. In general, Quick View passes the Show command from its WinMain function directly to IFileViewer::Show, which passes the command to ShowWindow. Since Quick View obtains this parameter from the shell, this design enables the shell to open a file viewer in the minimized, normal, or maximized state and even allows the shell to hide a file viewer (with the SW_HIDE value). There is no extra overhead in providing this flexibility. Note that the Windows 95 shell always starts Quick View with the SW_SHOWNORMAL value.

The only case when Show can fail is if ShowInitialize has not been called. In that case, it returns the E_UNEXPECTED status code. Otherwise, Show must return the NOERROR error code.

The PrintTo method is like Show in that it does not return until it finishes printing or an error occurs. If an error occurs, the file viewer object is responsible for informing the user of the problem. When calling PrintTo, the shell specifies the name of the printer driver that the file viewer should use to print the file. The shell also specifies a flag that indicates whether the file viewer should display any user interface elements, including error messages, during the print operation. If the flag is FALSE, the file viewer may show Print dialog boxes, Printer Setup dialog boxes, error messages, and so on.

The IFileViewer interface identifier is defined in the Windows header files as the IID_IFileViewer.

File viewer creation

You can create a file viewer that interacts appropriately with Quick View by following these steps:

  1. Define the file viewer object to use the IPersistFile and IFileViewer interfaces. The object must also implement a separate IUnknown interface that does not delegate calls in aggregation situations. In general, a file viewer object creates or attaches to a window that displays a file's contents.
  2. Implement the IPersistFile::Load and IPersistFile::GetCurFile methods (as well as the IUnknown methods). The IPersistFile::IsDirty method can simply return ResultFromScode (S_FALSE) because a file viewer does not modify the file, and the IPersistFile::Save and IPersistFile::SaveCompleted methods should simply return ResultFromScode (E_NOTIMPL). IPersistFile::Load stores the file name but delays opening the file until the later call to the IFileViewer::ShowInitialize method. IPersistFile::GetCurFile returns ResultFromScode (E_UNEXPECTED) if Load has not yet been called. Otherwise, it copies the path and returns the NOERROR error code.
  3. Implement the IFileViewer::ShowInitialize and IFileViewer::Show methods (as well as the IUnknown methods). ShowInitialize must perform all operations that are prone to failure. Therefore, if ShowInitialize succeeds, Show will never fail. The implementation of these two member functions is similar to the implementation of an application's WinMain function. ShowInitialize registers window classes, creates any necessary windows, and loads the file as read-only with the path given in the IPersistFile::Load method. ShowInitialize uses the instance handle that the DLL receives in its DllEntryPoint function, not the instance of Quick View, when registering and creating windows. Then Show displays the contents of the file in the viewport window, shows the top-level file viewer window, and enters a message loop. To enhance the appearance of the user interface, the file should be loaded and completely displayed in the viewport window before the windows are made visible.

    IFileViewer::Show does not return until the user has closed the window; Quick View waits for Show to return before it terminates. Quick View delegates the responsibility of the message loop to the Show method, so ShowInitialize and Show look and behave exactly like a WinMain function in any application (the code is just stored in a DLL).

    Note that the path in the IPersistFile::Load method may be a uniform naming convention (UNC) path. Functions such as Win32 OpenFile and OLE StgOpenStorage automatically handle UNC paths. If you open a file any other way, you must be sure to handle UNC paths properly.

  4. Define the class factory object with the IClassFactory interface and implement the interface completely to create a file viewer object. The class factory must support aggregation and server locking, as required by the IClassFactory interface.
  5. Implement the DllGetClassObject function to create an instance of the class factory mentioned in step 4, and return a pointer to one of its interfaces, as required for any COM object DLL.
  6. Implement the DllCanUnloadNow function to return the appropriate code, depending on the number of file viewer objects in service and the number of lock counts implemented by using the IClassFactory::LockServer method, as required for any COM object DLL.
  7. Include the Print To feature by using the IFileViewer::PrintTo method. This step is optional. If this feature is not implemented, the member function must return ResultFromScode (E_NOTIMPL).
  8. Finish the DLL implementation by using the DllEntryPoint function, as required for any Win32-based DLL.

In general, only the implementations of IPersistFile::Load and the IFileViewer methods are specific to a file viewer. The other steps that deal with creating an OLE COM object are standard OLE mechanisms.

File Viewer User Interface Guidelines

This section describes the minimal user interface recommended for a file viewer. These guidelines are provided to promote a consistent user interface in all file viewers. You should follow these guidelines as closely as possible and include viewer-specific features within the context of these guidelines.

File viewer main window

A file viewer's main window should have Minimize, Maximize, and Close buttons and these top-level menu items: File, View, and Help. A file viewer should also include a toolbar and a status window. The appearance and contents of the viewport window, which occupies all space not used by the toolbar and status window, is left to the developer. However, the viewport window typically has proportional scroll bars if the file contents are not entirely visible in the viewport. The initial show state of the window (normal, minimized, or maximized) is given in the IFileViewer::Show method.

The following illustration shows an example of a file viewer window.

File viewer window in the typical initial state.

A file viewer can include other top-level menu items for file-specific features. For example, a file viewer should include an Edit menu with a single Copy command to allow the user to make a selection in the viewport window and copy it to the clipboard. However, such extensions are not part of the basic user interface for a file viewer.

You should also use the window flags to create a 3-D window appearance and use scroll bars with proportional scroll boxes.

File viewer File menu items

The standard file viewer File menu has the following four items (as well as separators), two of which are optional. A file viewer can add other items to the menu, but in most cases there is no need for other items.
Menu item string Result of selecting the menu item
"&Open File for Editing" Locates and starts the application that can open and edit the file. After successfully starting the application, the file viewer should hide its window immediately, shut down, and return from IFileViewer::Show, after which the Quick View process terminates. If the file viewer fails to start the application, it should display the following message:
There is no application available that can open this file.
Separator Not applicable.
"Page Set&up" (optional) Activates the standard Page Setup dialog box (or an application-specific dialog box if desired), the results of which affect the display of the file in the viewport window. The effects of the Page Setup command last only for the duration of the file viewer and do not affect the contents of the disk file. This menu item should appear if the file viewer supports printing and only if the Print menu item appears as well.
"&Print\tCtrl+P" (optional) Activates the standard Print/Printer Setup property sheet. Any changes made to the printer setup that would affect the display of the file in the viewport window last only for the duration of the file viewer and do not affect the contents of the disk file. This menu item should appear only if the file viewer supports printing a file without starting the full application.
Separator Not applicable.
"E&xit" Hides the main window, closes the file, destroys all the windows, performs other necessary cleanup, and returns with NOERROR from IFileViewer::Show. The window should be hidden before cleanup happens to avoid marring its appearance when the system destroys the toolbar and other controls.

File viewer View menu items

The View menu of a standard file viewer has the following items.
Menu item string Result of selecting the menu item
"&Toolbar" Used to switch between displaying and hiding the toolbar. This item is checked when the toolbar is visible and unchecked when it is hidden.
"&Status Bar" Used to switch between displaying and hiding the status window. This item is checked when the status bar is visible and unchecked when it is hidden.
"&Page View" Used to switch between a full-sized view and a single-page view and vice versa.
"Replace &Window" Used to switch between reusing the current window to view a file and creating a new window to view a file.
Separator Not applicable.
"&Landscape" Used to switch between landscape and portrait views when in page view.
"&Rotate" Rotates a raster graphic image 90 degrees every time the image is selected.
Separator Not applicable.
"&Font" Displays a dialog box that allows the user to select a font and point size for viewing word processing documents and spreadsheets.

File viewer Help menu items

The standard file viewer Help menu has the following items.
Menu item string Result of selecting the menu item
"&Help Topics" Activates Winhelp.exe with the file viewer's Help file.
"&About fileviewer name" Displays an About dialog box for the file viewer. The About dialog box identifies the vendor of the file viewer.

A file viewer can also add other Help items and context-sensitive Help.

File viewer toolbar buttons

A file viewer must include a toolbar with a single button tied to the Open File for Editing menu item on the File menu described previously. The image in this button is a 16-by-15-pixel bitmap derived from the icon of the application that would be started if the user opened the file from the shell (using the shell's association route). The image is obtained by calling the SHGetFileInfo function with the path of the file. If this function fails, a file viewer can include a button that contains its own image and attempt to start the parent application, or the file viewer can remove the button and disable the Open File for Editing menu item on the File menu. This single button must be the leftmost item on the toolbar and must be separated from any other buttons that are specific to the file viewer.

The following illustration shows an example of an Open File for Editing button implementation.

An Open File for Editing button.

Other buttons should correspond roughly to the functions present in the file viewer menus. A file viewer that supports a Font menu item should have Increase Font Size and Decrease Font Size buttons. Other file viewer classes may need to include printing and rotation buttons on the toolbar.

A standard toolbar button is the Replace Window button. The default behavior for file viewers is for a new file viewer instance to be created whenever the user chooses the Quick View menu item. When the Replace Window button is switched to the "on" position, however, a new instance is not created; instead, the contents of the relevant file viewer window are replaced by a view of the new file.

All buttons should have a corresponding tooltip control that displays some context information when the mouse cursor is positioned on the button. The standard Windows 95 toolbar control provides built-in support for tooltip controls, so you only have to provide the text string. The following illustration shows a tooltip control for a toolbar button.

Tooltip control for a toolbar button.

The recommended tooltip strings for various toolbar buttons follow.
Toolbar Button Tooltip String
Open File for Editing Open File for Editing
Font Increase Increase Font Size
Font Decrease Decrease Font Size
Small View Toggle view size
Landscape Toggle portrait/landscape
Rotate [Again] Rotate image 90 degrees
Replace Window Replace Window

File viewer status window messages

A file viewer should display status window messages for the system menu and all top-level and pop-up menu items. The messages for the system menu and other menu items used by the default Windows file viewers follow:
[Menu] Item Message
[System] Commands for manipulating this and other windows.
[System] Restore Restores this window to normal size/Expands this window to full screen size.
[System] Move Moves this window to another screen location.
[System] Size Resizes this window.
[System] Minimize Collapses this window to an icon.
[System] Maximize Expands this window to full screen size.
[System] Close Closes this window.
[System] Switch To... Switch to another task.
[File] Contains commands for opening the file and quitting Quick View.
[File] Open File for Editing Opens the file for editing.
[File] Page Setup Changes the page setup for printing.
[File] Print... Prints the file contents.
[File] Exit Quits Quick View.
[View] Contains commands for customizing this window.
[View] Toolbar Shows or hides the toolbar.
[View] Status Bar Shows or hides the status bar.
[View] Page View Switches between document and page views.
[View] Replace Window Displays new files in current Quick View window.
[View] Landscape Switches between portrait and landscape.
[View] Rotate (Again) Rotates the image by 90 degrees.
[View] Font Changes the display font.
[Help] Contains commands for displaying Help and information about Quick View.
[Help] Help Topics Displays the Help Contents and Index.
[Help] About Displays program information, version number, and copyright.

The following standard messages for other conditions not related to menu items are implemented in the Windows default file viewers.

File viewer viewport window contents

The viewport window is where you provide most file-specific user interface elements. The viewport occupies all space in the client area of the main window not used for the toolbar and status bar. It displays the file contents in whatever mode is applicable, and it is sensitive to the user-selected printer and page setup, as well as other View menu commands.

If the contents of the file are too large to be completely displayed within the viewport, the file viewer should provide scroll bars (with proportional scroll boxes) to shift the image. If the contents of the file are smaller than the viewport window, no scroll bars should appear. In addition, the file contents should not be initially scaled to fill the viewport window unless the user selects scaling through the View menu commands.

The only other requirement for the viewport window is that it should provide a context menu for the file. The context menu should appear when the user clicks the viewport with the right mouse button. The context menu should include the following items.
Menu item string Equivalent found on other menu
"&Open File for Editing" Open File for Editing command on the File menu
Separator Not applicable
"Page Se&tup" (optional) Page Setup command on the File menu
"&Print" (optional) Print command on the File menu (note, no accelerator)
Separator Not applicable

You can add more menu items as needed. The Toolbar and Status bar menu item commands on the View menu should not appear in the context menu.

Drag-and-Drop in File Viewers

The default file viewers in Windows allow the user to drag a file from the desktop or Explorer and drop the file on a file viewer's window. A file viewer should show the small document icon that includes the + sign when the mouse is over the file viewer's window before the drop takes place. The Replace Window command in the View menu controls whether another file viewer window is displayed or the same window is reused.

Sophisticated File Viewers

This overview only describes the minimal file viewer user interface. There are, of course, many other possibilities besides just rudimentary printing and viewing capabilities. One useful feature is the ability to copy data from a document either to the clipboard or in a drag-and-drop operation. In such cases, the file viewer needs to provide the ability to select data in the file, a Copy command (on an Edit menu as well as in a context menu), and the ability to pick up the selection and drag it elsewhere. However, the file viewer should not be a drop target and should not support the Cut and Paste commands on the Edit menu (or other variants) because those operations modify the file.

If the parent application creating the files that are handled in a specific file viewer is an OLE compound document container, the file viewer itself must be sensitive to viewing a compound document. That means that the file viewer itself will support some minimal container features and will, of course, use OLE to load and display compound document objects in the file itself. If the file viewer also supports in-place activation, it can activate inside-out objects in-place to allow the user to select and copy data from embedded objects.


Up Top of Page
© 1997 Microsoft Corporation. All rights reserved. Terms of Use.