LOOKING AT SOME EXAMPLES OF API CALLS

It's time now for some real examples. The rest of this chapter will look at some actual examples of API calls being used. Before jumping into the individual examples, however, look again at the API declarations used for all of them, merely for your convenience and to refresh them in your mind (see Listing 15.2). These can be found in the module modWindowsAPIRoutines, in Chap15.mdb.

Listing 15.2. Chap15.mdb: Declaring API Calls
Option Compare Database
Option Explicit

'-- API Call for finding the associated file
Declare Function wu_FindExecutable Lib "shell32.dll" Alias _
   "FindExecutableA" (ByVal lpFile As String, _
   ByVal lpDirectory As String, ByVal lpResult As String) As Long

'-- API Calls for adding and cancelling network connection
'-- programmatically
Declare Function wu_NetAddConnection Lib "mpr" Alias _
   "WNetAddConnectionA" (ByVal NetPath$, ByVal Password$, _
   ByVal LocalDrive$) As Integer
Declare Function wu_NetCancelConnection Lib "mpr" Alias _
   "WNetCancelConnectionA" (ByVal NetPath$, ByVal FileForce%) _
   As Integer

'-- API Calls for calling the network connect and
'-- disconnect dialogs
Declare Function wu_WNetConnectionDialog Lib "mpr" Alias _
   "WNetConnectionDialog" (ByVal hwnd As Long, ByVal dwType As Long) _
   As Long
Declare Function wu_WNetDisconnectDialog Lib "mpr" Alias _
   "WNetDisconnectDialog" (ByVal hwnd As Long, _
   ByVal dwType As Long) As Long

'-- API Calls for getting the current user and computer names
Declare Function wu_GetUserName Lib "advapi32.dll" Alias _
   "GetUserNameA" (ByVal lpBuffer As String, nSize As Long) _
   As Long
Declare Function wu_GetComputerName Lib "kernel32" Alias _
   "GetComputerNameA" (ByVal lpBuffer As String, nSize As Long) _
   As Long

'-- API Calls for getting the windows, system, and temp directory for
'-- the current computer.
Declare Function wu_GetWindowsDirectory Lib "kernel32" Alias _
   "GetWindowsDirectoryA" (ByVal lpBuffer As String, _
   ByVal nSize As Long) As Long
Declare Function wu_GetSystemDirectory Lib "kernel32" Alias _
   "GetSystemDirectoryA" (ByVal lpBuffer As String, _
   ByVal nSize As Long) As Long
Declare Function wu_GetTempPath Lib "kernel32" Alias _
   "GetTempPathA" (ByVal nBufferLength As Long, _
   ByVal lpBuffer As String) As Long

Finding an Executable Application Associated with a File

The first example will use the FindExecutable() API routine. This function is useful when you want to let users choose between different file types to open. Rather than hard-code which application to use, you can check to make sure that it's associated with an application.

Looking at the Form Used

The form used for this example, FindExecutableExample, is located in Chap15.mdb in the ExamplesChap15 folder on the CD-ROM. The form consists of a combo box named cboFileToFindExe, a text box named txtExecutablePath, and a command button named cmdOpenApplication.

cboFileToFileExe is interesting in itself because it uses a function to populate itself. This function, ListFiles(), is placed in the combo box's Row Source Type property (see Figure 15.5). Listing 15.3 shows the code used in the ListFiles() function.

Figure 15.5. Using a function to populate a combo box is sometimes the only way to quickly create one dynamically.


Listing 15.3. Chap15.mdb: Filling in a Combo Box
Function ListFiles(fld As Control, id As Variant, row As Variant, _
   col As Variant, code As Variant) As Variant

   Static astrFiles(127) As String, intEntries As Integer

   Dim varReturnVal As Variant
   varReturnVal = Null

   Select Case code
      Case LB_INITIALIZE      ' Initialize.
         intEntries = 0
         '-- Get the path of the application
         strAppPath = Left$(CurrentDb.Name, _
            InStrRev(CurrentDb.Name, ""))
         '-- Populate the array
         astrFiles(intEntries) = Dir(strAppPath & "*.*")
         Do Until astrFiles(intEntries) = "" Or intEntries >= 127
            intEntries = intEntries + 1
            astrFiles(intEntries) = Dir
         Loop
         varReturnVal = intEntries

      Case LB_OPEN            ' Open.
         varReturnVal = Timer    ' Generate unique ID for control.

      Case LB_GETROWCOUNT     ' Get number of rows.
         varReturnVal = intEntries

      Case LB_GETCOLUMNCOUNT     ' Get number of columns.
         varReturnVal = 1

      Case LB_GETCOLUMNWIDTH     ' Column width.
         varReturnVal = -1       ' -1 forces use of default width.

      Case LB_GETVALUE        ' Get data.
         varReturnVal = astrFiles(row)

      Case LB_END             ' End.
         For intEntries = 0 To 127
            astrFiles(intEntries) = ""
         Next
   End Select

   ListFiles = varReturnVal
End Function

The ListFiles() function is standard for populating a combo box programmatically. The combo box is used to place all the filenames in the current folder in the astrFiles array.

When the combo box is populated, users can choose a file to examine from the list. When they do, the AfterUpdate event of the combo box has an event attached to it that uses the FindExecutable() API function to locate the executable application for the file, if one exists. Listing 15.4 shows the code for the cboFileToFindExe_AfterUpdate sub.

Listing 15.4. Chap15.mdb: Displaying the Associated File
Private Sub cboFileToFindExe_AfterUpdate()

   Dim strFileName As String
   Dim lngReturnVal
   '-- Set up the string buffer used for the actual return value.
   Dim EXEPath As String
   EXEPath = String$(255, 0)

   '-- Actual API Call
   lngReturnVal = wu_FindExecutable(Me!cboFileToFindExe, _
   strAppPath, EXEPath)
   If lngReturnVal > 32 Then
      Me!txtExecutablePath = Left(EXEPath, InStr(1, EXEPath, Chr(0)) - 1)
      '-- Greater then 32 means an exe has been found.
   Else
      Me!txtExecutablePath = "Not Associated with an Application"
   End If

End Sub

Here are a couple of main points about the cboFileToFindExe_AfterUpdate routine:

  • The following lines are quite common for setting up strings used to return a string value from an API call:

    '-- Set up the string buffer used for the actual return value.
      Dim EXEPath As String
      EXEPath = String$(255, 0)
    

Note

You have to pad out a string to a maximum fixed length because API calls can't deal with Access variable-length strings. The API call can't expand a string, so you need to make it the maximum size possible.


  • In the following code lines, Me!cboFileToFindExe is the combo box value that's a filename, strAppPath is the path of the application that was retrieved in the ListFiles() function, and EXEPath is the return buffer set up earlier in the function:

    '-- Actual API Call
    lngReturnVal = wu_FindExecutable(Me!cboFileToFindExe, _
       strAppPath, EXEPath)
    
  • The last line trims off the Null value that's placed the end of a string retrieved from the API call:

    Me!txtExecutablePath = Left(EXEPath, InStr(1, _
       EXEPath, Chr(0)) - 1)
    

Figure 15.6 shows the form just after it looks up the executable for Win32api.txt.

Figure 15.6. The API call FindExecutable() is useful for locating associated applications.


The other interesting code takes the executable path that was stored in txtExecutablePath and uses Shell() to start the application, opening the file chosen in the cboFileToFindExe combo box. The code, shown in Listing 15.5, is attached to the cmdOpenApplication command button on the OnClick event.

Listing 15.5. Chap15.mdb: Opening the Requested File
Private Sub cmdOpenApplication_Click()

  Dim lngReturnVal As Long
   '-- Test to make sure a file has been chosen
   If IsNull(Me!cboFileToFindExe) Then
      MsgBox "No File Chosen!"
      Exit Sub
  End If

  '-- Make sure an application is associated
  If Me!txtExecutablePath = "Not Associated with an Application" Then
     MsgBox "This file has no application associated with it!"
     Exit Sub
  End If

  '-- Call the shell command
  lngReturnVal = Shell(Me!txtExecutablePath & " " & strAppPath & _
     Me!cboFileToFindExe, 3)

End Sub

This code can be useful when used in an environment that you don't know which applications will be needed. Other useful routines are those that can help with handling the network from within Access.

Connecting and Disconnecting Network Drives from Within Access

Being able to manipulate the network from within your application gives you just that much more power, so you won't have to rely on outside applications to help control the environment.Two ways to do that are demonstrated in the following sections for both connecting and disconnecting network drives:

  • Programmatically connecting and disconnecting network drives directly

  • By calling the standard dialogs to connect and disconnect the network drives

Programmatically Connecting and Disconnecting Network Drives Directly

The following API declarations—WNetAddConnectionA and WNetCancelConnectionA—are dealt with in this section:

Declare Function wu_NetAddConnection Lib "mpr" Alias _
   "WNetAddConnectionA" (ByVal NetPath$, ByVal Password$, _
   ByVal LocalDrive$) As Integer

Declare Function wu_NetCancelConnection Lib "mpr" Alias _
   "WNetCancelConnectionA" (ByVal NetPath$, ByVal FileForce%) _
   As Integer

The form used for this example is named—aptly enough—ConnectAndDisconnectDriveExample. In Figure 15.7, see what Explorer shows for existing drive connections.

Figure 15.7. Notice that no drive G is currently connected.


Open the ConnectAndDisconnectDriveExample form. Next, fill in the Server Path to Connect text box, which is also called txtPathToConnect. Also fill in the Drive to Connect text box, which is also called txtDriveToConnect. You can see the resulting text in the form in Figure 15.8.

Figure 15.8. These two fields will work together to create a new connection.


Click the command button labeled Connect New Drive, otherwise known as cmdConnectNewDrive. If the connection is successful, you'll see a message saying so; if not, you'll see an error message. After the connection, Explorer should look like Figure 15.9.

Figure 15.9. Drive G is now connected and looking fine.


The actual code to perform this magic is a little more than a dozen lines (see Listing 15.6). The tough one is performed with one API call. The routine, cmdConnectNewDrive_Click, is attached to the command button cmdConnectNewDrive.

Listing 15.6. Chap15.mdb: Connecting a Network Drive Programmatically
Private Sub cmdConnectNewDrive_Click()
   Dim lngResult As Long

   '-- Make sure both fields are there.
   If IsNull(Me!txtPathToConnect) Or IsNull(Me!txtDriveToConnect) Then
      MsgBox "Please supply both a path and a drive!"
      Exit Sub
  End If
  '-- Attempt the connection
  lngResult = wu_NetAddConnection(Me!txtPathToConnect, "", _
     Me!txtDriveToConnect)

  If lngResult = 0 Then
     MsgBox "Drive connected successfully!"
  Else
     MsgBox "Error occurred!"
  End If

End Sub

As you can see, the workhorse is the line that reads

lngResult = wu_NetAddConnection(Me!txtPathToConnect, "", _
Me!txtDriveToConnect)

This routine takes the path and the drive to connect. (The empty quotation marks in the middle are for a password, if required.)

The last part of this example disconnects the drive specified in txtDriveToConnect. The interesting part of this code is it tries to disconnect gently first. This means that if any files are still open, the disconnection will fail.

The routine then brings back a message box, asking whether the user wants to strong-arm the file(s) and force the closing. The code is attached to the OnClick event of the cmdDisconnect command button and is shown in Listing 15.7.

Listing 15.7. Chap15.mdb: Disconnecting a Network Drive
Private Sub cmdDisconnect_Click()
  Dim lngResult As Long

  '-- Try a gentle disconnect first
  If wu_NetCancelConnection(Me!txtDriveToConnect, 0) <> 0 Then
    Beep

  If MsgBox("The Connection could not be disconnected, " & _
   "this is probably because you have files open on this drive." _
   & vbCrLf & vbCrLf & "Do you want to force the disconnection" _
   & " with a possible loss of data?", 20, "Disconnect Error") = 6 Then
   '-- If permission was granted, then force the disconnect
   lngResult = wu_NetCancelConnection(Me!txtDriveToConnect, 1)
    Else '-- If no, then leave
       Exit Sub
    End If
  End If

  MsgBox "Drive disconnected successfully!"

End Sub

The idea behind these routines is to use them when you don't want to have user intervention. They're used on a form here, but can be called without users even knowing about them. Generally, if you want users to supply the paths, you can just call the standard dialogs.

Calling Standard Dialogs to Connect and Disconnect Network Drives

By calling the standard network dialogs, users have a familiar way to choose network drives and paths in which to create connections. The routines to call the functions WNetConnectionDialog and WNetDisconnectDialog are very straightforward to call, but require some arguments to be passed. You might not want to have to deal with these arguments each time you call because they have no real effect and don't change when you call them. When this is the case, you can call them from other routines.

Note

Routines such as these are sometimes called wrappers, because they're wrapped around the function and set up variables within them. You can then call them fairly easily from anywhere in the application.


To simplify things even further, however, I've created some wrappers for the API calls. The declarations for the two routines are as follows:

Declare Function wu_WNetConnectionDialog Lib "mpr" Alias _
   "WNetConnectionDialog" (ByVal hwnd As Long, ByVal dwType As Long) _
   As Long
Declare Function wu_WNetDisconnectDialog Lib "mpr" Alias _
   "WNetDisconnectDialog" (ByVal hwnd As Long, _
   ByVal dwType As Long) As Long

The form used for these examples is ConnectAndDisconnectDialogsExample. Figure 15.10 shows this form with the connect dialog (Map Network Drive) displayed by clicking the command button labeled Call Network Connect Dialog.

Figure 15.10. The wrapper function is called directly from an event on a command button on this form.


The wrapper functions used—ap_CallNetworkConnectDialog() and ap_CallNetworkDisconnectDialog()—are placed in the OnClick event of each of the command buttons. Listing 15.8 shows the code for p_CallNetworkConnectDialog().

Listing 15.8. Chap15.mdb: Calling the Network Connect Dialog
Public Function ap_CallNetworkConnectDialog()
    Dim lngDummy As Long
    Dim lngHWind As Long

    lngDummy = wu_WNetConnectionDialog(lngHWind, 1)

End Function

Pretty extensive, isn't it? As mentioned before, this call doesn't even necessarily require a wrapper function. The function ap_CallNetworkDisconnectDialog() isn't really any more difficult, as you can see in Listing 15.9.

Listing 15.9. Chap15.mdb: Calling the Network Disconnect
Function ap_CallNetworkDisconnectDialog()
   Dim lngDummy As Long
   Dim lngHWind As Long
   lngDummy = wu_WNetDisconnectDialog(lngHWind, 1)

End Function

Note

The return value of both API calls isn't used for these examples. If successful in their tasks, the routines return a 0; anything else means that a problem occurred or Cancel was chosen. Different values are returned for various situations, and you'll need to play with them to determine which to trap.


Figure 15.11 shows the dialog that's brought up by clicking the Call Network Disconnect Dialog button.

Figure 15.11. This is just one of many system utilities that you can include in your applications.


There are additional networking API calls as well. The examples shown here have proven to be the most valuable to me. Another set of valuable routines is discussed in the next section.

Displaying the Current User and Computer Name

The next two API routines, GetUserNameA and GetComputerNameA, return the current user and computer name. Here are the declarations for these routines:

Declare Function wu_GetUserName Lib "advapi32.dll" Alias "GetUserNameA" _
   (ByVal lpBuffer As String, nSize As Long) As Long

Declare Function wu_GetComputerName Lib "kernel32" Alias _
   "GetComputerNameA" (ByVal lpBuffer As String, nSize As Long) As Long

These routines come in handy for creating a logon screen for your application that automatically polls who the user is from the system. You can then pass the information on when dealing with ODBC queries, as well as when dealing with Access's own security.

The form, GetUserAndComputerNameExample, is located in the Chap15.mdb database. It has two text boxes, txtUserName and txtComputerName. As you can see in Figure 15.12, the actual API calls are called from within other wrapper functions.

Figure 15.12. The actual calls can be seen here in the ControlSource properties of these text boxes.


Listing 15.10 shows the code for ap_GetUserName().

Listing 15.10. Chap15.mdb: Retrieving the User's Name
Function ap_GetUserName() As Variant

   Dim strUserName As String
   Dim lngLength As
Long
   Dim lngResult As Long

   '-- Set up the buffer
   strUserName = String$(255, 0)
   lngLength = 255
   '-- Make the call
   lngResult = wu_GetUserName(strUserName, lngLength)

  '-- Assign the value
  ap_GetUserName = strUserName

End Function

Pretty tough, huh? The code for ap_GetComputerName() is about as “hard,” as Listing 15.11 shows.

Listing 15.11. Chap15.mdb: Retrieving the Computer's Name
Function ap_GetComputerName() As Variant

   Dim strComputerName As String
   Dim lngLength As Long
   Dim lngResult As Long

   '-- Set up buffer.
   strComputerName = String$(255, 0)
   lngLength = 255

   '-- Make the call.
   lngResult = wu_GetComputerName(strComputerName, lngLength)

   '-- Clean up and assign the value.
   ap_GetComputerName = Left(strComputerName, InStr(1, strComputerName, _
      Chr(0)) - 1)

End Function

That's all there is to it. Figure 15.13 shows the form in Run mode, with the user and computer name showing.

Figure 15.13. Grabbing the user and computer are just two of hundreds of system operations you can perform.


The next set of API calls displays additional information about the computer you're using. These calls display various paths of the three most important folders used by most Windows setups:

  • Windows folder

  • Windows System folder

  • Temp folder

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

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