Windows Programming


Extending the Windows File Manager

Trevor Harmon


Trevor Harmon works for Microdyne Development Technologies, which provides custom controls and other tools for Microsoft Windows programmers. He is currently pursuing degrees in Computer Engineering and German. Trevor can be reached on CompuServe at 73771,3307 or on the Internet at73771.3307@compuserve.com.Trevor.

When Microsoft introduced Windows 3.1, it redesigned the File Manager and replaced it with a friendlier and more flexible version. Among its many enhancements the new File Manager included an open, documented interface to allow integration with other programs. These programs, called Extensions, can supplement the Windows File Manager by adding a custom menu to its menu bar. The custom menu can provide access to external programs and, in effect, add new features to the File Manager.

The number of applications that take advantage of this interface is growing. Naturally, Microsoft's MS-DOS 6.x includes a File Manager Extension for a quick path to its disk-management utilities. You might choose to create these same types of Extensions for your products. Or, if you see a feature that File Manager lacks, you can build an Extension to fill the gap. This article will help you create a File Manager Extension. It includes a sample program which is a trivial, but complete, Extension illustrating the components of File Manager Extensions and serving as a framework for writing your own.

How Extensions Work

A File Manager Extension is simply a Windows DLL with one addition: an external callback function called FMExtensionProc. This function connects the DLL with the File Manager and receives all notification messages sent to the DLL. These messages, defined in the header file WFEXT.H, indicate certain File Manager events, such as loading of the Extension or selection of an item from the Extension's menu.

FMExtensionProc can also query the File Manager for information. By calling the standard SendMessage API function, FMExtensionProc can retrieve drive information or the names of selected files. It can also tell the File Manager to update its windows or reload its Extensions.

Messages From File Manager

When File Manager starts, it looks for an [AddOns] section in the file WINFILE.INI. File Manager reads the first five entries in this section, locates the DLL specified by each entry, and sends an FMEVENT_LOAD message to each DLL's FMExtensionProc. Note that if the [Addons] section, an entry, or even a DLL is missing, File Manager does not issue any error messages. Also, although File Manager attempts to load up to five of the listed DLLs, only the first four will work properly.

File Manager sends three parameters to FMExtensionProc: the File Manager's window handle, the Extension message number, and a 32bit lParam that supplies data specific to each message. In the case of FMEVENT_LOAD, lParam contains a pointer to an FMS_LOAD structure.

The sample program (Listing 1) shows how this structure is filled. The first field, dwSize, holds the size of the structure and is used for version checks. The second, szMenuName, contains the title string of the Extension menu and therefore must have less than MENU_TEXT_LEN characters. Like any other Windows menu, this string may include an ampersand (&) character to indicate the menu label's underlined letter. The third field, hMenu, holds the Extension menu.

To fill hMenu, the sample program calls LoadMenu, which retrieves the Extension menu from FMEXT.RC. Alternatively, you can use LoadMenuIndirect to supply the hMenu field. Note that each item in the menu should have an ID between 1 and 99.

The last field, wMenuDelta, is unique to each Extension and is used by File Manager to prevent menu conflicts between Extensions. All Extensions have menu IDs ranging from 1 to 99. When an Extension references one of its menu items, it should add wMenuDelta to the menu ID to produce a unique identifier. This procedure allows several Extensions to operate on the same File Manager while still having menu IDs between 1 and 99. Unlike the first three fields, which must be initialized by the Extension, wMenuDelta is initialized by the File Manager. File Manager begins by calculating an ID that is higher than all other menu IDs and saves this value as a unique wMenuDelta in the FMS_LOAD structure.

In addition to FMS_LOAD, File Manager relays four other messages that notify an Extension of events. File Manager sends FMEVENT_INITMENU whenever the user clicks on the Extension's menu. This message contains the menu handle in the high-order word of lParam and the menu-delta value in the low-order word. FMEVENT_INITMENU allows the Extension to update check marks or disabled items on its menu. The sample program includes an example of FMEVENT_INITMENU; notice that the program adds the wMenuDelta value to the menu item ID when calling CheckMenuItem.

The File Manager sends FMEVENT_SELCHANGE if the user changes any selections in the File Manager. An Extension's modeless dialog box may respond to this message if it wants to update its display of selections. File Manager does not use 1Param in FMEVENT_SELCHANGE.

File Main sends FMEVENT_USER_REFRESH when the user chooses the File Manager's Window | Refresh menu. This message serves as a broadcast to all Extensions telling them that they should refresh their windows. lParam is not used.

File Manager sends the FMEVENT_UNLOAD message just before it unloads an Extension; lParam again is not used. An Extension can use this message to clean itself up, just as a DLL performs cleanup in the Windows Exit Procedure (WEP). Because the sample program does not allocate memory or perform other such tasks when starting, it does not respond to FMEVENT_UNLOAD.

Lastly, the File Manager sends menu item IDs if the user clicks on the matching menu item. Rather than send the WM_COMMAND message that Windows executables receive, File Manager sends the actual ID to FMExtensionProc and does not add the wMenuDelta value to it.

Messages to the File Manager

Communication between the File Manager and its Extensions can travel in two directions. The File Manager sends a notification message to an Extension, and the Extension can send command messages back to the File Manager to get information. For instance, an Extension can send the FM_GETDRIVEINFO message to obtain data on the current File Manager drive.

The example program illustrates this message. In the function FillDriveInfoDlg, which runs when the user selects the Drive Information menu, the sample code calls SendMessage with a pointer to an FMS_GETDRIVEINFO structure as the lParam parameter. When the File Manager receives FM_GETDRIVEINFO, it fills FMS_GETDRIVEINFO with the byte capacity, free space, current path, volume label, and network sharepoint of the current drive. (Look in the Windows WFEXT.H header for the complete definition of FMS_GETDRIVEINFO.)

Probably the most commonly used File Manager Extension message is FM_GETFILESEL. When combined with FM_GETSELCOUNT, this message can retrieve the currently selected items in the File Manager window. The sample Extension demonstrates the procedure, first by sending the FM_GETSEL-COUNT message to the File Manager with no parameters. The value returned is the number of items selected. The example code then executes a loop; each time through the loop it calls SendMessage with the FM_GETFILESEL message, containing the index of the selected item for which it wants information, and a pointer to an FMS_GETFILESEL structure. This structure holds the date and time stamp, size, attributes, and name of the selected file. (For the bAttr field, 00100000 = archive, 00010000 = directory, 00000100 = system, 00000010 = hidden, and 00000001 = read-only.) After each call to SendMessage, the sample program copies the item name from the structure and adds it to a list box for display.

File Manager provides two extra messages similar to FM_GETSELCOUNT and FM_GETFILESEL. These messages, FM_GETSELCOUNTLFN and FM_GETFILESELLFN, return network-style long file names and should only be sent if you design your Extension to run on a network.

To learn which window has the File Manager's focus, an Extension can send FM_GETFOCUS without parameters. The return value will be one of the following, depending on the current input focus: FMFOCUS_DIR for directory window, FMFOCUS_TREE for tree window, FMFOCUS_DRIVES for drive bar, or FMFOCUS_SEARCH for Search Results window.

The other two messages an Extension can send do not retrieve information from the File Manager; they instruct it to carry out a task. FM_REFRESH_WINDOWS asks the File Manager to refresh its windows in the same way it would if the user selected Window | Refresh. An Extension can send this message if it modifies any files or directories and wants the File Manager to reflect the current display. The Extension should set the wParam parameter to zero if it wants the File Manager to refresh only the active window; wParam should be non-zero if the Extension wants all windows updated. lParam is not used.

The FM_RELOAD_EXTENSIONS message causes the File Manager to unload and then reload all Extensions listed in WINFILE.INI. This message allows an Extension to uninstall itself. The sample program gives an example of this type of self-removal. The program first prompts the user to make sure the Extension should be uninstalled. It then calls WritePrivateProfileString to delete the Generic File Manager Extension entry from WINFILE.INI. Finally, the program sends the FM_RELOAD_EXTENSIONS message to the File Manager with no parameters.

Installing the Sample Program

The included source code demonstrates most of the above operations. To install it, you must first compile it into a DLL. The program source is in Listing 1, and a header is provided in Listing 2. Be sure to include FMEXT.RC (Listing 3) and FMEXT. DEF (Listing 4) along with FMEXT.C in your MAKE or project file.

Next, you must tell the File Manager where to find your DLL. Edit the File Manager's WINFILE.INI initialization file and look for the [AddOns] section, adding it yourself if it does not exist. Under [AddOns], on a separate line, type the description of your Extension. Because File Manager sees the name only as a placeholder, anything you type will suffice. For the sample program, however, you should title it Generic File Manager Extension so the Extension will be able to remove it later. Follow the name with an equals sign and the full filespec of your DLL.

Conclusion

Blend these messages together and you will have a File Manager Extension that places your program on a common foundation with many Windows programs. This rare open standard combines products from widely disparate vendors into a solid yet dynamic file-management tool. That sentence may sound like a glowing advertisement from Microsoft, but I stubbornly believe the File Manager Extension interface sets an example for future products. It all adds up to an easier life for Windows users.

Sidebar: "Extensions for Windows NT"