SimConnect - Accessing from VB

From FSDeveloper Wiki
Jump to: navigation, search

Introduction

The SimConnect documentation states that you must use C or C++ to access SimConnect, unless you use the managed API, in which case you can use any of the Microsoft .Net language compilers. However I have found, after a bit of experimentation, that you can access the non-managed SimConnect API from VB and VBA, using appropriate DECLARE statements.

Below are the DECLARE statements I have written so far. Others can contribute to this section if they wish, until the entire API is covered.

Note : to make these work, you'll have to place a copy of SimConnect.dll somewhere where VB can find it, or else specify the path to it directly in the Declare statement

Declare Statements

Declare Function SimConnect_Open Lib "SimConnect.dll" _
   (phSimConnect As Long, _
    ByVal szName As String, _
    ByVal hWnd As Long, _
    ByVal UserEventWin32 As Long, _
    ByVal hEventHandle As Long, _
    ByVal ConfigIndex As Long) As Long
 
Declare Function SimConnect_GetNextDispatch Lib "SimConnect.dll" _
      (ByVal hSimConnect As Long, _
       ppData As Long, _
       pcbData As Long) As Long
       
Declare Function SimConnect_AddToDataDefinition Lib "SimConnect.dll" _
      (ByVal hSimConnect As Long, _
       ByVal DefineID As Long, _
       ByVal DatumName As String, _
       ByVal UnitsName As String, _
       Optional ByVal DatumType As Long, _
       Optional ByVal fEpsilon As Single, _
       Optional ByVal DatumID As Long) As Long
       
Declare Function SimConnect_RequestDataOnSimObjectType Lib "SimConnect.dll" _
      (ByVal hSimConnect As Long, _
       ByVal RequestID As Long, _
       ByVal DefineID As Long, _
       ByVal dwRadiusMeters As Long, _
       ByVal ObjectType As Long) As Long
       
Declare Function SimConnect_Close Lib "SimConnect.dll" (ByVal hSimConnect As Long) As Long

Constants & Enums

Const S_OK = 0
Const E_FAIL = &H80004005
Const E_INVALIDARG = &H80070057

Enum SIMCONNECT_RECV_ID
    SIMCONNECT_RECV_ID_NULL
    SIMCONNECT_RECV_ID_EXCEPTION
    SIMCONNECT_RECV_ID_OPEN
    SIMCONNECT_RECV_ID_QUIT
    SIMCONNECT_RECV_ID_EVENT
    SIMCONNECT_RECV_ID_EVENT_OBJECT_ADDREMOVE
    SIMCONNECT_RECV_ID_EVENT_FILENAME
    SIMCONNECT_RECV_ID_EVENT_FRAME
    SIMCONNECT_RECV_ID_SIMOBJECT_DATA
    SIMCONNECT_RECV_ID_SIMOBJECT_DATA_BYTYPE
    SIMCONNECT_RECV_ID_WEATHER_OBSERVATION
    SIMCONNECT_RECV_ID_CLOUD_STATE
    SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID
    SIMCONNECT_RECV_ID_RESERVED_KEY
    SIMCONNECT_RECV_ID_CUSTOM_ACTION
    SIMCONNECT_RECV_ID_SYSTEM_STATE
    SIMCONNECT_RECV_ID_CLIENT_DATA
End Enum

Enum SIMCONNECT_DATATYPE
    SIMCONNECT_DATATYPE_INVALID        ' invalid data type
    SIMCONNECT_DATATYPE_INT32          ' 32-bit integer number
    SIMCONNECT_DATATYPE_INT64          ' 64-bit integer number
    SIMCONNECT_DATATYPE_FLOAT32        ' 32-bit floating-point number (float)
    SIMCONNECT_DATATYPE_FLOAT64        ' 64-bit floating-point number (double)
    SIMCONNECT_DATATYPE_STRING8        ' 8-byte string
    SIMCONNECT_DATATYPE_STRING32       ' 32-byte string
    SIMCONNECT_DATATYPE_STRING64       ' 64-byte string
    SIMCONNECT_DATATYPE_STRING128      ' 128-byte string
    SIMCONNECT_DATATYPE_STRING256      ' 256-byte string
    SIMCONNECT_DATATYPE_STRING260      ' 260-byte string
    SIMCONNECT_DATATYPE_STRINGV        ' variable-length string

    SIMCONNECT_DATATYPE_INITPOSITION   ' see SIMCONNECT_DATA_INITPOSITION
    SIMCONNECT_DATATYPE_MARKERSTATE    ' see SIMCONNECT_DATA_MARKERSTATE
    SIMCONNECT_DATATYPE_WAYPOINT       ' see SIMCONNECT_DATA_WAYPOINT
    SIMCONNECT_DATATYPE_LATLONALT      ' see SIMCONNECT_DATA_LATLONALT
    SIMCONNECT_DATATYPE_XYZ            ' see SIMCONNECT_DATA_XYZ

    SIMCONNECT_DATATYPE_MAX             ' enum limit
End Enum

Enum SIMCONNECT_SIMOBJECT_TYPE
  SIMCONNECT_SIMOBJECT_TYPE_USER
  SIMCONNECT_SIMOBJECT_TYPE_ALL
  SIMCONNECT_SIMOBJECT_TYPE_AIRCRAFT
  SIMCONNECT_SIMOBJECT_TYPE_HELICOPTER
  SIMCONNECT_SIMOBJECT_TYPE_BOAT
  SIMCONNECT_SIMOBJECT_TYPE_GROUND
End Enum

Enum SIMCONNECT_EXCEPTION
  SIMCONNECT_EXCEPTION_NONE = 0
  SIMCONNECT_EXCEPTION_ERROR = 1
  SIMCONNECT_EXCEPTION_SIZE_MISMATCH = 2
  SIMCONNECT_EXCEPTION_UNRECOGNIZED_ID = 3
  SIMCONNECT_EXCEPTION_UNOPENED = 4
  SIMCONNECT_EXCEPTION_VERSION_MISMATCH = 5
  SIMCONNECT_EXCEPTION_TOO_MANY_GROUPS = 6
  SIMCONNECT_EXCEPTION_NAME_UNRECOGNIZED = 7
  SIMCONNECT_EXCEPTION_TOO_MANY_EVENT_NAMES = 8
  SIMCONNECT_EXCEPTION_EVENT_ID_DUPLICATE = 9
  SIMCONNECT_EXCEPTION_TOO_MANY_MAPS = 10
  SIMCONNECT_EXCEPTION_TOO_MANY_OBJECTS = 11
  SIMCONNECT_EXCEPTION_TOO_MANY_REQUESTS = 12
  SIMCONNECT_EXCEPTION_WEATHER_INVALID_PORT = 13
  SIMCONNECT_EXCEPTION_WEATHER_INVALID_METAR = 14
  SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_GET_OBSERVATION = 15
  SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_CREATE_STATION = 16
  SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_REMOVE_STATION = 17
  SIMCONNECT_EXCEPTION_INVALID_DATA_TYPE = 18
  SIMCONNECT_EXCEPTION_INVALID_DATA_SIZE = 19
  SIMCONNECT_EXCEPTION_DATA_ERROR = 20
  SIMCONNECT_EXCEPTION_INVALID_ARRAY = 21
  SIMCONNECT_EXCEPTION_CREATE_OBJECT_FAILED = 22
  SIMCONNECT_EXCEPTION_LOAD_FLIGHTPLAN_FAILED = 23
  SIMCONNECT_EXCEPTION_OPERATION_INVALID_FOR_OJBECT_TYPE = 24
  SIMCONNECT_EXCEPTION_ILLEGAL_OPERATION = 25
  SIMCONNECT_EXCEPTION_ALREADY_SUBSCRIBED = 26
  SIMCONNECT_EXCEPTION_INVALID_ENUM = 27
  SIMCONNECT_EXCEPTION_DEFINITION_ERROR = 28
  SIMCONNECT_EXCEPTION_DUPLICATE_ID = 29
  SIMCONNECT_EXCEPTION_DATUM_ID = 30
  SIMCONNECT_EXCEPTION_OUT_OF_BOUNDS = 31
End Enum

Structures

Type SIMCONNECT_RECV
   dwSize As Long
   dwVersion As Long
   dwID As Long
End Type

Type SIMCONNECT_RECV_EXCEPTION
  dwException As Long
  dwSendID As Long
  dwIndex As Long
End Type

Type SIMCONNECT_RECV_OPEN
  szApplicationName As String * 256
  dwApplicationVersionMajor As Long
  dwApplicationVersionMinor As Long
  dwApplicationBuildMajor As Long
  dwApplicationBuildMinor As Long
  dwSimConnectVersionMajor As Long
  dwSimConnectVersionMinor As Long
  dwSimConnectBuildMajor As Long
  dwSimConnectBuildMinor As Long
  dwReserved1 As Long
  dwReserved2 As Long
End Type

Type SIMCONNECT_RECV_SIMOBJECT_DATA
  dwRequestID As Long
  dwObjectID As Long
  dwDefineID As Long
  dwFlags As Long
  dwentrynumber As Long
  dwoutof As Long
  dwDefineCount As Long
  dwData As Long
End Type

Sample Code

This code retrieves the latitude / longitude of the user aircraft.

Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
      (Destination As Any, _
       Source As Any, _
       ByVal Length As Long)

Public Declare Function GetTickCount Lib "kernel32" () As Long

Enum DATA_DEFINE_ID
   DATA_DEF_POSITION
End Enum

Enum DATA_REQUEST_ID
   DATA_REQUEST_POSITION
End Enum

Enum DATA_IDS
   DATA_LATITUDE
   DATA_LONGITUDE
End Enum

Type PosRec
   Latitude As Double
   Longitude As Double
End Type

Dim hSimConnect As Long
Dim Position As PosRec
   
Sub GetPosition()
   Dim hr As Long
   Dim T As Long
   
   hr = SimConnect_Open(hSimConnect, "MYAPP", 0, 0, 0, 0)
   If (hr <> S_OK) Then
      MsgBox "Unable to connect with FSX!", vbExclamation, "SimConnect"
   Else
      hr = SimConnect_AddToDataDefinition(hSimConnect, DATA_DEF_POSITION, "PLANE LATITUDE", "Degrees", _
                  SIMCONNECT_DATATYPE_FLOAT64, 0, DATA_LATITUDE)
      hr = SimConnect_AddToDataDefinition(hSimConnect, DATA_DEF_POSITION, "PLANE LONGITUDE", "Degrees", _
                  SIMCONNECT_DATATYPE_FLOAT64, 0, DATA_LONGITUDE)
      hr = SimConnect_RequestDataOnSimObjectType(hSimConnect, DATA_REQUEST_POSITION, DATA_DEF_POSITION, _
                  0, SIMCONNECT_SIMOBJECT_TYPE_USER)
      T = GetTickCount()
      Do
         DoEvents
         RequestID = GetNextDispatch()
      Loop Until (RequestID = DATA_REQUEST_POSITION) Or (GetTickCount() > T + 2000)
      If RequestID = DATA_REQUEST_POSITION Then
         MsgBox "Latitude : " + Format(Position.Latitude, "Fixed") + vbCrLf + _
                "Longitude : " + Format(Position.Longitude, "Fixed"), vbInformation
      Else
         MsgBox "No data available!", vbExclamation
      End If
      SimConnect_Close hSimConnect
   End If
End Sub

Function GetNextDispatch() As Long
   ' this function returns the dwRequestID field of SIMCONNECT_RECV_SIMOBJECT_DATA, if applicable
   ' otherwise -1
   Dim hr As Long
   Dim pData As Long, pcbData As Long
   Dim Recv As SIMCONNECT_RECV
   
   GetNextDispatch = -1
   hr = SimConnect_GetNextDispatch(hSimConnect, pData, pcbData)
   If hr = S_OK Then
      CopyMemory Recv, ByVal pData, Len(Recv)
      Select Case Recv.dwID
         Case SIMCONNECT_RECV_ID_OPEN
            Dim RecvOpen As SIMCONNECT_RECV_OPEN
            pData = pData + Len(Recv)
            CopyMemory RecvOpen, ByVal pData, Len(RecvOpen)
            ' add code here
         Case SIMCONNECT_RECV_ID_EXCEPTION
            Dim RecvException As SIMCONNECT_RECV_EXCEPTION
            pData = pData + Len(Recv)
            CopyMemory RecvException, ByVal pData, Len(RecvException)
            ' add code here
         Case SIMCONNECT_RECV_ID_SIMOBJECT_DATA_BYTYPE
            Dim RecvData As SIMCONNECT_RECV_SIMOBJECT_DATA
            pData = pData + Len(Recv)
            CopyMemory RecvData, ByVal pData, Len(RecvData)
            GetNextDispatch = RecvData.dwRequestID
            Select Case RecvData.dwRequestID
               Case DATA_REQUEST_POSITION
                  pData = pData + Len(RecvData) - 4
                  CopyMemory Position, ByVal pData, Len(Position)
            End Select
      End Select
   End If
End Function

--Russdirks 19:04, 9 October 2006 (CEST)