Most of Win32 functions are user friendly. Not as user friendly as .NET framework, but once you see specification, everything is clear. There is no problem translating it to P/Interop call.
But there is one issue that may be problematic - unions. They are used in C++ programs in order to force multiple variables to use same memory space. We will use INPUT structure as example here:
typedef struct tagINPUT {
DWORD type;
union {
MOUSEINPUT mi;
KEYBDINPUT ki;
HARDWAREINPUT hi;
};
} INPUT, *PINPUT;
typedef struct tagMOUSEINPUT {
LONG dx;
LONG dy;
DWORD mouseData;
DWORD dwFlags;
DWORD time;
ULONG_PTR dwExtraInfo;
} MOUSEINPUT, *PMOUSEINPUT;
typedef struct tagKEYBDINPUT {
WORD wVk;
WORD wScan;
DWORD dwFlags;
DWORD time;
ULONG_PTR dwExtraInfo;
} KEYBDINPUT, *PKEYBDINPUT;
typedef struct tagHARDWAREINPUT {
DWORD uMsg;
WORD wParamL;
WORD wParamH;
} HARDWAREINPUT, *PHARDWAREINPUT;
Although this code is little bit messy, it should be mostly clear to C# developer:
public struct MOUSEINPUT {
public Int32 dx;
public Int32 dy;
public Int32 mouseData;
public Int32 dwFlags;
public Int32 time;
public UInt32 dwExtraInfo;
}
public struct KEYBDINPUT {
public Int16 wVk;
public Int16 wScan;
public Int32 dwFlags;
public Int32 time;
public UInt32 dwExtraInfo;
}
public struct HARDWAREINPUT {
public Int32 uMsg;
public Int16 wParamL;
public Int16 wParamH;
}
While this conversion is clear, what is not so clear is what to do with tagINPUT.
Solution in C# could look like this:
public struct tagHARDWAREINPUT {
[FieldOffset(0)]
public MOUSEINPUT mi;
[FieldOffset(0)]
public KEYBDINPUT ki;
[FieldOffset(0)]
public HARDWAREINPUT hi;
}
This makes all fields aligned on first byte and thus they behave identically to C++ structure union.