ACC2000: Screen.ActiveForm Returns the Main Form, Not the Subform (210210)



The information in this article applies to:

  • Microsoft Access 2000

This article was previously published under Q210210
Advanced: Requires expert coding, interoperability, and multiuser skills.

This article applies to a Microsoft Access database (.mdb) and to a Microsoft Access project (.adp).

SYMPTOMS

If the currently active control on the screen is in a subform, Screen.ActiveControl correctly references this control. Screen.ActiveForm, however, references the main form and not the subform that the control is contained on.

CAUSE

A subform is not really a form, but a control (just like a text box or command button) that appears on a form. Screen.ActiveForm always returns the active form, not a subform control.

RESOLUTION

You can use the Set_Screen_ActiveSubformControl function described in the "More Information" section to determine what subform control contains the Screen.ActiveControl. This function sets a global control variable Screen_ActiveSubformControl to the currently active subform control on screen. The Set_Screen_ActiveSubformControl() function returns one of the following results:

True: Screen_ActiveSubformControl was set to the subform control that contains Screen.ActiveControl.

-or-

False: Screen.ActiveControl does not exist or is not in a subform.

MORE INFORMATION

How To Create the Set_Screen_ActiveSubformControl() Function

To create the Set_Screen_ActiveSubformControl() function, follow these steps:
  1. Create a module and type the following lines in the Declarations section if they are not already there:
    Option Explicit
    Dim Screen_ActiveSubformControl As Control
    					
  2. Type the following two procedures:
    Function Set_Screen_ActiveSubformControl()
      Dim frmActive As Form, ctlActive As Control
      Dim hWndParent As Long
    
      ' Clear the control variable.
      Set Screen_ActiveSubformControl = Nothing
    
      ' Assume a subform is not active.
      Set_Screen_ActiveSubformControl = False
    
      ' Get the active form and control.
      On Error Resume Next
      Set frmActive = Screen.ActiveForm
      Set ctlActive = Screen.ActiveControl
      If Err <> 0 Then Exit Function
    
      ' Get the unique window handle identifying the form
      ' .. the active control is on.
      hWndParent = ctlActive.Parent.Properties("hWnd")
    
      ' If the active form window handle is the same as the window
      ' handle of the form the active control is on, then we are on the
      ' mainform, so exit.
      If hWndParent = frmActive.hWnd Then Exit Function
    
      ' Find a subform control that has a window handle matching the
      ' .. window handle of the form the active control is on.
      Set_Screen_ActiveSubformControl = FindSubform(frmActive, _
          hWndParent)
    
    End Function
    
    Function FindSubform(frmSearch As Form, hWndFind As Long)
      Dim i As Integer
      On Error GoTo Err_FindSubForm
    
      ' Assume we will find a subform control with a window
      ' .. handle matching hWndFind.
      FindSubform = True
    
      ' Visit each control on the form frmSearch.
      For i = 0 To frmSearch.Count - 1
         ' If the control is a subform control...
         If TypeOf frmSearch(i) Is SubForm Then
            ' .. does the window handle match the one we are looking
            ' for?
         If frmSearch(i).Form.hWnd = hWndFind Then
            ' We found it! Set the global control variable and exit.
            Set Screen_ActiveSubformControl = frmSearch(i)
            Exit Function
         Else
            ' Otherwise, search this subform control (recursively)
            ' .. to see if it contains a sub-subform control
            ' .. with a window handle matching the one we are
            ' .. interested in.
    
            ' If we found a subform control, then exit.
            If FindSubform(frmSearch(i).Form, hWndFind) Then
               Exit Function
            End If
         End If
      End If
    Next i
    
    Bye_FindSubform:
    ' If we didn't exit the function earlier, then there is no
    ' .. subform or sub-subform control on this form that has a window
    ' .. handle matching the one we are interested in, so return false.
    FindSubform = False
    Exit Function
    
    Err_FindSubForm:
      MsgBox Error$, 16, "FindSubform"
      Resume Bye_FindSubform
    End Function
    					

How to Use the Set_Screen_ActiveSubformControl() Function

To use the Set_Screen_ActiveSubformControl() function to determine what subform control contains the Screen.ActiveControl, follow these steps:

CAUTION: If you follow the steps in this example, you modify the sample database Northwind.mdb. You may want to back up the Northwind.mdb file and follow these steps on a copy of the database.

  1. Start Microsoft Access and open the sample database Northwind.mdb or the sample project NorthwindCS.adp.
  2. Create the functions described in the previous section "How To Create the Set_Screen_ActiveSubformControl() Function."
  3. Create a new macro called AutoKeys as follows:
       Macro Name   Action      Action Arguments
       -------------------------------------------------------------------
       {F2}         RunCode     Function Name: =DisplayActiveSubformName()
    					
  4. Add the following function to the module that you created in step 1:
    Function DisplayActiveSubformName()
       Dim Msg As String
       Dim CR As String
       CR = Chr$(13)  ' Carriage Return.
    
       If Set_Screen_ActiveSubformControl() = False Then
          Msg = "There is no active subform!"
       Else
          Msg = "Active Form Name = " & Screen.ActiveForm.Name
          Msg = Msg & CR
          Msg = Msg & "Active ControlName = " & Screen.ActiveControl.Name
          Msg = Msg & CR
          Msg = Msg & "Active Subform ControlName = "
          Msg = Msg & Screen_ActiveSubformControl.Name
          Msg = Msg & CR
          Msg = Msg & "Active Subform Form Name = "
          Msg = Msg & Screen_ActiveSubformControl.Form.Name
       End If
    
       MsgBox Msg
    
    End Function
    					
  5. Open the Customers form in Design view, and then press F11 to switch to the Database window.
  6. Drag the Orders form from the Database window to the bottom of the Customers form to create a subform control. This action enables you to test the function on a subform and a sub-subform.
  7. Select the new subform control and set the following properties:

    Name: Testing 123
    SourceObject: Orders

  8. View the Customers form in Form view. Note that the Orders subform contains only orders for the current customer.
  9. Set the focus to a control in the Customers form, the Orders form (subform), or the Orders Subform (sub-subform), and then press the F2 key to run the macro.

Modification Type:MajorLast Reviewed:6/29/2004
Keywords:kbprb KB210210