Skip to content
View in the app

A better way to browse. Learn more.

The AVSIM Community

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

PMDG 737NGX SDK C# P3D

Featured Replies

Hi,

 

I'm busy writing an application in Visual C# 2010 to interface with the 737 NGX CDU's via the SDK. So far I'm able to control the key press events on both CDU's and I'm able to catch all the events returned from P3D when the data on the CDU has changed.

 

I'm struggling with marshalling the PMDG_NGX_CDU_Cell and PMDG_NGX_CDU_Screen structs to managed code in C# to be able to read the CDU screen data.

The PMDG_NGX_Control struct was straight forward to marshal.

I'm not too sure how to define these structs and which method(s) to call to register them:

  • simconnect.AddToDataDefinition
  • simconnect.RegisterDataDefineStruct
  • simconnect.RegisterStruct

Has anyone managed to do this in C#? My C++ Console app is working 100%, but I'm not a C++ expert and I would like to have a GUI for my app.

 

Any help would be greatly appreciated.

 

PS: I know I can just go and buy VAInterface... but this app will be the "poor" simmers option.  ^_^

Jean Joubert

Boeing777_Banner_Pilot.jpg

private enum DATA_REQUEST_ID : byte
{
    DATA_REQUEST = 100,
    CONTROL_REQUEST,
    CDU_REQUEST
}

PMDG_NGX_CDU_Screen cdu_Screen;

simconnect.MapClientDataNameToID(PMDG_NGX_CDU_0_NAME, PMDG_NGX_CDU_0_ID);
simconnect.AddToClientDataDefinition(PMDG_NGX_CDU_0_DEFINITION, 0, (uint)System.Runtime.InteropServices.Marshal.SizeOf(cdu_Screen), 0, 0);
simconnect.RegisterStruct<SIMCONNECT_RECV_CLIENT_DATA, PMDG_NGX_CDU_Screen>(PMDG_NGX_CDU_0_DEFINITION);    
simconnect.RequestClientData(PMDG_NGX_CDU_0_ID, DATA_REQUEST_ID.CDU_REQUEST, PMDG_NGX_CDU_0_DEFINITION, SIMCONNECT_CLIENT_DATA_PERIOD.ON_SET, SIMCONNECT_CLIENT_DATA_REQUEST_FLAG.CHANGED, 0, 0, 0);
  

Should be what you need.

 

Best wishes

Steve

Stephen Munn

 

Just a question, If this is for andoid tablets, please maximize the screen space...I've got a Nexus 7 and the other FMC app leaves some blank space around the edge that looks nice, but I'd rather have the biggest buttons I can on my small screen. 

  • Author

Hi Steve,

 

Thanks for the info... I really appreciate it.

 

Would you mind showing me how you've declared your PMDG_NGX_CDU_Screen and PMDG_NGX_CDU_Cell structs in C#? 

Here's my struct code so far... I'm not sure as to how to declare the screen struct containing the cell struct and whether I'm using the correct StructLayouts and Marshal settings:

// NGX CDU Screen Cell Structure
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
struct PMDG_NGX_CDU_Cell
{
    public char Symbol;
    public char Color;
    public char Flags;
}

// NGX CDU Screen Data Structure

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
struct PMDG_NGX_CDU_Screen
{
    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct)]
    public PMDG_NGX_CDU_Cell[,] Cells;
    [MarshalAs(UnmanagedType.Bool)]
    public bool Powered; // true if the CDU is powered
}
Any help with this would once again be greatly appreciated.

 

Thanks and regards,

Jean Joubert

Boeing777_Banner_Pilot.jpg

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)]
public struct PMDG_NGX_CDU_Cell
{
    public char Symbol;
    public char Color;
    public char Flags;
}

[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)]
public struct PMDG_NGX_CDU_Screen
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 24)]
    public CDUROWS[] cduCols;

    [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)]
    public struct CDUROWS
    {
         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)]
         public PMDG_NGX_CDU_Cell[] cduRows;
    }

    public Boolean Powered;	// true if the CDU is powered
 };

You'll need something like this (sorry not at my development PC, so can't check):

Stephen Munn

 

  • Author

Steve,

 

Thanks. Using your code above for the Screen struct has the unfortunate side-effect of blocking/breaking all simconnect_OnRecvClientData events... I'm not getting any updates back from the CDU. Weird...

 

Anyhow, I'll play around with this to see if I can figure out why.

 

If you don't mind could you perhaps check your code on your dev pc... when you have a moment? I'll really appreciate it.

 

I know I'm close with this because my silly screen struct was returning portions of the CDU data, albeit not very useful.

 

Thanks and regards,

Jean Joubert

Boeing777_Banner_Pilot.jpg

Hi Jean,

 

Just realised my mistake. Change "public Boolean Powered;" to "public byte Powered;". I would also change Color and Flags to byte as they are bit mapped.

 

Final thought is that you have remembered to add these entries into the 737NGXOptions.ini file:

 

[sDK]
EnableDataBroadcast=1
EnableCDUBroadcast.0=1
EnableCDUBroadcast.1=1

 

I'm sure that will make it work OK now.

 

Best wishes

Steve

Stephen Munn

 

  • Author

Steve,

 

You're the man.

 

I couldn't understand why my OnRecvClientData event wasn't triggered... turns out to be the space occupied by a boolean instead of a byte in managed code. 

I actually modified your recommendation slightly to keep a bool in c#, by marshalling it to a 1-byte signed integer: (perfect for handling C-style bool values)

[MarshalAs(UnmanagedType.I1)]
public bool Powered;	// true if the CDU is powered

Thanks ever so much for all your assistance. I really appreciate it.

 

Regards,

Jean

Jean Joubert

Boeing777_Banner_Pilot.jpg

Easily overlooked mistake caused much head scratching! Glad its working OK.

 

Best wishes

Steve

Stephen Munn

 

  • 4 years later...

Resurrecting a super old topic here, but maybe @Steve1969 or @jfjoubert can help me if either of you are still around. I'm pulling CDU displays via C# successfully, but I can't figure out how to parse the bits for the cell flags. I've tried setting up a flags enum (see below), but no way that I've tried to convert to the Cell.Flags char into usable flags has worked...

[Flags]public enum PMDG_CDU_CELL_FLAGS : uint
{
SMALL_FONT = 0x01,
REVERSE = 0x02,
UNUSED = 0x04
}

 

I've just had a quick look at my code and its the same as yours except I'm using a byte not a unit.

Best wishes

Steve

Stephen Munn

 

2 hours ago, Steve1969 said:

I've just had a quick look at my code and its the same as yours except I'm using a byte not a unit.

Best wishes

Steve

How are you actually parsing the flags against the enum, if you don't mind me asking. I've been pulling my hair out for days 😞

20 hours ago, webdes03 said:

How are you actually parsing the flags against the enum, if you don't mind me asking. I've been pulling my hair out for days 😞

Disregard, I switched back to a byte and refactored the parsing logic and it's working now, thanks @Steve1969!

Archived

This topic is now archived and is closed to further replies.

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.