Managed SimConnect Projects


Overview

There is a managed wrapper for SimConnect that enables .NET language programmers to write SimConnect clients. This section describes how to set up a managed client project, and the key differences to look out for when programming to the wrapper. There are also a number of Managed Code Samples included with the SDK.

Getting Started With Managed SimConnect

  1. Ensure the Microsoft .NET Framework 4.7.2 Developer Pack is installed as many of the Managed Samples target this version of the framework.
  2. Create a new project using Visual Studio 2017 using one of the following project types:
    • C#: WinForms, WPF, Console
    • VB.NET: WinForms, WPF, Console
  3. Add a new reference to LockheedMartin.Prepar3D.SimConnect.dll in your project. This file can be found in this directory of the SDK:
    SDK\lib\SimConnect\managed
  4. Import the following assemblies in the code files using SimConnect functionality:
    C#
    using LockheedMartin.Prepar3D.SimConnect;
    using System.Runtime.InteropServices;
    VB.NET
    Imports LockheedMartin.Prepar3D.SimConnect
    Imports System.Runtime.InteropServices
  5. Set up the initialization and deinitialization of the SimConnect Client.


    The native function calls SimConnect_Open and SimConnect_Close have been replaced by the SimConnect constructor, and Dispose method respectively. This means that there is no handle required for the function calls, so for the most part the managed calls use the same parameters as the native calls, except without the SimConnect handle. The code to open and close a SimConnect client is:


    C#
    // Open
    // Declare a SimConnect object
    SimConnect simconnect = null;
    // User-defined win32 event
    const int WM_USER_SIMCONNECT = 0x0402;
    try
    {
      simconnect = new SimConnect("Managed Data Request", this.Handle, WM_USER_SIMCONNECT, null, 0);
    }
    catch (COMException ex)
    {
      // A connection to the SimConnect server could not be established
    }
    What would have been a failed HRESULT returned in the native API translates to a COMException.

    // Close
    if (simconnect != null)
    {
      simconnect.Dispose();
      simconnect = null;
    }

    VB.NET

    Rem Open
    Try
       simconnect = New SimConnect(" VB Managed Data Request", Me.Handle, WM_USER_SIMCONNECT, Nothing, 0)
    Catch ex As Exception
       Rem Failed to connect
    End Try
    What would have been a failed HRESULT returned in the native API translates to a COMException.

    Rem Close
    If simconnect IsNot Nothing Then
       simconnect.Dispose()
       simconnect = Nothing
    End If

  6. Recieve messages from the SimConnect server.


    The top level ReceiveDispatch switch case statement is not necessary. The client should register a handler for the appropriate OnRecvXXX event, and call ReceiveMessage when it is notified that messages are waiting in the queue. For Windows applications use a win32 handle (a Control.Handle) to SimConnect to receive notifications when a message arrives. The code for this is as follows:


    C#: WinForms
    protected override void DefWndProc(ref Message m)
    {
      if (m.Msg == WM_USER_SIMCONNECT)
      {
        if (simconnect != null)
        {
          simconnect.ReceiveMessage();
        }
      }
      else
      {
        base.DefWndProc(ref m);
      }
    }

    C# WPF
    IntPtr handle;
    HwndSource handleSource;

    // Register WPF window
    YourWPFWindow()
    {
      handle = new WindowInteropHelper(this).Handle; // Get handle of main WPF Window
      handleSource = HwndSource.FromHwnd(handle); // Get source of handle in order to add event handlers to it
      handleSource.AddHook(HandleSimConnectEvents);
    }

    ~YourWPFWindow()
    {
      if (handleSource != null)
      {
        handleSource.RemoveHook(HandleSimConnectEvents);
      }
    }

    private IntPtr HandleSimConnectEvents(IntPtr hWnd, int message, IntPtr wParam, IntPtr lParam, ref bool isHandled)
    {
      isHandled = false;
      
      switch (message)
      {
        case WM_USER_SIMCONNECT:
        {
          if (simConnect != null)
          {
            simConnect.ReceiveMessage();
            isHandled = true;
          }
        }
        break;

        default:
          break;
      }

      return IntPtr.Zero;
    }
    VB.NET
    Protected Overrides Sub DefWndProc(ByRef m As Message)
       If m.Msg = WM_USER_SIMCONNECT Then
          If simconnect IsNot Nothing Then
             simconnect.ReceiveMessage()
          End If
       Else
          MyBase.DefWndProc(m)
       End If
    End Sub

Managed SimConnect Programming Differences

Besides the differences in initialization, deinitialization, and recieving dispatched messages, there are other nuances to be aware of. This section enumerates key differences to be aware of as a developer: