[ Team LiB ] |
Recipe 4.8 Use the Windows File Open/Save Common Dialogs4.8.1 ProblemYou need to allow users to choose filenames for opening and saving files. You know that Windows supports a common way to get these names. How can you use this mechanism from within Access? 4.8.2 SolutionNot only can you use the common File Open/Save dialogs, but you even have three ways to do it:
If you don't have the developer version of Office, or Visual Basic, the first suggestion won't help. In addition, distribution of applications that use the common dialog ActiveX can get complex, because of ActiveX versioning issues. The FileDialog object added in Access 2002 makes it easier to select files, but it's not available in earlier versions. Therefore, this solution shows how to call the Windows API directly and lists all the options you have when using these common dialogs. Open and run the form frmTestOpenSave from 04-08.MDB. This sample form allows you to set various flags (described later in this solution) and to see the results. You can try both the File Save and File Open common dialogs. Try changing some of the settings and see what happens. Figure 4-16 shows the File Open dialog—with the Read Only checkbox hidden and allowing for multiple selections—displayed in explorer mode (as opposed to the older Program Manager look, which is what Windows will use if you specify the multiselect option by itself ). Figure 4-16. The sample form, frmTestOpenSave, showing the File Open dialog in useTo use this functionality within your own applications, follow these steps:
4.8.3 DiscussionWhen you call acbCommonFileOpenSave, you're actually calling the GetOpenFileName or GetSaveFileName Windows API functions. The acbCommonFileOpenSave function takes only the parameters you send it, replacing missing ones with the default values shown in Table 4-2, and fills in a user-defined data structure that both API functions expect to receive. The API functions actually do the work, and acbCommonFileOpenSave returns to you the chosen filename. Although you may find it interesting to dig into the details of calling the API functions directly, that's beyond the scope of this solution. The wrapper function, acbCommonFileOpenSave, handles a large majority of the cases in which you'll need to use common File Open/Save dialogs. Table 4-3 lists all the values you can use in the Flags parameter of the call to acbCommonFileOpenSave. You can skip the parameter altogether, or you can use one or more of these values, combined with the OR operator. For example, to hide the Read Only checkbox and allow multiple files to be selected, use this code: lngFlags = acbOFN_HIDEREADONLY Or acbOFN_ALLOWMULTISELECT
Not all of the flags make sense for both File Open and File Save operations, of course. Your best bet is to experiment with the flags, either in your own code or using the sample form frmTestOpenSave from 04-08.MDB. Some of the flags are useful only on return from the function call. For example, if you select the Read Only checkbox on the common dialog, Windows passes that fact back to you in the Flags parameter. To retrieve that information from your call to acbCommonFileOpenSave, pass the Flags argument in a variable, not directly as a literal value. Because acbCommonFileOpenSave accepts the Flags argument by reference, it can return the value to your calling procedure after you've selected a filename. To check if a particular flag value was set during the call to acbCommonFileOpenSave, use the AND operator with the return value, as in this example fragment (see the Solution in Recipe 11.1 for more information on using the AND and OR operators): Dim lngFlags As Long Dim varFileName As Variant lngFlags = 0 varFileName = antCommonFileOpenSave(Flags:=lngFlags) If lngFlags AND acbOFN_READONLY <> 0 Then ' The user checked the Read Only checkbox. End if If you pass a variable to acbCommonFileOpenSave containing the Flags information (rather than not sending the parameter, or sending a literal value), the function will return to the caller information about what happened while the dialog was in use. Several of the flags listed in Table 4-3 provide information on output. That is, you can check the state of the Flags variable, and if it contains the flags from Table 4-3, you know that the tested condition was true. For example, to open a file and then check to see if the selected file is to be opened read-only, you could use code like this: Dim lngFlags As Long Dim varRetval As Variant varRetval = acbCommonFileOpenSave(Flags:=lngFlags) If Not IsNull(varRetval) Then If lngFlags AND acbOFN_READONLY Then MsgBox "You opened the file read-only!" End If End If As you can see in this example, you can use the AND operator to see if Flags contains the specific flag in which you're interested. The file filter (the Filter parameter to acbCommonFileOpenSave) has a unique format: it consists of pairs of strings. Each item is terminated with vbNullChar (Chr$(0)). The first item in the pair supplies the text portion, which appears in the combo box in the lower-left corner of the dialog. The second item supplies the file specifications that Windows uses to filter the list of files. Though it doesn't matter what you use in the first item, by convention, most applications use something like this: Oogly Files (*.oog) listing the file description. The conventional file specification looks something like this: *.oog To simplify building these filter strings, use the acbAddFilter function from basCommonFile. See Step 3 for an example. If you select the acbOFN_AllowMultiSelect flag, the result value may contain a null-delimited list of files, starting with the folder containing the files. For example, if you navigated to C:\AccessCookbook, and selected 04-04.mdb and 04-06.mdb, the return value from acbCommonFileOpenSave would contain the following text (we've used the vertical pipe symbol here to represent Chr(0) within the text): C:\AccessCookbook|04-04.mdb|04-06.mdb The sample form replaces the Chr(0) with a space character for you: Private Sub cmdFileOpen_Click( ) Dim varResult As Variant varResult = FileOpenSave(True) Me.txtFileOpen = Replace(varResult, vbNullChar, " ") End Sub If you allow multiple file selection, it's up to you to parse the various the file path and names yourself. Take the time to study all the parameters in Table 4-2 and all the options in Table 4-3. There's not room here to go into detail for each one, so your best bet is to try out all of them. You can play with frmTestOpenSave to test the effects of some of the flag values. See what happens when you place a value into one of them, and then experiment from there. Although you have no direct control over the placement of the common dialogs when they pop up, the choice of the parent window can affect the location. If you pass 0, Application.hWndAccessApp, or a normal form's hWnd property for the hWnd argument to acbCommonFileOpenSave (or just don't send a value, so it uses the default value), the dialog will appear in the upper-left corner of the Access MDI client window. If, on the other hand, you pass it the hWnd property of a pop-up form, Windows will place the dialog in the upper-left corner of that pop-up form even if the form is not visible. Therefore, for complete control over the placement of the dialog, create a form, set its PopUp property to True, and use that form to place the dialog. Finally, remember that these dialogs don't actually do anything—they just supply you with the names of files. It's up to your application code to open or save the requested files. 4.8.4 See AlsoFor more information on working with the Windows API, see Chapter 11. |
[ Team LiB ] |