Calling Win32 Routines

This section describes general information about calling Win32 routines from Visual Fortran applications. It describes the following topics:

A Comparison of Visual Fortran and Win32 Routines

Visual Fortran provides Fortran 95/90 language elements (such as intrinsic procedures and statements) that conform to the Fortran 95 standard. Visual Fortran also provides language elements that are language extensions, including library routines.

The library routines provided by Visual Fortran:

In contrast, the Win32 Application Programming Interface (API) routines provided by the Windows operating system:

There are many groups of Win32 routines (see the Platform SDK and other resources). Win32 routines provide sophisticated window management, memory management, graphics support, threading, security, and networking.

You can access many Win32 routines from any Fortran application, including Fortran Console and Fortran QuickWin applications. Only the Fortran Windows application project type provides access to the full set of Win32 routines needed to create GUI applications.

Fortran Console applications are text-only applications. Fortran QuickWin applications allow you to build Windows style applications easily, but access only a small subset of the available Win32 API features. (Fortran QuickWin applications also allow you to use graphics.) For differences between Fortran QuickWin and Fortran Windows applications, see Comparing QuickWin with Windows-Based Applications.

Including the Visual Fortran Interface Definitions for Win32 Routines

Visual Fortran provides interface definitions for both the Visual Fortran library routines and nearly all of the Win32 API routines in the standard include directory:

  ...\DF98\INCLUDE\

To include the Win32 interface definitions, do one of the following:

  1. Add the statement USE DFWIN to include all Win32 API routine definitions.

    The USE DFWIN statement makes all parameters and interfaces for most Windows routines available to your Visual Fortran program. Any program or subprogram that uses the Windows features can include the statement USE DFWIN, which is needed in each subprogram that makes graphics calls.

    Add the USE statement before any declaration statements (such as IMPLICIT NONE or INTEGER) or any other modules containing declaration statements.

  2. You can limit the type of parameters and interfaces for Windows applications to make compilation times faster. To do this, include only the subsets of the Win32 API needed in multiple USE statements (see the file ...\DF98\INCLUDE\DFWIN.F90).

    To locate the specific libraries for the routines being called, view the QuickInfo at the bottom of the routine page in the Platform SDK documentation, which lists the import library name. For example, to call only GetSystemTime, you need the interface definitions provided in kernel32.mod (binary form). To do this, add the following USE statement:

     USE KERNEL32

    If you want to further minimize compile time, add the ONLY keyword to the USE statement. For example:

     USE KERNEL32, only: GetSystemTime, GetLastError
    

Calling Win32 Routines Using the Visual Fortran Interface Definitions

To call the appropriate Win32 routine after including the Visual Fortran interface definitions, follow these guidelines:

  1. Examine the documentation for the appropriate routine in the Platform SDK (for example GetSystemTime) to obtain the following information:
  2. If you are not sure about the data type of arguments or its function return value, you can examine the interface definitions in the appropriate .F90 file in ...\DF98\INCLUDE\. For example, to view the interface definition for GetSystemTime:
    1. In a text editor (such as Notepad), open the file kernel32.f90 from ...\DF98\INCLUDE\.
    2. Search (or Find) the routine name (such as GetSystemTime)
    3. View the interface definition and copy-and-paste parts of it into your source file text editor window.

  3. If one of the arguments is a structure, you should look up the definition in DFWINTY.F90 in ...\DF98\INCLUDE\. For example, to view the data type definition for the T_SYSTEMTIME type used in GetSystemTime:
    1. In a text editor (such as Notepad), open the file DFWINTY.F90 from ...\DF98\INCLUDE\.
    2. Search (or Find) the data type name (such as T_SYSTEMTIME).
    3. View the data type definition and copy-and-paste parts of it into your source file text editor window. Note the defined field names for later use.
    4. Define a variable name to use the derived-type definition in your program, such as:
      TYPE (T_SYSTEMTIME) MYTIME
        
    5. Use the variable definition to call the Win32 routine. For example, the completed program follows:
       !  Getsystime.f90 file, shows how to call a Win32 routine
       !
       ! Since the only routine called is GetSystemTime, only include
       ! interface definitions from kernel32.mod instead of all modules
       ! included by dfwin.f90. Type definitions are defined in DFWINTY,
       ! which is used within KERNEL32.
      
        PROGRAM Getsystime
      
         USE KERNEL32
      
         TYPE (T_SYSTEMTIME) MYTIME
      
         CALL GetSystemTime(MYTIME)
      
         WRITE (*,*) 'Current UTC time hour and minute:', Mytime.wHour, Mytime.Wminute
      
        END PROGRAM
        

      You might create a new Fortran Console (or QuickWin) application project, add the code shown above as a source file, build it, and view the result.

Special Naming Convention for Certain QuickWin and Win32 Graphics Routines

Most QuickWin routines have a QQ appended to their name ito differentiate them from equivalent Win32 operating system routines. However, a small group of QuickWin graphics routines have the same name as the Win32 routines, causing a potential naming conflict if your program unit includes both USE DFLIBS (which includes QuickWin routine interface definitions) and USE DFWIN (which includes Win32 API routine interface definitions).

The QuickWin routines perform the same functions as the SDK routines but take a unit number, or use the unit in focus at the time of call, instead of taking a device context (DC) as one of their arguments.

To handle this situation, a special MSFWIN$ prefix is used for the Win32 routines. These prefixed names must be used even if you only specify USE DFWIN.

For example, Rectangle is a QuickWin routine, not a Win32 SDK routine, and you must use the name MSFWIN$Rectangle to refer to the SDK routine:

QuickWin Routine Win32 API Routine
ARC MSFWIN$Arc
ELLIPSE MSFWIN$Ellipse
FLOODFILL MSFWIN$FloodFill
GETBKCOLOR MSFWIN$GetBkColor
GETPIXEL MSFWIN$GetPixel
GETTEXTCOLOR MSFWIN$GetTextColor
LINETO MSFWIN$LineTo
PIE MSFWIN$Pie
POLYGON MSFWIN$Polygon
RECTANGLE MSFWIN$Rectangle
1 MSFWIN$SelectPalette
SETBKCOLOR MSFWIN$SetBkColor
SETPIXEL MSFWIN$SetPixel
SETTEXTCOLOR MSFWIN$SetTextColor

1 There is no longer a QuickWin routine named SELECTPALLETE.

Understanding Data Type Differences

The files referenced by the DFWIN module are a Fortran version (a subset) of the Win32 WINDOWS.H header file. The correspondence of data types is given in the following table:

Win32 Data Type Equivalent Fortran Data Type
BOOL, BOOLEAN LOGICAL(4)
BYTE BYTE
CHAR, CCHAR, UCHAR CHARACTER
COLORREF INTEGER(4)
DWORD, INT, LONG, ULONG INTEGER(4)
SHORT, USHORT, WORD INTEGER(2)
FLOAT REAL(4)
All Handles INTEGER(4)
All Pointers (LP*, P*) INTEGER(4) (Integer Pointers)

Other notes about equivalent data types for arguments:

The structures in WINDOWS.H have been converted to derived types in DFWINTY. Unions in structures are converted to union/maps within the derived type. Names of components are unchanged. Bit fields are converted to Fortran's INTEGER(4). Functions accessing bit fields are contained in the DFWIN.F90 module with names of the form:

   StructureName$BitfieldName

These bit field functions take an integer argument and return an integer. All bit fields are unsigned integers. The following shows the WINDOWS.H definition. It is followed by an example program where Win32 structures are represented as Fortran derived types.

WINDOWS.H Definition

typedef struct _LDT_ENTRY {
  WORD LimitLow;
  WORD BaseLow;
  union {
     struct {
        BYTE BaseMid;
        BYTE Flags1;
        BYTE Flags2;
        BYTE BaseHi;
     } Bytes;

     struct {
        DWORD BaseMid : 8;
        DWORD Type : 5;
        DWORD Opl : 2;
        DWORD Pres : 1;
        DWORD LimitHi : 4;
        DWORD Sys : 1;
        DWORD Reserved_0 : 1;
        DWORD Default_Big : 1;
        DWORD Granularity : 1;
        DWORD BaseHi : 8;
     } Bits;
  } HighWord;
 } LDT_ENTRY, *PLDT_ENTRY;

Note that _LDT_ENTRY and PLDT_ENTRY do not exist in the Fortran definition. Also note that Bits.xxx is not the same as the C version. In the Fortran case, the bit field functions must be used. For example, the C variable yyy.HighWord.Bits.BaseHi is represented in Fortran by LDT_ENTRY$BaseHi(ldtentry%HighWord%bits).

The following Fortran example shows the use of the corresponding Fortran data definitions and the use of a bit extraction utility routine:

Program Test
    type T_LDT_ENTRY$HIGHWORD_BYTES
       sequence
       BYTE  BaseMid
       BYTE  Flags1
       BYTE  Flags2
       BYTE  BaseHi
    end type T_LDT_ENTRY$HIGHWORD_BYTES

    type  T_LDT_ENTRY$HIGHWORD
       sequence
       union
          map
             type (T_LDT_ENTRY$HIGHWORD_BYTES)  Bytes
          end map
          map
             integer(4)  Bits
          end map
       end union
    end type T_LDT_ENTRY$HIGHWORD

    type T_LDT_ENTRY
       sequence
       integer(2) LimitLow
       integer(2) BaseLow
       type (T_LDT_ENTRY$HIGHWORD)  HighWord
    end type T_LDT_ENTRY

type(T_LDT_ENTRY) ldtentry

integer(4) thebits

external LDT_ENTRY$BaseHi
integer(4) LDT_ENTRY$BaseHi

ldtentry%HighWord%bits = #ABFFFFFF

thebits = LDT_ENTRY$BaseHi(ldtentry%HighWord%bits)
write(*,'(Z)') thebits
end program Test

integer(4) function LDT_ENTRY$BaseHi (Bits)
integer(4)   Bits
   LDT_ENTRY$BaseHi = IAND(ISHFT(bits,-24),#FF)
end function LDT_ENTRY$BaseHi

In addition to using the TYPE statement, you can use the STRUCTURE statement as shown by the following example. If you have embedded data types, the data type definitions are easier to read. Also, selecting the components is more natural. For example:

  program struct
 STRUCTURE /T_LDT_ENTRY/
    integer(2) LimitLow
    integer(2) BaseLow
    UNION
       MAP
         STRUCTURE /f_Bytes/ Bytes
            BYTE  BaseMid
            BYTE  Flags1
            BYTE  Flags2
            BYTE  BaseHi
         END STRUCTURE
       END MAP
		
       MAP
         STRUCTURE /f_Bits/ Bits
             INTEGER(4) Bits		   
         END STRUCTURE
       END MAP
    END UNION
 END STRUCTURE
 
 type(T_LDT_ENTRY) ldtentry

 ldtentry%Bits%Bits = #7f6f5f4f
 write(*,'(8Z)') ldtentry%Bits%Bits
 write(*,'(8Z)') ldtentry%Bytes%BaseMid
 
 end program

The expected program output follows:

 7F6F5F4F
  4F

You can create a data object defined by a STRUCTURE statement in two ways, by using one of the following:

The example program shows how to access a field in a structured data object, for example:

 I4=ldtentry%Bits%Bits

Examples Programs and Samples

Visual Fortran provides many Sample programs that show Fortran Windows applications that call Win32 routines, such as the following:

Additional Resources

For more information about Win32 API routines and Windows programming, see the following:

Visual Fortran provides an online bookstore that lists suggested titles:

  1. Open the Visual Fortran home page (http://www.compaq.com/fortran)
  2. Click Bookstore in the left margin
  3. Click the link to the Compaq Fortran Online Bookstore
  4. Click the link for the appropriate area of interest, such as Win32
  5. View the descriptions of the appropriate books