PERFORMING TASKS WITH THE REGISTRY API CALLS

You can actually perform all the tasks that are done with the built-in VBA commands quite nicely with API calls, as well as much more. Some tasks are covered in the rest of this chapter:

  • Creating a new Registry key

  • Checking to see if a Registry key already exists

  • Creating a new Registry value

  • Updating a Registry value

  • Deleting a key from the Registry

  • Retrieving a value from the Registry

  • Retrieving all the subkeys for a given Registry key

These tasks are demonstrated by using a utility created in Access that allows you to relink a front-end database to various back-end databases. These back ends are tracked by using the Windows Registry. Figure 18.7 shows the main form used in the example.

Figure 18.7. This form lets you browse for a database to link to, link to current databases, and delete (from the Registry) a database from the list.


Working with Multiple Back-End Databases

Most database application development is performed by using a single back-end database. However, I've come across more and more need to have the ability to work with more than one back end for the same front end. When discussing multiple back ends in this chapter, I mean that the same back end is used for all tables at one time—however, the ability to switch which back end is being used at a given time is what's being covered.

Some examples of types of applications that could use this utility are as follows:

  • Any application dealing with multiple companies for accounting purposes. The companies might need to have their data separate from each other for security reasons, but the same application would be used for maintaining the information.

  • Mailing list programs that use various sets of data from multiple sources.

  • Data analysis applications.

These are just a few examples; there are many more.

Looking at the Sample Application

In looking at the sample application, the first nice thing to note is that the only Access objects used are a table and form, with the rest of the example consisting of VBA code. Figure 18.8 shows the tblLinkedTables table. Figure 18.9 shows the form used for the sample application, frmMaintainBERegistryEntries, in Design view.

Figure 18.8. tblLinkedTables consists of the names of the tables to be linked to in the various back ends.


Figure 18.9. Use this form to track multiple back ends.


The form consists of one unbound list box control, lstBackends, which holds the list of back ends now listed in the Registry. The following is the list of the rest of the controls, all command buttons, on the form:

  • The Link button, cmdLink, calls code that links the back end now selected in the lstBackends list box.

  • The Browse button, cmdBrowse, calls the wrapper routine that calls the API Open File dialog, allowing users to browse to a new back-end database to add to the list in the Registry. (The user has to click the Link button to actually link to the database.)

  • The Delete button, cmdDelete, deletes the Registry entry for the currently selected back end in lstBackends.

  • The Close button, cmdClose, closes the frmMaintainBERegistryEntries form.

Note

The routine for the Browse button doesn't check the validity of the back-end database. If you're going to use this for your own purposes, you would want to add some code to do this.


The rest of the application consists of VBA code, stored in standard modules:

  • The modUtilityRoutines module stores general routines used throughout the application. The routines here might or might not be discussed in detail because they have nothing to do with the Registry, but just support the overall application.

  • The modOpenFileAPIRoutines module stores the code for the OpenFile API call.

  • The modRegistryAPIRoutines module stores wrapper routines for the actual API call to the Registry. Although these routines are used for a specific purpose in this application, you can copy this module out into any other application that uses VBA and call these routines.

  • The routines in the modBERegistryRoutines module are customized for tracking the multiple back ends in this application. They call the routines in the modRegistryAPIRoutines module.

Working with the Actual Code

Although it normally would be logical to look at the load event when looking at the code behind a form, in this case the code behind the cmdBrowse command button will be examined. It contains all that necessary code for examining the Registry structure used in the application.

Browsing for a Back End to Track

The cmdBrowse button uses the click event to performs two tasks (discussed shortly). First, Listing 18.4 shows the code for cmdBrowse_Click.

Listing 18.4. Chap18.mdb: The Windows Open File Dialog and Creating the Registry Entries
Private Sub cmdBrowse_Click()

   Dim strFileName As String

   strFileName = ap_OpenFile(, "Pick a Backend Database to register")

   If Len(strFileName) <> 0 Then
      AddBEToRegistry strFileName

      Me!lstBackends.RowSource = _
            GetRegistrySubKeys(HKEY_CURRENT_USER, MyAppBEsKey)

   End If

End Sub

First, the cmdBrowse_Click routine gets the full file path and name of the database that you want to track with the Registry and link to. (Note that it doesn't actually perform the link; this is done by using the Link command button.) The way the full file path and name is retrieved from the user is in calling the ap_OpenFile function (see Listing 18.5). This routine is located in modOpenFileRoutine, which is listed in its entirety.

Listing 18.5. Chap18.mdb: The Code Necessary for Calling the Open File Dialog
Option Compare Text
Option Explicit

Private Declare Function ap_GetOpenFileName Lib "comdlg32.dll" _
                    Alias "GetOpenFileNameA" _
                        (pOpenfilename As OPENFILENAME) As Long

Private Type OPENFILENAME
    lStructSize As Long
    hwndOwner As Long
    hInstance As Long
    lpstrFilter As String
    lpstrCustomFilter As String
    nMaxCustFilter As Long
    nFilterIndex As Long
    lpstrFile As String
    nMaxFile As Long
    lpstrFileTitle As String
    nMaxFileTitle As Long
    lpstrInitialDir As String
    lpstrTitle As String
    flags As Long
    nFileOffset As Integer
    nFileExtension As Integer
    lpstrDefExt As String
    lCustData As Long
    lpfnHook As Long
    lpTemplateName As String
End Type

Const cdlOFNAllowMultiselect = &H200
Const cdlOFNCreatePrompt = &H2000
Const cdlOFNExplorer = &H80000
Const cdlOFNExtensionDifferent = &H400
Const cdlOFNFileMustExist = &H1000
Const cdlOFNHelpButton = &H10
Const cdlOFNHideReadOnly = &H4
Const cdlOFNLongNames = &H200000
Const cdlOFNNoChangeDir = &H8
Const CdlOFNNoDereferenceLinks = &H100000
Const cdlOFNNoLongNames = &H40000
Const CdlOFNNoReadOnlyReturn = &H8000
Const cdlOFNNoValidate = &H100
Const cdlOFNOverwritePrompt = &H2
Const cdlOFNPathMustExist = &H800
Const cdlOFNReadOnly = &H1
Const CdlOFNShareAware = &H4000

Public Function ap_OpenFile(Optional ByVal strFileNameIn _
                                         As String = "", Optional                         
                                             strDialogTitle _
                                         As String = "Name of File to Open")

    Dim lngReturn As Long
    Dim intLocNull As Integer
    Dim strTemp As String
    Dim ofnFileInfo As OPENFILENAME
    Dim strInitialDir As String
    Dim strFileName As String

    '-- if a file path passed in with the name,
    '-- parse it and split it off.

    If InStr(strFileNameIn, "") <> 0 Then

        strInitialDir = Left(strFileNameIn, InStrRev(strFileNameIn, ""))
        strFileName = Left(Mid$(strFileNameIn, _
                                        InStrRev(strFileNameIn, "") + 1) & _
                                        String(256, 0), 256)

    Else
        strInitialDir = Left(CurrentDb.Name, _
                                        InStrRev(CurrentDb.Name, "") - 1)
        strFileName = Left(strFileNameIn & String(256, 0), 256)

    End If

    With ofnFileInfo
        .lStructSize = Len(ofnFileInfo)
        .lpstrFile = strFileName
        .lpstrFileTitle = String(256, 0)
        .lpstrInitialDir = strInitialDir
        .hwndOwner = Application.hWndAccessApp
        .lpstrFilter = "All Files (*.*)" & Chr(0) & "*.*" & Chr(0)
        .nFilterIndex = 1
        .nMaxFile = Len(strFileName)
        .nMaxFileTitle = ofnFileInfo.nMaxFile
        .lpstrTitle = strDialogTitle
        .flags = cdlOFNFileMustExist Or cdlOFNHideReadOnly Or _
                            cdlOFNNoChangeDir
        .hInstance = 0
        .lpstrCustomFilter = String(255, 0)
        .nMaxCustFilter = 255
        .lpfnHook = 0
    End With

    lngReturn = ap_GetOpenFileName(ofnFileInfo)

    If lngReturn = 0 Then
       strTemp = ""
    Else

       '-- Trim off any null string
       strTemp = Trim(ofnFileInfo.lpstrFile)
       intLocNull = InStr(strTemp, Chr(0))

       If intLocNull Then
          strTemp = Left(strTemp, intLocNull - 1)
       End If

    End If

    ap_OpenFile = strTemp

End Function

Tip

Notice that the structure used in this module has a distinct “C” flavor to it. As with many API calls and the wrapper functions created, they can originally be from another language and modified for use in your own functions. I tend to leave API functions and wrappers as close to the original form as possible while modifying them for my own needs. This leads to less “complications” using them.


This routine takes the structure created in the declarations area, sets it up with the desired defaults, and then calls the API call ap_GetOpenFileName (my Alias). Figure 18.10 shows the Open File dialog in action.

Figure 18.10. The second of the two back ends used for this example, Chap18BE2.mdb, has been chosen by using the Open File dialog.


Note

The Common Dialogs ActiveX control wasn't used. Although ActiveX controls can be more convenient to use than API calls, with ActiveX controls users must have the same version of the control on their system, when in many installations isn't the case.


Registering the Database

The sample application is registering the back-end database into the application entry in the Registry, and storing the following pieces of information about the database:

  • Filename only

  • Filename and extension

  • File path

  • Full filename and path

Using Chap18BE2.mdb as the example, Figure 18.11 shows the back-end information as it's stored in the Registry.

Figure 18.11. Storing the information at a bite-size level makes it more convenient to use later in the application.


All the information stored in the values in Figure 18.11 were parsed from the file path and name retrieved, and then stored into strFileName in the cmdBrowse_Click routine. The following code calls the routine to add the entries:

AddBEToRegistry strFileName

The routine AddBEToRegistry is located in the modBERegistryRoutines module. This module was created custom for the purpose of manipulating Registry entries for this particular application. You can see the AddBEToRegistry subroutine in Listing 18.6.

Listing 18.6. Chap18.mdb: Parsing the Filename and Path to Add Entries to the Registry
Sub AddBEToRegistry(strFileName As String)

  Dim strFileAndExt As String
  Dim strFileOnly As String
  Dim strPathOnly As String

  '-- Parse all the pertinent information out of the full path &
  '-- file name
  strFileAndExt = Mid$(strFileName, ap_LastInStr(strFileName, "") + 1)
  strFileOnly = Left$(strFileAndExt, Len(strFileAndExt) - 4)
  strPathOnly = Left$(strFileName, InStr(strFileName, strFileAndExt) - 1)

  '-- Create a key based on the file name
  CreateNewRegKey HKEY_CURRENT_USER, MyAppBEsKey & "" & strFileOnly

  '-- Record the individual values you want to track for the key.

  SetRegKeyValue HKEY_CURRENT_USER, MyAppBEsKey & "" & strFileOnly, _
     "FullPath", strFileName, REG_SZ

  SetRegKeyValue HKEY_CURRENT_USER, MyAppBEsKey & "" & strFileOnly, _
     "FileAndExt", strFileAndExt, REG_SZ

  SetRegKeyValue HKEY_CURRENT_USER, MyAppBEsKey & "" & strFileOnly, _
     "FileOnly", strFileOnly, REG_SZ

  SetRegKeyValue HKEY_CURRENT_USER, MyAppBEsKey & "" & strFileOnly, _
     "PathOnly", strPathOnly, REG_SZ

End Sub

Before going through the code step by step, check out a few constants:

  • HKEY_CURRENT_USER represents the value of the predefined HKEY_CURRENT_USER key and can be found in the declaration section of the modRegistryAPIRoutines module. Here is the whole list of predefined keys constant declarations that can be found in the module:

    Public Const HKEY_CURRENT_USER = &H80000001
    Public Const HKEY_CLASSES_ROOT = &H80000000
    Public Const HKEY_LOCAL_MACHINE = &H80000002
    Public Const HKEY_USERS = &H80000003
    

Note

Again, for purposes of most of your applications, you want to stick to using HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE, depending on whether you want settings for each individual user or each machine.


  • MyAppBEsKey represents the Registry path used to store the sample application's values. This line of code performs this:

    Public Const MyAppBEsKey = _
         "SoftwareApplications PlusChap18Backends"
    

  • REG_SZ is one of several constants, again located in modRegistryAPIRoutines, used for defining the data type for the value you're creating in the Registry. Here are the whole list of declarations found there:

    Global Const REG_SZ As Long = 1
    Global Const REG_EXPAND_SZ As Long = 2
    Global Const REG_BINARY As Long = 3
    Global Const REG_DWORD As Long = 4
    

Note that there are more Registry types that can be used, but aren't necessarily recommended.

This routine performs the following tasks:

1.
Parse all the pertinent information out of the full path & file name:

strFileAndExt = Mid$(strFileName, ap_LastInStr(strFileName, "") _
   + 1)
strFileOnly = Left$(strFileAndExt, Len(strFileAndExt) _
   - 4)
strPathOnly = Left$(strFileName, InStr(strFileName, strFileAndExt) _
   - 1)

2.
Create a key based on the filename:

CreateNewRegKey HKEY_CURRENT_USER, MyAppBEsKey & "" & strFileOnly

In this case, it creates the key Chap18BE2. If the rest of the branch didn't exist, it would have been created.

Because this is the first API call discussed, Listing 18.7 shows it in its entirety.

Listing 18.7. Chap18.mdb: Takes the Arguments Passed in and Creates a New Registry Key
Public Sub CreateNewRegKey(lngPredefinedKey As Long, _
strNewKeyName As String)

    Dim hNewKey As Long         'handle to the new key
    Dim lRetVal As Long         'result of the RegCreateKeyEx function

    lRetVal = RegCreateKeyEx(lngPredefinedKey, strNewKeyName, 0&, _
                 vbNullString, REG_OPTION_NON_VOLATILE, KEY_WRITE, _
                 0&, hNewKey, lRetVal)

    RegCloseKey (hNewKey)

End Sub

Note

Another reason for using wrapper routines already created for you: You must call the RegCloseKey routine to clear the reference to the key that you opened by calling RegCreateKeyEx(). If you didn't know this, you would start getting errors or just flaky results.


The RegCreateKeyEx() API function is one of many API routines supplied in the sample application. To see them, look at the next section, “Listing the API Declarations and Wrapper Routines for the Registry.”

3.
The last task records the individual values you want to track for the key:

   SetRegKeyValue HKEY_CURRENT_USER, MyAppBEsKey & "" & _
      strFileOnly, "FullPath", strFileName, REG_SZ

   SetRegKeyValue HKEY_CURRENT_USER, MyAppBEsKey & "" & _
      strFileOnly, "FileAndExt", strFileAndExt, REG_SZ

   SetRegKeyValue HKEY_CURRENT_USER, MyAppBEsKey & "" & _
      strFileOnly, "FileOnly", strFileOnly, REG_SZ

   SetRegKeyValue HKEY_CURRENT_USER, MyAppBEsKey & "" & _
      strFileOnly, "PathOnly", strPathOnly, REG_SZ

The last step required a call to the SetRegKeyValue routine, another API wrapper located in the modRegistryAPIRoutines module. With this routine, like the other API wrapper routines, it's not necessary to go through step by step what it does in setting up and calling the API routine. In this case, it's known that it takes the parameters passed to it and creates the individual value in the Registry.

In the following section, you can see RegCreateKeyEx() and other API declarations used in the sample application, as well as others you might find useful your own applications.

Listing the API Declarations and Wrapper Routines for the Registry

The API declarations in Listing 18.8 can be found in modRegistryAPIRoutines.

Listing 18.8. Chap18.mdb: Declaring API Routines Before You Can Use Them
Declare Function RegCloseKey Lib "advapi32.dll" _
   (ByVal hKey As Long) As Long
Declare Function RegCreateKeyEx Lib "advapi32.dll" Alias _
   "RegCreateKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, _
   ByVal Reserved As Long, ByVal lpClass As String, ByVal dwOptions _
   As Long, ByVal samDesired As Long, ByVal lpSecurityAttributes _
   As Long, phkResult As Long, lpdwDisposition As Long) As Long
Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias _
   "RegOpenKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, _
   ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As _
   Long) As Long
Declare Function RegQueryValueExString Lib "advapi32.dll" Alias _
   "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As _
   String, ByVal lpReserved As Long, lpType As Long, ByVal lpData _
   As String, lpcbData As Long) As Long
Declare Function RegQueryValueExLong Lib "advapi32.dll" Alias _
   "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As _
   String, ByVal lpReserved As Long, lpType As Long, lpData As _
   Long, lpcbData As Long) As Long
Declare Function RegQueryValueExNULL Lib "advapi32.dll" Alias _
   "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As _
   String, ByVal lpReserved As Long, lpType As Long, ByVal lpData _
   As Long, lpcbData As Long) As Long
Declare Function RegSetValueExString Lib "advapi32.dll" Alias _
   "RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName As String, _
   ByVal Reserved As Long, ByVal dwType As Long, ByVal lpValue As _
   String, ByVal cbData As Long) As Long
Declare Function RegSetValueExLong Lib "advapi32.dll" Alias _
   "RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName As String, _
   ByVal Reserved As Long, ByVal dwType As Long, lpValue As Long, _
   ByVal cbData As Long) As Long
Declare Function RegQueryInfoKey Lib "ADVAPI32" Alias _
   "RegQueryInfoKeyA" (ByVal hKey As Long, ByVal lpszClass As String, _
    ByRef lpcchClass As Long, ByVal lpdwReserved As Long, _
    ByRef lpcSubKeys As Long, ByRef lpcchMaxSubkey As Long, _
    ByRef lpcchMaxClass As Long, ByRef lpcValeus As Long, _
    ByRef lpcchMaxValueName As Long, _
    ByRef lpcbMaxValueData As Long,  _
    ByRef lpcbSecurityDescriptor As Long, _
    ByRef lpftLastWriteTime As FILETIME) As Long
Declare Function RegEnumKeyEx Lib "ADVAPI32" Alias _
    "RegEnumKeyExA" (ByVal hKey As Long, ByVal iSubkey As Long, _
    ByVal lpszName As String, ByRef lpcchName As Long, _
    ByVal lpdwReserved As Long, ByVal lpszClass As String, _
    ByRef lpcchClass As Long, _
    ByRef lpftLastWrite As FILETIME) As Long
Declare Function RegDeleteKey Lib "advapi32.dll" Alias "RegDeleteKeyA" _
   (ByVal hKey As Long, ByVal lpSubKey As String) As Long
Declare Function RegDeleteValue Lib "advapi32.dll" Alias _
   "RegDeleteValueA" (ByVal hKey As Long, ByVal lpSubValue As String) _
   As Long

After going through the wrapper routines in modRegistryAPIRoutines, you should get a good idea of what it takes to work with the API calls for the Registry.

Note

More API declarations are included than are used for this example. This is to save you the trouble of hunting them down yourself.


In Table 18.3, you can see the wrapper functions created and used in the sample application.

Table 18.3. Even the Wrapper Functions Call Other Functions
Wrapper Routine Purpose
CreateNewRegKey Deletes a key or value from an application
DeleteAllRegEntriesForKey Deletes all entries for a given key
GetRegistrySubKeys Retrieves all subkeys for the given Registry key
QueryValueEx Called by the QueryRegValue wrapper routine that returns the value from the registry.
QueryRegValue Set up variables and calls the API call QueryValueEx
SetRegKeyValue Set up variables and calls the API call SetValueEx
SetValueEx Called by the SetRegKeyValue wrapper routine, this routine actually sets the registry value.

A couple of these routines have already been discussed, and more will be seen as we move on.

Getting a List of Subkeys for a Registry Key

The last task performed in this routine (refer to Listing 18.5) hasn't yet been discussed. The last task is to populate the lstBackends list box with a list of back ends from the Registry.

Taking the single line of code that performs this:

Me!lstBackends.RowSource = _
      GetRegistrySubKeys(HKEY_CURRENT_USER, MyAppBEsKey)

You can see that the GetRegistrySubKeys() wrapper function is called to perform this task. This function iterates through the subkeys of a given key, concatenating them into a string separated by semicolons.

Well, that's it for the first command button. Fortunately, this is the most complicated command button as well. By looking at the form's Load event, you can see that the only task that occurs is the loading of the list box:

Private Sub Form_Load()

   Me!lstBackends.RowSource = GetRegistrySubKeys(HKEY_CURRENT_USER, _
      MyAppBEsKey)

End Sub

Linking the Tables

The next routine to look at is the click event of the cmdLink command button (see Listing 18.10).

Listing 18.10. Chap18.mdb: Setting the Current Back End and Linking the Tables
Private Sub cmdLink_Click()

   If IsNull(Me!lstBackends) Then

      MsgBox "Please select a backend to link", vbInformation, _
         ap_AppTitle()
      Me!lstBackends.SetFocus

   Else

      SetCurrentBE Me!lstBackends
      LinkTables CurrBENameAndPath()
      DoCmd.Close acForm, Me.Name

   End If

End Sub

The cmdLink_Click routine first checks to see whether an item is selected in the list box. If it is, three routines are then called, one of which, CurrBENameAndPath(), is passed as a parameter.

Here is the first routine called at this point, SetCurrentBE:

Sub SetCurrentBE(strCurrBE As String)

   SetRegKeyValue HKEY_CURRENT_USER, MyAppBEsKey, "CurrentBE", _
         strCurrBE, REG_SZ

End Sub

This routine, located in the modBERegistryRoutines module, sets the CurrentBE value to the path specifying where the current back end is linked. This is so that you can later refer to this value whenever you need to access any other values for the current back end.

The next routine, LinkTables, really has nothing to do with Registry entries, but is shown in Listing 18.11. This routine can be found in modUtilityRoutines.

Listing 18.11. Chap18.mdb: Creating or Reconnecting Links
Function LinkTables(strDBToLink As String) As Boolean
    Dim dbLocal As Database
    Dim snpLinkedTbls As DAO.Recordset
    Dim tdfCurrent As TableDef
    Dim flgAddTable As Boolean
    Dim intTotalTbls As Integer
    Dim intCurrTbl As Integer

    On Error GoTo Err_LinkTables
    Set dbLocal = CurrentDb
    Set snpLinkedTbls = dbLocal.OpenRecordset("tblLinkedTables", _
       dbOpenSnapshot)

    '-- Get the total # of linked tables, then display the progress meter.
    snpLinkedTbls.MoveLast
    intTotalTbls = snpLinkedTbls.RecordCount
    snpLinkedTbls.MoveFirst

    SysCmd acSysCmdInitMeter, "Linking Tables....", intTotalTbls

    intCurrTbl = 1

    Do Until snpLinkedTbls.EOF

        '-- Update the progress meter
        SysCmd acSysCmdUpdateMeter, intCurrTbl
        '-- Attempt to open the current link
        On Error Resume Next
        Set tdfCurrent = dbLocal.TableDefs(snpLinkedTbls!TableName)

        flgAddTable = Err.Number

        On Error GoTo Err_LinkTables

        '-- If there was an error, create the link from scratch,
        '-- otherwise, just update the connect string
        If flgAddTable Then

            Set tdfCurrent = _
               dbLocal.CreateTableDef(snpLinkedTbls!TableName)
            tdfCurrent.SourceTableName = snpLinkedTbls!TableName
            tdfCurrent.Connect = ";DATABASE=" & strDBToLink
            CurrentDb.TableDefs.Append tdfCurrent

        Else

            tdfCurrent.Connect = ";DATABASE=" & strDBToLink
            tdfCurrent.RefreshLink

        End If

        snpLinkedTbls.MoveNext
        intCurrTbl = intCurrTbl + 1

    Loop

    SysCmd acSysCmdRemoveMeter

    LinkTables = True

Exit_LinkTables:
    Exit Function

Err_LinkTables:
    LinkTables = False
    Resume Exit_LinkTables

End Function

The idea behind this routine is to take the string of the full path and filename of the back end and, if the tabledef isn't already created, create it; otherwise, fix up the connect string and refresh the link. This routine also updates the Access status bar by using the SysCmd statement. Figure 18.12 shows the LinkTable routine in action.

Figure 18.12. Linking the current back-end database while displaying a status bar.


Note

This routine was done using DAO. You can see how to link tables by using ADO in Chapter 27, “Startup Checking System Routines Using ADO.”


Deleting a Back End from the Registry

The last thing to discuss is how to delete a back-end entry from the Registry. Note that the application deletes the Registry entry, not the file itself. Listing 18.12 shows the code for cmdDelete_Click.

Listing 18.12. Chap18.mdb: Deleting a Back End from the Registry
Private Sub cmdDeleteBEReg_Click()

   If IsNull(Me!lstBackends) Then

      MsgBox "Please select a backend to delete the registry entry.", _
         vbInformation, ap_AppTitle()
      Me!lstBackends.SetFocus

   Else

      DeleteBERegEntry Me!lstBackends
      Me!lstBackends.RowSource = _
         GetRegistrySubKeys(HKEY_CURRENT_USER, MyAppBEsKey)
      Me!lstBackends.Requery
   End If

End Sub

You can see that this routine is similar to the cmdLink_Click routine in that it makes sure that you've chosen a value from the list box before trying to perform the action of deleting the routine. The first task performed is to call DeleteBERegEntry, located in the modBERegistryRoutines module:

Sub DeleteBERegEntry(strBEToDelete As String)

   DeleteAllRegEntriesForKey HKEY_CURRENT_USER, MyAppBEsKey & "" & _
                  strBEToDelete

End Sub

Taking the back-end name to delete, this routine calls the DeleteAllRegEntriesForKey routine, which is located in the modRegistryAPIRoutines module and is an API wrapper routine.

The last control was the cmdClose button, which simply uses the DoCmd statement to close the form.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.196.175