Using Intel® Visual Fortran to Create and Build Windows*-Based Applications

ID 757211
Date 7/23/2021
Public
Document Table of Contents

Adding Code to Your Application

The structure of your application remains the same as when using a dialog box that does not contain an ActiveX control. See Writing a Dialog Application Overview for details. This section discusses programming specific to ActiveX controls.

Your application must call COMINITIALIZE before calling DLGINIT with a dialog box that contains an ActiveX control. Your application must include the statement USE IFCOM to access COMINITIALIZE. Your application must call COMUNINITIALIZE when you are done using ActiveX controls, but not before calling DLGUNINIT for the dialog box that contains the ActiveX control.

You can call the methods of an ActiveX control and set and retrieve its property values using the interfaces generated by the Intel Fortran Module Wizard or by using the IFAUTO routines. To do this, you must have the object's IDispatch interface pointer. Use the DLGGET function with the ActiveX control's name, the DLG_IDISPATCH control index, and an integer variable to receive the IDispatch pointer. For example:

  retlog = DlgGet( dlg, IDC_ACTIVEX, idispatch, DLG_IDISPATCH )

You do not need to specify the index DLG_IDISPATCH because it is the default integer index for an ActiveX control.

However, the control's IDispatch pointer is not available until after the control has been created and is only valid until the dialog box is closed. The control is created during the call to DLGMODALDLGMODELESS or . If you call DLGGET to retrieve the IDispatch pointer before calling DLGMODAL or DLGMODELESS, the value returned will be 0.

Do not call COMRELEASEOBJECT with the iDispatch pointer returned by DLGGET. The dialog procedures use a reference counting optimization since the lifetime of the control is guaranteed to be less than the lifetime of the dialog box.

If you want to use a method or property of a control before the dialog box is displayed to your application's user, you can use a DLG_INIT callback. Call DLGSETSUB using the dialog box name and the DLG_INIT index to define the callback. For example:

  retlog = DlgSetSub( dlg, IDD_DIALOG, DlgSub, DLG_INIT )

The DLG_INIT callback is called after the dialog box is created but before it is displayed (with callbacktype=DLG_INIT) and immediately before the dialog box is destroyed (with callbacktype=DLG_DESTROY). The DLG_INIT callback is the soonest that the control's IDispatch pointer is available. The DLG_DESTROY callback is the latest that this pointer is valid. After the DLG_DESTROY callback, the ActiveX control is destroyed.

The following example shows using a DLG_INIT callback to reset the state of a control property before it is destroyed:

  SUBROUTINE mmplayerSub( dlg, id, callbacktype )
   !DEC$ ATTRIBUTES DEFAULT :: mmplayerSub
   use iflogm
   use ifcom
   use ifauto
   implicit none
   type (dialog) dlg
   integer id, callbacktype
   include 'resource.fd'
   integer obj, iret
   logical lret
   if (callbacktype == dlg_init) then
       lret = DlgGet(dlg, IDC_ACTIVEMOVIECONTROL1, obj)
       !  Add any method or property calls here before the
       !  dialog box is displayed
   else if (callbacktype == dlg_destroy) then
       !  Reset the filename to "" to "close" the current file
       lret = DlgGet(dlg, IDC_ACTIVEMOVIECONTROL1, obj)
       iret = AUTOSETPROPERTY(obj, "FileName", "")
   endif
  END SUBROUTINE mmplayerSub

The module generated by the Fortran Module Wizard for an ActiveX control contains a number of sections:

  • ! CLSIDs

    Parameters of derived type GUID which identify the ActiveX control class. Your application typically doesn't need to use this parameter.

  • ! IIDs

    Parameters of derived type GUID which identify source (event) interfaces of the ActiveX control. Your application can use these values in calls to DLGSETCTRLEVENTHANDLER (see below).

  • ! Enums

    Parameters of type integer that identify constants used in the ActiveX control's interfaces.

  • ! Interfaces

    Interfaces for the source (event) interfaces that are defined by the ActiveX control. There may be 0, 1, or more source interfaces implemented by the control. A control does not have to support events.

  • ! Module Procedures

    Wrapper routines that make it easy to call the control's methods and get or retrieve the control's properties.

See the Language Reference for more information on using the method and property interfaces generated by the Intel Fortran Module Wizard.

In addition to methods and properties, ActiveX controls also define events to notify your application that something has happened to the control. The dialog procedures provide a routine, DLGSETCTRLEVENTHANDLER, that allows you to define a routine to be executed when an event occurs.

The DLGSETCTRLEVENTHANDLER function has the following interface:

integer DlgSetCtrlEventHandler( dlg, controlid, handler, dispid, iid )

The arguments are as follows:

dlg

(Input) Derived type DIALOG. Contains dialog box parameters.

controlid

(Input) Integer. Specifies the identifier of a control within the dialog box (from the .FD file).

handler

(Input) EXTERNAL. Name of the routine to be called when the event occurs.

dispid

(Input) Integer. Specifies the member id of the method in the event interface that identifies the event

iid

(Input, Optional) Derived type (GUID). Specifies the Interface identifier of the source (event) interface. If not supplied, the default source interface of the ActiveX control is used.

Consider the following function call:

  ret = DlgSetCtrlEventHandler( dlg, IDC_ACTIVEMOVIECONTROL1, &
      ActiveMovie_ReadyStateChange, -609, IID_DActiveMovieEvents2 )

In this function call:

  • IDC_ACTIVEMOVIECONTROL1 identifies an ActiveMovie control in the dialog box.

  • ActiveMovie_ReadyStateChange is the name of the event handling routine.

  • -609 is the member id of the ActiveMovie's control ReadyStateChange event. You can get this number from:

    • The module that the Fortran Module Wizard generated. There is a "MEMBERID = nn" comment generated for each method in a source interface (see the example below).

    • The documentation of the ActiveX control.

    • A tool that allows you to examine the type information of the ActiveX control, for example, the OLE/COM Object Viewer in the Microsoft Visual Studio* IDE.

  • IID_DActiveMovieEvents2 is the identifier of the source (event) interface.

The interface generated by the Intel Fortran Module Wizard for the ReadyStateChange event follows:

 INTERFACE
   !Reports that the ReadyState property of the ActiveMovie Control 
   !has changed
   ! MEMBERID = -609
   SUBROUTINE DActiveMovieEvents2_ReadyStateChange($OBJECT, ReadyState)
       INTEGER(4), INTENT(IN)	:: $OBJECT	 ! Object Pointer
       !DEC$ ATTRIBUTES VALUE	:: $OBJECT
       INTEGER(4)	:: ReadyState
       !DEC$ ATTRIBUTES VALUE	:: ReadyState
       !DEC$ ATTRIBUTES STDCALL :: DActiveMovieEvents2_ReadyStateChange
    END SUBROUTINE DActiveMovieEvents2_ReadyStateChange
  END INTERFACE

The handler that you define in your application must have the same interface. Otherwise, your application will likely crash in unexpected ways because of the application's stack getting corrupted.

Note that an object is always the first parameter in an event handler. This object value is a pointer to the control's source (event) interface, not the IDispatch pointer of the control. You can use DLGGET as described above to retrieve the control's IDispatch pointer.